
Le guide complet de l'internationalisation Next.js
Configurez next-intl avec l'App Router, mettez en place le routage par locale et automatisez les traductions avec l'IA.
Installez next-intl
next-intl est un package unique qui gère le routage par locale, le chargement des messages et les hooks de traduction pour l'App Router de Next.js.
npm install next-intlCréez la configuration de requête i18n
Créez deux fichiers : src/i18n/request.ts pour le chargement des messages et src/i18n/routing.ts pour la définition des locales. Ils configurent la manière dont next-intl résout les messages et les routes.
// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';
export const routing = defineRouting({
locales: ['en', 'de', 'ja', 'es'],
defaultLocale: 'en',
localePrefix: 'as-needed', // /about for en, /de/about for de
});
export const { Link, redirect, usePathname, useRouter } =
createNavigation(routing);Configurez le middleware
Ajoutez middleware.ts pour gérer la détection de locale, la réécriture d'URL et les redirections. Le middleware intercepte chaque requête et garantit l'application de la bonne locale.
// middleware.ts <- Must be in project ROOT, not src/
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';
export default createMiddleware(routing);
export const config = {
matcher: ['/((?!api|_next|.*\\..*).*)'],
};Mettez en place la structure de dossiers [locale]
Déplacez vos routes d'application dans app/[locale]/. Ajoutez generateStaticParams pour générer les pages de chaque locale au moment de la compilation. Cela crée une structure d'URL du type /en/about, /de/about, etc.
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}Mettez à jour votre layout racine
Chargez les messages avec getMessages() et transmettez-les à NextIntlClientProvider dans votre layout racine de locale. Définissez l'attribut lang du html à partir du paramètre locale.
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, setRequestLocale } from 'next-intl/server';
import { routing } from '@/i18n/routing';
import { notFound } from 'next/navigation';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: { locale: string };
}) {
const { locale } = await params;
if (!routing.locales.includes(locale as any)) notFound();
setRequestLocale(locale);
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider locale={locale} messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}Utiliser les traductions dans les composants
Les composants serveur utilisent getTranslations (async, await). Les composants client utilisent useTranslations (hook). Choisissez en fonction du lieu de rendu de votre composant — les composants serveur excluent entièrement les traductions du bundle JavaScript.
// Server Component (default)
import { getTranslations, setRequestLocale } from 'next-intl/server';
export default async function AboutPage({
params,
}: { params: { locale: string } }) {
const { locale } = await params;
setRequestLocale(locale);
const t = await getTranslations('AboutPage');
return <h1>{t('title')}</h1>;
}
// Client Component ('use client')
'use client';
import { useTranslations } from 'next-intl';
export default function SearchBar() {
const t = useTranslations('SearchBar');
return <input placeholder={t('placeholder')} />;
}Ajoutez le SEO : métadonnées et hreflang
Utilisez generateMetadata pour produire des titres et descriptions de page propres à chaque locale. Ajoutez alternates.languages pour les balises hreflang afin que les moteurs de recherche découvrent toutes les versions linguistiques de chaque page.
// app/[locale]/layout.tsx or any page.tsx
import { getTranslations } from 'next-intl/server';
import { routing } from '@/i18n/routing';
export async function generateMetadata({
params,
}: { params: { locale: string } }) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: 'Metadata' });
return {
title: t('title'),
description: t('description'),
alternates: {
languages: Object.fromEntries(
routing.locales.map((l) => [l, `/${l}`])
),
},
};
}Gérez les pages d'erreur et introuvables
error.tsx et not-found.tsx nécessitent un traitement particulier, car ils peuvent s'afficher en dehors du layout de locale normal. Le not-found.tsx racine nécessite sa propre configuration de provider i18n pour afficher des messages d'erreur localisés.
// app/[locale]/error.tsx
'use client';
import { useTranslations } from 'next-intl';
export default function Error() {
const t = useTranslations('Error');
return (
<div>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</div>
);
}
// app/not-found.tsx (root level -- needs own provider)
import { routing } from '@/i18n/routing';
export default async function GlobalNotFound() {
return (
<html lang={routing.defaultLocale}>
<body>
<h1>404 - Page Not Found</h1>
</body>
</html>
);
}Automatiser les traductions
Une fois votre configuration i18n terminée, traduisez vos fichiers de messages avec l'IA directement depuis votre IDE, ou utilisez le CLI i18n Agent dans votre pipeline CI/CD pour une traduction automatisée à chaque déploiement.
# In your IDE, ask your AI assistant:
> Translate messages/en.json to German, Japanese, and Spanish
✓ messages/de.json created (1.1s)
✓ messages/ja.json created (1.4s)
✓ messages/es.json created (1.0s)Automatiser la qualité des traductions
Outils open source pour l'i18n Next.js
Ces packages open source résolvent les difficultés courantes des flux de travail d'internationalisation dans Next.js.
next-intl-localechain
La version standard de next-intl revient directement à votre locale par défaut lorsqu'une traduction est manquante. Un utilisateur portugais brésilien voit alors s'afficher l'anglais au lieu d'excellentes traductions en pt-PT. next-intl-localechain ajoute des chaînes de repli intelligentes — il fusionne en profondeur les traductions des locales apparentées afin que les utilisateurs régionaux voient toujours la traduction disponible la plus proche.
import { getRequestConfig } from 'next-intl/server';
import { withLocaleChain } from 'next-intl-localechain';
export default getRequestConfig(withLocaleChain({
loadMessages: (locale) =>
import(`../../messages/${locale}.json`).then(m => m.default),
defaultLocale: 'en'
}));@i18n-agent/cli
Un outil en ligne de commande pour traduire vos fichiers de messages Next.js sans quitter le terminal. Traduisez directement vos fichiers, vérifiez l'état des tâches et téléchargez les résultats. Fonctionne dans les pipelines CI/CD grâce à l'authentification par clé API, pour des flux de localisation entièrement automatisés.
# Install the CLI
npm install -g @i18n-agent/cli
# Authenticate
i18nagent login
# Translate your message files
i18nagent translate ./messages/en.json --lang de,ja,es
# Or use in CI/CD with an API key
export I18N_AGENT_API_KEY=your-key-here
i18nagent translate ./messages/en.json --lang de,ja,esPièges courants
« Unable to find next-intl locale »
Le middleware n'a pas correspondu à la requête. Vérifiez : middleware.ts est-il à la racine du projet ? Le motif du matcher exclut-il correctement les fichiers statiques ? La locale est-elle incluse dans votre configuration de routage ?
Rendu dynamique inattendu
setRequestLocale(locale) est absent d'une page ou d'un layout. Sans cela, next-intl utilise les en-têtes/cookies pour détecter la locale, ce qui force un rendu dynamique et empêche la génération statique.
Les routes parallèles cassent avec i18n
Les routes parallèles (@modal) et les routes d'interception ((.)photo) présentent des incompatibilités connues avec le segment dynamique [locale]. Utilisez un routage basé sur le middleware comme solution de contournement pour ces schémas de routage avancés.
Le changement de langue fait perdre la route actuelle
Lors du changement de locale, conservez le chemin d'accès actuel à l'aide de usePathname() et remplacez uniquement le segment de locale — attention aux paramètres de route dynamiques : ils doivent être résolus de nouveau pour la nouvelle locale.
Structure de fichiers recommandée
my-nextjs-app/
├── middleware.ts # Locale routing (project root!)
├── next.config.mjs
├── messages/
│ ├── en.json # Source messages
│ ├── de.json
│ └── ja.json
├── src/
│ ├── i18n/
│ │ ├── request.ts # Message loading config
│ │ └── routing.ts # Locale definitions
│ └── app/
│ └── [locale]/
│ ├── layout.tsx # Root locale layout
│ ├── page.tsx # Home page
│ ├── error.tsx # Localized error page
│ ├── not-found.tsx # Localized 404
│ └── about/
│ └── page.tsx
└── 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 next-intl-localechain
Lorsqu'une clé de traduction est manquante dans une locale régionale comme pt-BR, next-intl passe directement à la locale par défaut au lieu de vérifier d'abord la locale parente pt.
npm install next-intl-localechainimport { withLocaleChain } from 'next-intl-localechain';
export default withLocaleChain({
fallbacks: {
'pt-BR': ['pt', 'en'],
'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
},
defaultLocale: 'en',
loadMessages: (locale) => import(`./messages/${locale}.json`),
});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 →