Internationalisation
Fluixi intègre l'i18n. createI18n vous donne un traducteur réactif et correct en SSR :
import { createI18n } from '@fluixi/core/i18n';
const i18n = createI18n({
locale: 'fr',
locales: ['en', 'fr'] as const,
messages: { en: { hello: 'Hello, {name}' }, fr: { hello: 'Bonjour, {name}' } },
});
export const { t, locale, setLocale } = i18n;
t('hello', { name: 'Ada' }); // « Bonjour, Ada »
t lit la locale de façon réactive : une chaîne traduite dans un template se met donc à
jour quand la locale change — sans remontage ni rechargement.
Clés de message
Les clés peuvent être plates ou imbriquées, et les deux se résolvent par le même chemin pointé :
messages: {
fr: {
'nav.dashboard': 'Tableau de bord', // plate, pointée
nav: { settings: 'Paramètres' }, // imbriquée
},
}
t('nav.dashboard');
t('nav.settings');
Les clés plates sont consultées en premier : une clé pointée l'emporte donc sur un chemin imbriqué de même nom. Cela compte quand on fusionne l'export plat d'un traducteur dans une arborescence écrite à la main.
t('…') complète automatiquement les clés depuis vos messages : une faute de frappe est
une erreur de typage plutôt qu'une chaîne manquante à l'exécution.
Interpolation, pluriels et formats
Les emplacements {name} sont remplis depuis le second argument. La pluralisation utilise
Intl.PluralRules ; les nombres et les dates utilisent Intl.NumberFormat /
Intl.DateTimeFormat — les règles viennent donc de la plateforme, pas d'une table à
maintenir.
Changer de locale
setLocale('en');
Côté client, cela met à jour un signal et persiste le choix, qui survit donc à un rechargement. Côté serveur, cela définit la locale pour la requête courante uniquement et la sème dans la page.
SSR, et pourquoi il n'y a pas de fuite
C'est la partie qui mérite d'être comprise. Sur le serveur, la locale active vit dans le contexte de requête, pas dans un signal de module. Deux requêtes traitées simultanément dans le même processus ne peuvent donc pas voir la locale l'une de l'autre : le scénario où la page d'un utilisateur s'affiche dans la langue d'un autre ne peut tout simplement pas se produire.
Côté client il n'y a qu'un utilisateur : la locale y est un signal réactif ordinaire.
La locale résolue par le serveur est sérialisée dans la page et relue avant le premier rendu client : l'hydratation correspond donc à ce qui a été rendu — pas de clignotement de langue, pas d'incohérence d'hydratation.
Découverte automatique
Placez les traductions dans src/i18n/<locale>.json et @fluixi/start les expose sous
virtual:fluixi-i18n — typées d'après le JSON, les clés arrivent donc directement dans
createI18n sans type écrit à la main.
import messages from 'virtual:fluixi-i18n';
const i18n = createI18n({ locale: 'fr', locales: ['en', 'fr'] as const, messages });
Ajouter une locale revient alors à ajouter un fichier.
Choisir la locale initiale
detectLocale choisit à partir de ce que la requête propose — l'en-tête
Accept-Language, un cookie persisté — en se limitant aux locales que vous livrez, avec
votre valeur par défaut en repli.
Ceci conclut le guide v1. Explorez le cœur réactif en direct dans le Bac à sable.