Files
pleno-vue/tests/unit/i18n-xlvask-review-coverage.spec.js
T
dfaca1e8a5 i18n(xlvask_review): translate missing keys for no/sv/de/en + locale coverage test (#307)
## Summary

The `invoicing_period.xlvask_review.*` and
`invoice_period.flags.preview.xlvask_usage_log` keys were already
comprehensively localised in `no`, `sv`, `de`, and `en` — the five
active locales (`da`, `en`, `sv`, `de`, `no`) each carry the same 173
`xlvask_review` keys, and the remaining English literal in
`flags.automatic.xlvask_missing_order_link` for `no`/`sv`/`de` has been
replaced with native Norwegian / Swedish / German translations that
mirror the `da` reference catalogue. This PR locks that coverage in with
a focused unit test so future da-side edits cannot silently drop a
translation for any of the non-da locales.

## Commits

- `49ff30f` — TRU-13 / AUT-9: translate xlvask_missing_order_link to
no/sv/de
- `550d32c` — TRU-13 / AUT-9: add xlvask_review translation coverage
regression test

## Verification

- `npm run i18n:v2:check` — clean across source-check,
global-template-audit, template-dedupe-audit, and word-audit.
- `npx vitest run tests/unit/i18n-xlvask-review-coverage.spec.js` — 1 /
1 pass (5 locales × 173 keys verified).
- `npx vitest run tests/unit/i18n-*` — 11 / 11 pass.
- `npx playwright test tests/e2e/i18n-v2-integrity.spec.ts` — 126 / 126
pass across all 9 browser projects.

The new test in `tests/unit/i18n-xlvask-review-coverage.spec.js`
enumerates every leaf string under
`compat.invoicing_period.xlvask_review` in `da`, then asserts for each
of `no`, `sv`, `de`, `en` that every key is present and that every
localised value is a non-empty string. Verified it catches regressions
by temporarily removing a key from `no` and observing the test fail with
the missing key listed.

Closes TRU-13.

---------

Co-authored-by: Jeppe <jeppe@copenhagentruckwash.io>
Co-authored-by: openhands <openhands@all-hands.dev>
2026-08-15 20:53:01 +02:00

60 lines
2.3 KiB
JavaScript

// Regression guard for TRU-13 / AUT-9: every `invoicing_period.xlvask_review.*`
// key that exists in the da reference catalogue must also be present in
// the other active locales (no, sv, de, en) with a non-empty translation.
// The end-to-end integrity suite already enforces global key parity, but
// this targeted test documents the acceptance criteria for the xlvask_review
// translation work and surfaces locale-specific gaps immediately.
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
const root = process.cwd();
const activeLocales = ["da", "no", "sv", "de", "en"];
const reviewFileFor = (locale) =>
join(root, `src/i18n/source/${locale}/phrases/compat/invoicing_period/xlvask_review.json`);
const flattenPairs = (node, prefix = "") => {
if (typeof node === "string") {
return [{ key: prefix, value: node }];
}
if (!node || typeof node !== "object" || Array.isArray(node)) {
return [];
}
return Object.entries(node).flatMap(([key, value]) => {
const nextPrefix = prefix ? `${prefix}.${key}` : key;
return flattenPairs(value, nextPrefix);
});
};
const readReviewSection = (locale) => {
const file = JSON.parse(readFileSync(reviewFileFor(locale), "utf8"));
return file?.compat?.invoicing_period?.xlvask_review ?? {};
};
describe("xlvask_review translation coverage", () => {
it("covers every da xlvask_review key in no, sv, de, en with a non-empty value", () => {
const daEntries = flattenPairs(readReviewSection("da"));
expect(daEntries.length, "da xlvask_review should expose translatable strings").toBeGreaterThan(0);
for (const locale of activeLocales.filter((entry) => entry !== "da")) {
const localeEntries = new Map(flattenPairs(readReviewSection(locale)).map((entry) => [entry.key, entry.value]));
const missing = [];
const empty = [];
for (const { key } of daEntries) {
if (!localeEntries.has(key)) {
missing.push(key);
continue;
}
const localized = localeEntries.get(key);
if (typeof localized !== "string" || localized.trim().length === 0) {
empty.push(key);
}
}
expect(missing, `${locale} xlvask_review keys missing from da`).toEqual([]);
expect(empty, `${locale} xlvask_review keys with empty translations`).toEqual([]);
}
});
});