Skip to main content

O guia completo da internacionalização em Next.js

Configure next-intl com o App Router, defina o encaminhamento regional e automatize as traduções com IA.

1

Instalar next-intl

next-intl é um único pacote que trata do encaminhamento regional, do carregamento das mensagens e dos hooks de tradução no App Router do Next.js.

Terminal
npm install next-intl
Porquê next-intl em vez de next-i18next? next-intl foi criado para o App Router e os componentes de servidor. next-i18next foi concebido para o Pages Router e oferece compatibilidade limitada com o App Router.
2

Criar a configuração de pedidos de i18n

Crie dois ficheiros: src/i18n/request.ts para carregar mensagens e src/i18n/routing.ts para definir regiões. Estes configuram a forma como next-intl resolve mensagens e rotas.

src/i18n/routing.ts
// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';

export const routing = defineRouting({
  locales: ['en', 'de', 'ja', 'es'],
  defaultLocale: 'en',
  localePrefix: 'as-needed',  // /about for en, /de/about for de
});

export const { Link, redirect, usePathname, useRouter } =
  createNavigation(routing);
Turbopack —o empacotador predefinido do Next.js 15— exige experimental.turbo.resolveAlias em next.config.js. Sem esta opção, recebe erros «Couldn't find next-intl config file».
3

Configurar o middleware

Adicione middleware.ts para tratar da deteção regional, reescrita de URL e redirecionamentos. O middleware interceta todos os pedidos e garante a aplicação da região correta.

middleware.ts
// middleware.ts  <- Must be in project ROOT, not src/
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: ['/((?!api|_next|.*\\..*).*)'],
};
middleware.ts TEM de estar no diretório de raiz do projeto, não dentro de src/. Este é o erro de configuração mais frequente com next-intl.
4

Configurar a estrutura de pastas [locale]

Mova as rotas da aplicação para app/[locale]/. Adicione generateStaticParams para gerar páginas de cada região durante a compilação. Isto cria a estrutura de URL /en/about, /de/about, etc.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
TEM de chamar setRequestLocale(locale) em todos os page.tsx e layout.tsx que utilizem traduções. Sem esta chamada, o Next.js recorre à apresentação dinâmica e o desempenho da compilação degrada-se consideravelmente.
5

Atualizar a disposição de raiz

Carregue as mensagens com getMessages() e passe-as para NextIntlClientProvider na disposição regional de raiz. Defina o atributo lang de html a partir do parâmetro regional.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, setRequestLocale } from 'next-intl/server';
import { routing } from '@/i18n/routing';
import { notFound } from 'next/navigation';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default async function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  const { locale } = await params;
  if (!routing.locales.includes(locale as any)) notFound();

  setRequestLocale(locale);
  const messages = await getMessages();

  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}
NextIntlClientProvider exige uma propriedade locale explícita. Omiti-la provoca erros subtis nos componentes de cliente, difíceis de resolver.
6

Utilizar traduções nos componentes

Os componentes de servidor utilizam getTranslations —assíncrono, com await—. Os de cliente utilizam useTranslations —hook—. Escolha conforme o local de apresentação: os componentes de servidor mantêm as traduções totalmente fora do pacote JavaScript do cliente.

app/[locale]/page.tsx
// Server Component (default)
import { getTranslations, setRequestLocale } from 'next-intl/server';

export default async function AboutPage({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  setRequestLocale(locale);
  const t = await getTranslations('AboutPage');

  return <h1>{t('title')}</h1>;
}

// Client Component ('use client')
'use client';
import { useTranslations } from 'next-intl';

export default function SearchBar() {
  const t = useTranslations('SearchBar');
  return <input placeholder={t('placeholder')} />;
}
Prefira componentes de servidor no conteúdo traduzido. Mantêm as cadeias fora do pacote JavaScript do cliente e reduzem o tempo de carregamento.
7

Adicionar SEO: metadados e hreflang

Utilize generateMetadata para produzir títulos e descrições de página específicos de cada região. Adicione alternates.languages para etiquetas hreflang, para os motores de pesquisa descobrirem todas as versões linguísticas de cada página.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx or any page.tsx
import { getTranslations } from 'next-intl/server';
import { routing } from '@/i18n/routing';

export async function generateMetadata({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'Metadata' });

  return {
    title: t('title'),
    description: t('description'),
    alternates: {
      languages: Object.fromEntries(
        routing.locales.map((l) => [l, `/${l}`])
      ),
    },
  };
}
Na Vercel, as compilações podem gerar localhost como URL canónico se metadataBase não estiver definido. Defina sempre metadataBase na disposição de raiz com o seu domínio de produção.
8

Tratar páginas de erro e não encontradas

error.tsx e not-found.tsx precisam de tratamento especial porque podem ser apresentados fora da disposição regional normal. O not-found.tsx de raiz precisa da sua própria configuração do fornecedor de i18n para mostrar mensagens de erro localizadas.

app/[locale]/error.tsx
// app/[locale]/error.tsx
'use client';
import { useTranslations } from 'next-intl';

export default function Error() {
  const t = useTranslations('Error');
  return (
    <div>
      <h1>{t('title')}</h1>
      <p>{t('description')}</p>
    </div>
  );
}

// app/not-found.tsx (root level -- needs own provider)
import { routing } from '@/i18n/routing';

export default async function GlobalNotFound() {
  return (
    <html lang={routing.defaultLocale}>
      <body>
        <h1>404 - Page Not Found</h1>
      </body>
    </html>
  );
}
O Next.js só apresenta a sua página 404 localizada quando notFound() é chamado explicitamente no código. As rotas desconhecidas sem página correspondente mostram a página 404 predefinida do Next.js, não a versão localizada.
9

