Tradução de sites

Internacionalização do Next.js para o App Router e o Pages Router

Internacionalização do Next.js para o App Router e o Pages Router
Rayne Aguilar
Escrito por
Rayne Aguilar
Elizabeth Pokorny
Revisado por
Elizabeth Pokorny
Atualizado em
12 de junho de 2026

O Next.js possui duas páginas oficiais de documentação sobre internacionalização (i18n) que descrevem sistemas completamente diferentes, sem qualquer referência cruzada entre elas.

Um trata do Pages Router. O outro trata do App Router. Nenhum dos dois explica como os dois se relacionam, quais bibliotecas usar ou como lidar com o hreflang para SEO multilíngue.

Vamos conectar os dois roteadores. Abordaremos estratégias de roteamento, seleção de bibliotecas, configuração de middleware, traduções de componentes do servidor e SEO multilíngue.

Nosso objetivo é criar um recurso útil para desenvolvedores que foram solicitados a adicionar suporte a idiomas a uma aplicação Next.js e precisam ter uma visão clara antes de se comprometerem com uma abordagem. Vamos começar!

O que o Next.js oferece para a internacionalização

A internacionalização possui três camadas:

  • Roteamento, que atribui a cada localidade sua própria URL.
  • Tradução, que carrega as strings corretas.
  • Formatação de datas, números e moedas.

O Next.js apenas auxilia no roteamento.

O Pages Router possui roteamento i18n integrado desde a versão 10.0.0. Um bloco de configuração com três campos no arquivo next.config.js lida automaticamente com a detecção de localidade, a adição de prefixos às URLs e os redirecionamentos.

O App Router é diferente. Sua página de documentação sobre internacionalização (i18n) descreve um padrão que você mesmo monta usando middleware, um [local] segmento dinâmico e uma biblioteca.

No que diz respeito a traduções e formatação, você terá que se virar sozinho, independentemente do roteador que usar. A documentação do App Router lista todas as bibliotecas compatíveis, mas não oferece orientações sobre qual escolher. Nenhuma das páginas de documentação aborda as tags hreflang ou os mapas de site multilíngues.

Como a internacionalização difere entre o roteador de páginas e o roteador de aplicativos

A abordagem do Pages Router consiste em uma alteração na configuração. Adicione um bloco i18n ao arquivo next.config.js com três campos:

// next.config.js
module.exports = {  
  i18n: {    
    locales: ['en', 'fr', 'de'],    
    defaultLocale: 'en',  
  },
}

É isso aí.

O Next.js detecta automaticamente a localização a partir do Accept-Language cabeçalho, respeita um PRÓXIMA_LOCALIZAÇÃO substitui o cookie e expõe a localidade ativa por meio de useRouter().locale. Você não precisa de nenhum middleware nem de reestruturar diretórios.

O App Router não possui uma configuração equivalente. Você mesmo define o roteamento a partir de três elementos:

  • proxy.ts, anteriormente chamado de middleware.ts, lida com a detecção de localidade e redirecionamentos. Ele utiliza @formatjs/intl-localematcher e negociador para analisar Accept-Language cabeçalhos. A documentação oficial deixa a lógica de detecção propriamente dita em aberto: função getLocale(request) { ... }. Vamos abordar isso na próxima seção.
  • [local] O segmento dinâmico envolve todo o seu app/ diretório. Cada rota passa a ser sensível à localidade por meio da estrutura de pastas.
  • gerarParâmetrosEstáticos pré-gerencia cada variante de localização durante a compilação.

Das três funções, a `generateStaticParams` é a que substitui o que o Pages Router fazia automaticamente durante a compilação.

export function generateStaticParams() {  
	return [{ locale: 'en' }, { locale: 'fr' }, { locale: 'de' }]
}

🚨 A internacionalização (i18n) integrada do Pages Router não funciona com saída: 'exportar'. Se você precisar de uma exportação totalmente estática, será necessário utilizar o roteamento manual baseado em pastas. Essa limitação se aplica apenas à configuração integrada. Ambos os roteadores suportam exportações estáticas com uma configuração manual.

