test(i18n): non-empty + non-placeholder parity assertion

Phase C4 audit found EN/DE locale files in perfect parity (1817 keys
each, 0 drift, 0 empty values, 0 TODO/FIXME placeholders) — the five
B-agents and the C2/C3 phases each shipped their own translations
inline.

This commit hardens the parity test to lock that state in:
- empty-string assertion (per locale, fails on `"key": ""`)
- key-equals-value assertion (fails when EN==DE==key.lastSegment, with
  an explicit allow-list for 5 legitimate cases: `settings.ntfy`,
  `classifications.{bp.Optimal,bp.Normal,pulse.Normal,bodyFat.Fitness}`)
- TODO/FIXME/XXX/TBD assertion (per locale)

EN-only key=value cases (e.g. `"of": "of"` where DE = `"von"`) are
deliberately NOT flagged — those are natural, since key names derive
from the EN word. The dual-locale check catches the real placeholder
pattern (`"bugReport": "bugReport"` in both locales) without false
positives.

Audit report: docs/audit/v1415-i18n-coverage.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-09 21:43:27 +02:00
1 parent 27310e4f9a
commit 01a10de5d8
2 files changed
+231

No files matched your search

@@ -212,4 +212,107 @@ describe("i18n locale file integrity", () => {
"Locale files drifted apart — every key must exist in both locales.",
).toEqual({ onlyInEn: [], onlyInDe: [] });
});
// Flat helper used by the value-quality checks below.
function flattenValues(obj: unknown, prefix: string, out: [string, string][]) {
if (obj == null || typeof obj !== "object") return;
for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {
const key = prefix ? `${prefix}.${k}` : k;
if (typeof v === "string") out.push([key, v]);
else if (typeof v === "object") flattenValues(v, key, out);
}
}
// Translations whose last-segment legitimately equals the value in BOTH
// locales — brand names, anglicisms, identical EN/DE technical terms.
// See `docs/audit/v1415-i18n-coverage.md` §Legitimate EN==DE==key cases.
const PLACEHOLDER_ALLOWLIST = new Set<string>([
"settings.ntfy",
"classifications.bp.Optimal",
"classifications.bp.Normal",
"classifications.pulse.Normal",
"classifications.bodyFat.Fitness",
]);
it.each([
["en", EN_PATH],
["de", DE_PATH],
])("%s locale has no empty values", (_locale, path) => {
const data = JSON.parse(readFileSync(path, "utf8")) as Record<
string,
unknown
>;
const flat: [string, string][] = [];
flattenValues(data, "", flat);
const empties = flat.filter(([, v]) => v === "").map(([k]) => k);
expect(
empties,
`Empty translations are forbidden — every key needs a real string:\n` +
empties.map((k) => ` ${k}`).join("\n"),
).toEqual([]);
});
it("has no placeholder values (value === key last segment in BOTH locales)", () => {
// We only fail when the same key has value == last-segment in BOTH locales.
// EN-only matches are usually legitimate (the key is named after the EN word
// so naturally `"of": "of"` looks like a match — but DE has `"of": "von"`,
// which is a real translation). EN+DE both equalling the key is a strong
// signal of a forgotten placeholder like `"bugReport": "bugReport"`.
const en = JSON.parse(readFileSync(EN_PATH, "utf8")) as Record<
string,
unknown
>;
const de = JSON.parse(readFileSync(DE_PATH, "utf8")) as Record<
string,
unknown
>;
const enFlat: [string, string][] = [];
const deFlat: [string, string][] = [];
flattenValues(en, "", enFlat);
flattenValues(de, "", deFlat);
const deMap = new Map(deFlat);
const placeholders = enFlat
.filter(([k, enV]) => {
if (PLACEHOLDER_ALLOWLIST.has(k)) return false;
const last = k.split(".").pop();
if (last === undefined) return false;
if (enV !== last) return false;
const deV = deMap.get(k);
return deV !== undefined && deV === last;
})
.map(([k, v]) => `${k} = ${JSON.stringify(v)}`);
expect(
placeholders,
`Found keys whose value equals the key's last segment in BOTH locales —\n` +
`usually a forgotten placeholder (e.g. \`"bugReport": "bugReport"\`).\n` +
`Either replace with real translations or add to PLACEHOLDER_ALLOWLIST\n` +
`in this test if the match is genuinely intentional (brand names,\n` +
`identical EN/DE terms):\n` +
placeholders.map((s) => ` ${s}`).join("\n"),
).toEqual([]);
});
it.each([
["en", EN_PATH],
["de", DE_PATH],
])(
"%s locale has no TODO/FIXME placeholders in values",
(_locale, path) => {
const data = JSON.parse(readFileSync(path, "utf8")) as Record<
string,
unknown
>;
const flat: [string, string][] = [];
flattenValues(data, "", flat);
const todoRe = /\b(TODO|FIXME|XXX|TBD)\b/;
const todos = flat
.filter(([, v]) => todoRe.test(v))
.map(([k, v]) => `${k} = ${JSON.stringify(v)}`);
expect(
todos,
`Found TODO/FIXME/XXX/TBD placeholders in translation values:\n` +
todos.map((s) => ` ${s}`).join("\n"),
).toEqual([]);
},
);
});