Iniziare a internazionalizzare (i18n) con Intlayer e Next.js 14 con App Router

    Cos'è Intlayer?

    Intlayer è una libreria innovativa e open-source di internazionalizzazione (i18n) progettata per semplificare il supporto multilingue nelle moderne applicazioni web. Intlayer si integra senza problemi con il più recente framework Next.js 14, incluso il potente App Router. È ottimizzato per lavorare con i Server Components per un rendering efficiente ed è completamente compatibile con Turbopack (da Next.js >= 15).

    Con Intlayer, puoi:

    • Gestire facilmente le traduzioni utilizzando dizionari dichiarativi a livello di componente.
    • Localizzare dinamicamente metadati, percorsi e contenuti.
    • Accedere alle traduzioni sia nei componenti lato client che nei componenti lato server.
    • Garantire il supporto TypeScript con tipi generati automaticamente, migliorando l'autocompletamento e la rilevazione degli errori.
    • Beneficiare di funzionalità avanzate, come la rilevazione dinamica della lingua e il passaggio.

    Intlayer è compatibile con Next.js 12, 13, 14 e 15. Se stai usando Next.js Page Router, puoi fare riferimento a questa guida. Per Next.js 15 con o senza turbopack, fai riferimento a questa guida.


    Guida Passo-Passo per Configurare Intlayer in un'Applicazione Next.js

    Passo 1: Installa le Dipendenze

    Installa i pacchetti necessari utilizzando npm:

    bash
    npm install intlayer next-intlayer
    • intlayer

      Il pacchetto core che fornisce strumenti di internazionalizzazione per la gestione della configurazione, traduzione, dichiarazione del contenuto, transpilation e comandi CLI.

    • next-intlayer

      Il pacchetto che integra Intlayer con Next.js. Fornisce provider di contesto e hook per l'internazionalizzazione di Next.js. Inoltre, include il plugin Next.js per integrare Intlayer con Webpack o Turbopack, così come middleware per rilevare la lingua preferita dell'utente, gestire i cookie e gestire la reindirizzazione degli URL.

    Passo 2: Configura il Tuo Progetto

    Crea un file di configurazione per configurare le lingue della tua applicazione:

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

    Attraverso questo file di configurazione, puoi impostare URL localizzati, reindirizzamento middleware, nomi dei cookie, la posizione e l'estensione delle tue dichiarazioni di contenuto, disabilitare i log di Intlayer nella console e altro ancora. Per un elenco completo dei parametri disponibili, fai riferimento alla documentazione di configurazione.

    Passo 3: Integra Intlayer nella Tua Configurazione di Next.js

    Configura il tuo setup Next.js per usare Intlayer:

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

    Il plugin withIntlayer() di Next.js è utilizzato per integrare Intlayer con Next.js. Garantisce la creazione di file di dichiarazione del contenuto e ne monitora la modifica in modalità di sviluppo. Definisce le variabili ambientali di Intlayer all'interno degli ambienti Webpack o Turbopack. Inoltre, fornisce alias per ottimizzare le prestazioni e garantire la compatibilità con i server components.

    Passo 4: Configura il Middleware per la Rilevazione della Lingua

    Imposta il middleware per rilevare la lingua preferita dell'utente:

    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).*)",};

    Il intlayerMiddleware è utilizzato per rilevare la lingua preferita dell'utente e reindirizzarlo all'URL appropriato come specificato nella configurazione. Inoltre, abilita il salvataggio della lingua preferita dell'utente in un cookie.

    Adatta il parametro matcher per compilare le rotte della tua applicazione. Per ulteriori dettagli, fai riferimento alla documentazione di Next.js sulla configurazione del matcher.

    Passo 5: Definisci Rotte Locali Dinamiche

    Rimuovi tutto da RootLayout e sostituiscilo con il seguente codice:

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

    Mantenere il componente RootLayout vuoto consente di impostare gli attributi lang e dir al tag <html>.

    Per implementare il routing dinamico, fornisci il percorso per la lingua aggiungendo un nuovo layout nella directory [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;

    Il segmento di percorso [locale] viene utilizzato per definire la lingua. Esempio: /en-US/about si riferirà a en-US e /fr/about a fr.

    Poi, implementa la funzione generateStaticParams nel layout della tua applicazione.

    src/app/[locale]/layout.tsx
    export { generateStaticParams } from "next-intlayer"; // Riga da inserireconst LocaleLayout: Next14LayoutIntlayer = ({  children,  params: { locale },}) => {  /*... Rest del codice*/};export default LocaleLayout;

    generateStaticParams garantisce che la tua applicazione precompili le pagine necessarie per tutte le lingue, riducendo il calcolo a runtime e migliorando l'esperienza utente. Per ulteriori dettagli, fare riferimento alla documentazione di Next.js su generateStaticParams.

    Passo 6: Dichiarare il Tuo Contenuto

    Crea e gestisci le tue dichiarazioni di contenuto per memorizzare le traduzioni:

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

    Le tue dichiarazioni di contenuto possono essere definite ovunque nella tua applicazione finché sono incluse nella directory contentDir (per impostazione predefinita, ./src). E corrispondono all'estensione dei file di dichiarazione del contenuto (per impostazione predefinita, .content.{ts,tsx,js,jsx,mjs,cjs}). Per ulteriori dettagli, fai riferimento alla documentazione sulla dichiarazione del contenuto.

    Passo 7: Utilizza il Contenuto nel Tuo Codice

    Accedi ai tuoi dizionari di contenuto in tutta la tua applicazione:

    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 è utilizzato per fornire la lingua ai componenti lato client. Può essere posizionato in qualsiasi componente parent, incluso il layout. Tuttavia, è consigliato posizionarlo in un layout perché il codice del layout di Next.js è condiviso tra le pagine, rendendolo più efficiente. Utilizzando IntlayerClientProvider nel layout, eviti di reinizializzarlo per ogni pagina, migliorando le prestazioni e mantenendo un contesto di localizzazione coerente in tutta la tua applicazione.
    • IntlayerServerProvider è utilizzato per fornire la lingua ai bambini server. Non può essere impostato nel layout.

    Layout e pagina non possono condividere un contesto server comune perché il sistema di contesto server si basa su un'archiviazione di dati per richiesta (tramite il meccanismo di cache di React), causando la ricreazione di ogni “contesto” per segmenti diversi dell'applicazione. Posizionare il provider in un layout condiviso comprometterebbe questa isolamento, impedendo la corretta propagazione dei valori di contesto server ai tuoi componenti server.

    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"); // Crea la dichiarazione di contenuto correlata  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"); // Crea la dichiarazione di contenuto correlata  return (    <div>      <h2>{content.title} </h2>      <p>{content.content}</p>    </div>  );};

    Se vuoi usare il tuo contenuto in un attributo string, come alt, title, href, aria-label, ecc., devi chiamare il valore della funzione, come:

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

    Per saperne di più sull'hook useIntlayer, fai riferimento alla documentazione.

    (Opzionale) Passo 8: Internazionalizzazione dei tuoi metadati

    Nel caso in cui tu voglia internazionalizzare i tuoi metadati, come il titolo della tua pagina, puoi utilizzare la funzione generateMetadata fornita da Next.js. All'interno della funzione utilizza la funzione getTranslationContent per tradurre i tuoi metadati.

    src/app/[locale]/layout.tsx o 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);  /**   * Genera un oggetto contenente tutti gli URL per ogni lingua.   *   * Esempio:   * ```ts   *  getMultilingualUrls('/about');   *   *  // Restituisce   *  // {   *  //   en: '/about',   *  //   fr: '/fr/about',   *  //   es: '/es/about',   *  // }   * ```   */  const multilingualUrls = getMultilingualUrls("/");  return {    title: t<string>({      en: "Il mio titolo",      fr: "Mon titre",      es: "Mi título",    }),    description: t({      en: "La mia descrizione",      fr: "Ma description",      es: "Mi descripción",    }),    alternates: {      canonical: "/",      languages: { ...multilingualUrls, "x-default": "/" },    },    openGraph: {      url: multilingualUrls[locale],    },  };};// ... Rest del codice

    Scopri di più sull'ottimizzazione dei metadati nella documentazione ufficiale di Next.js.

    (Opzionale) Passo 9: Internazionalizzazione del tuo sitemap.xml e robots.txt

    Per internazionalizzare il tuo sitemap.xml e robots.txt, puoi utilizzare la funzione getMultilingualUrls fornita da Intlayer. Questa funzione ti consente di generare URL multilingue per il tuo 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;

    Scopri di più sull'ottimizzazione del sitemap nella documentazione ufficiale di Next.js. Scopri di più sull'ottimizzazione di robots.txt nella documentazione ufficiale di Next.js.

    (Opzionale) Passo 10: Cambia la lingua del tuo contenuto

    Per cambiare la lingua del tuo contenuto, puoi utilizzare la funzione setLocale fornita dall'hook useLocale. Questa funzione ti consente di impostare la lingua dell'applicazione e aggiornare di conseguenza il contenuto.

    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>              {/* Lingua nella propria lingua - e.g. Français */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* Lingua nella lingua corrente - e.g. Francés con lingua corrente impostata su Locales.SPANISH */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Lingua in inglese - e.g. French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>            <span>              {/* Lingua nella propria lingua - e.g. FR */}              {localeItem}            </span>          </a>        </li>      ))}    </ol>  );};

    Riferimenti alla documentazione:

    Configura TypeScript

    Intlayer utilizza l'augmentation dei moduli per trarre vantaggio da TypeScript e rendere il tuo codice più robusto.

    alt text

    alt text

    Assicurati che la tua configurazione TypeScript includa i tipi generati automaticamente.

    tsconfig.json
    {  // ... Le tue configurazioni TypeScript esistenti  "include": [    // ... Le tue configurazioni TypeScript esistenti    "types", // Includi i tipi generati automaticamente  ],}

    Configurazione di Git

    È consigliabile ignorare i file generati da Intlayer. Questo ti consente di evitare di commetterli nel tuo repository Git.

    Per farlo, puoi aggiungere le seguenti istruzioni al tuo file .gitignore:

    .gitignore
    # Ignora i file generati da Intlayer.intlayer

    Se hai un’idea per migliorare questa documentazione, non esitare a contribuire inviando una pull request su GitHub.

    Collegamento GitHub alla documentazione