createStringsResource: support merged imports
This commit is contained in:
		
							parent
							
								
									4f8b31ca31
								
							
						
					
					
						commit
						8a9c788fe1
					
				
					 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": "通知"
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue