createStringsResource: support merged imports
This commit is contained in:
parent
b4fa751345
commit
c49ae6fe0a
6 changed files with 58 additions and 32 deletions
|
@ -35,7 +35,7 @@ export function autoMatchLangTag() {
|
|||
return match(Array.from(navigator.languages), SUPPORTED_LANGS, DEFAULT_LANG);
|
||||
}
|
||||
|
||||
const DateFnLocaleCx = createContext<Accessor<Locale>>(() => enGB);
|
||||
const DateFnLocaleCx = /* __@PURE__ */createContext<Accessor<Locale>>(() => enGB);
|
||||
|
||||
const cachedDateFnLocale: Record<string, Locale> = {
|
||||
enGB,
|
||||
|
@ -149,11 +149,20 @@ export function useLanguage() {
|
|||
return () => settings().language || autoMatchLangTag();
|
||||
}
|
||||
|
||||
type ImportFn<T> = (name: string) => Promise<{default: T}>
|
||||
|
||||
type ImportedModule<F> = F extends ImportFn<infer T> ? T: never
|
||||
|
||||
type MergedImportedModule<T> =
|
||||
T extends [] ? {} :
|
||||
T extends [infer I] ? ImportedModule<I> :
|
||||
T extends [infer I, ...infer J] ? ImportedModule<I> & MergedImportedModule<J> : never
|
||||
|
||||
export function createStringResource<
|
||||
M extends Record<string, string | Template<any>>,
|
||||
>(importFn: (code: string) => Promise<{ default: M }>) {
|
||||
T extends ImportFn<Record<string, string | Template<any> | undefined>>[],
|
||||
>(...importFns: T) {
|
||||
const language = useLanguage();
|
||||
const cache: Record<string, M | undefined> = {};
|
||||
const cache: Record<string, MergedImportedModule<T>> = {};
|
||||
|
||||
return createResource(
|
||||
() => [language()] as const,
|
||||
|
@ -162,9 +171,13 @@ export function createStringResource<
|
|||
return cache[nlang];
|
||||
}
|
||||
|
||||
const { default: dict } = await importFn(`${nlang}`);
|
||||
const results = await Promise.all(importFns.map(x => x(nlang).then(v => v.default)))
|
||||
|
||||
return dict;
|
||||
const merged: MergedImportedModule<T> = Object.assign({}, ...results)
|
||||
|
||||
cache[nlang] = merged;
|
||||
|
||||
return merged;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from "@suid/material";
|
||||
import {
|
||||
Close as CloseIcon,
|
||||
Logout,
|
||||
Public as PublicIcon,
|
||||
Refresh as RefreshIcon,
|
||||
Translate as TranslateIcon,
|
||||
|
@ -38,11 +39,19 @@ import {
|
|||
SUPPORTED_REGIONS,
|
||||
useDateFnLocale,
|
||||
} from "../platform/i18n.jsx";
|
||||
import { resolveTemplate, translator } from "@solid-primitives/i18n";
|
||||
import { resolveTemplate, translator, type Template } from "@solid-primitives/i18n";
|
||||
|
||||
type Strings = {
|
||||
["lang.auto"]: Template<{detected: string}>
|
||||
} & Record<string, string | undefined>
|
||||
|
||||
const Settings: ParentComponent = () => {
|
||||
const [strings] = createStringResource(
|
||||
(code) => import(`./i18n/${code}.json`),
|
||||
(code) =>
|
||||
import(`./i18n/${code}.json`) as Promise<{
|
||||
default: Strings;
|
||||
}>,
|
||||
() => import(`./i18n/lang-names.json`)
|
||||
);
|
||||
const t = translator(strings, resolveTemplate);
|
||||
const navigate = useNavigate();
|
||||
|
@ -87,31 +96,34 @@ const Settings: ParentComponent = () => {
|
|||
<li>
|
||||
<ul>
|
||||
<ListSubheader>{t("Accounts")}</ListSubheader>
|
||||
<ListItem>
|
||||
<ListItemButton disabled>
|
||||
<ListItemText>{t("All Notifications")}</ListItemText>
|
||||
<ListItemSecondaryAction>
|
||||
<Switch value={false} />
|
||||
<Switch value={false} disabled/>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItem>
|
||||
<ListItemButton disabled>
|
||||
<ListItemText>{t("Sign in...")}</ListItemText>
|
||||
</ListItem>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
</ul>
|
||||
<For each={profiles()}>
|
||||
{({ account: acct, inf }) => (
|
||||
<ul data-site={acct.site} data-username={inf?.username}>
|
||||
<ListSubheader>{`@${inf?.username ?? "..."}@${new URL(acct.site).host}`}</ListSubheader>
|
||||
<ListItem>
|
||||
<ListItemText>Notifications</ListItemText>
|
||||
<ListItemButton disabled>
|
||||
<ListItemText>{t("Notifications")}</ListItemText>
|
||||
<ListItemSecondaryAction>
|
||||
<Switch value={false} />
|
||||
<Switch value={false} disabled/>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
<ListItemButton onClick={[doSignOut, acct]}>
|
||||
<ListItemText>Sign out</ListItemText>
|
||||
<ListItemIcon>
|
||||
<Logout/>
|
||||
</ListItemIcon>
|
||||
<ListItemText>{t("Sign out")}</ListItemText>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
</ul>
|
||||
|
@ -120,11 +132,7 @@ const Settings: ParentComponent = () => {
|
|||
</li>
|
||||
<li>
|
||||
<ListSubheader>{t("Reading")}</ListSubheader>
|
||||
<ListItem>
|
||||
<ListItemText secondary="Regular">Fonts</ListItemText>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
<ListItem
|
||||
<ListItemButton
|
||||
onClick={(e) =>
|
||||
$settings.setKey(
|
||||
"prefetchTootsDisabled",
|
||||
|
@ -138,7 +146,7 @@ const Settings: ParentComponent = () => {
|
|||
<ListItemSecondaryAction>
|
||||
<Switch checked={!settings$().prefetchTootsDisabled} />
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
</ListItemButton>
|
||||
<Divider />
|
||||
</li>
|
||||
<li>
|
||||
|
@ -162,7 +170,7 @@ const Settings: ParentComponent = () => {
|
|||
>
|
||||
<option value={"xauto"}>
|
||||
{t("lang.auto", {
|
||||
detected: t("lang." + autoMatchLangTag()),
|
||||
detected: t("lang." + autoMatchLangTag()) ?? autoMatchLangTag(),
|
||||
})}
|
||||
</option>
|
||||
<For each={SUPPORTED_LANGS}>
|
||||
|
@ -191,7 +199,7 @@ const Settings: ParentComponent = () => {
|
|||
>
|
||||
<option value={"xauto"}>
|
||||
{t("region.auto", {
|
||||
detected: t("region." + autoMatchRegion()),
|
||||
detected: t("region." + autoMatchRegion()) ?? autoMatchRegion(),
|
||||
})}
|
||||
</option>
|
||||
<For each={SUPPORTED_REGIONS}>
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
"Language": "Language",
|
||||
"Region": "Region",
|
||||
"lang.auto": "Auto({{detected}})",
|
||||
"lang.zh-Hans": "中文(简体)",
|
||||
"lang.en": "English",
|
||||
"region.auto": "Auto({{detected}})",
|
||||
"region.en_GB": "Great Britan (English)",
|
||||
"region.en_US": "United States (English)",
|
||||
"region.zh_CN": "China Mainland (Chinese)",
|
||||
"datefmt": "yyyy/MM/dd"
|
||||
"datefmt": "yyyy/MM/dd",
|
||||
"Sign out": "Sign out",
|
||||
"Notifications": "Notifications"
|
||||
}
|
4
src/settings/i18n/lang-names.json
Normal file
4
src/settings/i18n/lang-names.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"lang.zh-Hans": "中文(简体)",
|
||||
"lang.en": "English"
|
||||
}
|
|
@ -15,11 +15,11 @@
|
|||
"Language": "语言",
|
||||
"Region": "区域",
|
||||
"lang.auto": "自动({{detected}})",
|
||||
"lang.zh-Hans": "中文(简体)",
|
||||
"lang.en": "English",
|
||||
"region.auto": "自动({{detected}})",
|
||||
"region.en_GB": "英国和苏格兰(英语)",
|
||||
"region.en_US": "美国(英语)",
|
||||
"region.zh_CN": "中国大陆(中文)",
|
||||
"datefmt": "yyyy年MM月dd日"
|
||||
"datefmt": "yyyy年MM月dd日",
|
||||
"Sign out": "登出此账户",
|
||||
"Notifications": "通知"
|
||||
}
|
|
@ -11,5 +11,6 @@
|
|||
"types": ["vite/client", "vite-plugin-pwa/solid"],
|
||||
"noEmit": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue