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
routingcentral. - Uma locale desconhecida dispara um
notFound()limpo em vez de uma página quebrada. - A navegação passa por um
Linklocalizado 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
generateAlternatesque produz as tagsalternate. - 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. setRequestLocaleantes das traduções: inegociável para manter o estático.- Os
hreflangsã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.