Roteamento de subcaminhos, roteamento de domínios e internacionalização sem alterações na URL

Antes de escolher uma biblioteca, defina uma estratégia de roteamento. Isso afeta o SEO, a configuração do DNS e a quantidade de middleware que você precisará desenvolver:

  • O roteamento por subcaminhos inclui a localização no caminho da URL, como /fr/produtos ou /de/produtos. Essa é a configuração padrão para sites voltados ao público em geral. Os mecanismos de busca indexam cada localização como uma página distinta, o que é ideal para o SEO multilíngue.
  • O roteamento de domínios mapeia regiões para domínios ou subdomínios distintos, como example.fr ou de.example.com. Ele transmite sinais de segmentação geográfica mais fortes por meio dos ccTLDs, mas exige configuração de DNS e complica o desenvolvimento local.
  • Sem roteamento mantém todas as configurações regionais na mesma URL e determina a configuração regional a partir de um cookie ou da preferência do usuário armazenada em um perfil. Os mecanismos de busca veem uma única URL e não conseguem indexar as variantes regionais separadamente. Esse é um padrão válido para aplicativos SaaS autenticados e ferramentas internas nas quais o SEO não é um requisito. próximo-intl apoia essa opção como uma das melhores.

Para sites públicos em que o SEO é fundamental, o roteamento por subcaminho é a configuração padrão recomendada. O roteamento por domínio só justifica a complexidade se houver uma necessidade específica de sinais fortes de segmentação geográfica.

Se você preferir não gerenciar a estrutura de URLs manualmente, o proxy reversoWeglot lida automaticamente com o roteamento de subdiretórios e subdomínios, incluindo a inserção de hreflang e URLs traduzidos.

next-intl vs. react-i18next vs. Lingui

Como mencionamos anteriormente, a documentação oficial lista bibliotecas sem recomendar nenhuma em particular. Veja a seguir uma comparação entre as principais opções:

Recurso próximo-intl react-i18next Lingui
Suporte RSC Nativo Por meio da inicialização assíncrona Por meio de macros
SEO/hreflang Manual via API de metadados Manual via API de metadados Manual via API de metadados
Roteamento Integrado Por meio do next-i18n-router Manual
TypeScript Tipagem estrita Por meio de plugins Por extração
Formatação Envolve as APIs da Intl por meio do useFormatter Participantes do FormatJS Manual

O next-intl é o padrão de fato para o App Router. O suporte ao RSC vem integrado, o roteamento está incorporado e o autocompletar do TypeScript funciona sem necessidade de configuração adicional.

O react-i18next é a melhor opção se você estiver usando o Pages Router ou já estiver utilizando o i18next em outra parte da sua pilha de tecnologia. O suporte ao App Router funciona, mas requer mais configuração manual.

O Lingui é ideal para equipes que já utilizam fluxos de trabalho com arquivos .po. As traduções são extraídas durante a compilação, de modo que as mensagens não utilizadas nunca são enviadas.

💡 O Paraglide JS não está exatamente entre os principais players, mas vale a pena mencioná-lo como uma alternativa baseada em compilador que gera pacotes mais compactos. Se você estiver interessado, porém, precisará levar em conta que seu ecossistema é mais recente do que o dos demais.

Para a formatação de datas e números, o next-intl utiliza as APIs Intl nativas por meio do useFormatter. As demais bibliotecas delegam essa tarefa ao FormatJS ou deixam a seu critério a chamada direta das funções Intl.DateTimeFormat e Intl.NumberFormat.

💡 Essas bibliotecas cuidam da renderização. Ainda é preciso que alguém produza as traduções e as mantenha sincronizadas à medida que o conteúdo muda. Weglot em uma camada totalmente diferente, gerenciando o conteúdo traduzido por meio de um proxy reverso fora da base de código. Não pense nisso como um substituto para as bibliotecas.

Configuração de middleware, detecção de localidade e traduções de componentes do servidor

O Next.js 16 renomeou o arquivo ` middleware.ts` para `proxy.ts`. Isso foi feito porque o termo “middleware” era ambíguo e sugeria uma lógica genérica dentro do aplicativo. Na verdade, o arquivo é executado na camada de rede, interceptando e modificando solicitações como um proxy antes que elas cheguem ao aplicativo.

