IntlPull
Guide
18 min read

react-i18next : Le Guide Complet de l'Internationalisation React en 2026

Maîtrisez react-i18next pour les apps React. Tutoriel complet couvrant la configuration, les hooks, les espaces de noms, la pluralisation, le chargement paresseux, TypeScript et les meilleures pratiques de production.

IntlPull Team
IntlPull Team
03 Feb 2026, 11:44 AM [PST]
On this page
Summary

Maîtrisez react-i18next pour les apps React. Tutoriel complet couvrant la configuration, les hooks, les espaces de noms, la pluralisation, le chargement paresseux, TypeScript et les meilleures pratiques de production.

Réponse Rapide

react-i18next est la bibliothèque i18n la plus populaire pour React avec 3,5M+ téléchargements hebdomadaires npm. Installez avec npm install react-i18next i18next, créez des fichiers de traduction JSON, configurez i18next avec i18n.init(), puis utilisez le hook useTranslation : const { t } = useTranslation(); return <h1>{t('welcome')}</h1>. Pour les applications en production, combinez avec IntlPull pour la gestion de traduction alimentée par IA et les mises à jour OTA.


Qu'est-ce que react-i18next ?

react-i18next est une liaison React pour i18next, le framework d'internationalisation JavaScript le plus éprouvé au combat. Il fournit :

  • Hooks React (useTranslation) pour composants fonctionnels
  • HOCs et render props pour composants de classe
  • Support Suspense pour le chargement asynchrone de traduction
  • Compatibilité SSR avec Next.js, Remix et Gatsby
  • Écosystème de plugins pour backends, détection de langue et mise en cache

Pourquoi Choisir react-i18next ?

Fonctionnalitéreact-i18nextreact-intlnext-intl
Téléchargements Hebdo3.5M+1.2M800K
Taille Bundle~15KB~25KB~12KB
FrameworkTout ReactTout ReactNext.js seulement
Courbe d'ApprentissageFaibleMoyenneFaible
Système PluginÉtenduLimitéN/A
TypeScriptExcellentBonExcellent

Installation et Configuration

Étape 1 : Installer les Dépendances

Terminal
1npm install react-i18next i18next
2# ou
3yarn add react-i18next i18next
4# ou
5pnpm add react-i18next i18next

Plugins optionnels :

Terminal
1# Détection de langue
2npm install i18next-browser-languagedetector
3
4# Charger les traductions depuis le backend
5npm install i18next-http-backend
6
7# Pour React Native
8npm install react-i18next i18next @os-team/i18next-react-native-language-detector

Étape 2 : Créer les Fichiers de Traduction

src/
├── locales/
│   ├── en/
│   │   ├── common.json
│   │   └── home.json
│   ├── es/
│   │   ├── common.json
│   │   └── home.json
│   └── fr/
│       ├── common.json
│       └── home.json
└── i18n.ts

en/common.json:

JSON
1{
2  "welcome": "Welcome to our app",
3  "nav": {
4    "home": "Home",
5    "about": "About",
6    "contact": "Contact"
7  },
8  "buttons": {
9    "submit": "Submit",
10    "cancel": "Cancel",
11    "save": "Save"
12  }
13}

fr/common.json:

JSON
1{
2  "welcome": "Bienvenue sur notre application",
3  "nav": {
4    "home": "Accueil",
5    "about": "À propos",
6    "contact": "Contact"
7  },
8  "buttons": {
9    "submit": "Envoyer",
10    "cancel": "Annuler",
11    "save": "Enregistrer"
12  }
13}

Étape 3 : Configurer i18next

