61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
// Interface language: fr, en, es (Yvv, 2026-10-21). French is the source.
|
|
import { en } from './en';
|
|
import { es } from './es';
|
|
import { fr, type Key, type Messages } from './fr';
|
|
import type { Lang } from '../types';
|
|
|
|
export const LANGS: Lang[] = ['fr', 'en', 'es'];
|
|
const CATALOGS: Record<Lang, Messages> = { fr, en, es };
|
|
const LOCALES: Record<Lang, string> = { fr: 'fr-FR', en: 'en-GB', es: 'es-ES' };
|
|
|
|
function initial(): Lang {
|
|
try {
|
|
const saved = localStorage.getItem('ld:lang');
|
|
if (saved === 'fr' || saved === 'en' || saved === 'es') return saved;
|
|
} catch {
|
|
/* no storage */
|
|
}
|
|
const nav = (typeof navigator !== 'undefined' ? navigator.language : 'fr').slice(0, 2);
|
|
return nav === 'en' || nav === 'es' ? nav : 'fr';
|
|
}
|
|
|
|
class I18n {
|
|
lang = $state<Lang>('fr');
|
|
|
|
init() {
|
|
this.set(initial());
|
|
}
|
|
|
|
set(lang: Lang) {
|
|
this.lang = lang;
|
|
document.documentElement.lang = lang;
|
|
try {
|
|
localStorage.setItem('ld:lang', lang);
|
|
} catch {
|
|
/* no storage */
|
|
}
|
|
}
|
|
|
|
t = (key: Key, params: Record<string, string | number> = {}): string => {
|
|
const raw = CATALOGS[this.lang][key] ?? fr[key] ?? key;
|
|
return raw.replace(/\{(\w+)\}/g, (_, k: string) => (k in params ? String(params[k]) : `{${k}}`));
|
|
};
|
|
|
|
/** `<key>.one` / `<key>.other` — French says « 0 session », English and Spanish « 0 sessions ». */
|
|
plural = (key: string, n: number, params: Record<string, string | number> = {}): string => {
|
|
const one = this.lang === 'fr' ? n <= 1 : n === 1;
|
|
return this.t(`${key}.${one ? 'one' : 'other'}` as Key, { n, ...params });
|
|
};
|
|
|
|
date = (iso: string | null | undefined): string => {
|
|
if (!iso) return '';
|
|
return new Date(iso).toLocaleDateString(LOCALES[this.lang], { day: 'numeric', month: 'long', year: 'numeric' });
|
|
};
|
|
|
|
number = (n: number): string => n.toLocaleString(LOCALES[this.lang]);
|
|
}
|
|
|
|
export const i18n = new I18n();
|
|
export const t = i18n.t;
|
|
export type { Key };
|