Pourquoi Internationalisation (i18n) avec React ?
L'internationalisation, souvent abrégée en i18n, est un processus essentiel pour rendre vos applications web accessibles à un public mondial. Dans un monde où la diversité culturelle et linguistique est omniprésente, il est crucial que les sites Web soient capables de s'adapter aux préférences des utilisateurs en termes de langue, de format de date, d'units de mesure, etc. En tant qu'écosystème populaire pour le développement web, React offre des outils puissants pour faciliter l'internationalisation.
Un cas concret de l'importance de la i18n est une application multi-auteur pour un blog international. Pour que chaque auteur puisse écrire en sa langue native et que les articles soient présentés aux lecteurs dans leur langue préférée, il faut une solution efficace d'internationalisation.
Prerequis
Pour suivre ce tutoriel, vous aurez besoin des connaissances suivantes :
- Connaissance de base de React
- Familiarité avec les concepts de composants et de props
- Maîtrise de la gestion du state (utilisant
useState,useContextou Redux) - Compréhension des hooks personnalisés
Vous aurez besoin d'installer les outils suivants :
- Node.js (v14.0.0 ou plus)
- npm (v6.0.0 ou plus)
Concepts fondamentaux
1. Utilisation de react-i18next
react-i18next est une bibliothèque populaire pour l'internationalisation dans React. Elle permet d'charger facilement des fichiers de traduction et de gérer les changements de langue en temps réel.
Installation :
npm install react-i18next i18next --save
Code de base :
// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// Fichiers de traduction en anglais et français
import enTranslation from './locales/en/translation.json';
import frTranslation from './locales/fr/translation.json';
const resources = {
en: {
translation: enTranslation,
},
fr: {
translation: frTranslation,
},
};
i18n
.use(initReactI18next) // Pas besoin de plugins supplémentaires!
.init({
resources,
lng: 'en', // Langue par défaut
fallbackLng: 'en',
interpolation: {
escapeValue: false, // React already safes from xss
},
});
export default i18n;
2. Utilisation des Hooks useTranslation et useEffect
useTranslation est un hook personnalisé fourni par react-i18next qui vous permet d'accéder aux traductions et de gérer le changement de langue.
// src/App.js
import React from 'react';
import { useTranslation } from 'react-i18next';
function App() {
const { t, i18n } = useTranslation();
function changeLanguage(language) {
i18n.changeLanguage(language);
}
return (
<div className="App">
<h1>{t('welcome')}</h1>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('fr')}>Français</button>
</div>
);
}
export default App;
3. Chargement de fichiers de traduction dynamiques
Pour une application plus grande, il peut être utile de charger les fichiers de traduction dynamiquement pour améliorer la performance et réduire le temps de chargement initial.
// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
function loadLanguageResources(lng) {
return import(`./locales/${lng}/translation.json`);
}
const resources = {};
i18n
.use(initReactI18next)
.init({
lng: 'en',
fallbackLng: 'en',
interpolation: {
escapeValue: false,
},
initImmediate: false, // Désactiver l'initialisation immédiate pour charger dynamiquement les fichiers
resources,
});
i18n.loadNamespaces = async (lng) => {
if (!resources[lng]) {
const translations = await loadLanguageResources(lng);
i18n.addResourceBundle(lng, 'translation', translations.default, true, false);
resources[lng] = translations;
}
};
export default i18n;
Mise en pratique : projet fil rouge
Dans ce tutoriel, nous allons construire un simple gestionnaire de tâches internationalisé avec React et react-i18next.
Étape 1 : Configuration de base
npx create-react-app task-manager-i18n
cd task-manager-i18n
npm install react-i18next i18next --save
src/i18n.js :
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
const resources = {
en: {
translation: {
welcome: 'Welcome to the Task Manager',
addTask: 'Add a new task',
deleteTask: 'Delete task',
tasks: 'Tasks',
},
},
fr: {
translation: {
welcome: 'Bienvenue dans le Gestionnaire de tâches',
addTask: 'Ajouter une nouvelle tâche',
deleteTask: 'Supprimer la tâche',
tasks: 'Tâches',
},
},
};
i18n
.use(initReactI18next)
.init({
resources,
lng: 'en',
fallbackLng: 'en',
interpolation: {
escapeValue: false,
},
});
export default i18n;
src/App.js :
import React from 'react';
import { useTranslation } from 'react-i18next';
function App() {
const { t, i18n } = useTranslation();
function changeLanguage(language) {
i18n.changeLanguage(language);
}
return (
<div className="App">
<h1>{t('welcome')}</h1>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('fr')}>Français</button>
</div>
);
}
export default App;
Étape 2 : Création des composants
src/components/TaskList.js :
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
function TaskList() {
const [tasks, setTasks] = useState([]);
const { t } = useTranslation();
function addTask(task) {
setTasks([...tasks, task]);
}
function deleteTask(index) {
setTasks(tasks.filter((_, i) => i !== index));
}
return (
<div>
<h2>{t('tasks')}</h2>
<ul>
{tasks.map((task, index) => (
<li key={index}>
{task}
<button onClick={() => deleteTask(index)}>{t('deleteTask')}</button>
</li>
))}
</ul>
<input type="text" placeholder={t('addTask')} />
<button onClick={() => addTask(document.querySelector('input').value)}>Add</button>
</div>
);
}
export default TaskList;
src/App.js :
import React from 'react';
import { useTranslation } from 'react-i18next';
import TaskList from './components/TaskList';
function App() {
const { t, i18n } = useTranslation();
function changeLanguage(language) {
i18n.changeLanguage(language);
}
return (
<div className="App">
<h1>{t('welcome')}</h1>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('fr')}>Français</button>
<TaskList />
</div>
);
}
export default App;
Étape 3 : Ajout de styles (facultatif)
src/App.css :
.App {
text-align: center;
padding-top: 50px;
}
h1, h2 {
color: #61dafb;
}
Erreurs frequentes et debugging
Erreur 1 : Fichier de traduction non trouvé
Code incorrect :
import enTranslation from './locales/en/translation.json';
Code correct :
const resources = {
en: {
translation: require('./locales/en/translation.json'),
},
};
Erreur 2 : Changement de langue non réactif
Code incorrect :
i18n.changeLanguage('fr');
Code correct :
i18n.changeLanguage('fr').then(() => {
// Code à exécuter après le changement de langue
});
Erreur 3 : Traduction manquante
Code incorrect :
const { t } = useTranslation();
console.log(t('non_existent_key'));
Code correct :
const { t, i18n } = useTranslation();
function getTranslation(key) {
const translation = t(key);
return translation === key ? `[${key}]` : translation;
}
console.log(getTranslation('non_existent_key'));
Pour aller plus loin
1. Utilisation de contexte personnalisé pour partager l'état internationalisation
Vous pouvez créer un contexte personnalisé pour partager l'état d'internationalisation dans toute votre application.
src/contexts/I18nContext.js :
import React, { createContext, useContext } from 'react';
import i18n from 'i18next';
const I18nContext = createContext();
export function useI18n() {
return useContext(I18nContext);
}
export function I18nProvider({ children }) {
const changeLanguage = (language) => {
i18n.changeLanguage(language).then(() => {
// Code à exécuter après le changement de langue
});
};
return (
<I18nContext.Provider value=changeLanguage>
{children}
</I18nContext.Provider>
);
}
src/App.js :
import React from 'react';
import { I18nProvider } from './contexts/I18nContext';
import TaskList from './components/TaskList';
function App() {
return (
<I18nProvider>
<TaskList />
</I18nProvider>
);
}
export default App;
2. Utilisation de react-i18next-scanner pour générer automatiquement les fichiers de traduction
Vous pouvez utiliser le scanneur react-i18next-scanner pour automatiser la création des fichiers de traduction en analysant votre code React.
Installation :
npm install react-i18next-scanner --save-dev
Configuration :
// .i18nrc.js
module.exports = {
input: ['src/**/*.{js,jsx}'],
output: './locales',
};
Commande de scanneur :
npx i18next-scanner
3. Utilisation de react-i18next avec Next.js
Si vous utilisez Next.js pour le développement d'applications web, il est recommandé d'utiliser react-i18next avec next-i18next, une bibliothèque spécifique à Next.js.
Installation :
npm install next-i18next --save
Configuration :
// next.config.js
const { i18n } = require('./next-i18next.config');
module.exports = {
i18n,
};
Configuration des fichiers de traduction :
mkdir public/locales
cp src/i18n/en.json public/locales/en.json
cp src/i18n/fr.json public/locales/fr.json
src/pages/_app.js :
import '../i18n';
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
Défi pratique
Créez une application React simple qui affiche un tableau de données (par exemple, des informations sur les utilisateurs) et permet aux utilisateurs de changer la langue en temps réel. Assurez-vous d'utiliser react-i18next pour gérer l'internationalisation.