TypeScript
1// src/i18n.ts
2import i18n from 'i18next';
3import { initReactI18next } from 'react-i18next';
4import LanguageDetector from 'i18next-browser-languagedetector';
5
6// Importer les traductions
7import enCommon from './locales/en/common.json';
8import enHome from './locales/en/home.json';
9import frCommon from './locales/fr/common.json';
10import frHome from './locales/fr/home.json';
11
12i18n
13  .use(LanguageDetector)
14  .use(initReactI18next)
15  .init({
16    resources: {
17      en: {
18        common: enCommon,
19        home: enHome,
20      },
21      fr: {
22        common: frCommon,
23        home: frHome,
24      },
25    },
26    defaultNS: 'common',
27    fallbackLng: 'en',
28    supportedLngs: ['en', 'fr'],
29
30    interpolation: {
31      escapeValue: false, // React échappe déjà
32    },
33
34    detection: {
35      order: ['localStorage', 'navigator', 'htmlTag'],
36      caches: ['localStorage'],
37    },
38  });
39
40export default i18n;

Étape 4 : Initialiser dans Votre App

TSX
1// src/main.tsx ou src/index.tsx
2import React from 'react';
3import ReactDOM from 'react-dom/client';
4import './i18n'; // Importer la configuration i18n
5import App from './App';
6
7ReactDOM.createRoot(document.getElementById('root')!).render(
8  <React.StrictMode>
9    <App />
10  </React.StrictMode>
11);

Utiliser le Hook useTranslation

Le hook useTranslation est le moyen principal d'accéder aux traductions dans les composants fonctionnels.

Usage de Base

TSX
1import { useTranslation } from 'react-i18next';
2
3function Header() {
4  const { t } = useTranslation();
5
6  return (
7    <header>
8      <h1>{t('welcome')}</h1>
9      <nav>
10        <a href="/">{t('nav.home')}</a>
11        <a href="/about">{t('nav.about')}</a>
12      </nav>
13    </header>
14  );
15}

Avec Espaces de Noms

TSX
1import { useTranslation } from 'react-i18next';
2
3function HomePage() {
4  // Charger un espace de noms spécifique
5  const { t } = useTranslation('home');
6
7  return <h1>{t('hero.title')}</h1>;
8}
9
10function MultiNamespace() {
11  // Charger plusieurs espaces de noms
12  const { t } = useTranslation(['common', 'home']);
13
14  return (
15    <div>
16      <h1>{t('home:hero.title')}</h1>
17      <button>{t('common:buttons.submit')}</button>
18    </div>
19  );
20}

Changer de Langue

TSX
1import { useTranslation } from 'react-i18next';
2
3function LanguageSwitcher() {
4  const { i18n } = useTranslation();
5
6  const changeLanguage = (lng: string) => {
7    i18n.changeLanguage(lng);
8  };
9
10  return (
11    <div>
12      <button onClick={() => changeLanguage('en')}>English</button>
13      <button onClick={() => changeLanguage('fr')}>Français</button>
14    </div>
15  );
16}

Interpolation de Variable

Variables de Base

JSON
1{
2  "greeting": "Bonjour, {{name}} !",
3  "itemCount": "Vous avez {{count}} articles dans votre panier"
4}
TSX
1function Greeting({ user }) {
2  const { t } = useTranslation();
3
4  return (
5    <div>
6      <h1>{t('greeting', { name: user.name })}</h1>
7      <p>{t('itemCount', { count: user.cartItems })}</p>
8    </div>
9  );
10}

Formatage des Valeurs

JSON
1{
2  "price": "Total : {{price, currency}}",
3  "date": "Créé le {{date, datetime}}"
4}
TypeScript
1// i18n.ts - Ajouter formateurs
2i18n.init({
3  // ... autre config
4  interpolation: {
5    escapeValue: false,
6    format: (value, format, lng) => {
7      if (format === 'currency') {
8        return new Intl.NumberFormat(lng, {
9          style: 'currency',
10          currency: 'USD',
11        }).format(value);
12      }
13      if (format === 'datetime') {
14        return new Intl.DateTimeFormat(lng).format(value);
15      }
16      return value;
17    },
18  },
19});

Pluralisation

Pluriels de Base

