import fr from './fr.json' import gcf from './gcf.json' import { browser } from '$app/environment' import { defaultLocale, type Locale } from './locales' export { locales, localeNames, defaultLocale, type Locale } from './locales' type Dict = typeof fr // gcf est vérifié par TypeScript contre la forme du français : une clé // manquante est une erreur de build, pas un fallback silencieux (ADR-001). const dicts: Record = { fr, gcf } const STORAGE_KEY = 'oki-lang' function initialLocale(): Locale { if (!browser) return defaultLocale const saved = localStorage.getItem(STORAGE_KEY) return saved === 'gcf' || saved === 'fr' ? saved : defaultLocale } // Rune d'état partagée (Svelte 5) : la langue de l'interface. // Le HTML prérendu est en fr ; le créole est une amélioration progressive // (persistance localStorage — mission §4.3, doctrine §4.2). const state = $state({ locale: initialLocale() }) export function getLocale(): Locale { return state.locale } export function setLocale(locale: Locale) { state.locale = locale if (browser) { localStorage.setItem(STORAGE_KEY, locale) document.documentElement.lang = locale } } function lookup(dict: Dict, path: string): unknown { return path.split('.').reduce((node, key) => { if (node && typeof node === 'object' && key in node) { return (node as Record)[key] } return undefined }, dict) } /** Chaîne d'interface pour `path` dans la langue courante (réactif). */ export function t(path: string): string { const hit = lookup(dicts[state.locale], path) ?? lookup(dicts[defaultLocale], path) if (typeof hit !== 'string') { throw new Error(`Clé i18n manquante « ${path} » (locale : ${state.locale})`) } return hit }