Ir para o conteúdo principal

Um site Next.js realmente multilíngue com next-intl

Routing localizado, renderização estática, hreflang e troca de idioma: como estruturo um site Next.js em dez idiomas sem sacrificar o desempenho nem o SEO.

Por que o multilíngue é um verdadeiro tema de arquitetura

Traduzir uma interface é fácil. Fazer um site multilíngue correto — indexável, rápido, manutenível — é uma decisão de arquitetura que se toma no início, não no fim. Este portfólio existe em dez idiomas, e eis as escolhas que se sustentam em escala.

O routing por segmento de locale

A abordagem mais robusta com o App Router: um segmento dinâmico [locale] na raiz. Cada página vive sob app/[locale]/…, e o idioma se torna um dado de URL de primeira ordem (/fr/projects, /en/projects).

Com o next-intl, esse segmento é validado na renderização:

  • As locales suportadas são listadas numa configuração routing central.
  • Uma locale desconhecida dispara um notFound() limpo em vez de uma página quebrada.
  • A navegação passa por um Link localizado que prefixa automaticamente o idioma certo.

A vantagem: os componentes nunca manipulam a locale «na mão». Pedem uma tradução e o sistema cuida do resto.

A armadilha da renderização estática

É o erro que mais custa em produção. Se você chama as traduções sem fixar a locale primeiro, o next-intl lê os cabeçalhos da requisição. Resultado: a página passa para renderização dinâmica e você perde o prerender estático — às vezes com um erro DYNAMIC_SERVER_USAGE em produção.

A solução cabe numa linha, logo no topo de cada página:

setRequestLocale(locale);

Chamada antes de qualquer getTranslations, ela garante uma renderização totalmente estática. Combinada com um generateStaticParams que cruza locale × slug, ela prerenderiza cada página em cada idioma no build.

O multilíngue estático não é mais lento que o monolíngue. É apenas mais exigente quanto à ordem das chamadas.

Os hreflang, ou como evitar competir consigo mesmo

Sem nenhuma indicação, o Google trata suas dez versões linguísticas como dez páginas rivais nas mesmas palavras-chave. A solução é o hreflang: cada página declara o conjunto de suas variantes.

Dois lugares precisam permanecer sincronizados:

  • Os metadados de cada página — via um helper generateAlternates que produz as tags alternate.
  • O sitemap — cada URL lista ali seus idiomas e um x-default.

A coerência entre essas duas fontes é o que faz uma busca em espanhol cair em /es e não em /fr.

A troca de idioma, do lado do usuário

Um seletor de idioma deve trocar a locale sem perder a página atual. O reflexo ingênuo — mandar de volta à home — é frustrante. Com o usePathname localizado do next-intl, você recupera o caminho sem prefixo e o reemite no idioma escolhido. O usuário permanece exatamente onde estava.

O que eu levo comigo

  • O segmento [locale] na raiz é a fundação; tudo decorre dela.
  • setRequestLocale antes das traduções: inegociável para manter o estático.
  • Os hreflang são geridos em dobro (metadados e sitemap), sempre sincronizados.
  • A direção do texto (RTL para o árabe) é controlada no nível do <html dir>, não página por página.

Bem feito, o multilíngue se torna invisível: cada visitante tem a impressão de que o site foi escrito para ele, e o Google sabe exatamente qual porta lhe abrir.

AGENTS.md e os agentes de código: o novo ferramental do desenvolvedor