test(i18n): enforce catalogue key placeholder and nonblank parity
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
# Direct roadmap integration — 2 November 2026
|
# Direct roadmap integration — 2 November 2026
|
||||||
|
|
||||||
|
Published implementation checkpoint `557efde073a380030a39066fab2e6d961ce717f4` was independently read back on origin/codex/direct-roadmap-integration. Follow-up test-only catalogue QA adds three invariants and runs with existing provider/persistence stability tests: 10 passed in three additional suites; see ../i18n/EN_NB_CATALOGUE_QA.md. No runtime application change after the passing build.
|
||||||
|
|
||||||
Validated isolated review branch `codex/direct-roadmap-integration`. Base Phase 10 `db818e5ebd19eeedc05ae58dc3f7a908ce0e713d`; selected application paths and docs/i18n from published `4172c23d7ce13e8327a5e51bbb09f296c24fb9b8`; backup parser/deploy function and release-readiness reports from `f19e7ebf4aeae350b43fa84cf115c393030280f0`. Content was integrated by explicit owned paths, preserving the Phase 10 accepted handoff records and approved App.css deletion. No full-branch history overwrite, orchestrator access, main merge, final UI design or deployment.
|
Validated isolated review branch `codex/direct-roadmap-integration`. Base Phase 10 `db818e5ebd19eeedc05ae58dc3f7a908ce0e713d`; selected application paths and docs/i18n from published `4172c23d7ce13e8327a5e51bbb09f296c24fb9b8`; backup parser/deploy function and release-readiness reports from `f19e7ebf4aeae350b43fa84cf115c393030280f0`. Content was integrated by explicit owned paths, preserving the Phase 10 accepted handoff records and approved App.css deletion. No full-branch history overwrite, orchestrator access, main merge, final UI design or deployment.
|
||||||
|
|
||||||
## Fresh qualification
|
## Fresh qualification
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
|||||||
|
# Automated EN/Bokmål catalogue QA
|
||||||
|
|
||||||
|
2 November 2026. Added translation-catalogue.test.ts to the existing Jest suite. Reuses the current interpolation contract and the checks demonstrated by the historical Phase 9 localisation helper; that helper/report was not modified or overwritten.
|
||||||
|
|
||||||
|
Three automated invariants: equal English/Bokmål key sets; equal sets of current `{word}` substitution variables per message; no blank message values. Current resources contain 3,119 English and 3,119 Bokmål keys. These are resource counts, not thousands of test cases. Identical proper names/technical labels are allowed; machine equality does not determine whether natural-language copy is translated well.
|
||||||
|
|
||||||
|
PASSED: 10 tests across translation-catalogue, i18n-provider and locale-fetch-stability, zero failures/pending, native exit 0. This includes the three new global invariants and existing persistence/legacy alias/fetch-stability coverage. Scoped lint passed and full typechecking completed without errors. [Native report](../direct-roadmap/integration-evidence/locale-catalogue-native.json.gz). These three suites are separate from the 16-suite/195-test integration execution; do not represent them as a single fresh full-suite run. Runtime application source is unchanged from the passing integration production build; no build was repeated for a test-only addition.
|
||||||
|
|
||||||
|
Limits: current simple interpolation only, not a future ICU/plural engine; no every-string/frontend/backend completeness, native translation quality, human/device or European locale release acceptance. The 60 research locale candidates remain unshipped. Native terminology, market priorities, Montenegrin identity/canonicalisation and registry/migration decisions retain their documented gates.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { translations } from './i18n/translations';
|
||||||
|
|
||||||
|
const placeholders = (text: string) => [...new Set(text.match(/\{\w+\}/g) ?? [])].sort();
|
||||||
|
|
||||||
|
test('English and Bokmål expose the same UI message keys', () => {
|
||||||
|
expect(Object.keys(translations.nb).sort()).toEqual(Object.keys(translations.en).sort());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Bokmål preserves every English substitution variable', () => {
|
||||||
|
const mismatches = Object.entries(translations.en).filter(([key, text]) =>
|
||||||
|
JSON.stringify(placeholders(text)) !== JSON.stringify(placeholders(translations.nb[key as keyof typeof translations.en]))
|
||||||
|
).map(([key]) => key);
|
||||||
|
expect(mismatches).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('supported UI catalogues contain no blank messages', () => {
|
||||||
|
const blanks = Object.entries(translations).flatMap(([language, messages]) =>
|
||||||
|
Object.entries(messages).filter(([, text]) => !text.trim()).map(([key]) => `${language}.${key}`)
|
||||||
|
);
|
||||||
|
expect(blanks).toEqual([]);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user