i18n
Règles
- Next.js App Router : utilisez
next-intl — hook useTranslations(), NextIntlClientProvider, middleware pour la détection de la langue
- React SPA : utilisez
react-i18next — hook useTranslation(), i18n.init() avec i18next-http-backend pour le chargement paresseux
- Routage tenant compte de la locale :
/en/about, /fr/about — utilisez un middleware pour détecter l'en-tête Accept-Language et rediriger
- Fichiers de traduction : JSON par locale et par namespace —
messages/en/common.json, messages/fr/common.json
- Découpage par namespace : un namespace par fonctionnalité/page —
auth.json, dashboard.json, settings.json — ne charger que ce dont la page a besoin
- Pluriel : utilisez le format de message ICU —
{count, plural, one {# élément} other {# éléments}}
- Interpolation :
t('salutation', { nom }) — ne concaténez jamais les chaînes traduites
- Formatage des dates/nombres/monnaies : utilisez
Intl.DateTimeFormat, Intl.NumberFormat — ne codez jamais les formats en dur
- Support RTL : utilisez
dir="rtl" sur <html>, propriétés CSS logiques (margin-inline-start pas margin-left), testez avec de l'arabe ou de l'hébreu
Modèles
import createMiddleware from "next-intl/middleware";
export default createMiddleware({
locales: ["en", "fr", "de", "ar"],
defaultLocale: "en",
});
import { useTranslations } from "next-intl";
function ProductCard({ prix, date }: { prix: number; date: Date }) {
const t = useTranslations("products");
const format = useFormatter();
return (
<div>
<h2>{t("titre")}</h2>
<p>{format.number(prix, { style: "currency", currency: "USD" })}</p>
<p>{format.dateTime(date, { dateStyle: "medium" })}</p>
</div>
);
}
À éviter
- Coder en dur des chaînes destinées à l'utilisateur — chaque chaîne doit passer par
t()
- Concaténer des chaînes pour le texte traduit — utilisez l'interpolation ou le format ICU
- Charger toutes les locales upfront — chargez paresseusement par locale et namespace
- Utiliser
left/right en CSS pour la mise en page — utilisez des propriétés logiques pour la compatibilité RTL
- Stocker la locale uniquement dans localStorage — utilisez une locale basée sur l'URL pour le SEO et la partageabilité