Getting Started internationalizing (i18n) with Intlayer and Next.js 14 with App Router

    What is Intlayer?

    Intlayer é uma biblioteca inovadora e de código aberto de internacionalização (i18n) projetada para simplificar o suporte multilíngue em aplicações web modernas. Intlayer se integra perfeitamente com o mais recente framework Next.js 14, incluindo seu poderoso App Router. É otimizado para trabalhar com Server Components para renderização eficiente e é totalmente compatível com Turbopack (a partir do Next.js >= 15).

    Com o Intlayer, você pode:

    • Gerenciar traduções facilmente usando dicionários declarativos no nível do componente.
    • Localizar dinamicamente metadados, rotas e conteúdo.
    • Acessar traduções em componentes do lado do cliente e do lado do servidor.
    • Garantir suporte TypeScript com tipos autogerados, melhorando a autocompletação e a detecção de erros.
    • Beneficiar-se de recursos avançados, como detecção e troca dinâmica de locais.

    Nota: O Intlayer é compatível com Next.js 12, 13, 14 e 15. Se você estiver usando Next.js Page Router, pode consultar este guia. Para Next.js 15 com ou sem turbopack, consulte este guia.


    Step-by-Step Guide to Set Up Intlayer in a Next.js Application

    Step 1: Install Dependencies

    Instale os pacotes necessários usando npm:

    bash
    npm install intlayer next-intlayer
    
    bash
    yarn add intlayer next-intlayer
    
    bash
    pnpm add intlayer next-intlayer
    

    Step 2: Configure Your Project

    Crie um arquivo de configuração para configurar os idiomas da sua aplicação:

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

    Para ver todos os parâmetros disponíveis, consulte a documentação de configuração aqui.

    Step 3: Integrate Intlayer in Your Next.js Configuration

    Configure sua configuração do Next.js para usar o Intlayer:

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

    Step 4: Configure Middleware for Locale Detection

    Configure um middleware para detectar o idioma preferido do usuário:

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

    Step 5: Define Dynamic Locale Routes

    Implemente o roteamento dinâmico para conteúdo localizado:

    Mude src/app/page.ts para src/app/[locale]/page.ts

    Em seguida, implemente a função generateStaticParams em seu Layout da aplicação.

    tsx
    // src/app/layout.tsx
    
    import type { ReactNode } from "react";
    import "./globals.css";
    
    export { generateStaticParams } from "next-intlayer"; // Linha a ser inserida
    
    const RootLayout = ({
      children,
    }: Readonly<{
      children: ReactNode;
    }>) => children;
    
    export default RootLayout;
    

    Em seguida, adicione um novo layout em seu diretório [locale]:

    tsx
    // 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;
    

    Step 6: Declare Your Content

    Crie e gerencie seus dicionários de conteúdo:

    tsx
    // 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;
    

    Veja como declarar seus arquivos de declaração Intlayer.

    Step 7: Utilize Content in Your Code

    Acesse seus dicionários de conteúdo em toda a sua aplicação:

    tsx
    // src/app/[locale]/page.ts
    
    import { ClientComponentExample } from "@component/ClientComponentExample";
    import { LocaleSwitcher } from "@component/LangSwitcherDropDown";
    import { NestedServerComponentExample } from "@component/NestedServerComponentExample";
    import { ServerComponentExample } from "@component/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 é usado para fornecer o idioma para os filhos do servidor
           *   Não funciona se definido no layout
           */}
          <IntlayerServerProvider locale={locale}>
            <ServerComponentExample />
          </IntlayerServerProvider>
          {/**
           *   IntlayerClientProvider é usado para fornecer o idioma para os filhos do cliente
           *   Pode ser definido em qualquer componente pai, incluindo o layout
           */}
          <IntlayerClientProvider locale={locale}>
            <ClientComponentExample />
          </IntlayerClientProvider>
        </>
      );
    };
    
    export default Page;
    
    tsx
    // src/components/ClientComponentExample.tsx
    
    "use client";
    
    import { useIntlayer } from "next-intlayer";
    
    export const ClientComponentExample = () => {
      const content = useIntlayer("client-component-example"); // Crie a declaração de conteúdo relacionada
    
      return (
        <div>
          <h2>{content.title} </h2>
          <p>{content.content}</p>
        </div>
      );
    };
    
    tsx
    // src/components/ServerComponentExample.tsx
    
    import { useIntlayer } from "next-intlayer/server";
    
    export const ServerComponentExample = () => {
      const content = useIntlayer("server-component-example"); // Crie a declaração de conteúdo relacionada
    
      return (
        <div>
          <h2>{content.title} </h2>
          <p>{content.content}</p>
        </div>
      );
    };
    

    Nota: Se você quiser usar seu conteúdo em um atributo string, como alt, title, href, aria-label, etc., você deve chamar o valor da função, como:

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

    Para um uso mais detalhado do intlayer em componente Cliente ou Servidor, veja o exemplo do Next.js aqui.

    (Optional) Step 8: Internationalization of your metadata

    No caso de você querer internacionalizar seus metadados, como o título da sua página, você pode usar a função generateMetadata fornecida pelo Next.js. Dentro da função, use a função getTranslationContent para traduzir seus metadados.

    typescript
    // src/app/[locale]/layout.tsx ou 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);
    
      /**
       * Gera um objeto contendo todas as urls para cada localidade.
       *
       * Exemplo:
       * ```ts
       *  getMultilingualUrls('/about');
       *
       *  // Retorna
       *  // {
       *  //   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: url,
          languages: { ...multilingualUrls, "x-default": "/" },
        },
        openGraph: {
          url: multilingualUrls[locale],
        },
      };
    };
    
    // ... Restante do código
    

    Aprenda mais sobre a otimização de metadados na documentação oficial do Next.js.

    (Optional) Step 9: Internationalization of your sitemap.xml and robots.txt

    Para internacionalizar seu sitemap.xml e robots.txt, você pode usar a função getMultilingualUrls fornecida pelo Intlayer. Essa função permite que você gere URLs multilíngues para seu sitemap.

    tsx
    // 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;
    
    tsx
    // 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;
    

    Aprenda mais sobre a otimização do sitemap na documentação oficial do Next.js. Aprenda mais sobre a otimização do robots.txt na documentação oficial do Next.js.

    (Optional) Step 10: Change the language of your content

    Para mudar o idioma do seu conteúdo, você pode usar a função setLocale fornecida pelo hook useLocale. Essa função permite que você defina o idioma da aplicação e atualize o conteúdo de acordo.

    tsx
    import { Locales } from "intlayer";
    import { useLocale } from "next-intlayer";
    
    const MyComponent = () => {
      const { setLocale } = useLocale();
    
      return (
        <button onClick={() => setLocale(Locales.English)}>Mudar Idioma</button>
      );
    };
    

    Configure TypeScript

    Intlayer usa augmentação de módulo para obter benefícios do TypeScript e tornar seu código mais robusto.

    alt text

    alt text

    Certifique-se de que sua configuração TypeScript inclua os tipos autogerados.

    json5
    // tsconfig.json
    
    {
      // sua configuração personalizada
      include: [
        "src",
        "types", // <- Inclua os tipos auto gerados
      ],
    }
    

    Git Configuration

    É recomendado ignorar os arquivos gerados pelo Intlayer. Isso permite que você evite se comprometer com eles em seu repositório Git.

    Para fazer isso, você pode adicionar as seguintes instruções ao seu arquivo .gitignore:

    gitignore
    # Ignore os arquivos gerados pelo Intlayer
    .intlayer
    

    Se você tiver uma ideia para melhorar esta documentação, sinta-se à vontade para contribuir enviando uma pull request no GitHub.

    Link do GitHub para a documentação