fix(cli): resolve OMNIROUTE_LANG aliases (uk → uk-UA, fil → phi) from config/i18n.json

This commit is contained in:
Markus Hartung
2026-09-02 03:32:19 -03:00
parent daadfba2f8
commit 637b4ef3d6
2 changed files with 50 additions and 2 deletions

View File

@@ -5,6 +5,25 @@ import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const LOCALES_DIR = join(__dirname, "locales");
const FALLBACK_LOCALE = "en";
const I18N_CONFIG_PATH = join(__dirname, "..", "..", "config", "i18n.json");
let aliasMap = null; // lower-case tag → canonical locale code
function loadAliasMap() {
if (aliasMap) return aliasMap;
aliasMap = new Map();
try {
const { locales } = JSON.parse(readFileSync(I18N_CONFIG_PATH, "utf8"));
for (const entry of locales) {
aliasMap.set(entry.code.toLowerCase(), entry.code);
for (const alias of entry.aliases || []) {
aliasMap.set(String(alias).toLowerCase(), entry.code);
}
}
} catch {
// config absent (trimmed package): keep file-based detection only
}
return aliasMap;
}
const cache = new Map();
let activeLocale = null;
@@ -24,8 +43,16 @@ function normalize(raw) {
const stripped = String(raw).split(".")[0].replaceAll("_", "-");
if (!stripped || !/^[a-zA-Z0-9-]+$/.test(stripped)) return FALLBACK_LOCALE;
if (hasCatalog(stripped)) return stripped;
const base = stripped.split("-")[0];
const lower = stripped.toLowerCase();
const base = lower.split("-")[0];
const aliases = loadAliasMap();
const viaAlias = aliases.get(lower) ?? aliases.get(base);
if (viaAlias && hasCatalog(viaAlias)) return viaAlias;
if (hasCatalog(base)) return base;
const regional = [...new Set(aliases.values())].find(
(code) => code.includes("-") && code.toLowerCase().split("-")[0] === base
);
if (regional && hasCatalog(regional)) return regional;
return FALLBACK_LOCALE;
}
@@ -103,4 +130,5 @@ export function resetForTests() {
cache.clear();
activeLocale = null;
fallbackCatalog = null;
aliasMap = null;
}

View File

@@ -74,7 +74,10 @@ test("pt-BR.json tem todas as seções top-level de en.json", () => {
assert.deepEqual(missing, [], `Seções top-level faltando em pt-BR.json: ${missing.join(", ")}`);
});
for (const [name, cat] of [["zh-CN", zhCN], ["zh-TW", zhTW]] as const) {
for (const [name, cat] of [
["zh-CN", zhCN],
["zh-TW", zhTW],
] as const) {
test(name + ".json tem paridade total de chaves com en.json", () => {
const catKeys = flattenKeys(cat as Record<string, unknown>);
const missing = [...enKeys].filter((k) => !catKeys.has(k));
@@ -106,6 +109,23 @@ test("i18n.mjs usa fallback en quando locale não existe", async () => {
resetForTests();
});
test("i18n.mjs resolve alias do config: OMNIROUTE_LANG=uk → uk-UA, fil_PH.UTF-8 → phi", async () => {
const { resetForTests, detectLocale } = await import("../../bin/cli/i18n.mjs");
const orig = process.env.OMNIROUTE_LANG;
process.env.OMNIROUTE_LANG = "uk";
resetForTests();
assert.equal(detectLocale(), "uk-UA");
process.env.OMNIROUTE_LANG = "fil_PH.UTF-8";
resetForTests();
assert.equal(detectLocale(), "phi");
process.env.OMNIROUTE_LANG = "uk_UA.UTF-8";
resetForTests();
assert.equal(detectLocale(), "uk-UA");
if (orig === undefined) delete process.env.OMNIROUTE_LANG;
else process.env.OMNIROUTE_LANG = orig;
resetForTests();
});
test("t() interpola variáveis {var}", async () => {
const { resetForTests, t, setLocale } = await import("../../bin/cli/i18n.mjs");
resetForTests();