Aqui está uma implementação completa de detecção de localidade e redirecionamento que preenche a lacuna mencionada na documentação oficial:

// proxy.ts
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import { NextRequest, NextResponse } from 'next/server'

const locales = ['en', 'fr', 'de']
const defaultLocale = 'en'

function getLocale(request: NextRequest): string {
  const cookie = request.cookies.get('NEXT_LOCALE')?.value
  if (cookie && locales.includes(cookie)) return cookie

  const headers = { 'accept-language': request.headers.get('accept-language') ?? '' }
  const languages = new Negotiator({ headers }).languages()
  return match(languages, locales, defaultLocale)
}

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl
  const hasLocale = locales.some(l => pathname.startsWith(`/${l}/`) || pathname === `/${l}`)
  if (hasLocale) return

  const locale = getLocale(request)
  request.nextUrl.pathname = `/${locale}${pathname}`
  return NextResponse.redirect(request.nextUrl)
}

Os arquivos estão aninhados sob app/[idioma]/, com um dicionários/ pasta ao lado dos seus layouts e páginas. O layout raiz recebe configuração regional como parâmetro e o define no html tag:

export default async function RootLayout({ children, params }) {
  const { locale } = await params

  return (
    <html lang={locale}>
      <body>{children}</body>
    </html>
  )
}

Para traduções, a documentação oficial apresenta um modelo de dicionário simples que não requer nenhuma biblioteca:

const dictionaries = {
  en: () => import('./dictionaries/en.json').then(m => m.default),
  fr: () => import('./dictionaries/fr.json').then(m => m.default),
}

export const getDictionary = async (locale: string) => dictionaries[locale]()

Isso funciona, mas não oferece suporte à pluralização nem à interpolação. próximo-intl abrange ambos por meio de getTranslations() e useTranslations() em Componentes do servidor e componentes do cliente respectivamente.

De qualquer forma, os arquivos de tradução são processados no servidor e apenas o HTML resultante chega ao navegador; portanto, o tamanho do arquivo de mensagem não afeta o tamanho do pacote do cliente.

Para componentes de cliente, passe as strings traduzidas como propriedades a partir de um componente de servidor pai, sempre que possível. Use PróximoProvedorDeClientesInternacionais com um subconjunto de mensagens delimitado apenas quando um componente cliente precisa lidar diretamente com as traduções.

No caso de um seletor de idioma, um Componente de Servidor exibe os rótulos de localização, enquanto um Componente de Cliente lida com a useRouter() chamada:

// LocaleSwitcher.tsx (Server Component)
import LocaleSwitcherClient from './LocaleSwitcherClient'

export default function LocaleSwitcher({ locale }) {
  return <LocaleSwitcherClient locale={locale} labels={{ en: 'English', fr: 'Français' }} />
}

O cliente fica atento a alterações na seleção e envia a nova rota de localidade:

// LocaleSwitcherClient.tsx
'use client'
import { useRouter } from 'next/navigation'

export default function LocaleSwitcherClient({ locale, labels }) {
  const router = useRouter()
  return (
    <select value={locale} onChange={e => router.push(`/${e.target.value}`)}>
      {Object.entries(labels).map(([value, label]) => (
        <option key={value} value={value}>{label}</option>
      ))}
    </select>
  )
}

Se você estiver usando Weglot, nada disso se aplica. Weglot um widget de seleção de idioma integrado e não requer configuração de proxy nem middleware.

SEO multilíngue com hreflang, mapas de site e metadados

Nenhum dos dois roteadores lida com SEO multilíngue automaticamente:

  • O roteador de páginas define html lang corretamente, mas a documentação diz que a implementação do hreflang fica “a seu critério”.
  • O App Router não faz nenhuma menção ao hreflang.

Com o App Router, a API de metadados é o que mais se aproxima da automação. Defina URLs de localidade em gerar metadados através do idiomas alternativos objeto e o Next.js injeta automaticamente link rel="alternate" hreflang="..." tags:

