Table des matières
React i18n : Le Guide Complet de l'Internationalisation dans les Applications React
L'internationalisation (i18n) fait partie de ces fonctionnalités qui semblent simples de l'extérieur et se transforment en labyrinthe de plusieurs semaines une fois qu'on commence à les implémenter. Une application React qui accueille les utilisateurs en anglais a besoin de bien plus que du simple remplacement de chaînes pour vraiment servir un public mondial. Elle a besoin du formatage des devises, des règles de pluriel, de la localisation des dates, du support des mises en page de droite à gauche, et d'un flux de travail de traduction qui ne se casse pas chaque fois qu'un développeur renomme une clé.
Ce guide explique tout ce que vous devez savoir pour livrer une application React multilingue prête pour la production en 2026 — du choix de la bonne bibliothèque à l'évitement des erreurs qui vous coûteront du temps plus tard.
TL;DR / Points clés
- React n'a pas d'i18n intégré. L'API
Intldu navigateur gère le formatage, mais vous avez besoin d'une bibliothèque dédiée pour gérer les chaînes de traduction, le chargement dynamique et le routage de langues. - react-intl (FormatJS) et react-i18next sont les options les plus adoptées avec de grandes communautés et des années d'utilisation en production.
- LinguiJS est le meilleur choix si vous voulez une extraction à la compilation et une taille de bundle minimale à l'exécution.
- Better i18n est le nouvel entrant — il ajoute des traductions propulsées par IA et la livraison par CDN, mais sa communauté est plus petite que les alternatives établies.
- La bonne bibliothèque dépend de la taille de votre équipe, des exigences SSR et de l'importance que vous accordez à l'automatisation du flux de travail de traduction par rapport à la maturité de l'écosystème.
Pourquoi React a besoin d'une bibliothèque i18n
React affiche l'interface utilisateur. Il ne gère pas les traductions, ne détecte pas les langues du navigateur, ne charge pas les fichiers de langues de manière asynchrone, et ne gère pas les règles de formatage complexes qui diffèrent selon les langues. C'est conçu ainsi — React est une bibliothèque de vue.
Le navigateur est livré avec l'API Intl, qui est genuinement puissante. Intl.DateTimeFormat, Intl.NumberFormat et Intl.PluralRules vous donnent un formatage conscient de la locale sans aucune dépendance externe. Mais Intl résout le formatage, pas la gestion des chaînes.
Ce dont vous avez encore besoin au-delà d'Intl :
- Un catalogue de chaînes — Une structure pour stocker les chaînes traduites par langue et ID de message.
- Un binding React — Des hooks et des composants qui lisent dans le catalogue et se re-rendent quand la langue change.
- Le chargement dynamique — Charger uniquement les chaînes de la locale active, pas toutes à la fois.
- La pluralisation et l'interpolation — Gérer
"1 élément"contre"3 éléments"et insérer des valeurs dynamiques comme les noms d'utilisateurs dans les messages. - Un flux de travail de traduction — Comment les traducteurs reçoivent les nouvelles chaînes, les traduisent, et comment ces traductions reviennent dans votre application.
Faire tout cela soi-même est possible mais déconseillé. Les bibliothèques ci-dessous ont résolu ces problèmes dans des millions de déploiements en production. Commencez avec l'une d'elles.
Comparaison des bibliothèques React i18n populaires
| Bibliothèque | Taille du bundle | Support ICU | Support TypeScript | Support SSR | Courbe d'apprentissage |
|---|---|---|---|---|---|
| react-intl (FormatJS) | ~20KB gzipped | Complet | Fort | Oui | Moyenne |
| react-i18next | ~6KB gzipped | Via plugin | Fort | Oui | Faible-Moyenne |
| LinguiJS | ~2KB runtime | Complet | Fort | Oui | Moyenne-Élevée |
| Better i18n React SDK | ~2KB | Partiel | Complet (inféré) | Oui | Faible |
Les tailles de bundle sont approximatives et dépendent du tree-shaking et des fonctionnalités que vous utilisez. Le format de message ICU (International Components for Unicode) est le standard pour la pluralisation complexe, la sélection de genre et le texte conditionnel — toutes les bibliothèques ne le supportent pas nativement.
react-intl (FormatJS)
react-intl fait partie de la suite FormatJS maintenue par Formatly (anciennement Yahoo). C'est le standard de facto pour l'i18n complexe dans React depuis des années et offre l'implémentation la plus complète du format de message ICU dans l'écosystème.
Installation
npm install react-intl
Envelopper votre application avec IntlProvider
IntlProvider établit le contexte de locale pour l'ensemble de votre arbre de composants. Chaque appel à FormattedMessage et useIntl en dessous lit depuis ce contexte.
// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { IntlProvider } from "react-intl";
import App from "./App";
import enMessages from "./locales/en.json";
import frMessages from "./locales/fr.json";
const messages: Record<string, Record<string, string>> = {
en: enMessages,
fr: frMessages,
};
const userLocale = navigator.language.split("-")[0] ?? "en";
const activeLocale = userLocale in messages ? userLocale : "en";
ReactDOM.createRoot(document.getElementById("root")!).render(
<IntlProvider locale={activeLocale} messages={messages[activeLocale]}>
<App />
</IntlProvider>
);
Votre catalogue de messages est un fichier JSON plat :
// src/locales/en.json
{
"greeting": "Hello, {name}!",
"itemCount": "{count, plural, one {# item} other {# items}}",
"welcomeBack": "Welcome back, <bold>{name}</bold>!"
}
Composant FormattedMessage
Utilisez FormattedMessage quand vous avez besoin de formatage de texte riche ou de JSX inline dans vos traductions :
// src/components/Welcome.tsx
import React from "react";
import { FormattedMessage } from "react-intl";
interface WelcomeProps {
name: string;
itemCount: number;
}
export function Welcome({ name, itemCount }: WelcomeProps) {
return (
<div>
<h1>
<FormattedMessage
id="greeting"
values={{ name }}
/>
</h1>
<p>
<FormattedMessage
id="itemCount"
values={{ count: itemCount }}
/>
</p>
<p>
<FormattedMessage
id="welcomeBack"
values={{
name,
bold: (chunks) => <strong>{chunks}</strong>,
}}
/>
</p>
</div>
);
}
Hook useIntl
Pour une utilisation impérative — formater des chaînes en dehors du JSX, dans des gestionnaires d'événements, ou pour des attributs aria-label — utilisez le hook useIntl :
// src/components/SearchBar.tsx
import React from "react";
import { useIntl } from "react-intl";
export function SearchBar() {
const intl = useIntl();
const placeholder = intl.formatMessage({
id: "search.placeholder",
defaultMessage: "Search products...",
});
const formattedPrice = intl.formatNumber(29.99, {
style: "currency",
currency: "USD",
});
const formattedDate = intl.formatDate(new Date(), {
year: "numeric",
month: "long",
day: "numeric",
});
return (
<div>
<input type="search" placeholder={placeholder} aria-label={placeholder} />
<span>{formattedPrice}</span>
<time>{formattedDate}</time>
</div>
);
}
La documentation de react-intl est sur formatjs.io/docs/react-intl.
react-i18next
react-i18next est le binding React pour i18next, le framework JavaScript d'i18n le plus largement utilisé. Sa force est la flexibilité : il fonctionne avec React, React Native, Node.js et les environnements non-React. Si votre équipe utilise déjà i18next ailleurs, le modèle mental partagé est un vrai avantage.
Installation
npm install i18next react-i18next
Configuration
// src/i18n/config.ts
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import enCommon from "./locales/en/common.json";
import enDashboard from "./locales/en/dashboard.json";
import frCommon from "./locales/fr/common.json";
import frDashboard from "./locales/fr/dashboard.json";
i18n
.use(initReactI18next)
.init({
resources: {
en: {
common: enCommon,
dashboard: enDashboard,
},
fr: {
common: frCommon,
dashboard: frDashboard,
},
},
lng: "en",
fallbackLng: "en",
defaultNS: "common",
interpolation: {
escapeValue: false, // React échappe déjà les valeurs
},
});
export default i18n;
Importez la config au point d'entrée de votre application avant que tout composant ne s'affiche :
// src/main.tsx
import "./i18n/config";
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")!).render(<App />);
Hook useTranslation et séparation par espaces de noms
La séparation par espaces de noms est l'une des fonctionnalités les plus utiles de react-i18next pour les grandes applications. Au lieu de charger un énorme fichier JSON, vous divisez les traductions par fonctionnalité ou domaine et chargez les espaces de noms à la demande.
// src/i18n/locales/en/common.json
{
"nav.home": "Home",
"nav.dashboard": "Dashboard",
"nav.settings": "Settings",
"button.save": "Save",
"button.cancel": "Cancel"
}
// src/i18n/locales/en/dashboard.json
{
"title": "Your Dashboard",
"stats.users": "{{count}} active user",
"stats.users_other": "{{count}} active users",
"welcome": "Welcome back, {{name}}!"
}
// src/components/Dashboard.tsx
import React from "react";
import { useTranslation } from "react-i18next";
interface DashboardProps {
userName: string;
activeUsers: number;
}
export function Dashboard({ userName, activeUsers }: DashboardProps) {
// Charge l'espace de noms "dashboard" spécifiquement
const { t } = useTranslation("dashboard");
return (
<main>
<h1>{t("title")}</h1>
<p>{t("welcome", { name: userName })}</p>
<p>{t("stats.users", { count: activeUsers })}</p>
</main>
);
}
// src/components/Nav.tsx
import React from "react";
import { useTranslation } from "react-i18next";
export function Nav() {
// Utilise l'espace de noms "common" par défaut
const { t, i18n } = useTranslation();
const switchLanguage = (locale: string) => {
i18n.changeLanguage(locale);
};
return (
<nav>
<a href="/">{t("nav.home")}</a>
<a href="/dashboard">{t("nav.dashboard")}</a>
<button onClick={() => switchLanguage("fr")}>Français</button>
<button onClick={() => switchLanguage("en")}>English</button>
</nav>
);
}
La documentation de react-i18next est sur react.i18next.com.
LinguiJS
LinguiJS adopte une approche fondamentalement différente. Au lieu de gérer des clés de traduction dans des fichiers JSON que vous référencez par ID, vous écrivez votre interface en langage naturel directement dans votre JSX. Un CLI extrait ensuite ces chaînes dans un catalogue, que les traducteurs remplissent. Au moment de la compilation, les messages sont compilés dans un format binaire optimisé.
Le résultat est un bundle d'exécution plus petit et un risque moindre de références de clés cassées — mais cela nécessite une étape de compilation que les autres bibliothèques n'ont pas.
Installation
npm install @lingui/react @lingui/core npm install --save-dev @lingui/cli @lingui/macro @lingui/vite-plugin
Configuration
// lingui.config.js
/** @type {import('@lingui/conf').LinguiConfig} */
module.exports = {
locales: ["en", "fr", "de"],
sourceLocale: "en",
catalogs: [
{
path: "src/locales/{locale}/messages",
include: ["src"],
},
],
format: "po",
};
Utiliser @lingui/macro
Le macro transforme les chaînes en langage naturel à la compilation, de sorte que votre code source se lit comme de l'anglais simple tout en étant entièrement localisable :
// src/components/ProductCard.tsx
import React from "react";
import { Trans, Plural } from "@lingui/macro";
import { useLingui } from "@lingui/react";
interface ProductCardProps {
productName: string;
price: number;
reviewCount: number;
}
export function ProductCard({ productName, price, reviewCount }: ProductCardProps) {
const { i18n } = useLingui();
const formattedPrice = i18n.number(price, {
style: "currency",
currency: "USD",
});
return (
<article>
<h2>
<Trans>Buy {productName} today</Trans>
</h2>
<p>{formattedPrice}</p>
<p>
<Plural
value={reviewCount}
one="# customer review"
other="# customer reviews"
/>
</p>
<p>
<Trans>
Free shipping on orders over <strong>$50</strong>.
</Trans>
</p>
</article>
);
}
Flux de travail d'extraction
Après avoir écrit vos composants, lancez le CLI pour extraire les chaînes :
# Extraire toutes les chaînes des fichiers sources dans le catalogue npx lingui extract # Traduire les fichiers .po (ou les envoyer à votre service de traduction) # Puis les compiler pour la production npx lingui compile
Les catalogues compilés sont légers et se chargent rapidement. LinguiJS est particulièrement attrayant pour les équipes qui souhaitent un flux de travail avec des fichiers PO convivial pour les traducteurs et la charge utile d'exécution la plus petite possible.
La documentation complète est sur lingui.dev.
Better i18n React SDK
Better i18n est un nouvel entrant dans l'espace React i18n. Plutôt que de concurrencer uniquement en tant que bibliothèque de rendu de traductions, il intègre une plateforme de flux de travail complète : traductions propulsées par IA avec une conscience du contexte de marque, découverte automatique de clés via le scanning AST, et livraison par CDN pour que les mises à jour de traduction soient disponibles sans reconstruction.
Soyez honnête sur les compromis avant de le choisir : La communauté est une fraction de la taille de react-intl ou i18next. Les réponses sur Stack Overflow sont rares. Si vous rencontrez un cas particulier, vous êtes plus susceptible de vous appuyer sur la documentation officielle ou le canal de support que sur des solutions communautaires. La bibliothèque est bien maintenue et en développement actif, mais elle n'a pas encore les années de tests en conditions réelles que les options établies ont.
Installation
npm install @better-i18n/react
Configuration
// src/providers/I18nProvider.tsx
import React, { type ReactNode } from "react";
import { BetterI18nProvider } from "@better-i18n/react";
interface I18nProviderProps {
children: ReactNode;
locale: string;
}
export function I18nProvider({ children, locale }: I18nProviderProps) {
return (
<BetterI18nProvider
projectId={process.env.VITE_BETTER_I18N_PROJECT_ID!}
locale={locale}
>
{children}
</BetterI18nProvider>
);
}
// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { I18nProvider } from "./providers/I18nProvider";
const locale = navigator.language.split("-")[0] ?? "en";
ReactDOM.createRoot(document.getElementById("root")!).render(
<I18nProvider locale={locale}>
<App />
</I18nProvider>
);
Hook useTranslations
// src/components/HeroSection.tsx
import React from "react";
import { useTranslations } from "@better-i18n/react";
interface HeroSectionProps {
userName: string;
planName: string;
}
export function HeroSection({ userName, planName }: HeroSectionProps) {
const t = useTranslations("hero");
return (
<section>
<h1>{t("title", { name: userName })}</h1>
<p>{t("subtitle", { plan: planName })}</p>
<a href="/signup">{t("cta")}</a>
</section>
);
}
Les clés de traduction sont définies dans le tableau de bord Better i18n ou découvertes automatiquement depuis votre code source par le scanner CLI. Quand un traducteur approuve un changement, il est livré à votre application via le réseau edge CDN de Cloudflare — sans reconstruction ni redéploiement nécessaire.
La documentation de Better i18n est sur better-i18n.com/docs.
Quand choisir Better i18n plutôt que les alternatives : Votre équipe veut des traductions assistées par IA dès le départ, vous êtes à l'aise avec une plateforme gérée plutôt qu'une bibliothèque entièrement autonome, et l'automatisation du flux de travail (découverte automatique de clés, livraison par CDN, synchronisation basée sur les PR GitHub) vaut plus pour vous que l'ampleur de l'écosystème.
Quand choisir autre chose : Vous avez besoin de la plus grande communauté possible, d'années de réponses sur Stack Overflow, ou d'une solution entièrement auto-hébergée sans dépendance à un service externe. Dans ce cas, react-i18next ou react-intl sont le choix le plus sûr.
Patrons d'implémentation clés
Changement de langue
Le changement de langue doit être avec état et reflété dans l'URL pour que les utilisateurs puissent partager des liens localisés. L'approche la plus simple stocke la locale dans l'état et la passe à votre provider, mais une approche basée sur l'URL est plus robuste pour le SSR et les liens profonds.
// src/hooks/useLocale.ts
import { useState, useCallback } from "react";
const SUPPORTED_LOCALES = ["en", "fr", "de", "es"] as const;
type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
function getInitialLocale(): SupportedLocale {
const fromUrl = window.location.pathname.split("/")[1] as SupportedLocale;
if (SUPPORTED_LOCALES.includes(fromUrl)) return fromUrl;
const fromBrowser = navigator.language.split("-")[0] as SupportedLocale;
if (SUPPORTED_LOCALES.includes(fromBrowser)) return fromBrowser;
return "en";
}
export function useLocale() {
const [locale, setLocale] = useState<SupportedLocale>(getInitialLocale);
const switchLocale = useCallback((next: SupportedLocale) => {
setLocale(next);
document.documentElement.lang = next;
// Optionnel : pousser vers l'historique du routeur pour le routage basé sur l'URL
}, []);
return { locale, switchLocale, supportedLocales: SUPPORTED_LOCALES };
}
Chargement différé des traductions
Charger tous les bundles de langues à l'avance gaspille de la bande passante. Chargez uniquement la langue active et récupérez les autres à la demande :
// src/i18n/loader.ts
const localeCache = new Map<string, Record<string, string>>();
export async function loadLocale(locale: string): Promise<Record<string, string>> {
if (localeCache.has(locale)) {
return localeCache.get(locale)!;
}
// Import dynamique — le bundler divise cela en un chunk séparé par locale
const messages = await import(`./locales/${locale}.json`);
const resolved = messages.default as Record<string, string>;
// Retourne une nouvelle entrée de map plutôt que de muter en place
const updated = new Map(localeCache);
updated.set(locale, resolved);
localeCache.clear();
updated.forEach((v, k) => localeCache.set(k, v));
return resolved;
}
Considérations SSR / SSG
Lors du rendu côté serveur, la détection de langue passe de navigator.language aux en-têtes HTTP (Accept-Language) ou aux segments d'URL. La locale doit être résolue avant que le rendu commence pour que le serveur et le client produisent un HTML identique.
// src/app/[locale]/layout.tsx (exemple Next.js App Router)
import { notFound } from "next/navigation";
import { type ReactNode } from "react";
const SUPPORTED_LOCALES = ["en", "fr", "de"];
interface LocaleLayoutProps {
children: ReactNode;
params: { locale: string };
}
export default function LocaleLayout({ children, params }: LocaleLayoutProps) {
if (!SUPPORTED_LOCALES.includes(params.locale)) {
notFound();
}
return (
<html lang={params.locale} dir={params.locale === "ar" ? "rtl" : "ltr"}>
<body>{children}</body>
</html>
);
}
export function generateStaticParams() {
return SUPPORTED_LOCALES.map((locale) => ({ locale }));
}
Routage de locale basé sur l'URL
Les moteurs de recherche traitent example.com/fr/produits et example.com/en/products comme des pages séparées et indexables. Le routage basé sur l'URL est fortement préféré à la détection basée sur les cookies ou les en-têtes pour le SEO. Structurez vos routes avec un segment [locale] à la racine et ajoutez des balises de lien hreflang dans le <head> pour chaque langue supportée.
Pluralisation
Chaque bibliothèque couverte ici gère la pluralisation différemment, mais les règles sous-jacentes proviennent du CLDR (Common Locale Data Repository). L'anglais a deux formes plurielles. L'arabe en a six. Ne codez jamais en dur votre propre logique de pluralisation.
Avec react-i18next (utilisant les suffixes _one / _other) :
{
"notification": "{{count}} notification",
"notification_other": "{{count}} notifications"
}
t("notification", { count: 1 }); // "1 notification"
t("notification", { count: 5 }); // "5 notifications"
Formatage des dates et des nombres
Utilisez les utilitaires de formatage intégrés de la bibliothèque ou revenez directement à Intl. Ne concaténez jamais des valeurs formatées sous forme de chaînes — l'ordre des unités diffère selon la locale.
// Utiliser Intl directement (fonctionne avec n'importe quelle bibliothèque)
const formatter = new Intl.NumberFormat(locale, {
style: "currency",
currency: "EUR",
});
// "€1,234.56" en en-US, "1 234,56 €" en fr-FR — même nombre, format différent
formatter.format(1234.56);
Erreurs courantes
Concaténation de chaînes. Ne construisez jamais des phrases en joignant des fragments traduits avec + ou des littéraux de gabarit. L'ordre des mots varie selon la langue. "Bonjour " + t("monde") casse dans les langues où la salutation vient après le nom. Passez toujours les variables d'interpolation à la fonction de traduction.
Oublier le contexte. Le mot anglais "File" peut signifier le nom (un document) ou le verbe (déposer une plainte). Les traducteurs ont besoin de contexte pour choisir le bon mot. La plupart des bibliothèques supportent un paramètre context ou un champ de description — utilisez-le.
Ne pas gérer les états de chargement. Quand les traductions se chargent de manière asynchrone, il y a une fenêtre où votre composant s'affiche avant que les chaînes soient disponibles. Affichez un squelette, un spinner, ou rien — mais n'affichez jamais des clés de traduction brutes comme "dashboard.title" à l'utilisateur.
Regrouper toutes les langues ensemble. Envoyer les traductions en français, allemand, espagnol et japonais à un utilisateur qui ne lit qu'anglais gaspille de la bande passante et augmente votre Time to Interactive. Utilisez des imports dynamiques ou une stratégie de livraison basée sur CDN pour ne charger que ce qui est nécessaire.
Coder en dur le formatage spécifique à une locale. Ne codez pas en dur les formats de date comme MM/DD/YYYY. Les utilisateurs allemands attendent DD.MM.YYYY. Déléguez toujours le formatage à Intl ou aux utilitaires de formatage de votre bibliothèque.
Rendre du HTML traduit comme balisage brut. Injecter des chaînes traduites comme HTML brut est un risque XSS si votre source de traduction est jamais compromise. Utilisez les composants de texte riche sécurisés de votre bibliothèque — FormattedMessage avec des valeurs d'éléments dans react-intl, ou le composant Trans dans react-i18next — plutôt que de rendre des chaînes HTML directement.
FAQ
Q : Ai-je besoin du support du format de message ICU ?
ICU est le standard pour les messages complexes impliquant des pluriels, la sélection de genre et le texte conditionnel. Si votre application a des phrases comme "Jean et 3 autres ont aimé ceci", ICU rend l'expression de ces règles propre et portable. Si votre application n'a besoin que d'un simple remplacement de chaînes, ICU est une surcharge optionnelle. react-intl et LinguiJS supportent ICU nativement. react-i18next nécessite le plugin i18next-icu.
Q : Quelle bibliothèque fonctionne le mieux avec Next.js App Router ?
react-i18next et react-intl supportent tous deux l'App Router avec une certaine configuration. L'écosystème Next.js a convergé autour de next-intl pour les projets App Router en raison de son support de première classe des Server Components. Better i18n propose également un SDK Next.js dédié. LinguiJS fonctionne mais nécessite une gestion soigneuse de l'étape de compilation dans le pipeline de build.
Q : Comment dois-je structurer mes fichiers de traduction ?
Pour les petites applications, un seul fichier JSON par langue (en.json, fr.json) convient. Pour les applications plus grandes, divisez par fonctionnalité ou domaine (espaces de noms dans i18next, catalogues séparés dans LinguiJS). Évitez les objets profondément imbriqués — les clés plates ou à un niveau de profondeur sont plus faciles à gérer à grande échelle et moins sujettes aux conflits de fusion.
Q : Comment gérer les traductions qui incluent du balisage comme du texte en gras ou des liens ?
La plupart des bibliothèques supportent le texte riche via un render prop ou un système de slots. Dans react-intl, passez un élément JSX comme valeur à FormattedMessage. Dans react-i18next, utilisez le composant Trans. Ces approches gardent le HTML dans React où il peut être correctement échappé et assaini, plutôt que de mélanger du balisage dans votre catalogue de chaînes.
Q : Quand devrais-je commencer à penser à l'i18n ? Plus tôt que vous ne le pensez. Rétrofit l'i18n dans une base de code existante signifie chercher chaque chaîne codée en dur, chaque format de date, chaque hypothèse de pluriel, et chaque mise en page qui se casse avec les mots allemands plus longs. S'il y a une chance que votre application atteigne des locuteurs non anglophones, ajoutez l'infrastructure i18n dans votre configuration initiale, même si vous ne livrez qu'en anglais le premier jour.
Conclusion
React i18n n'a pas de réponse unique et correcte. La bonne bibliothèque est celle qui correspond au flux de travail de votre équipe, à la complexité de votre application et à votre tolérance au risque de l'écosystème.
Si vous démarrez un nouveau projet et souhaitez le plus grand soutien communautaire et l'écosystème le plus profond, react-i18next est le choix par défaut sûr. Son système d'espaces de noms passe bien à l'échelle, sa documentation est complète, et vous trouverez des réponses à la plupart des cas particuliers sur Stack Overflow.
Si votre application a des exigences de formatage de messages genuinement complexes — genre conditionnel, pluriels multi-niveaux, balisage riche inline — react-intl est l'implémentation la plus complète du standard ICU dans l'écosystème React.
Si vous voulez le bundle d'exécution le plus petit et un flux de travail d'extraction appliqué par le compilateur, LinguiJS offre une alternative convaincante, particulièrement pour les équipes à l'aise avec l'ajout d'une étape de compilation.
Si vous voulez des traductions assistées par IA, une livraison par CDN sans cycle de reconstruction, et une plateforme gérée qui automatise le pipeline de traduction, Better i18n vaut la peine d'être évalué — avec la mise en garde honnête que vous pariez sur un écosystème plus jeune avec une communauté plus petite.
Quel que soit votre choix, engagez-vous tôt, gardez vos fichiers de traduction organisés, et traitez l'i18n comme une fonctionnalité de première classe plutôt qu'une réflexion après coup. Vos utilisateurs internationaux remarqueront la différence.
Références
- react-intl (FormatJS) : formatjs.io/docs/react-intl
- react-i18next : react.i18next.com
- i18next core : www.i18next.com
- LinguiJS : lingui.dev
- Better i18n React SDK : better-i18n.com/docs
- Unicode CLDR Plural Rules : cldr.unicode.org/index/cldr-spec/plural-rules
- MDN Intl API reference : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl