Commencer l'internationalisation (i18n) avec Intlayer et Next.js 14 avec App Router

    Qu'est-ce qu'Intlayer ?

    Intlayer est une bibliothèque innovante et open-source d'internationalisation (i18n) conçue pour simplifier le support multilingue dans les applications web modernes. Intlayer s'intègre parfaitement avec le dernier framework Next.js 14, y compris son puissant App Router. Il est optimisé pour travailler avec les Server Components pour un rendu efficace et est entièrement compatible avec Turbopack (à partir de Next.js >= 15).

    Avec Intlayer, vous pouvez :

    • Gérer facilement les traductions grâce à des dictionnaires déclaratifs au niveau des composants.
    • Localiser dynamiquement les métadonnées, les routes et le contenu.
    • Accéder aux traductions à la fois dans les composants côté client et côté serveur.
    • Assurer le support TypeScript avec des types générés automatiquement, améliorant ainsi l'autocomplétion et la détection d'erreurs.
    • Bénéficier de fonctionnalités avancées, comme la détection et le changement dynamiques de la locale.

    Intlayer est compatible avec Next.js 12, 13, 14 et 15. Si vous utilisez le Next.js Page Router, vous pouvez vous référer à ce guide. Pour Next.js 15 avec ou sans turbopack, reportez-vous à ce guide.


    Guide étape par étape pour configurer Intlayer dans une application Next.js

    Étape 1 : Installer les dépendances

    Installez les paquets nécessaires en utilisant npm :

    bash
    npm install intlayer next-intlayer
    • intlayer

      Le paquet principal qui fournit des outils d'internationalisation pour la gestion de la configuration, la traduction, la déclaration de contenu, la transpilation, et les commandes CLI.

    • next-intlayer

      Le paquet qui intègre Intlayer avec Next.js. Il fournit des contextes et des hooks pour l'internationalisation sous Next.js. De plus, il comprend le plugin Next.js pour intégrer Intlayer avec Webpack ou Turbopack, ainsi que du middleware pour détecter la locale préférée de l'utilisateur, gérer les cookies, et gérer la redirection des URL.

    Étape 2 : Configurer votre projet

    Créez un fichier de configuration pour configurer les langues de votre application :

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // Vos autres locales    ],    defaultLocale: Locales.ENGLISH,  },};export default config;

    Grâce à ce fichier de configuration, vous pouvez configurer des URL localisées, la redirection de middleware, les noms de cookies, l'emplacement et l'extension de vos déclarations de contenu, désactiver les journaux Intlayer dans la console, et plus encore. Pour une liste complète des paramètres disponibles, referez-vous à la documentation de configuration.

    Étape 3 : Intégrer Intlayer dans votre configuration Next.js

    Configurez votre installation Next.js pour utiliser Intlayer :

    next.config.mjs
    import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = {};export default withIntlayer(nextConfig);

    Le plugin withIntlayer() de Next.js est utilisé pour intégrer Intlayer avec Next.js. Il garantit la construction des fichiers de déclaration de contenu et les surveille en mode développement. Il définit les variables d'environnement Intlayer dans les environnements Webpack ou Turbopack. De plus, il fournit des alias pour optimiser les performances et garantir la compatibilité avec les composants du serveur.

    Étape 4 : Configurer le middleware pour la détection de la locale

    Configurez le middleware pour détecter la locale préférée de l'utilisateur :

    src/middleware.ts
    export { intlayerMiddleware as middleware } from "next-intlayer/middleware";export const config = {  matcher:    "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",};

    Le intlayerMiddleware est utilisé pour détecter la locale préférée de l'utilisateur et rediriger vers l'URL appropriée comme spécifié dans la configuration. De plus, il permet de sauvegarder la locale préférée de l'utilisateur dans un cookie.

    Adaptez le paramètre matcher pour faire correspondre les routes de votre application. Pour plus de détails, consultez la documentation Next.js sur la configuration du matcher.

    Étape 5 : Définir des routes locales dynamiques

    Supprimez tout de RootLayout et remplacez-le par le code suivant :

    src/app/layout.tsx
    import type { PropsWithChildren, FC } from "react";import "./globals.css";const RootLayout: FC<PropsWithChildren> = ({ children }) => children;export default RootLayout;

    Garder le composant RootLayout vide permet de définir les attributs lang et dir dans la balise <html>.

    Pour mettre en œuvre le routage dynamique, fournissez le chemin de la locale en ajoutant un nouveau layout dans votre répertoire [locale] :

    src/app/[locale]/layout.tsx
    import type { Next14LayoutIntlayer } from "next-intlayer";import { Inter } from "next/font/google";import { getHTMLTextDir } from "intlayer";const inter = Inter({ subsets: ["latin"] });const LocaleLayout: Next14LayoutIntlayer = ({  children,  params: { locale },}) => (  <html lang={locale} dir={getHTMLTextDir(locale)}>    <body className={inter.className}>{children}</body>  </html>);export default LocaleLayout;

    Le segment de chemin [locale] est utilisé pour définir la locale. Exemple : /en-US/about référencera en-US et /fr/about référencera fr.

    Ensuite, implémentez la fonction generateStaticParams dans le layout de votre application.

    src/app/[locale]/layout.tsx
    export { generateStaticParams } from "next-intlayer"; // Ligne à insérerconst LocaleLayout: Next14LayoutIntlayer = ({  children,  params: { locale },}) => {  /*... Reste du code*/};export default LocaleLayout;

    generateStaticParams garantit que votre application pré-construit les pages nécessaires pour toutes les locales, réduisant ainsi le calcul d'exécution et améliorant l'expérience utilisateur. Pour plus de détails, consultez la documentation Next.js sur generateStaticParams.

    Étape 6 : Déclarer votre contenu

    Créez et gérez vos déclarations de contenu pour stocker des traductions :

    src/app/[locale]/page.content.ts
    import { t, type DeclarationContent } from "intlayer";const pageContent = {  key: "page",  content: {    getStarted: {      main: t({        en: "Get started by editing",        fr: "Commencez par éditer",        es: "Comience por editar",      }),      pageLink: "src/app/page.tsx",    },  },} satisfies DeclarationContent;export default pageContent;

    Vos déclarations de contenu peuvent être définies n'importe où dans votre application dès qu'elles sont incluses dans le répertoire contentDir (par défaut, ./src). Et correspondent à l'extension de fichier de déclaration de contenu (par défaut, .content.{ts,tsx,js,jsx,mjs,cjs}). Pour plus de détails, reportez-vous à la documentation de déclaration de contenu.

    Étape 7 : Utiliser le contenu dans votre code

    Accédez à vos dictionnaires de contenu tout au long de votre application :

    src/app/[locale]/page.tsx
    import { ClientComponentExample } from "@components/ClientComponentExample";import { ServerComponentExample } from "@components/ServerComponentExample";import { type Next14PageIntlayer, IntlayerClientProvider } from "next-intlayer";import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";const Page: Next14PageIntlayer = ({ params: { locale } }) => {  const content = useIntlayer("page", locale);  return (    <>      <p>        {content.getStarted.main}        <code>{content.getStarted.pageLink}</code>      </p>      <IntlayerServerProvider locale={locale}>        <IntlayerClientProvider locale={locale}>          <ServerComponentExample />          <ClientComponentExample />        </IntlayerClientProvider>      </IntlayerServerProvider>    </>  );};export default Page;
    • IntlayerClientProvider est utilisé pour fournir la locale aux composants côté client. Il peut être placé dans n'importe quel composant parent, y compris le layout. Cependant, il est recommandé de le placer dans un layout car Next.js partage le code de layout entre les pages, ce qui le rend plus efficace. En utilisant IntlayerClientProvider dans le layout, vous évitez de le réinitialiser pour chaque page, améliorant ainsi les performances et maintenant un contexte de localisation cohérent dans toute votre application.
    • IntlayerServerProvider est utilisé pour fournir la locale aux enfants du serveur. Il ne peut pas être défini dans le layout.

      Le layout et la page ne peuvent pas partager un contexte de serveur commun car le système de contexte de serveur est basé sur un stockage de données par requête (via le cache de React), ce qui fait que chaque “contexte” est recréé pour différents segments de l'application. Placer le fournisseur dans un layout partagé romprendrait cette isolation, empêchant la bonne propagation des valeurs de contexte de serveur vers vos composants serveur.

    src/components/ClientComponentExample.tsx
    "use client";import type { FC } from "react";import { useIntlayer } from "next-intlayer";const ClientComponentExample: FC = () => {  const content = useIntlayer("client-component-example"); // Créer la déclaration de contenu associée  return (    <div>      <h2>{content.title} </h2>      <p>{content.content}</p>    </div>  );};
    src/components/ServerComponentExample.tsx
    import type { FC } from "react";import { useIntlayer } from "next-intlayer/server";const ServerComponentExample: FC = () => {  const content = useIntlayer("server-component-example"); // Créer la déclaration de contenu associée  return (    <div>      <h2>{content.title} </h2>      <p>{content.content}</p>    </div>  );};

    Si vous souhaitez utiliser votre contenu dans un attribut string, tel que alt, title, href, aria-label, etc., vous devez appeler la valeur de la fonction, comme ceci :

    jsx
    <img src={content.image.src.value} alt={content.image.value} />

    Pour en savoir plus sur le hook useIntlayer, reportez-vous à la documentation.

    (Optionnel) Étape 8 : Internationalisation de vos métadonnées

    Dans le cas où vous souhaitez internationaliser vos métadonnées, telles que le titre de votre page, vous pouvez utiliser la fonction generateMetadata fournie par Next.js. À l'intérieur de la fonction, utilisez la fonction getTranslationContent pour traduire vos métadonnées.

    src/app/[locale]/layout.tsx or src/app/[locale]/page.tsx
    import {  type IConfigLocales,  getTranslationContent,  getMultilingualUrls,} from "intlayer";import type { Metadata } from "next";import type { LocalParams } from "next-intlayer";export const generateMetadata = ({  params: { locale },}: LocalParams): Metadata => {  const t = <T>(content: IConfigLocales<T>) =>    getTranslationContent(content, locale);  /**   * Génère un objet contenant toutes les url pour chaque locale.   *   * Exemple :   * ```ts   *  getMultilingualUrls('/about');   *   *  // Renvoie   *  // {   *  //   en: '/about',   *  //   fr: '/fr/about',   *  //   es: '/es/about',   *  // }   * ```   */  const multilingualUrls = getMultilingualUrls("/");  return {    title: t<string>({      en: "My title",      fr: "Mon titre",      es: "Mi título",    }),    description: t({      en: "My description",      fr: "Ma description",      es: "Mi descripción",    }),    alternates: {      canonical: "/",      languages: { ...multilingualUrls, "x-default": "/" },    },    openGraph: {      url: multilingualUrls[locale],    },  };};// ... Reste du code

    En savoir plus sur l'optimisation des métadonnées dans la documentation officielle de Next.js.

    (Optionnel) Étape 9 : Internationalisation de votre sitemap.xml et robots.txt

    Pour internationaliser votre sitemap.xml et robots.txt, vous pouvez utiliser la fonction getMultilingualUrls fournie par Intlayer. Cette fonction vous permet de générer des URL multilingues pour votre sitemap.

    src/app/sitemap.ts
    import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [  {    url: "https://example.com",    alternates: {      languages: getMultilingualUrls("https://example.com"),    },  },  {    url: "https://example.com/login",    alternates: {      languages: getMultilingualUrls("https://example.com/login"),    },  },  {    url: "https://example.com/register",    alternates: {      languages: getMultilingualUrls("https://example.com/register"),    },  },];export default sitemap;
    src/app/robots.ts
    import type { MetadataRoute } from "next";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const robots = (): MetadataRoute.Robots => ({  rules: {    userAgent: "*",    allow: ["/"],    disallow: getAllMultilingualUrls(["/login", "/register"]),  },  host: "https://example.com",  sitemap: `https://example.com/sitemap.xml`,});export default robots;

    En savoir plus sur l'optimisation du sitemap dans la documentation officielle de Next.js. En savoir plus sur l'optimisation de robots.txt dans la documentation officielle de Next.js.

    (Optionnel) Étape 10 : Changer la langue de votre contenu

    Pour changer la langue de votre contenu, vous pouvez utiliser la fonction setLocale fournie par le hook useLocale. Cette fonction vous permet de définir la locale de l'application et de mettre à jour le contenu en conséquence.

    src/components/LocaleSwitcher.tsx
    "use client";import {  Locales,  getHTMLTextDir,  getLocaleName,  getLocalizedUrl,} from "intlayer";import { useLocale } from "next-intlayer";import { type FC } from "react";const LocaleSwitcher: FC = () => {  const { locale, pathWithoutLocale, availableLocales, setLocale } =    useLocale();  return (    <ol>      {availableLocales.map((localeItem) => (        <li key={localeItem}>          <a            href={getLocalizedUrl(pathWithoutLocale, localeItem)}            hrefLang={localeItem}            aria-current={locale === localeItem ? "page" : undefined}            onClick={(e) => {              e.preventDefault();              setLocale(localeItem);            }}          >            <span>              {/* Langue dans sa propre locale - e.g. Français */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* Langue dans la locale actuelle - e.g. Francés avec la locale actuelle définie sur Locales.SPANISH */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Langue en anglais - e.g. French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>            <span>              {/* Langue dans sa propre locale - e.g. FR */}              {localeItem}            </span>          </a>        </li>      ))}    </ol>  );};

    Références documentaires :

    Configurer TypeScript

    Intlayer utilise l'augmentation de module pour tirer parti de TypeScript et renforcer votre base de code.

    alt text

    alt text

    Assurez-vous que votre configuration TypeScript inclut les types générés automatiquement.

    tsconfig.json
    {  // ... Vos configurations TypeScript existantes  "include": [    // ... Vos configurations TypeScript existantes    "types", // Inclure les types auto-générés  ],}

    Configuration Git

    Il est recommandé d'ignorer les fichiers générés par Intlayer. Cela vous permet d'éviter de les commettre dans votre dépôt Git.

    Pour ce faire, vous pouvez ajouter les instructions suivantes à votre fichier .gitignore :

    .gitignore
    # Ignorer les fichiers générés par Intlayer.intlayer

    Si vous avez une idée d’amélioration pour améliorer cette documentation, n’hésitez pas à contribuer en submitant une pull request sur GitHub.

    Lien GitHub de la documentation