Automatizar as traduções

Depois de concluir a configuração de i18n, traduza os ficheiros de mensagens com IA diretamente no IDE ou utilize a CLI do i18n Agent no pipeline de CI/CD para automatizar a tradução em cada implementação.

Terminal
# In your IDE, ask your AI assistant:
> Translate messages/en.json to German, Japanese, and Spanish

✓ messages/de.json created (1.1s)
✓ messages/ja.json created (1.4s)
✓ messages/es.json created (1.0s)
Utilize next-intl-localechain para recursos regionais inteligentes: um utilizador pt-BR vê traduções pt-PT em vez de recorrer ao inglês quando o português do Brasil não está disponível.

Automatizar a qualidade das traduções

Detete chaves em falta e marcadores danificados antes da publicação com i18n-validate. Teste a interface com traduções simuladas através de i18n-pseudo antes de chegarem as traduções reais.

Ferramentas de código aberto para i18n no Next.js

Estes pacotes de código aberto resolvem problemas frequentes nos fluxos de internacionalização do Next.js.

next-intl-localechain

O next-intl normal recorre diretamente à região predefinida quando falta uma tradução. Um utilizador de português do Brasil vê inglês em vez de traduções pt-PT perfeitamente válidas. next-intl-localechain acrescenta cadeias de recurso inteligentes: combina profundamente traduções de regiões relacionadas para os utilizadores regionais verem sempre a tradução disponível mais próxima.

src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { withLocaleChain } from 'next-intl-localechain';

export default getRequestConfig(withLocaleChain({
  loadMessages: (locale) =>
    import(`../../messages/${locale}.json`).then(m => m.default),
  defaultLocale: 'en'
}));
Combina automaticamente e em profundidade as traduções das cadeias regionais
Cadeias integradas para português, espanhol, francês, alemão e outros idiomas
Ignora devidamente ficheiros de mensagens em falta sem apresentar erros
Configuração numa linha: envolve o seu getRequestConfig existente
Ver no GitHub

@i18n-agent/cli

Uma ferramenta de linha de comandos para traduzir ficheiros de mensagens do Next.js sem sair do terminal. Traduza diretamente os ficheiros, consulte o estado das tarefas e transfira os resultados. Funciona em pipelines de CI/CD com autenticação por chave de API para fluxos de localização totalmente automatizados.

Terminal
# Install the CLI
npm install -g @i18n-agent/cli

# Authenticate
i18nagent login

# Translate your message files
i18nagent translate ./messages/en.json --lang de,ja,es

# Or use in CI/CD with an API key
export I18N_AGENT_API_KEY=your-key-here
i18nagent translate ./messages/en.json --lang de,ja,es
Traduzir JSON, YAML, PO e outros formatos de i18n a partir do terminal
Pronto para CI/CD: autenticação através de uma variável de ambiente para pipelines automatizados
Acompanhar o estado das tarefas, retomar tarefas falhadas e transferir resultados
Resultado JSON legível por máquinas para scripts e automatização
Ver no GitHub

Erros frequentes

«Unable to find next-intl locale»

O middleware não correspondeu ao pedido. Verifique: middleware.ts está na raiz do projeto? O padrão matcher exclui corretamente os ficheiros estáticos? A região está incluída na configuração de encaminhamento?

Apresentação dinâmica inesperada

Falta setRequestLocale(locale) numa página ou disposição. Sem esta chamada, next-intl utiliza cabeçalhos/cookies para detetar a região, o que força a apresentação dinâmica e impede a geração estática.

As rotas paralelas quebram com i18n

As rotas paralelas (@modal) e as rotas intercetadas ((.)photo) têm incompatibilidades conhecidas com o segmento dinâmico [locale]. Utilize encaminhamento baseado em middleware como solução para estes padrões avançados.

A seleção do idioma perde a rota atual

Ao mudar de região, preserve o caminho atual com usePathname() e substitua apenas o segmento regional. Tenha cuidado com os parâmetros de rotas dinâmicas: têm de ser resolvidos novamente para a nova região.

Estrutura de ficheiros recomendada

Project Structure
my-nextjs-app/
├── middleware.ts              # Locale routing (project root!)
├── next.config.mjs
├── messages/
│   ├── en.json                # Source messages
│   ├── de.json
│   └── ja.json
├── src/
│   ├── i18n/
│   │   ├── request.ts         # Message loading config
│   │   └── routing.ts         # Locale definitions
│   └── app/
│       └── [locale]/
│           ├── layout.tsx     # Root locale layout
│           ├── page.tsx       # Home page
│           ├── error.tsx      # Localized error page
│           ├── not-found.tsx  # Localized 404
│           └── about/
│               └── page.tsx
└── package.json

Experimente já o i18n Agent

Largue aqui o seu ficheiro de tradução

JSON, YAML, PO, XML, CSV, Markdown, Properties

ou clique para selecionar

Idiomas de destino

Sem registoEstimativa imediata

Recurso regional com next-intl-localechain

Quando falta uma chave de tradução numa região como pt-BR, next-intl passa diretamente para a região predefinida em vez de verificar primeiro a região principal pt.

Terminal
npm install next-intl-localechain
Configuration
import { withLocaleChain } from 'next-intl-localechain';

export default withLocaleChain({
  fallbacks: {
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  },
  defaultLocale: 'en',
  loadMessages: (locale) => import(`./messages/${locale}.json`),
});

Consulte o nosso guia de recurso regional para ver a lista completa de frameworks compatíveis e as 75 cadeias integradas. Learn more →

Perguntas frequentes