Começando a Internacionalização (i18n) com Intlayer e Next.js usando Page Router

    O que é Intlayer?

    Intlayer é uma biblioteca de internacionalização (i18n) inovadora e de código aberto, projetada para simplificar o suporte multilíngue em aplicações web modernas. O Intlayer se integra perfeitamente ao mais recente framework Next.js, incluindo seu tradicional Page Router.

    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.
    • 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.

    O Intlayer é compatível com Next.js 12, 13, 14 e 15. Se você estiver usando o App Router do Next.js, consulte o guia do App Router. Para o Next.js 15, siga este guia.


    Guia Passo a Passo para Configurar o Intlayer em uma Aplicação Next.js Usando Page Router

    Passo 1: Instalar Dependências

    Instale os pacotes necessários usando seu gerenciador de pacotes preferido:

    bash
    npm install intlayer next-intlayer
    • intlayer

      O pacote principal que fornece ferramentas de internacionalização para gerenciamento de configuração, tradução, declaração de conteúdo, transpiração e comandos CLI.

    • next-intlayer

      O pacote que integra Intlayer com Next.js. Ele fornece provedores de contexto e hooks para a internacionalização do Next.js. Além disso, inclui o plugin do Next.js para integrar o Intlayer com Webpack ou Turbopack, bem como middleware para detectar o local preferido do usuário, gerenciar cookies e lidar com redirecionamento de URLs.

    Passo 2: Configurar Seu Projeto

    Crie um arquivo de configuração para definir os idiomas suportados pela sua aplicação:

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

    Através deste arquivo de configuração, você pode configurar URLs localizadas, redirecionamento de middleware, nomes de cookies, a localização e extensão de suas declarações de conteúdo, desabilitar logs do Intlayer no console e muito mais. Para uma lista completa de parâmetros disponíveis, consulte a documentação de configuração.

    Passo 3: Integrar o Intlayer com a Configuração do Next.js

    Modifique sua configuração do Next.js para incorporar o Intlayer:

    next.config.mjs
    import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = {  // Sua configuração existente do Next.js};export default withIntlayer(nextConfig);

    O plugin withIntlayer() do Next.js é usado para integrar o Intlayer com o Next.js. Ele garante a construção de arquivos de declaração de conteúdo e os monitora em modo de desenvolvimento. Ele define variáveis de ambiente do Intlayer dentro dos ambientes Webpack ou Turbopack. Além disso, fornece aliases para otimizar o desempenho e garantir compatibilidade com componentes do servidor.

    Passo 4: Configurar Middleware para Detecção de Local

    Configure o middleware para detectar e lidar automaticamente com o local preferido do usuário:

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

    Adapte o parâmetro matcher para corresponder às rotas da sua aplicação. Para mais detalhes, consulte a documentação do Next.js sobre como configurar o matcher.

    Passo 5: Definir Rotas Dinâmicas de Local

    Implemente roteamento dinâmico para servir conteúdo localizado com base no local do usuário.

    1. Criar Páginas Específicas por Local:

      Renomeie seu arquivo da página principal para incluir o segmento dinâmico [locale].

      bash
      mv src/pages/index.tsx src/pages/[locale]/index.tsx
    2. Atualizar _app.tsx para Lidar com Localização:

      Modifique seu _app.tsx para incluir provedores do Intlayer.

      src/pages/_app.tsx
      import type { FC } from "react";import type { AppProps } from "next/app";import { IntlayerClientProvider } from "next-intlayer";const App = FC<AppProps>({ Component, pageProps }) => {  const { locale } = pageProps;  return (    <IntlayerClientProvider locale={locale}>      <Component {...pageProps} />    </IntlayerClientProvider>  );}export default MyApp;
    3. Configurar getStaticPaths e getStaticProps:

      No seu [locale]/index.tsx, defina os caminhos e props para lidar com diferentes locais.

      src/pages/[locale]/index.tsx
      import type { FC } from "react";import type { GetStaticPaths, GetStaticProps } from "next";import { type Locales, getConfiguration } from "intlayer";const HomePage: FC = () => <div>{/* Seu conteúdo aqui */}</div>;export const getStaticPaths: GetStaticPaths = () => {  const { internationalization } = getConfiguration();  const { locales } = internationalization;  const paths = locales.map((locale) => ({    params: { locale },  }));  return { paths, fallback: false };};export const getStaticProps: GetStaticProps = ({ params }) => {  const locale = params?.locale as string;  return {    props: {      locale,    },  };};export default HomePage;

    getStaticPaths e getStaticProps garantem que sua aplicação pré-construa as páginas necessárias para todos os locais no Page Router do Next.js. Essa abordagem reduz a computação em tempo de execução e melhora a experiência do usuário. Para mais detalhes, consulte a documentação do Next.js sobre getStaticPaths e getStaticProps.

    Passo 6: Declarar Seu Conteúdo

    Crie e gerencie suas declarações de conteúdo para armazenar traduções.

    src/pages/[locale]/home.content.ts
    import { t, type DeclarationContent } from "intlayer";const homeContent = {  key: "home",  content: {    title: t({      en: "Welcome to My Website",      fr: "Bienvenue sur mon site Web",      es: "Bienvenido a mi sitio web",    }),    description: t({      en: "Get started by editing this page.",      fr: "Commencez par éditer cette page.",      es: "Comience por editar esta página.",    }),  },} satisfies DeclarationContent;export default homeContent;

    Para mais informações sobre como declarar conteúdo, consulte o guia de declaração de conteúdo.

    Passo 7: Utilizar Conteúdo em Seu Código

    Acesse seus dicionários de conteúdo em toda a sua aplicação para exibir conteúdo traduzido.

    src/pages/[locale]/index.tsx
    import type { FC } from "react";import { useIntlayer } from "next-intlayer";import { ComponentExample } from "@components/ComponentExample";const HomePage: FC = () => {  const content = useIntlayer("home");  return (    <div>      <h1>{content.title}</h1>      <p>{content.description}</p>      <ComponentExample />      {/* Componentes adicionais */}    </div>  );};// ... Resto do código, incluindo getStaticPaths e getStaticPropsexport default HomePage;
    src/components/ComponentExample.tsx
    import type { FC } from "react";import { useIntlayer } from "next-intlayer";export const ComponentExample: FC = () => {  const content = useIntlayer("component-example"); // Certifique-se de ter uma declaração de conteúdo correspondente  return (    <div>      <h2>{content.title}</h2>      <p>{content.content}</p>    </div>  );};

    Ao usar traduções em atributos de string (por exemplo, alt, title, href, aria-label), chame o valor da função da seguinte forma:

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

    Para aprender mais sobre o hook useIntlayer, consulte a documentação.

    (Opcional) Passo 8: Internacionalizar Seus Metadados

    Para internacionalizar metadados como títulos e descrições de páginas, use a função getStaticProps em conjunto com a função getTranslationContent do Intlayer.

    src/pages/[locale]/index.tsx
    import { GetStaticPaths, GetStaticProps } from "next";import { type IConfigLocales, getTranslationContent, Locales } from "intlayer";import { useIntlayer } from "next-intlayer";interface HomePageProps {  locale: string;  metadata: Metadata;}const HomePage = ({ metadata }: HomePageProps) => {  // Os metadados podem ser usados no cabeçalho ou em outros componentes, conforme necessário  return (    <div>      <Head>        <title>{metadata.title}</title>        <meta name="description" content={metadata.description} />      </Head>      {/* Conteúdo adicional */}    </div>  );};export const getStaticProps: GetStaticProps = async ({ params }) => {  const locale = params?.locale as string;  const t = <T,>(content: IConfigLocales<T>) =>    getTranslationContent(content, locale);  const metadata = {    title: t({      en: "My Website",      fr: "Mon Site Web",      es: "Mi Sitio Web",    }),    description: t({      en: "Welcome to my website.",      fr: "Bienvenue sur mon site Web.",      es: "Bienvenido a mi sitio web.",    }),  };  return {    props: {      locale,      metadata,    },  };};export default HomePage;// ... Resto do código incluindo getStaticPaths

    (Opcional) Passo 9: Mudar o Idioma do Seu Conteúdo

    Para permitir que os usuários mudem de idioma dinamicamente, use a função setLocale fornecida pelo hook useLocale.

    src/components/LanguageSwitcher.tsx
    import {  Locales,  getHTMLTextDir,  getLocaleName,  getLocalizedUrl,} from "intlayer";import { useLocalePageRouter } from "next-intlayer";import { type FC } from "react";const LocaleSwitcher: FC = () => {  const { locale, pathWithoutLocale, availableLocales, setLocale } =    useLocalePageRouter();  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>              {/* Idioma em seu próprio Local - e.g. Français */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* Idioma no Locale atual - e.g. Francés com local atual definido como Locales.SPANISH */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* Idioma em Inglês - e.g. French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>            <span>              {/* Idioma em seu próprio Local - e.g. FR */}              {localeItem}            </span>          </a>        </li>      ))}    </ol>  );};

    A API useLocalePageRouter é a mesma que useLocale. Para aprender mais sobre o hook useLocale, consulte a documentação.

    Referências da documentação:

    1. Exemplo dos Benefícios do TypeScript:

      Exemplo de Autocompletação

      Exemplo de Erro de Tradução

    Configuração do Git

    Para manter seu repositório limpo e evitar comprometer arquivos gerados, é recomendável ignorar arquivos criados pelo Intlayer.

    Adicione as seguintes linhas ao seu arquivo .gitignore:

    .gitignore
    # Ignore os arquivos gerados pelo Intlayer.intlayer

    Recursos Adicionais

    Seguindo este guia, você pode integrar efetivamente o Intlayer em sua aplicação Next.js usando o Page Router, habilitando suporte robusto e escalável à internacionalização para seus projetos web.

    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