Intégrer next-intl pour l’internationalisation dans Next.js 15 : Guide Complet
Tutoriel étape par étape pour intégrer next-intl pour la traduction dans un projet Next.js 15.

La traduction (i18n) est essentielle pour les applications web modernes. Avec Next.js 15, la méthode recommandée pour ajouter la traduction est d'utiliser next-intl. Dans ce guide, vous apprendrez à configurer next-intl dans un projet Next.js 15 de manière pratique et efficace.
🚀 Vous cherchez un template Next.js avec next-intl déjà intégré ?
Si vous voulez éviter la configuration et commencer avec un template prêt pour la production qui inclut déjà l'internationalisation next-intl, découvrez notre Template Dashboard Financier Next.js.
🎯 Ce template premium inclut :
- ✅ next-intl déjà configuré et prêt à utiliser
- ✅ Basculement thème sombre/clair
- ✅ Gestion d'état Redux Toolkit
- ✅ Interface de dashboard financier moderne
- ✅ Authentification par email
- ✅ Design responsive
- ✅ Support TypeScript
Parfait pour les applications fintech, tableaux de bord bancaires et systèmes de gestion financière.
Voir la démo | Obtenir le template
1. Installer next-intl
Commencez par installer le package :
npm install next-intl
2. Configurer le routage
Créez une configuration de routage pour définir vos langues supportées. Par exemple, dans src/i18n/routing.ts :
// src/i18n/routing.ts
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
locales: ['en', 'fr', 'ar', 'es'],
defaultLocale: 'en'
});
3. Ajouter les helpers de navigation
Configurez les helpers de navigation dans src/i18n/navigation.ts :
// src/i18n/navigation.ts
import { createNavigation } from 'next-intl/navigation';
import { routing } from './routing';
export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
4. Charger les messages côté serveur
Configurez le chargement des messages dans src/i18n/request.ts :
// src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { hasLocale } from 'next-intl';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested)
? requested
: routing.defaultLocale;
const [seoMessages] = await Promise.all([
import(`../messages/seo/${locale}.json`).then(module => module.default).catch(() => ({})),
]);
return {
locale,
messages: {
seo: seoMessages,
}
};
});
5. Fournir les messages à votre application
Encapsulez vos pages avec NextIntlClientProvider. Par exemple, dans src/app/[locale]/about/layout.tsx :
// src/app/[locale]/about/layout.tsx
import { NextIntlClientProvider } from "next-intl";
export default async function AboutLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const [about] = await Promise.all([
import(`@/messages/about/${locale}.json`).then((mod) => mod.default),
]);
const messages = { about };
return (
<NextIntlClientProvider locale={locale} messages={messages}>
{children}
</NextIntlClientProvider>
);
}
6. Organiser vos fichiers de messages
Stockez vos fichiers de traduction dans src/messages/, par exemple :
src/messages/about/en.json
src/messages/about/fr.json
src/messages/about/ar.json
src/messages/about/es.json
Chaque fichier contient les traductions pour un namespace, par exemple :
{
"header_story": "Notre histoire",
"header_title1": "Nous construisons"
// ...
}
7. Utiliser les traductions dans les composants
Utilisez le hook useTranslations de next-intl :
import { useTranslations } from "next-intl";
export default function AboutHeader() {
const t = useTranslations("about");
return <h1>{t("header_title1")}</h1>;
}
8. Ajouter un sélecteur de langue
Voici le code complet du composant LanguageSelector :
// src/components/LanguageSelector/index.tsx
"use client";
import React, { useState, useRef, useEffect } from "react";
import { useParams, useRouter } from "next/navigation";
import { cn } from "@/lib/utils";
import { IconLanguage, IconChevronDown } from "@/lib/icons";
interface Language {
code: string;
name: string;
rtl: boolean;
}
const languages: Language[] = [
{ code: "en", name: "English", rtl: false },
{ code: "fr", name: "Français", rtl: false },
{ code: "es", name: "Español", rtl: false },
{ code: "ar", name: "العربية", rtl: true },
];
export default function LanguageSelector() {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const router = useRouter();
const params = useParams();
const currentLocale = typeof params.locale === "string" ? params.locale : "en";
const currentLanguage = languages.find((lang) => lang.code === currentLocale) || languages[0];
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
const changeLanguage = (langCode: string) => {
const currentPath = window.location.pathname;
const pathSegments = currentPath.split('/');
pathSegments[1] = langCode;
const newPath = pathSegments.join('/');
router.push(newPath);
setIsOpen(false);
};
return (
<div className="relative" ref={dropdownRef}>
<button
onClick={() => setIsOpen(!isOpen)}
className="flex items-center cursor-pointer px-2 py-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 text-sm"
aria-expanded={isOpen}
aria-haspopup="true"
>
<IconLanguage className="w-4 h-4 mr-1" />
<span className="font-medium text-xs mr-1">{currentLanguage.code.toUpperCase()}</span>
<IconChevronDown className={cn("w-3 h-3 transition-transform", isOpen ? "rotate-180" : "")} />
</button>
{isOpen && (
<div className="absolute z-50 mt-1 bg-white dark:bg-neutral-900 border border-gray-200 dark:border-gray-700 rounded-md shadow-lg py-1 w-40 min-w-max right-0">
<ul className="py-1">
{languages.map((language) => (
<li key={language.code}>
<button
onClick={() => changeLanguage(language.code)}
className={cn(
"w-full text-left cursor-pointer px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-800 flex items-center",
language.code === currentLocale && "bg-gray-100 dark:bg-gray-800"
)}
>
<span className="inline-block me-2 w-max font-medium text-xs">{language.code.toUpperCase()}</span>
{language.name}
</button>
</li>
))}
</ul>
</div>
)}
</div>
);
}
9. Tester votre configuration
Démarrez votre serveur de développement et visitez /en/about, /fr/about, etc. Vous devriez voir les bonnes traductions et pouvoir changer de langue.
Conclusion
Avec next-intl, ajouter la traduction à Next.js 15 est simple et puissant.
Références :
Cet article vous a été utile?
Vous pourriez aussi aimer

Optimisation des performances Next.js : Guide pratique pour accélérer vos applications
Apprenez à accélérer les applications Next.js avec l'optimisation d'images, le fractionnement de code, la génération statique, le chargement de polices et la réduction de la taille des bundles.

Booster les performances Next.js avec TanStack Query (React Query)
Améliorez les performances Next.js grâce à TanStack Query : cache, revalidation en arrière-plan, mutations et hydration SSR/SSG.

Publino : Le template Next.js ultime pour les startups modernes
Découvrez Publino, un template Next.js haute performance et optimisé SEO, conçu pour les SaaS, startups et agences. Créez et lancez des sites web époustouflants en quelques minutes.