JSON
1{
2  "item_one": "{{count}} article",
3  "item_other": "{{count}} articles",
4  "item_zero": "Aucun article"
5}
TSX
1function CartCount({ count }) {
2  const { t } = useTranslation();
3
4  return <span>{t('item', { count })}</span>;
5  // count=0: "Aucun article"
6  // count=1: "1 article"
7  // count=5: "5 articles"
8}

Pluriels Complexes (Russe, Arabe, etc.)

JSON
1{
2  "item_zero": "нет товаров",
3  "item_one": "{{count}} товар",
4  "item_few": "{{count}} товара",
5  "item_many": "{{count}} товаров",
6  "item_other": "{{count}} товаров"
7}

Ordinaux

JSON
1{
2  "place_ordinal_one": "{{count}}er place",
3  "place_ordinal_two": "{{count}}nd place",
4  "place_ordinal_few": "{{count}}ème place",
5  "place_ordinal_other": "{{count}}ème place"
6}
TSX
t('place', { count: 1, ordinal: true }); // "1er place"
t('place', { count: 2, ordinal: true }); // "2nd place"
t('place', { count: 3, ordinal: true }); // "3ème place"

Texte Riche et Composants

Utiliser le Composant Trans

JSON
1{
2  "terms": "En vous inscrivant, vous acceptez nos <link>Conditions d'Utilisation</link>",
3  "welcome": "Bienvenue <bold>{{name}}</bold> sur notre plateforme !"
4}
TSX
1import { Trans, useTranslation } from 'react-i18next';
2
3function TermsText() {
4  return (
5    <Trans
6      i18nKey="terms"
7      components={{
8        link: <a href="/terms" className="text-blue-600" />,
9      }}
10    />
11  );
12}
13
14function WelcomeMessage({ name }) {
15  return (
16    <Trans
17      i18nKey="welcome"
18      values={{ name }}
19      components={{
20        bold: <strong className="font-bold" />,
21      }}
22    />
23  );
24}

HTML Imbriqué

JSON
{
  "description": "Découvrez nos <link>nouvelles fonctionnalités</link> et <button>commencez</button> aujourd'hui !"
}
TSX
1<Trans
2  i18nKey="description"
3  components={{
4    link: <a href="/features" />,
5    button: <button onClick={handleStart} />,
6  }}
7/>

Chargement Paresseux des Traductions

Pour les grandes apps, chargez les traductions à la demande pour réduire la taille initiale du bundle.

Backend HTTP

TypeScript
1import i18n from 'i18next';
2import { initReactI18next } from 'react-i18next';
3import HttpBackend from 'i18next-http-backend';
4import LanguageDetector from 'i18next-browser-languagedetector';
5
6i18n
7  .use(HttpBackend)
8  .use(LanguageDetector)
9  .use(initReactI18next)
10  .init({
11    fallbackLng: 'en',
12    ns: ['common'],
13    defaultNS: 'common',
14
15    backend: {
16      loadPath: '/locales/{{lng}}/{{ns}}.json',
17    },
18
19    react: {
20      useSuspense: true,
21    },
22  });
23
24export default i18n;

Avec Suspense

TSX
1import { Suspense } from 'react';
2
3function App() {
4  return (
5    <Suspense fallback={<LoadingSpinner />}>
6      <MainContent />
7    </Suspense>
8  );
9}

Charger l'Espace de Noms à la Demande

TSX
1import { useTranslation } from 'react-i18next';
2import { Suspense, lazy } from 'react';
3
4// Chargement paresseux du composant avec son espace de noms
5const SettingsPage = lazy(() => import('./SettingsPage'));
6
7function App() {
8  return (
9    <Suspense fallback={<LoadingSpinner />}>
10      <SettingsPage />
11    </Suspense>
12  );
13}
14
15// SettingsPage.tsx
16function SettingsPage() {
17  const { t, ready } = useTranslation('settings', { useSuspense: false });
18
19  if (!ready) return <LoadingSpinner />;
20
21  return <h1>{t('title')}</h1>;
22}

