Development

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.

By Mohamed DjoudirJune 07, 20256 min read
Partager:
Intégrer next-intl pour l’internationalisation dans Next.js 15 : Guide Complet
#Next.js#next-intl#i18n#Internationalization#React

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.

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 :

1// src/i18n/routing.ts
2import {defineRouting} from 'next-intl/routing';
3
4export const routing = defineRouting({
5  locales: ['en', 'fr', 'ar', 'es'],
6  defaultLocale: 'en'
7});

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 :

1// src/i18n/request.ts
2import { getRequestConfig } from 'next-intl/server';
3import { hasLocale } from 'next-intl';
4import { routing } from './routing';
5
6export default getRequestConfig(async ({ requestLocale }) => {
7    const requested = await requestLocale;
8    const locale = hasLocale(routing.locales, requested)
9        ? requested
10        : routing.defaultLocale;
11
12    const [seoMessages] = await Promise.all([
13        import(`../messages/seo/${locale}.json`).then(module => module.default).catch(() => ({})),
14    ]);
15
16    return {
17        locale,
18        messages: {
19            seo: seoMessages,
20        }
21    };
22});

5. Fournir les messages à votre application

Encapsulez vos pages avec NextIntlClientProvider. Par exemple, dans src/app/[locale]/about/layout.tsx :

1// src/app/[locale]/about/layout.tsx
2import { NextIntlClientProvider } from "next-intl";
3
4export default async function AboutLayout({
5  children,
6  params,
7}: {
8  children: React.ReactNode;
9  params: Promise<{ locale: string }>;
10}) {
11  const { locale } = await params;
12
13  const [about] = await Promise.all([
14    import(`@/messages/about/${locale}.json`).then((mod) => mod.default),
15  ]);
16
17  const messages = { about };
18  return (
19    <NextIntlClientProvider locale={locale} messages={messages}>
20      {children}
21    </NextIntlClientProvider>
22  );
23}

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 :

1import { useTranslations } from "next-intl";
2
3export default function AboutHeader() {
4  const t = useTranslations("about");
5  return <h1>{t("header_title1")}</h1>;
6}

8. Ajouter un sélecteur de langue

Voici le code complet du composant LanguageSelector :

1// src/components/LanguageSelector/index.tsx
2"use client";
3
4import React, { useState, useRef, useEffect } from "react";
5import { useParams, useRouter } from "next/navigation";
6import { cn } from "@/lib/utils";
7import { IconLanguage, IconChevronDown } from "@/lib/icons";
8
9interface Language {
10  code: string;
11  name: string;
12  rtl: boolean;
13}
14
15const languages: Language[] = [
16  { code: "en", name: "English", rtl: false },
17  { code: "fr", name: "Français", rtl: false },
18  { code: "es", name: "Español", rtl: false },
19  { code: "ar", name: "العربية", rtl: true },
20];
21
22export default function LanguageSelector() {
23  const [isOpen, setIsOpen] = useState(false);
24  const dropdownRef = useRef<HTMLDivElement>(null);
25  const router = useRouter();
26  const params = useParams();
27  const currentLocale = typeof params.locale === "string" ? params.locale : "en";
28  
29  const currentLanguage = languages.find((lang) => lang.code === currentLocale) || languages[0];
30
31  useEffect(() => {
32    const handleClickOutside = (event: MouseEvent) => {
33      if (
34        dropdownRef.current &&
35        !dropdownRef.current.contains(event.target as Node)
36      ) {
37        setIsOpen(false);
38      }
39    };
40
41    document.addEventListener("mousedown", handleClickOutside);
42    return () => {
43      document.removeEventListener("mousedown", handleClickOutside);
44    };
45  }, []);
46
47  const changeLanguage = (langCode: string) => {
48    const currentPath = window.location.pathname;
49    const pathSegments = currentPath.split('/');
50    pathSegments[1] = langCode;
51    const newPath = pathSegments.join('/');
52    router.push(newPath);
53    setIsOpen(false);
54  };
55
56  return (
57    <div className="relative" ref={dropdownRef}>
58      <button
59        onClick={() => setIsOpen(!isOpen)}
60        className="flex items-center  cursor-pointer px-2 py-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 text-sm"
61        aria-expanded={isOpen}
62        aria-haspopup="true"
63      >
64        <IconLanguage className="w-4 h-4 mr-1" />
65        <span className="font-medium text-xs mr-1">{currentLanguage.code.toUpperCase()}</span>
66        <IconChevronDown className={cn("w-3 h-3 transition-transform", isOpen ? "rotate-180" : "")} />
67      </button>
68
69      {isOpen && (
70        <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">
71          <ul className="py-1">
72            {languages.map((language) => (
73              <li key={language.code}>
74                <button
75                  onClick={() => changeLanguage(language.code)}
76                  className={cn(
77                    "w-full text-left cursor-pointer px-4 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-800 flex items-center",
78                    language.code === currentLocale && "bg-gray-100 dark:bg-gray-800"
79                  )}
80                 >
81                  <span className="inline-block me-2 w-max font-medium text-xs">{language.code.toUpperCase()}</span>
82                  {language.name}
83                </button>
84              </li>
85            ))}
86          </ul>
87        </div>
88      )}
89    </div>
90  );
91}

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?

Partager:

Communauté Mondiale d'Utilisateurs

Rejoignez des milliers de développeurs à travers le monde qui font confiance à Aniq-UI pour leurs projets. Nos modèles sont utilisés partout dans le monde pour créer des expériences web impressionnantes.

world map