Chargement des traductions
Utilisation d'un fournisseur pour gérer les messages
Problème
Coder en dur du texte, comme 'Hello World', directement dans les composants d'une application couple le contenu avec le code. Pour afficher une langue différente, les développeurs doivent dupliquer le composant ou ajouter une logique if/else, rendant la traduction non évolutive et nécessitant une modification complète du code pour chaque nouveau texte.
Solution
Utilisez IntlProvider de react-intl pour fournir des traductions. Chargez les messages de traduction sur le serveur dans le layout racine, transmettez-les à un composant provider côté client, puis consommez-les dans d'autres composants clients en utilisant le hook useIntl.
Étapes
1. Installer react-intl
D'abord, ajoutez react-intl comme dépendance à votre projet.
npm install react-intl
2. Créer des fichiers de traduction plats
Créez un dossier dictionaries. À l'intérieur, ajoutez un fichier JSON pour chaque langue. react-intl fonctionne mieux avec une structure clé-valeur plate.
// dictionaries/en.json
{
"home.title": "Home Page",
"home.welcome": "Hello, welcome to our site!",
"about.title": "About Us"
}
// dictionaries/es.json
{
"home.title": "Página de Inicio",
"home.welcome": "¡Hola, bienvenido a nuestro sitio!",
"about.title": "Sobre Nosotros"
}
3. Créer une fonction pour charger les dictionnaires
Créez une fonction d'aide pour charger le fichier de dictionnaire approprié sur le serveur en fonction du paramètre lang.
// app/get-dictionary.ts
import 'server-only';
// Define the type for our flat message object
type Messages = Record<string, string>;
const dictionaries: { [key: string]: () => Promise<Messages> } = {
en: () => import('@/dictionaries/en.json').then((module) => module.default),
es: () => import('@/dictionaries/es.json').then((module) => module.default),
// fr: () => import('@/dictionaries/fr.json').then((module) => module.default),
};
export const getDictionary = async (lang: string) => {
const load = dictionaries[lang];
if (load) {
return load();
}
// Fallback to English
return dictionaries.en();
};
4. Créer un fournisseur côté client
IntlProvider est un composant client qui utilise le Context de React. Nous devons créer un wrapper qui peut accepter les messages chargés depuis le serveur.
// app/components/IntlClientProvider.tsx
'use client';
import { IntlProvider } from 'react-intl';
type Props = {
children: React.ReactNode;
locale: string;
messages: Record<string, string>; // Objet de messages plat
};
export default function IntlClientProvider({
children,
locale,
messages,
}: Props) {
return (
<IntlProvider messages={messages} locale={locale} defaultLocale="en">
{children}
</IntlProvider>
);
}
5. Mettre à jour le layout racine
Modifiez votre app/[lang]/layout.tsx pour en faire un composant async. Il chargera les messages et les transmettra à IntlClientProvider.
// app/[lang]/layout.tsx
import { getDictionary } from '@/app/get-dictionary';
import IntlClientProvider from '@/app/components/IntlClientProvider';
export async function generateStaticParams() {
return [{ lang: 'en' }, { lang: 'es' }];
}
export default async function RootLayout({
children,
params,
}: {
children: React.ReactNode;
params: { lang: string };
}) {
// Charger les messages sur le serveur
const messages = await getDictionary(params.lang);
return (
<html lang={params.lang}>
<body>
{/* Transmettre les messages au fournisseur client */}
<IntlClientProvider locale={params.lang} messages={messages}>
{children}
</IntlClientProvider>
</body>
</html>
);
}
6. Utiliser les traductions dans un composant client
Vous pouvez maintenant utiliser le hook useIntl dans n'importe quel composant client. Les composants serveur ne peuvent pas utiliser ce hook.
Créez un nouveau composant client pour afficher le texte traduit :
// app/components/HomePageContent.tsx
'use client';
import { useIntl } from 'react-intl';
export default function HomePageContent() {
const intl = useIntl();
return (
<div>
<h1>{intl.formatMessage({ id: 'home.title' })}</h1>
<p>{intl.formatMessage({ id: 'home.welcome' })}</p>
</div>
);
}
7. Ajoutez le composant à votre page
Enfin, ajoutez votre nouveau composant client à votre page.
// app/[lang]/page.tsx
import HomePageContent from '@/app/components/HomePageContent';
export default function Home() {
// Cette page est un composant serveur
return (
<div>
{/* Elle rend le composant client */}
<HomePageContent />
</div>
);
}