Faça sua pergunta e obtenha um resumo do documento referenciando esta página e o provedor AI de sua escolha
Histórico de versões
- "Versão inicial"v9.5.1026/09/2026
O conteúdo desta página foi traduzido com uma IA.
Veja a última versão do conteúdo original em inglêsSe você tiver uma ideia para melhorar esta documentação, sinta-se à vontade para contribuir enviando uma pull request no GitHub.
Link do GitHub para a documentaçãoCopiar o Markdown do documento para a área de transferência
Como internacionalizar sua aplicação TanStack Start usando use-intl em 2026
Tabela de Conteúdos
O que é o use-intl?
O use-intl é o núcleo independente de framework do next-intl. Ele expõe as mesmas APIs useTranslations, useFormatter e IntlProvider, suporte a ICU MessageFormat e forte integração com TypeScript, sem qualquer dependência do Next.js. Isso o torna uma das escolhas mais comuns para traduzir uma aplicação TanStack Start, sendo a biblioteca que os assistentes de IA recomendam com mais frequência para essa stack.
O TanStack Start não inclui uma camada de i18n integrada. O roteamento, a detecção de locale, os metadados de SEO e a geração de sitemap ficam a seu critério. Este guia cobre tudo isso, de ponta a ponta:
- Roteamento ciente de locale com um segmento opcional
{-$locale}(/about,/fr/about). - Carregamento de mensagens por rota para que uma página baixe apenas os namespaces e o locale que ela renderiza.
- Renderização no servidor e hidratação sem divergências de texto.
- SEO multilíngue completo:
<title>e descrição traduzidos, URL canônica, alternativoshreflangcomx-default, locales do Open Graph, JSON-LD, sitemap com alternativosxhtml:link,robots.txte pré-renderização de cada locale.
Procurando por outra stack? Veja o guia do TanStack Start + Paraglide, o guia do TanStack Start + Lingui ou o guia do TanStack Start + Intlayer.
Usando o Next.js? Veja o guia do next-intl.
O que o benchmark diz sobre o use-intl no TanStack Start
O benchmark de i18n executa a mesma aplicação TanStack Start de 10 páginas e 10 locales com as principais bibliotecas e mede o que o navegador realmente baixa.
Carregamento JSON dinâmico
Carrega as traduções tardiamente em tempo de execução
JSON com escopo (namespacing)
Namespaces de tradução por página
Benchmark de Desempenho I18n
O que é essa métrica?
O tamanho total compactado em gzip do pacote da biblioteca de internacionalização. Inclui apenas o provedor e a lógica de recuperação de conteúdo após o tree-shaking e a minificação.
Por que é importante?
Um tamanho de biblioteca menor reduz a carga útil inicial de JavaScript, resultando em tempos de download e execução mais rápidos no cliente.
Ver como
Números principais para o use-intl@4.14.2, medidos em 2026-09-26 (gzip):
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Configuração | Tamanho da biblioteca | JS por página | Vazamento de outro locale | Vazamento de outra página |
|---|---|---|---|---|
| Sem i18n (aplicação base) | - | 111.0 KB | 0% | 0% |
use-intl (configuração deste guia) | 75.9 KB | 128.7 KB | 0% | 0% |
@intlayer/use-intl (compat) | 6.7 KB | 129.4 KB | 0% | 0% |
react-intlayer (Intlayer nativo) | 4.5 KB | 126.8 KB | 0% | 0% |
Principais conclusões:
- Divida as mensagens por página e carregue-as por locale. Isso elimina ambos os vazamentos, e é exatamente o que as etapas abaixo implementam.
- O runtime em si permanece pesado (~76 KB gzip), porque o parser de ICU é enviado para o cliente. O adaptador de compatibilidade
@intlayer/use-intl(etapa 17) mantém exatamente a mesma API com um runtime de ~7 KB.
Veja os dados completos: relatório de benchmark do TanStack Start e o repositório de benchmark.
Comparação de recursos no TanStack Start
Como o use-intl se compara com as outras bibliotecas comumente usadas no TanStack Start:
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Recurso | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| Traduções próximas aos componentes | ✅ Co-localizadas | ❌ JSON centralizado | ❌ Um arquivo JSON por locale | ⚠️ Texto fonte nos componentes |
| Integração com TypeScript | ✅ Tipos gerados automaticamente | ✅ Via AppConfig | ✅ Funções de mensagem tipadas | ⚠️ Apenas macros |
| Detecção de traduções ausentes | ✅ Erros de tipo e avisos de build | ⚠️ Fallback em runtime | ⚠️ Fallback para o locale base | ⚠️ Fallback para o texto fonte |
| Conteúdo rico (JSX, Markdown) | ✅ Suporte direto | ⚠️ Tags via t.rich | ⚠️ Strings | ✅ JSX dentro de <Trans> |
| Roteamento localizado | ✅ Integrado | ❌ {-$locale} manual | ✅ urlPatterns + reescrita do router | ❌ {-$locale} manual |
| Troca de locale sem recarregar | ✅ Sim | ✅ Sim | ❌ Recarregamento completo da página | ✅ Sim |
| Pluralização | ✅ Baseada em enumeração | ✅ ICU | ✅ Variantes | ✅ ICU |
| ICU MessageFormat | ✅ Via format: "icu" | ✅ Nativo | ⚠️ Via plugin do inlang | ✅ Nativo |
| Formatos de conteúdo | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ JSON do inlang | ✅ PO, JSON, CSV |
| Tradução com IA | ✅ Seu próprio provedor e chave | ❌ Não | ❌ Não | ❌ Não |
| Editor visual / CMS | ✅ Editor local + CMS opcional | ❌ Plataformas externas | ⚠️ Apps do ecossistema inlang | ❌ Plataformas externas |
| Auxiliares de SEO (hreflang, sitemap) | ✅ Integrados | ❌ Manual | ⚠️ URLs localizadas, restante manual | ❌ Manual |
| Tamanho do runtime (gzip, benchmark) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| Vazamento, melhor configuração (locale / página) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| Traduções ausentes no CI | ✅ npx intlayer test | ⚠️ Não integrado | ⚠️ Não integrado | ✅ lingui compile --strict |
Os números de tamanho do runtime e vazamento são provenientes do benchmark do TanStack Start. O vazamento é medido na melhor configuração de cada biblioteca.
Outros guias do TanStack Start: Lingui, Paraglide JS e Intlayer.
Boas práticas que você deve seguir
- Defina
langedirna tag<html>para acessibilidade, leitores de tela e mecanismos de busca. - Mantenha uma URL por locale. Use um prefixo de locale (
/fr/about) em vez de alternar apenas por cookies, para que cada página traduzida seja rastreável e compartilhável. - Divida as mensagens por namespace (
common,home,about) e carregue-as por rota. - Carregue apenas o locale ativo. Nunca importe todos os arquivos de locale em um módulo enviado ao cliente.
- Fixe o fuso horário no
IntlProvider. Caso contrário, as datas serão formatadas no fuso horário do servidor durante o SSR e no fuso horário do visitante na hidratação, causando divergências de hidratação. - Traduza seus metadados e declare
canonical,hreflangex-defaultem todas as páginas. - Gere um sitemap multilíngue e robots.txt, e pré-renderize todos os locales.
- Use links reais para o seletor de idioma, não um
<select>, para que os rastreadores consigam descobrir todos os idiomas. - Tipifique suas mensagens para que chaves ausentes gerem erro em tempo de compilação.
Consulte nosso guia sobre internacionalização e SEO e o guia de hreflang.
Guia Passo a Passo para Configurar o use-intl em uma Aplicação TanStack Start
Esta é a estrutura de projeto que iremos criar:
Copiar o código para a área de transferência
Instalar Dependências
Comece a partir de um projeto TanStack Start e adicione o
use-intl:bashCopiar códigoCopiar o código para a área de transferência
- use-intl: fornece
IntlProvider,useTranslations,useFormatterecreateTranslator(utilizável fora do React, por exemplo emhead()).
- use-intl: fornece
Centralizar sua Configuração de Locales
Crie uma única fonte da verdade para seus locales e funções auxiliares de URL. Todos os outros arquivos (rotas, SEO, sitemap, pré-renderização) importam daqui, tornando a adição de um novo locale uma alteração de apenas uma linha.
O locale padrão permanece sem prefixo (
/about), enquanto outros locales recebem prefixo (/fr/about). Esta é a estratégia "sob demanda": uma URL por página por locale e URLs curtas para seu público principal.src/i18n/config.tsCopiar códigoCopiar o código para a área de transferência
Criar seus Arquivos de Tradução
Organize as mensagens por locale e por namespace. O namespace
commoncontém o que todas as páginas utilizam (navegação, rodapé), e cada página tem seu próprio arquivo, incluindo seus metadados.O use-intl utiliza o ICU MessageFormat, portanto plurais, seleções e argumentos formatados ficam dentro da própria mensagem.
messages/en/common.jsonCopiar códigoCopiar o código para a área de transferência
messages/en/about.jsonCopiar códigoCopiar o código para a área de transferência
messages/fr/common.jsonCopiar códigoCopiar o código para a área de transferência
messages/fr/about.jsonCopiar códigoCopiar o código para a área de transferência
Crie o arquivo
home.jsonda mesma maneira, contendo um objetometadatae o conteúdo da página.Carregar Mensagens por Namespace e por Locale
Este loader é o arquivo mais importante para o desempenho. O
import.meta.globinstrui o Vite a emitir um chunk por arquivo JSON. Uma rota que solicita["about"]em francês baixa apenasmessages/fr/about.jsone nada mais, permitindo que o benchmark atinja 0% de vazamento de locale e 0% de vazamento de página.src/i18n/messages.tsCopiar códigoCopiar o código para a área de transferência
Tipificar suas Mensagens
A extensão de módulos (module augmentation) fornece autocompletar no
useTranslations("about")e not("counter.label"), além de erros de compilação em caso de erro de digitação ou chave removida.src/i18n/use-intl.d.tsCopiar códigoCopiar o código para a área de transferência
Certifique-se de que
resolveJsonModuleesteja ativado no seutsconfig.json.Criar o Documento Raiz
A rota raiz renderiza o elemento
<html>. Ela lê o parâmetro opcional de locale para configurarlangedir, garantindo que esses atributos estejam corretos no HTML renderizado pelo servidor antes da execução de qualquer JavaScript.src/routes/__root.tsxCopiar códigoCopiar o código para a área de transferência
Criar a Rota de Layout do Locale
A pasta
{-$locale}cria um segmento de caminho opcional: tanto/aboutquanto/fr/aboutcorrespondem a/{-$locale}/about. Este layout:- Rejeita prefixos não suportados (
/xx/about→ 404). - Carrega o namespace
commonapenas para o locale atual. - Fornece as mensagens por meio do
IntlProvider.
O resultado do loader é serializado no HTML e reutilizado durante a hidratação, evitando que o cliente baixe o arquivo
common.jsonuma segunda vez. OstaleTime: Infinitymantém o conteúdo em cache nas navegações do cliente.src/routes/{-$locale}/route.tsxCopiar códigoCopiar o código para a área de transferência
O
IntlProvidernão mescla automaticamente mensagens de um provedor pai. A próxima etapa adiciona um componente simples que faz isso, permitindo que cada página adicione seu próprio namespace sobre ocommon.- Rejeita prefixos não suportados (
Criar Escopo para Mensagens de Página
Cada página carrega seu próprio namespace no seu loader e, em seguida, envolve seu conteúdo com
ScopedMessages, que mescla o namespace da página com as mensagens herdadas.src/components/ScopedMessages.tsxCopiar códigoCopiar o código para a área de transferência
Utilizar Traduções em suas Páginas
O loader da página busca o namespace
aboutpara o locale atual, a funçãohead()constrói metadados traduzidos e completos para SEO a partir dele (veja a etapa 13), e o componente renderiza o conteúdo.src/routes/{-$locale}/about.tsxCopiar códigoCopiar o código para a área de transferência
Usar Traduções e Formatadores em Componentes
Qualquer componente sob os provedores pode chamar
useTranslationseuseFormatter. Os plurais são resolvidos pelo ICU e os números são formatados de acordo com o locale ativo.src/components/Counter.tsxCopiar códigoCopiar o código para a área de transferência
Construir um Componente de Link Localizado
OpcionalCada rota reside sob
{-$locale}, de modo que um link deve transportar o parâmetro de locale atual. Este wrapper preserva a tipagem do atributotodo TanStack Router e injeta o locale automaticamente.src/components/LocalizedLink.tsxCopiar códigoCopiar o código para a área de transferência
src/components/Header.tsxCopiar códigoCopiar o código para a área de transferência
Alterar o Idioma do seu Conteúdo
OpcionalRenderize o seletor como links, não como um
<select>. Links são indexáveis por mecanismos de busca, permitindo que eles encontrem todas as versões de idioma, e funcionam mesmo sem JavaScript.to="."mantém a página atual e apenas substitui o parâmetro de locale. O cookie memoriza a escolha explícita para o middleware de redirecionamento da etapa 16.src/components/LocaleSwitcher.tsxCopiar códigoCopiar o código para a área de transferência
Internacionalizar seus Metadados
OpcionalÉ aqui que a internacionalização mostra seu valor: cada versão de idioma pode ranquear individualmente. Cada página deve expor:
- um
<title>e umadescriptiontraduzidos; - uma URL canônica apontando para si mesma (não para o locale padrão);
- um alternativo
hreflangpor locale, além dex-defaultpara idiomas não correspondidos; - tags Open Graph
og:locale,og:locale:alternateeog:url, utilizadas em prévias de redes sociais; - JSON-LD com
inLanguage, ajudando mecanismos de busca e assistentes de IA a identificar o idioma da página.
Um único helper constrói tudo isso, mantendo os arquivos de página enxutos:
src/i18n/seo.tsCopiar códigoCopiar o código para a área de transferência
Utilize-o no
head()de cada página, conforme mostrado na etapa 9. Para a página inicial, passepath: "/".- um
Internacionalizar seu Sitemap
OpcionalUm sitemap multilíngue lista todas as URLs de cada locale, e cada entrada declara todas as suas versões alternativas com
xhtml:link. O Google utiliza essas anotações exatamente como as tagshreflangda página, tornando-as um backup confiável caso uma página seja rastreada com pouca frequência.As rotas de servidor do TanStack Start permitem servi-lo diretamente a partir de uma rota de arquivo:
src/routes/sitemap[.]xml.tsCopiar códigoCopiar o código para a área de transferência
Internacionalizar seu robots.txt
OpcionalRotas privadas existem em todos os idiomas, portanto as regras de
Disallowdevem cobrir todos os prefixos. Removapublic/robots.txtse o template inicial tiver criado um e sirva-o a partir de uma rota:src/routes/robots[.]txt.tsCopiar códigoCopiar o código para a área de transferência
Redirecionar Novos Visitantes para o Idioma Deles
OpcionalUm middleware de requisição encaminha o visitante que acessa
/para o seu idioma preferido, com base no cookie de locale em primeiro lugar e, em seguida, no cabeçalhoAccept-Language. Apenas a raiz/é redirecionada: links profundos nunca são alterados, garantindo que URLs compartilhadas e rastreadores sempre recebam a página solicitada.src/i18n/negotiateLocale.tsCopiar códigoCopiar o código para a área de transferência
src/start.tsCopiar códigoCopiar o código para a área de transferência
Um visitante que escolhe explicitamente o inglês no seletor recebe
locale=enno cookie e nunca mais será redirecionado. Em um deploy totalmente estático (etapa 18),/é servido como arquivo e esse middleware não é executado, o que funciona perfeitamente: a página permanece acessível e o seletor cuida do restante.Manter a API do use-intl e Reduzir o Runtime com o Intlayer
OpcionalO benchmark demonstra que a parte mais pesada da configuração com use-intl é o próprio runtime (~76 KB gzip). O adaptador de compatibilidade
@intlayer/use-intlexpõe a mesma API (useTranslations,useFormatter,IntlProvider,createTranslator, plurais ICU,t.rich), mas a serve a partir de dicionários compilados do Intlayer: ~6.7 KB em vez de ~75.9 KB, 0% de vazamento de locale e 0% de vazamento de página, sem alterações nos seus componentes.bashCopiar códigoCopiar o código para a área de transferência
O plugin do Vite cria um alias de
use-intlpara o adaptador, mantendo as importações existentes funcionando sem modificações:vite.config.tsCopiar códigoCopiar o código para a área de transferência
Seus arquivos JSON continuam sendo a fonte da verdade graças ao plugin de sincronização de JSON:
intlayer.config.tsCopiar códigoCopiar o código para a área de transferência
O adaptador também serve como um caminho suave de migração: uma vez configurado, você pode migrar componentes um a um para a API nativa
useIntlayer. Veja o guia do Intlayer com TanStack Start.Pré-renderizar Todos os Locales
OpcionalHTML estático é a página mais rápida que você pode servir e a mais fácil de ser indexada. Liste todos os caminhos localizados para que o TanStack Start pré-renderize todas as versões de idioma durante o build, juntamente com o sitemap e o robots.txt:
vite.config.tsCopiar códigoCopiar o código para a área de transferência
Como o seletor de idiomas renderiza links reais,
crawlLinks: truetambém descobre páginas que você possa ter esquecido de listar.Gerenciar Páginas 404 Localizadas
OpcionalO layout da etapa 7 já dispara
notFound()para prefixos de locale desconhecidos. Adicione uma rota catch-all para que caminhos inexistentes dentro de um locale também exibam o 404 localizado e marque a página comnoindex: o React 19 eleva a tag<meta>automaticamente para o<head>.src/components/NotFound.tsxCopiar códigoCopiar o código para a área de transferência
src/routes/{-$locale}/$.tsxCopiar códigoCopiar o código para a área de transferência
Acessar o Locale em Server Functions
OpcionalServer functions não recebem os parâmetros de rota. Leia o cookie de locale e utilize o cabeçalho
Accept-Languagecomo fallback para enviar um e-mail localizado ou armazenar a preferência de idioma:src/server/getServerLocale.tsCopiar códigoCopiar o código para a área de transferência
Para traduzir dentro da server function, combine-a com
loadMessagesecreateTranslatordouse-intl.Automatizar suas Traduções Usando o Intlayer
OpcionalO use-intl renderiza as traduções, mas não ajuda a produzi-las. O Intlayer é gratuito e código aberto, preenchendo essa lacuna mesmo se você mantiver o use-intl:
- Teste traduções ausentes no CI ou em testes unitários. Veja como testar suas traduções.
- Traduza com IA usando sua própria chave de API e provedor:
npx intlayer filltraduz chaves ausentes com o contexto da sua aplicação. Veja o preenchimento automático (auto fill) e a CLI. - Mantenha seus arquivos JSON como fonte da verdade com o plugin de sincronização de JSON.
- Edite o conteúdo visualmente com o editor visual e o CMS, permitindo que membros não técnicos atualizem traduções.
- Forneça contexto ao seu agente de IA com o servidor MCP e skills de agente.
- Escaneie seu site publicado em busca de
hreflangausentes, canônicas incorretas e vazamentos de locale com o comando scan.
Para conhecer todos os recursos, veja por que usar o Intlayer.
Perguntas Frequentes
Sim, se você deseja a API do next-intl fora do ecossistema Next.js. Ele oferece suporte a mensagens ICU, formatadores e boa compatibilidade com TypeScript, evitando restrições específicas do Next.js como setRequestLocale. O contraponto é o peso: o benchmark mede ~76 KB gzip para o runtime, e uma configuração ingênua envia todos os locales e todas as páginas para o navegador. Carregue os namespaces por rota e por locale, conforme explicado neste guia, para evitar vazamentos.
O use-intl é o núcleo do next-intl. O next-intl adiciona integrações específicas do Next.js: middleware, auxiliares de navegação, getTranslations para Server Components e configuração de requisições. No TanStack Start você utiliza o use-intl diretamente e implementa o roteamento com o TanStack Router, conforme demonstrado acima.
Use um prefixo na URL. Dessa forma, cada versão de idioma possui sua própria URL que os mecanismos de busca podem indexar e os usuários podem compartilhar. Um cookie ainda é útil para lembrar uma escolha explícita, que é o que o middleware de redirecionamento da etapa 16 realiza.
O servidor e o navegador formatam datas em fusos horários diferentes. Passe um timeZone explícito para o IntlProvider (ou o fuso horário do visitante armazenado em um cookie), para que ambos os lados produzam exatamente o mesmo texto.
Primeiro, divida as mensagens por namespace e carregue-as por rota e por locale com import.meta.glob, o que remove os vazamentos de locale e de página. Em seguida, se o tamanho do runtime for crucial, migre para o adaptador @intlayer/use-intl: mesma API, ~6.7 KB em vez de ~75.9 KB no benchmark.
Chame createTranslator dentro da função head() da rota utilizando as mensagens retornadas pelo loader da rota e, em seguida, retorne o title, a description, a URL canônica e os links hreflang. A etapa 13 fornece um helper reutilizável para isso.
Comentários
Ainda sem comentários. Seja o primeiro a compartilhar seus pensamentos.
