/** # 测试 后台 i18n 词典完整性:en 词典必须覆盖全部 t("…") 键与动态标签映射(后台默认英文) */ import { describe, expect, test } from "bun:test"; import { readdirSync } from "node:fs"; import { en } from "../src/admin-i18n/locales/en"; import { ADMIN_MENU_GROUPS } from "../src/admin-menus"; import { CONTENT_TYPE_LABEL, INQUIRY_STATUS_LABEL, ORDER_STATUS_LABEL } from "../src/components/admin/common"; // 扫描后台路由与组件源码中的 t("中文") 调用,收集全部静态源串键 const files = [ ...readdirSync("src/routes").filter((f) => f.startsWith("admin")).map((f) => `src/routes/${f}`), ...readdirSync("src/components/admin").map((f) => `src/components/admin/${f}`), ]; const keyRe = /\bt\(\s*"((?:[^"\\]|\\.)*)"/g; const keys = new Set(); for (const f of files) { const src = await Bun.file(f).text(); for (const m of src.matchAll(keyRe)) keys.add(m[1]!); } /** # 成员变量 动态键源(label 映射的值也作为 t() 的键使用,必须入词典) **/ const dynamicKeys: string[] = [ ...Object.values(ORDER_STATUS_LABEL), ...Object.values(INQUIRY_STATUS_LABEL), ...Object.values(CONTENT_TYPE_LABEL), ...ADMIN_MENU_GROUPS.flatMap((g) => [g.label, ...g.children.map((m) => m.label)]), ]; describe("后台 i18n 词典", () => { test("英文词典覆盖全部静态 t() 键", () => { const missing = [...keys].filter((k) => !(k in en)); expect(missing).toEqual([]); }); test("英文词典覆盖全部动态标签映射键", () => { const missing = dynamicKeys.filter((k) => !(k in en)); expect(missing).toEqual([]); }); test("英文词典键数合理(防止误清空)", () => { expect(Object.keys(en).length).toBeGreaterThan(200); }); });