
Guide react-intl : configuration de l'internationalisation React
Configurez FormatJS react-intl dans votre application React avec IntlProvider, FormattedMessage, useIntl, le format de message ICU et des traductions automatisées.
Vous utilisez plutôt react-i18next ? Consultez notre guide react-i18next
Installer react-intl
react-intl fait partie du projet FormatJS. Il fournit des composants et des hooks React pour formater les chaînes, les nombres, les dates et les pluriels selon la norme ICU MessageFormat.
npm install react-intlConfigurer IntlProvider
Enveloppez votre application avec IntlProvider à la racine. Transmettez la locale active et un objet messages à plat. Chaque composant peut ensuite accéder aux traductions via FormattedMessage ou useIntl.
import React from 'react';
import ReactDOM from 'react-dom/client';
import { IntlProvider } from 'react-intl';
import App from './App';
import enMessages from './messages/en.json';
import deMessages from './messages/de.json';
const messages: Record<string, Record<string, string>> = {
en: enMessages,
de: deMessages,
};
// Detect locale from browser or your routing layer
const locale = navigator.language.split('-')[0] || 'en';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<IntlProvider locale={locale} messages={messages[locale] || messages.en}>
<App />
</IntlProvider>
</React.StrictMode>
);Fichiers de messages
Créez un fichier JSON par locale. react-intl utilise nativement la syntaxe ICU MessageFormat : les pluriels, les select et les variables sont tous exprimés directement dans les chaînes de message.
// messages/en.json
{
"app.greeting": "Hello, {name}!",
"nav.home": "Home",
"nav.about": "About",
"nav.settings": "Settings",
"cart.itemCount": "{count, plural, one {# item} other {# items}} in your cart"
}
// messages/de.json
{
"app.greeting": "Hallo, {name}!",
"nav.home": "Startseite",
"nav.about": "Über uns",
"nav.settings": "Einstellungen",
"cart.itemCount": "{count, plural, one {# Artikel} other {# Artikel}} in Ihrem Warenkorb"
}Utiliser les traductions dans les composants
react-intl vous propose deux API principales : le composant FormattedMessage pour afficher du JSX traduit, et le hook useIntl pour un accès impératif (espaces réservés, libellés aria, formatage programmatique).
Composant FormattedMessage
Utilisez FormattedMessage pour des traductions déclaratives en JSX. Transmettez l'identifiant du message et les éventuelles valeurs d'interpolation. Il affiche directement la chaîne traduite.
import { FormattedMessage } from 'react-intl';
function Greeting({ userName }: { userName: string }) {
return (
<div>
<h1>
<FormattedMessage
id="app.greeting"
values={{ name: userName }}
/>
</h1>
<nav>
<a href="/"><FormattedMessage id="nav.home" /></a>
<a href="/about"><FormattedMessage id="nav.about" /></a>
</nav>
</div>
);
}Hook useIntl
Utilisez useIntl() lorsque vous avez besoin de la chaîne traduite sous forme de simple valeur : pour les espaces réservés de champs de saisie, les aria-label, document.title, ou pour transmettre des chaînes à des API non React. Il fournit également formatNumber, formatDate et formatRelativeTime.
import { useIntl } from 'react-intl';
function SearchBar() {
const intl = useIntl();
return (
<input
type="search"
placeholder={intl.formatMessage({ id: 'search.placeholder' })}
aria-label={intl.formatMessage({ id: 'search.ariaLabel' })}
/>
);
}
// useIntl also gives you formatNumber, formatDate, formatRelativeTime:
function PriceTag({ amount, currency }: { amount: number; currency: string }) {
const intl = useIntl();
return (
<span>{intl.formatNumber(amount, { style: 'currency', currency })}</span>
);
}Texte enrichi (HTML dans les traductions)
Intégrez du JSX dans les traductions à l'aide de balises de type XML dans vos chaînes de message. Transmettez les gestionnaires de balises via la prop values pour afficher des liens, du texte en gras ou n'importe quel composant React au sein d'un message traduit.
import { FormattedMessage } from 'react-intl';
// Message: "By signing up, you agree to our <link>Terms</link>."
// Key: "signup.terms"
// Value: "By signing up, you agree to our <link>Terms</link>."
function SignUp() {
return (
<FormattedMessage
id="signup.terms"
values={{
link: (chunks) => <a href="/terms" className="underline">{chunks}</a>,
}}
/>
);
}Extraction des messages avec @formatjs/cli
FormatJS fournit un CLI pour extraire automatiquement les identifiants de message de votre code source vers un fichier JSON. Cela garantit que votre fichier de messages reste synchronisé avec vos composants, sans suivi manuel.
# Install the CLI
npm install -g @formatjs/cli
# Extract messages from source code into a JSON file
formatjs extract 'src/**/*.tsx' --out-file messages/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'
# Or use explicit IDs (recommended):
formatjs extract 'src/**/*.tsx' --out-file messages/en.json
# Compile messages for production (optional, improves perf)
formatjs compile messages/en.json --out-file compiled/en.json
formatjs compile messages/de.json --out-file compiled/de.jsonPluriels et ICU select
react-intl utilise nativement ICU MessageFormat. Les pluriels, le select basé sur le genre et le formatage imbriqué sont tous exprimés directement dans les chaînes de message : aucune convention de suffixe ni de clé séparée n'est nécessaire.
// ICU MessageFormat syntax — react-intl uses this natively
// English
{
"cart.itemCount": "{count, plural, one {# item} other {# items}} in your cart",
"inbox.unread": "You have {count, plural, =0 {no unread messages} one {# unread message} other {# unread messages}}"
}
// Arabic — 6 plural forms
{
"cart.itemCount": "{count, plural, zero {لا عناصر} one {عنصر واحد} two {عنصران} few {# عناصر} many {# عنصرًا} other {# عنصر}} في سلتك"
}
// Japanese — 1 form (other)
{
"cart.itemCount": "カートに{count}個の商品があります"
}ICU select pour le genre et les rôles
Utilisez la syntaxe ICU select pour les traductions dépendant du contexte, comme le genre, les rôles utilisateur ou les valeurs de statut. L'expression select choisit la bonne variante selon la valeur fournie.
// Gender-dependent messages using ICU select
{
"user.greeting": "{gender, select, male {He} female {She} other {They}} liked your post.",
"user.invitation": "{role, select, admin {You can manage all settings.} editor {You can edit content.} other {You can view content.}}"
}
// Usage:
<FormattedMessage
id="user.greeting"
values={{ gender: user.gender }}
/>Automatiser la qualité des traductions
Pièges courants
Dépendance excessive à defaultMessage
Objets imbriqués au lieu de clés à plat
IntlProvider provoque des rendus inutiles
IntlProvider manquant dans les tests
Structure de fichiers recommandée
my-react-app/
├── messages/
│ ├── en.json # Source of truth (English)
│ ├── de.json # German
│ ├── ja.json # Japanese
│ └── es.json # Spanish
├── compiled/ # Optional: compiled messages for prod
│ ├── en.json
│ └── ...
├── src/
│ ├── main.tsx # App entry with IntlProvider
│ ├── App.tsx
│ └── components/
│ ├── Greeting.tsx # Uses FormattedMessage
│ └── SearchBar.tsx # Uses useIntl
└── package.jsonEssayez i18n Agent maintenant
Déposez votre fichier de traduction ici
JSON, YAML, PO, XML, CSV, Markdown, Properties
ou cliquez pour parcourir
Langues cibles
Repli de locale avec react-intl-locale-chain
Lorsqu'une clé de traduction est manquante dans une locale régionale comme pt-BR, react-intl bascule directement vers la locale par défaut au lieu de vérifier d'abord la locale parente pt.
npm install react-intl-locale-chain<LocaleChainProvider
fallbacks={{
'pt-BR': ['pt', 'en'],
'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
}}
defaultLocale="en"
>
<App />
</LocaleChainProvider>Consultez notre guide de repli de locale pour découvrir la liste complète des frameworks pris en charge et les 75 chaînes intégrées. Learn more →