Files
dusuniot/tests/i18n.test.ts
T

49 lines
1.7 KiB
TypeScript

/** # 测试 i18n 词典完整性:全部受支持语言必须覆盖全部英文键(不允许缺词回退上线) */
import { describe, expect, test } from "bun:test";
import { en } from "../src/i18n/locales/en";
import { LOCALES } from "../src/i18n/shared";
import "../src/i18n/locales";
// eslint-disable-next-line @typescript-eslint/no-var-requires
import { getDict } from "../src/i18n/index";
import { createT } from "../src/i18n/index";
const enKeys = Object.keys(en) as (keyof typeof en)[];
describe("i18n 词典", () => {
test("英文词典键数合理(防止误清空)", () => {
expect(enKeys.length).toBeGreaterThan(60);
});
test("每个受支持语言都有词典注册且覆盖全部键", () => {
for (const l of LOCALES) {
if (l.code === "en") continue;
const d = getDict(l.code);
expect(Object.keys(d).length).toBeGreaterThan(0);
const missing = enKeys.filter((k) => !(k in d));
expect(missing).toEqual([]);
}
});
test("插值占位符在各语言中保持一致", () => {
for (const l of LOCALES) {
if (l.code === "en") continue;
const d = getDict(l.code) as Record<string, string>;
for (const [k, v] of Object.entries(d)) {
const vars = (en[k as keyof typeof en] as string).match(/\{(\w+)\}/g) ?? [];
for (const vName of vars) {
expect(v.includes(vName)).toBe(true);
}
}
}
});
test("createT 回退与插值", () => {
const t = createT("zh-CN");
expect(t("nav_home")).toBe("首页");
expect(t("shop_showing", { from: 1, to: 24, total: 100 })).toContain("100");
// 未注册语言回退英文
const t2 = createT("xx-unknown");
expect(t2("nav_home")).toBe("Home");
});
});