Em 2023 lancei um site de e-commerce multilíngue para um cliente baseado em Berlim. Doze idiomas, App Router, tudo parecia organizado. Três meses depois suas páginas de produtos em alemão estavam classificando nos SERPs do Reino Unido e suas páginas em inglês estavam sendo servidas para usuários em Munique. As tags hreflang estavam tecnicamente presentes. Simplesmente estavam erradas de um jeito que levou uma tarde embaraçosa para eu desvendar. Essa experiência me ensinou mais sobre Next.js i18n do que qualquer página de documentação jamais fez.
Este não é um post "aqui está os documentos oficiais resumidos". É o que aprendi construindo sites multilíngues na Seahawk Media, o que afeta as pessoas repetidamente, e as decisões específicas que realmente impactam rankings em 2026.
---
O App Router Mudou Tudo (E Nem Tudo Para Melhor)
O Pages Router tinha suporte i18n integrado. Você colocava um bloco em next.config.js e Next.js tratava detecção de locale, roteamento sub-path e comutação de locale do componente Link quase automaticamente. Não era perfeito, mas era opinativo, o que significava menos armadilhas.
O App Router removeu completamente o roteamento i18n nativo. Sem chave i18n no next.config.js. Sem detecção automática de locale. Agora você é responsável pela lógica de roteamento completa, e essa responsabilidade é onde a maioria dos times silenciosamente faz uma bagunça.
A abordagem abençoada em 2026 é um segmento dinâmico [locale] na raiz do seu diretório app/. Algo como app/[locale]/page.tsx. Combine isso com next-intl ou i18next via react-i18next, um arquivo middleware que lê headers Accept-Language e redireciona acordamente, e você tem uma base funcionando.
Por Que Middleware É Mal-Entendido
O arquivo middleware está fazendo dois trabalhos separados que as pessoas confundem. Primeiro, detecção de locale: ler o header Accept-Language (ou um cookie, ou um prefixo de URL) e decidir qual locale servir. Segundo, redirecionar ou reescrever a URL para que o usuário acabe em /de/produkte em vez de /produkte com algum estado de locale escondido.
Ambos precisam acontecer antes da página renderizar. Isso soa óbvio. Mas vi times executarem detecção de locale dentro de um provedor de contexto React, o que significa que o HTML inicial servido ao Googlebot não tem sinal de locale algum. O bot vê uma página, a indexa sob a URL raiz, e de repente você tem uma bagunça canônica.
Mantenha a resolução de locale no middleware. Sempre.
---
Sub-path vs Sub-domínio: Escolha Um e Comprometa-se
O debate eterno. /en/about vs en.yoursite.com/about. Para a maioria dos projetos recomendo roteamento por sub-path, e eis por quê: ele concentra sua autoridade de domínio. Todo link apontando para seu .com beneficia todos os locales. Com sub-domínios você está efetivamente rodando sites separados aos olhos do Google, o que significa que você precisa construir autoridade para cada um independentemente.
Há uma exceção. Se você está em um mercado onde a TLD local importa enormemente para confiança (.de na Alemanha, .fr na França), uma TLD de país bate tanto sub-paths quanto sub-domínios para credibilidade local percebida. Isso não é uma afirmação de SEO, é uma afirmação de conversão. Vi testes A/B onde .de vs yourbrand.com/de moveu métricas de confiança significativamente mesmo quando os rankings eram idênticos.
Mas você não consegue executar uma configuração de ccTLD dentro de um único aplicativo Next.js facilmente. Então para 99% dos projetos: sub-paths, um app, um domínio.
---
hreflang: A Tag Que Mente Para Você
É aqui que vejo o maior dano. hreflang não é difícil conceitualmente. Ela diz aos mecanismos de busca: "esta página tem equivalentes em outros idiomas, aqui estão." Na prática, a implementação tem três modos de falha específicos que continuo encontrando.
Modo de Falha 1: As Tags Não São Recíprocas
Toda página em seu conjunto hreflang deve fazer referência a todas as outras páginas, incluindo a si mesma. Se /en/about tem um hreflang apontando para /de/about mas /de/about não tem um hreflang apontando de volta para /en/about, Google ignora o conjunto inteiro. Não penaliza. Ignora. Como se as tags não existissem.
Seahawk teve um projeto fintech no ano passado onde 40% de suas tags hreflang eram não-recíprocas porque dois desenvolvedores as implementaram independentemente em componentes diferentes sem coordenar. A correção levou uma hora. A recuperação de rankings levou dois meses.
Modo de Falha 2: A Tag x-default Está Faltando ou Mal Posicionada
x-default é para páginas que não direcionam um idioma ou região específicos. Tipicamente sua raiz / ou uma página de seletor de idioma. Alguns times colocam x-default em sua página em inglês, o que é aceitável se inglês é genuinamente seu fallback para todos os locales não correspondidos. Mas se você serve uma página diferente para usuários cujo idioma você não suporta, x-default deve apontar para lá.
Já vi x-default omitido inteiramente. Google não lança um erro. Simplesmente toma sua própria decisão sobre qual versão mostrar para consultas não correspondidas, e essa decisão muitas vezes é errada.
Modo de Falha 3: Barras Finais e Conflitos de Canonical
Sua tag hreflang diz https://yoursite.com/de/ueber-uns . Sua tag canonical na mesma página diz https://yoursite.com/de/ueber-uns/ (note a barra final). Google trata essas como URLs diferentes. Seu canonical e hreflang agora estão apontando para coisas diferentes, e você criou um conflito de sinal que suprime silenciosamente rankings sem nenhum erro visível no Search Console.
Configure trailingSlash em next.config.js e seja consistente em todos os lugares. Verifique. Realmente verifique fazendo curl nas suas próprias URLs e lendo o output.
A documentação do Google Search Central sobre hreflang realmente vale a pena ler na íntegra. É um daqueles raros documentos oficiais que é específico o bastante para ser útil.
---
Gerando hreflang em Escala no Next.js
Para um site com 5 idiomas você consegue escrever tags hreflang à mão. Para 12 locais em 3.000 páginas de produtos, você precisa de uma abordagem sistemática.
Aqui está o que eu uso:
- Defina sua lista de locais uma única vez, em um único arquivo de config. Algo como locales.config.ts exportando um array: ['en', 'de', 'fr', 'es', 'nl'...].
- Construa uma função utilitária getHreflangAlternates(pathname: string) que toma um caminho agnóstico de locale (/about ) e retorna um array de objetos { hreflang, href } para cada locale.
- Chame essa função no seu root layout.tsx e injete os resultados via a API metadata do Next.js usando o campo alternates.languages. Isso foi adicionado no Next.js 13.3 e gera automaticamente as tags <link rel="alternate" hreflang="..."> corretas no <head>.
- Para páginas com conteúdo dinâmico (posts de blog, páginas de produtos) onde nem toda locale tem tradução, passe um array supportedLocales para seu utilitário e gere tags apenas para locales onde o conteúdo realmente existe. Uma tag hreflang apontando para uma página que retorna 404 é pior do que nenhuma tag hreflang.
A abordagem alternates.languages na API metadata é a forma mais limpa que encontrei para lidar com isso. Sem malabarismo com <Head> customizado, sem pacotes de terceiros para as tags em si.
---
Detecção de Locale Sem Ser Chato
Há uma armadilha de UX aqui que também tem implicações de SEO. Redirecionamento automático agressivo baseado na locale do navegador é ruim para ambos.
Se um usuário na Alemanha visita yoursite.com/en/article e seu middleware faz um hard-redirect para /de/artikel sem perguntar, você quebrou a navegação pretendida dele. Você também potencialmente quebrou o compartilhamento de links: alguém compartilha a URL em inglês, o destinatário na França é redirecionado para francês, e o conteúdo que deveria ser visto pode não existir em francês ainda.
Minha regra: detecte, sugira, não force. Use o header Accept-Language para definir um padrão sensato na primeira visita (armazenado em um cookie), mas deixe usuários o sobrescreverem manualmente e respeite esse override em toda visita subsequente. O cookie tem prioridade sobre o header.
Para SEO especificamente: Googlebot não envia headers Accept-Language significativos. Ele fará crawl das suas URLs como estão. Então certifique-se de que toda URL de locale é diretamente acessível sem redirecionamento, e que seu sitemap inclui explicitamente todas as variantes de locale.
A documentação do next-intl middleware cobre bem essa estratégia de detecção, e é para onde eu encaminharia qualquer um começando um novo projeto.
---
Sitemaps para Sites Multilíngues
Um único sitemap.xml que inclui todas as variantes de localidade funciona bem para sites menores. Para sites grandes (dezenas de milhares de URLs em múltiplas localidades) eu divido: um índice de sitemap em /sitemap.xml, depois arquivos de sitemap separados por localidade em /sitemaps/en.xml, /sitemaps/de.xml, e assim por diante.
Cada entrada de URL deve incluir tags <xhtml:link rel="alternate"> que espelhem sua configuração de hreflang. Isso é redundante com as tags na página, mas ajuda o Googlebot a conectar os pontos em páginas que ele ainda não rastreou.
No Next.js 14+ você pode gerar sitemaps dinamicamente via app/sitemap.ts. O tipo de retorno suporta alternates.languages no mesmo formato da API de metadata. Conecte-a ao mesmo utilitário getHreflangAlternates que você construiu antes e você consegue consistência de graça.
Um número concreto: em um projeto com 8 localidades e 4.500 produtos, dividir sitemaps reduziu o tempo médio de rastreamento por localidade em aproximadamente 30% com base nas estatísticas de rastreamento do GSC. Não é sensacional, mas é significativo.
---
Bibliotecas de Tradução: O Que Realmente Uso
Há três que vale a pena conhecer. next-intl é minha padrão para projetos com App Router. Tem suporte de primeira classe para server components, lida com pluralização corretamente, e a API é limpa. Usei em cerca de 40 projetos desde meados de 2023.
react-i18next é testado em batalha e tem um ecossistema enorme, mas seu modelo mental foi construído para client components e adicionar suporte a server components via o núcleo do i18next parece remendado comparado à abordagem nativa do next-intl.
Lingui vale a pena se seu fluxo de tradução envolve tradutores profissionais em vez de um CMS. Suas ferramentas de extração são superiores. Mas para a maioria dos projetos de agência onde o conteúdo vem do Contentful ou Sanity, next-intl é mais simples.
O que eu evitaria: rolar a sua própria solução. Fiz isso uma vez em 2020 para um projeto onde o cliente insistiu que seus arquivos de tradução PHP existentes fossem reutilizados diretamente. Funcionou, mal e bem, e passei dois anos mantendo algo que next-intl agora resolve com uma única chamada useTranslations().
---
FAQ
O Next.js App Router suporta o antigo bloco `next.config.js` i18n?
Não. A chave de configuração i18n era específica do Pages Router. Se você está migrando para App Router, precisa implementar roteamento via um segmento dinâmico [locale] e um arquivo middleware. O bloco config antigo é silenciosamente ignorado em projetos App Router.
Devo usar `lang` no caminho da URL ou confiar em subdomínios?
Para a maioria dos projetos, lang no caminho da URL (sub-path routing como /de/) é a decisão certa. Subdomínios fragmentam sua autoridade de domínio e exigem configuração DNS separada. ccTLDs valem a complexidade apenas se sinais de confiança local estão genuinamente movimentando as taxas de conversão em seus mercados específicos.
Como o Googlebot lida com conteúdo de locale renderizado por JavaScript?
Mal, às vezes. Se sua detecção de locale é executada puramente no lado do cliente em um contexto React e o HTML inicial não tem marcador de locale, o Googlebot pode indexar o estado pré-hidratação. Sempre resolva locale no middleware e garanta que o atributo lang correto esteja no elemento <html> no HTML renderizado pelo servidor. Verifique isso visualizando o código-fonte, não usando devtools do navegador (que mostram o estado pós-hidratação).
Qual é o valor correto de `x-default` hreflang para um site sem página de seletor de idioma?
Aponte para a homepage da sua localidade primária, normalmente /en/. Isso sinaliza ao Google que inglês é seu fallback para usuários cujo idioma você não suporta. Não é uma penalidade fazer isso, é apenas um sinal de preferência leve que Google pode ou não honrar.
Posso verificar minha implementação de hreflang sem uma ferramenta SEO paga?
Sim. A ferramenta de Inspeção de URL do Google Search Console mostrará as tags hreflang detectadas para qualquer URL indexada. Não valida reciprocidade automaticamente, mas você pode verificar manualmente algumas páginas representativas. Para validação em massa, Screaming Frog (gratuito até 500 URLs) executa verificações de reciprocidade na sua aba de hreflang.
---
Acertar multilíngue em Next.js é genuinamente um trabalho pouco glamouroso. É arquivos de configuração, consistência de URL e garantir que dois desenvolvedores não tenham implementado a mesma coisa duas vezes em componentes diferentes. Mas os sites onde dediquei tempo para fazer direito têm rankings que se sustentam entre regiões, e os onde cortei caminho me ensinaram as lições que escrevi aqui.
O cliente de Berlin, aliás, eventualmente conseguiu suas páginas em alemão rankando na Alemanha. Levou uma recrawl completa e muito café.
