mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-16 03:42:21 +03:00
feat(i18n): declare locale aliases in config/i18n.json (uk, fil/tl, zh-hk/mo)
This commit is contained in:
@@ -57,6 +57,16 @@
|
||||
"flag": {
|
||||
"type": "string",
|
||||
"description": "Flag emoji shown next to the locale."
|
||||
},
|
||||
"aliases": {
|
||||
"type": "array",
|
||||
"description": "Browser/OS language tags (lower-case BCP-47) that resolve to this locale, e.g. `uk` → `uk-UA`, `fil`/`tl` → `phi`.",
|
||||
"items": { "type": "string", "pattern": "^[a-z]{2,3}(-[a-z0-9]{2,8})*$" },
|
||||
"uniqueItems": true
|
||||
},
|
||||
"script": {
|
||||
"type": "string",
|
||||
"description": "ISO 15924 script code (e.g. `Mymr`, `Khmr`). Informational only — the visual-QA report uses it to prioritise tall scripts."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,8 @@
|
||||
"name": "Filipino",
|
||||
"native": "Filipino",
|
||||
"english": "Filipino",
|
||||
"flag": "🇵🇭"
|
||||
"flag": "🇵🇭",
|
||||
"aliases": ["fil", "tl"]
|
||||
},
|
||||
{
|
||||
"code": "pl",
|
||||
@@ -315,7 +316,8 @@
|
||||
"name": "Українська",
|
||||
"native": "Українська",
|
||||
"english": "Ukrainian",
|
||||
"flag": "🇺🇦"
|
||||
"flag": "🇺🇦",
|
||||
"aliases": ["uk"]
|
||||
},
|
||||
{
|
||||
"code": "ur",
|
||||
@@ -347,7 +349,8 @@
|
||||
"name": "中文 (繁體)",
|
||||
"native": "中文 (繁體)",
|
||||
"english": "Chinese (Traditional)",
|
||||
"flag": "🇹🇼"
|
||||
"flag": "🇹🇼",
|
||||
"aliases": ["zh-hk", "zh-mo"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ type RawLocaleEntry = {
|
||||
native?: string;
|
||||
english?: string;
|
||||
flag: string;
|
||||
aliases?: readonly string[];
|
||||
script?: string;
|
||||
};
|
||||
|
||||
type RawI18nConfig = {
|
||||
@@ -51,4 +53,18 @@ export const LANGUAGES: readonly {
|
||||
|
||||
export const RTL_LOCALES: readonly Locale[] = config.rtl as readonly Locale[];
|
||||
|
||||
/**
|
||||
* Browser / OS language tags that resolve to a configured locale. Read by
|
||||
* `detectBrowserLocale` (client), `resolveRequestedLocale` (server cookie) and
|
||||
* mirrored by the CLI (`bin/cli/i18n.mjs`). Keys are locale codes, values are
|
||||
* lower-case BCP-47 tags. Only locales that declare `aliases` appear here.
|
||||
*/
|
||||
export const LOCALE_ALIASES: Readonly<Record<string, readonly string[]>> = Object.freeze(
|
||||
Object.fromEntries(
|
||||
config.locales
|
||||
.filter((entry) => Array.isArray(entry.aliases) && entry.aliases.length > 0)
|
||||
.map((entry) => [entry.code, Object.freeze([...(entry.aliases as string[])])])
|
||||
)
|
||||
);
|
||||
|
||||
export const LOCALE_COOKIE = "NEXT_LOCALE";
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
DEFAULT_LOCALE,
|
||||
LANGUAGES,
|
||||
LOCALES,
|
||||
LOCALE_ALIASES,
|
||||
LOCALE_COOKIE,
|
||||
RTL_LOCALES,
|
||||
} from "../../src/i18n/config.ts";
|
||||
@@ -34,3 +35,23 @@ test("i18n language metadata preserves native and English names", () => {
|
||||
flag: englishConfig?.flag,
|
||||
});
|
||||
});
|
||||
|
||||
test("locale aliases are lower-case, unique and never collide with a locale code", () => {
|
||||
const codes = new Set(LOCALES.map((code) => code.toLowerCase()));
|
||||
const seen = new Set<string>();
|
||||
for (const [code, aliases] of Object.entries(LOCALE_ALIASES)) {
|
||||
assert.ok(codes.has(code.toLowerCase()), `${code} is not a configured locale`);
|
||||
for (const alias of aliases) {
|
||||
assert.equal(alias, alias.toLowerCase(), `${alias} must be lower-case`);
|
||||
assert.ok(!codes.has(alias), `${alias} collides with a locale code`);
|
||||
assert.ok(!seen.has(alias), `${alias} is declared for two locales`);
|
||||
seen.add(alias);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("Ukrainian, Filipino and Hong-Kong/Macau browsers resolve through declared aliases", () => {
|
||||
assert.deepEqual(LOCALE_ALIASES["uk-UA"], ["uk"]);
|
||||
assert.deepEqual(LOCALE_ALIASES["phi"], ["fil", "tl"]);
|
||||
assert.deepEqual(LOCALE_ALIASES["zh-TW"], ["zh-hk", "zh-mo"]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user