export async function generateMetadata({ params: { locale } }) {
  return {
    alternates: {
      languages: {
        'en': 'https://example.com/en',
        'fr': 'https://example.com/fr',
        'de': 'https://example.com/de',
      },
    },
  }
}

A parte manual consiste em reunir a URL correta para cada variante de localização em cada página. Cabe a você implementar essa lógica.

Há outras duas coisas que exigem implementação manual, independentemente do roteador que você use. As URLs canônicas precisam ser definidas por localidade para evitar sinais de conteúdo duplicado. Seu sitemap.ts necessidades xhtml:link entradas para cada variante de localização de cada página.

No hreflang o próprio valor, usar hreflang="en-US" ao direcionar para uma região específica, e hreflang="en" ao direcionar o conteúdo para todos os falantes de inglês. Confundir esses dois aspectos envia sinais contraditórios aos mecanismos de busca.

próximo-intl adiciona uma automação parcial: seu proxy insere automaticamente o atributo hreflang Link cabeçalhos de resposta ao usar o roteamento por nomes de caminho localizados. Outras configurações de roteamento ainda exigem implementação manual.

Isso representa uma quantidade significativa de manutenção contínua à medida que seu site cresce. Felizmente, o proxy reverso Weglot cuida de tudo automaticamente no servidor, de modo que as páginas traduzidas são totalmente indexáveis sem a necessidade de código adicional.

A abordagem Weglot para o SEO multilíngue

Na verdade, o proxy reverso Weglot lida automaticamente com tudo o que foi abordado na seção anterior: tags hreflang, URLs traduzidas, tags canônicas e geração de mapas do site. As páginas traduzidas são geradas no servidor, portanto, são totalmente indexáveis pelos mecanismos de busca.

⚠️ snippet de JavaScript Weglot não oferece benefícios de SEO. A tradução do lado do cliente não é rastreável. Se o SEO for importante, é necessário configurar um proxy reverso.

Outra vantagem é o tempo de compilação. Weglot as páginas traduzidas a partir de sua própria CDN, em vez de gerá-las durante a compilação. Adicionar 10 idiomas a um site Weglot não afeta o tempo de próxima versão demora.

Escolhendo a abordagem certa para o seu projeto Next.js

A escolha certa depende do objetivo da otimização.

Se você estiver desenvolvendo com o App Router e começando do zero, próximo-intl é a opção padrão. Ele abrange roteamento, traduções, autocompletar do TypeScript e suporte a RSC em um único pacote.

Se você estiver usando o Pages Router ou já tiver o i18next em sua pilha de tecnologias, react-i18next é o caminho de menor resistência.

Se o SEO multilíngue e a gestão contínua das traduções são a prioridade, nenhuma dessas bibliotecas resolve o problema por completo. Você ainda precisará implementar hreflang, mapas do site e um fluxo de trabalho para manter as traduções atualizadas à medida que o conteúdo muda. O proxy reverso Weglot cuida de tudo isso automaticamente.

Weglot uma biblioteca no nível dos componentes não são mutuamente exclusivos. Weglot na camada de HTML e de proxy, portanto, pode coexistir com qualquer biblioteca que seus componentes utilizem.

Se essa abordagem se adequar à sua situação, consulte a página de integração com JavaScript Weglot como ponto de partida e experimente nossa versão de avaliação gratuita de 14 dias!

ícone de direção
Descubra a Weglot

Coisas boas vêm para aqueles que esperam. O tráfego internacional não.

Colocaremos seus primeiros idiomas em funcionamento. Você decide até onde deseja ir. Experimente Weglot hoje mesmo.

Neste artigo, vamos explorar:
Ícone do foguete

Pronto para começar?

A melhor maneira de compreender o poder do Weglot experimentá-lo você mesmo. Teste-o gratuitamente e sem qualquer compromisso.

Um site de demonstração está disponível no seu painel de controle, caso ainda não esteja pronto para conectar o seu site.

Leia artigos que você também pode gostar

Ícone de Perguntas Frequentes

Perguntas comuns

Nenhum item encontrado.

Seta azul

Seta azul

Seta azul