Intégration TypeScript

Traductions Type-Safe

TypeScript
1// src/types/i18next.d.ts
2import 'i18next';
3import common from '../locales/en/common.json';
4import home from '../locales/en/home.json';
5
6declare module 'i18next' {
7  interface CustomTypeOptions {
8    defaultNS: 'common';
9    resources: {
10      common: typeof common;
11      home: typeof home;
12    };
13  }
14}

Maintenant TypeScript autocomplétera les clés de traduction :

TSX
const { t } = useTranslation();
t('nav.home'); // ✅ Autocomplète
t('nav.invalid'); // ❌ Erreur TypeScript

Avec Plusieurs Espaces de Noms

TSX
1const { t } = useTranslation(['common', 'home']);
2
3t('buttons.submit'); // De common (défaut)
4t('home:hero.title'); // De l'espace de noms home

Rendu Côté Serveur (SSR)

Routeur Pages Next.js

TypeScript
1// next-i18next.config.js
2module.exports = {
3  i18n: {
4    defaultLocale: 'en',
5    locales: ['en', 'es', 'fr'],
6  },
7};
TSX
1// pages/index.tsx
2import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
3import { useTranslation } from 'next-i18next';
4
5export default function Home() {
6  const { t } = useTranslation('common');
7  return <h1>{t('welcome')}</h1>;
8}
9
10export async function getStaticProps({ locale }) {
11  return {
12    props: {
13      ...(await serverSideTranslations(locale, ['common'])),
14    },
15  };
16}

Routeur App Next.js

Pour le Routeur App Next.js, nous recommandons d'utiliser next-intl à la place. Voir notre guide next-intl.

Remix

TSX
1// app/entry.server.tsx
2import { createInstance } from 'i18next';
3import { initReactI18next } from 'react-i18next';
4
5export default async function handleRequest(request, ...) {
6  const i18n = createInstance();
7  await i18n.use(initReactI18next).init({
8    lng: locale,
9    resources: { [locale]: translations },
10  });
11
12  // Rendre avec instance i18n
13}

Tester avec react-i18next

Configuration Mock

TypeScript
1// test/setup.ts
2import i18n from 'i18next';
3import { initReactI18next } from 'react-i18next';
4
5i18n.use(initReactI18next).init({
6  lng: 'en',
7  fallbackLng: 'en',
8  resources: {
9    en: {
10      common: {
11        welcome: 'Welcome',
12        'buttons.submit': 'Submit',
13      },
14    },
15  },
16});
17
18export default i18n;

Tester les Composants

TSX
1import { render, screen } from '@testing-library/react';
2import { I18nextProvider } from 'react-i18next';
3import i18n from '../test/setup';
4import Header from './Header';
5
6describe('Header', () => {
7  it('renders translated welcome message', () => {
8    render(
9      <I18nextProvider i18n={i18n}>
10        <Header />
11      </I18nextProvider>
12    );
13
14    expect(screen.getByText('Welcome')).toBeInTheDocument();
15  });
16});

Meilleures Pratiques de Production

1. Organisation par Espace de Noms

locales/
├── en/
│   ├── common.json      # UI partagée (boutons, nav, erreurs)
│   ├── auth.json        # Connexion, inscription, réinit mot de passe
│   ├── dashboard.json   # Spécifique au tableau de bord
│   ├── settings.json    # Page de paramètres
│   └── errors.json      # Messages d'erreur

2. Convention de Nommage des Clés

JSON
1{
2  "page.section.element": "Valeur",
3  "auth.login.title": "Se connecter",
4  "auth.login.button": "Continuer",
5  "dashboard.stats.totalUsers": "Utilisateurs Totaux",
6  "errors.network.timeout": "Délai de requête dépassé"
7}

3. Gestion des Clés Manquantes

TypeScript
1i18n.init({
2  saveMissing: process.env.NODE_ENV === 'development',
3  missingKeyHandler: (lng, ns, key) => {
4    console.warn(`Missing translation: ${lng}/${ns}/${key}`);
5    // Signaler au suivi des erreurs
6  },
7});

