// Every locale namespace must carry the SAME key set in English and Hungarian. A key present // in one language but not the other renders the raw key string (missing translation) or is dead // weight (orphaned translation); this test fails loudly on either, per namespace. import { describe, expect, it } from "vitest"; const mods = import.meta.glob("./locales/*/*.json", { eager: true }) as Record< string, { default: Record } >; function flatten(obj: Record, prefix = ""): string[] { const out: string[] = []; for (const [k, v] of Object.entries(obj)) { const key = prefix ? `${prefix}.${k}` : k; if (v && typeof v === "object" && !Array.isArray(v)) { out.push(...flatten(v as Record, key)); } else { out.push(key); } } return out.sort(); } // { namespace: { en: {...}, hu: {...} } } const byNs: Record>> = {}; for (const [path, mod] of Object.entries(mods)) { const m = path.match(/\/locales\/([^/]+)\/([^/]+)\.json$/); const lang = m?.[1]; const ns = m?.[2]; if (!lang || !ns) continue; (byNs[ns] ??= {})[lang] = mod.default; } describe("i18n en/hu key parity", () => { it("loaded both languages for every namespace", () => { expect(Object.keys(byNs).length).toBeGreaterThan(0); for (const [ns, langs] of Object.entries(byNs)) { expect({ ns, langs: Object.keys(langs).sort() }).toEqual({ ns, langs: ["en", "hu"] }); } }); for (const [ns, langs] of Object.entries(byNs)) { it(`${ns}: en and hu declare identical keys`, () => { const en = flatten(langs.en ?? {}); const hu = flatten(langs.hu ?? {}); expect({ missingInHu: en.filter((k) => !hu.includes(k)), missingInEn: hu.filter((k) => !en.includes(k)), }).toEqual({ missingInHu: [], missingInEn: [] }); }); } });