autoMatchRegion: improved matching algorithm

This commit is contained in:
thislight 2024-11-04 00:13:21 +08:00
parent e8a206db96
commit b44d093f08
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E

View file

@ -11,7 +11,11 @@ import { $settings } from "../settings/stores";
import { enGB } from "date-fns/locale/en-GB"; import { enGB } from "date-fns/locale/en-GB";
import { useStore } from "@nanostores/solid"; import { useStore } from "@nanostores/solid";
import type { Locale } from "date-fns"; import type { Locale } from "date-fns";
import { resolveTemplate, translator, type Template } from "@solid-primitives/i18n"; import {
resolveTemplate,
translator,
type Template,
} from "@solid-primitives/i18n";
async function synchronised( async function synchronised(
name: string, name: string,
@ -34,29 +38,35 @@ export function autoMatchLangTag() {
return match(Array.from(navigator.languages), SUPPORTED_LANGS, DEFAULT_LANG); return match(Array.from(navigator.languages), SUPPORTED_LANGS, DEFAULT_LANG);
} }
const DateFnLocaleCx = /* __@PURE__ */createContext<Accessor<Locale>>(() => enGB); const DateFnLocaleCx = /* __@PURE__ */ createContext<Accessor<Locale>>(
() => enGB,
);
const cachedDateFnLocale: Record<string, Locale> = { const cachedDateFnLocale: Record<string, Locale> = {
enGB, enGB,
}; };
export function autoMatchRegion() { export function autoMatchRegion() {
const regions = navigator.languages const specifiers = navigator.languages.map((x) => x.split("-"));
.map((x) => {
const parts = x.split("_"); for (const s of specifiers) {
if (parts.length > 1) { if (s.length === 1) {
return parts[1]; const lang = s[0];
for (const available of SUPPORTED_REGIONS) {
if (available.toLowerCase().startsWith(lang.toLowerCase())) {
return available;
}
} }
return undefined; } else if (s.length === 2) {
}) const [lang, region] = s[1];
.filter((x): x is string => !!x); for (const available of SUPPORTED_REGIONS) {
for (const r of regions) { if (available.toLowerCase() === `${lang}_${region}`.toLowerCase()) {
for (const available of SUPPORTED_REGIONS) { return available;
if (available.toLowerCase().endsWith(r.toLowerCase())) { }
return available;
} }
} }
} }
return "en_GB"; return "en_GB";
} }
@ -148,14 +158,17 @@ export function useLanguage() {
return () => settings().language || autoMatchLangTag(); return () => settings().language || autoMatchLangTag();
} }
type ImportFn<T> = (name: string) => Promise<{default: T}> type ImportFn<T> = (name: string) => Promise<{ default: T }>;
type ImportedModule<F> = F extends ImportFn<infer T> ? T: never type ImportedModule<F> = F extends ImportFn<infer T> ? T : never;
type MergedImportedModule<T> = type MergedImportedModule<T> = T extends []
T extends [] ? {} : ? {}
T extends [infer I] ? ImportedModule<I> : : T extends [infer I]
T extends [infer I, ...infer J] ? ImportedModule<I> & MergedImportedModule<J> : never ? ImportedModule<I>
: T extends [infer I, ...infer J]
? ImportedModule<I> & MergedImportedModule<J>
: never;
export function createStringResource< export function createStringResource<
T extends ImportFn<Record<string, string | Template<any> | undefined>>[], T extends ImportFn<Record<string, string | Template<any> | undefined>>[],
@ -170,9 +183,11 @@ export function createStringResource<
return cache[nlang]; return cache[nlang];
} }
const results = await Promise.all(importFns.map(x => x(nlang).then(v => v.default))) const results = await Promise.all(
importFns.map((x) => x(nlang).then((v) => v.default)),
);
const merged: MergedImportedModule<T> = Object.assign({}, ...results) const merged: MergedImportedModule<T> = Object.assign({}, ...results);
cache[nlang] = merged; cache[nlang] = merged;
@ -181,8 +196,10 @@ export function createStringResource<
); );
} }
export function createTranslator<T extends ImportFn<Record<string, string | Template<any> | undefined>>[],>(...importFns: T) { export function createTranslator<
const res = createStringResource(...importFns) T extends ImportFn<Record<string, string | Template<any> | undefined>>[],
>(...importFns: T) {
const res = createStringResource(...importFns);
return [translator(res[0], resolveTemplate), res] as const return [translator(res[0], resolveTemplate), res] as const;
} }