Files
lage-chat-control/tests/unit/i18n-parity.test.ts
T
Aurealibe 8ebc1da9e4 Rebuild du site sur Astro : i18n multilingue, faits verifies, Docker, CI, tests
- Astro statique, EN par defaut + /fr/ + /nl/, detection langue navigateur
- i18n par fichiers JSON, ajouter une langue = ajouter des traductions
- Contenu original porte a l'identique (diff d'inventaire par langue)
- Chronologie legislative corrigee sur sources primaires (PE, Conseil, votes)
- Timeline 23 precedents + observatoire 35 items + annuaire 66 outils FOSS,
  chaque affirmation verifiee et sourcee
- Zero requete tierce (teste), lisible JS coupe, axe WCAG AA x2 themes
- Version offline monofichier par langue a chaque build
- Docker multi-stage vers nginx + CSP stricte auto-generee
- CI GitHub Actions (SHA-pinnees) + verification hebdo des liens
- CONTRIBUTING : divulgation d'affiliation obligatoire, allowlist de
  domaines testee en CI
2026-07-10 03:52:49 +01:00

46 lines
1.6 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import en from '../../src/i18n/en.json'
import fr from '../../src/i18n/fr.json'
import nl from '../../src/i18n/nl.json'
import { defaultLocale, locales } from '../../src/i18n/locales'
// Every locale dictionary must have exactly the English key shape:
// a missing key would silently fall back to English in production.
function keyPaths(node: unknown, prefix = ''): string[] {
if (typeof node === 'string') return [prefix]
if (node && typeof node === 'object') {
return Object.entries(node).flatMap(([k, v]) => keyPaths(v, prefix ? `${prefix}.${k}` : k))
}
return [prefix]
}
const dicts: Record<string, unknown> = { en, fr, nl }
describe('i18n dictionary parity', () => {
it('declares a dictionary for every locale', () => {
for (const locale of locales) expect(dicts[locale], `src/i18n/${locale}.json`).toBeDefined()
})
const reference = keyPaths(dicts[defaultLocale]).sort()
for (const locale of locales.filter((l) => l !== defaultLocale)) {
it(`${locale}.json matches the ${defaultLocale}.json key shape`, () => {
const keys = keyPaths(dicts[locale]).sort()
expect(keys).toEqual(reference)
})
}
it('has no empty strings', () => {
for (const [locale, dict] of Object.entries(dicts)) {
const walk = (node: unknown, path: string) => {
if (typeof node === 'string') {
expect(node.trim(), `${locale}:${path}`).not.toBe('')
} else if (node && typeof node === 'object') {
for (const [k, v] of Object.entries(node)) walk(v, `${path}.${k}`)
}
}
walk(dict, locale)
}
})
})