4. Optimisation de la Performance

TypeScript
1// Précharger les espaces de noms critiques
2i18n.loadNamespaces(['common', 'auth']);
3
4// Ne pas re-rendre au changement de langue pour le contenu statique
5const { t } = useTranslation('common', { useSuspense: false });

Mise à l'Échelle avec IntlPull

À mesure que votre application grandit, gérer les fichiers JSON manuellement devient douloureux. IntlPull fournit :

Intégration CLI

Terminal
1# Initialiser IntlPull dans votre projet
2npx @intlpullhq/cli init
3
4# Extraire les clés du code
5npx @intlpullhq/cli extract
6
7# Télécharger sur IntlPull
8npx @intlpullhq/cli upload
9
10# Télécharger les traductions
11npx @intlpullhq/cli download

Traduction IA

IntlPull traduit automatiquement vos clés en utilisant GPT-4, Claude ou DeepL tout en maintenant le contexte et la voix de la marque.

Mises à Jour OTA

Mettez à jour les traductions sans sorties d'application :

TypeScript
1import { IntlPullBackend } from '@intlpull/i18next-backend';
2
3i18n.use(IntlPullBackend).init({
4  backend: {
5    projectId: 'your-project-id',
6    apiKey: process.env.INTLPULL_API_KEY,
7  },
8});

Modèles Courants

Traductions Conditionnelles

JSON
1{
2  "greeting_morning": "Good morning!",
3  "greeting_afternoon": "Good afternoon!",
4  "greeting_evening": "Good evening!"
5}
TSX
1function Greeting() {
2  const { t } = useTranslation();
3  const hour = new Date().getHours();
4
5  const getGreetingKey = () => {
6    if (hour < 12) return 'greeting_morning';
7    if (hour < 18) return 'greeting_afternoon';
8    return 'greeting_evening';
9  };
10
11  return <h1>{t(getGreetingKey())}</h1>;
12}

Clés Dynamiques

TSX
1function StatusBadge({ status }: { status: 'pending' | 'approved' | 'rejected' }) {
2  const { t } = useTranslation();
3
4  // Clés : status.pending, status.approved, status.rejected
5  return <span>{t(`status.${status}`)}</span>;
6}

Contenu de Repli

TSX
1const { t } = useTranslation();
2
3// Fournir un repli
4const title = t('page.title', 'Default Title');
5
6// Vérifier si la clé existe
7const { exists } = useTranslation();
8if (exists('optional.feature')) {
9  // Montrer le contenu spécifique à la fonctionnalité
10}

Dépannage

Avertissements "Translation not found"

TypeScript
1// Vérifier si l'espace de noms est chargé
2i18n.hasLoadedNamespace('myNamespace');
3
4// S'assurer que la clé existe
5i18n.exists('myKey');
6
7// Mode débogage
8i18n.init({ debug: true });

Composant ne se re-rendant pas au changement de langue

TSX
1// Utiliser le hook correctement - il s'abonne aux changements
2const { t, i18n } = useTranslation();
3
4// Forcer le re-rendu avec la clé
5<MyComponent key={i18n.language} />

Inadéquation d'hydratation SSR

Assurez-vous que l'état initial correspond au serveur. Passez la locale initiale et les messages à votre provider pour éviter les différences.

Conclusion

react-i18next est un outil puissant pour construire des applications React mondiales. En suivant ces meilleures pratiques et en utilisant des outils comme IntlPull, vous pouvez créer des expériences localisées sans faille.

Prêt à commencer ? Configurez IntlPull gratuitement et gérez vos traductions react-i18next avec facilité.

Tags
react-i18next
i18next
react
i18n
internationalization
tutorial
2026
IntlPull Team
IntlPull Team
Engineering

Building tools to help teams ship products globally. Follow us for more insights on localization and i18n.