8ebc1da9e4
- 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
46 lines
1.6 KiB
TypeScript
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)
|
|
}
|
|
})
|
|
})
|