Faça sua pergunta e obtenha um resumo do documento referenciando esta página e o provedor AI de sua escolha
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
i18next VS @intlayer/i18next | Mesma API, Outro Bundle
@intlayer/i18next, @intlayer/react-i18next e @intlayer/next-i18next são adaptadores de compatibilidade. Eles expõem a API do i18next que seu código já utiliza (useTranslation, t(), <Trans>, i18n.changeLanguage(), getFixedT, serverSideTranslations...) e a fornecem a partir de dicionários compilados pelo Intlayer. Os componentes não mudam. O runtime abaixo deles sim.
Este artigo analisa essa substituição na mesma aplicação Next.js, construída uma vez com next-i18next e outra com @intlayer/next-i18next. Os dados são do Benchmark Bloom. Para comparar i18next e Intlayer como bibliotecas completas, leia i18next vs Intlayer. Este artigo se concentra no que o adaptador transforma quando você preserva seu código como está.
tl;dr: Na mesma aplicação Next.js, substituirnext-i18nextpor@intlayer/next-i18nextreduziu o JavaScript por página de 218.5 KB para 150.7 KB gzip (setup básico) e superou o setup donext-i18nexttotalmente otimizado (163.4 KB) em 12.7 KB. O componente médio caiu de 78.5 KB para 9.7 KB, o vazamento de strings para outras páginas foi de ~90% para 0%, a hidratação de 15.6 ms para 11.3 ms e o runtime de 19.7 KB para 9.4 KB. Nenhum componente foi editado; apenas um arquivo de provider foi ajustado. Plugins doi18next(backends, detectores de idioma) são aceitos mas não realizam nada: não há mais nada para carregar ou detectar em tempo de execução.
O que é o @intlayer/i18next
O i18next é um runtime. i18n.init({ resources }) ou um plugin de backend carrega locales/{lng}/{ns}.json em uma instância global; useTranslation("about") inscreve o componente nela; t("title") busca a chave no momento da renderização. Namespaces, carregamento sob demanda (lazy loading), listas de namespaces por página e segurança de tipos ficam sob sua responsabilidade de configuração e manutenção.
Os adaptadores preservam a API e substituem a instância:
- Aliases de importação.
createNextI18nPlugin()do@intlayer/next-i18next/plugin(ouwithI18next) envolve owithIntlayere cria aliases no Webpack / Turbopack para quenext-i18next,react-i18nextei18nextresolvam para os pacotes@intlayer/*. No Vite, oreactI18nextVitePlugin()do@intlayer/react-i18next/plugintem o mesmo papel. Nenhuma importação precisa ser renomeada. - JSON como fonte de verdade. O plugin
syncJSONlê seus arquivos existenteslocales/{lng}/{ns}.jsoncomformat: "i18next"(garantindo que{{name}}, aninhamento$t(),_one/_othere sufixos de contexto sejam interpretados adequadamente) e regrava as traduções quando a CLI ou o CMS as atualizam. - Vinculação no ponto de chamada. A etapa de otimização do Intlayer reescreve
useTranslation("about")em uma chamada que recebe o dicionárioaboutdiretamente, no idioma ativo. O componente deixa de acessar a store global.
Copiar o código para a área de transferência
Copiar o código para a área de transferência
Essa transformação é a razão pela qual as colunas de tamanho de componente e vazamento de página caem drasticamente nos dados abaixo.
O que os adaptadores mantêm, ignoram e não substituem
Abrir a tabela em um modal para ver todo o conteúdo claramente
API do i18next | Com @intlayer/* |
|---|---|
useTranslation("ns"), useTranslation("ns", { keyPrefix }) | ✅ Mantido. Vinculado ao dicionário ns em tempo de compilação; tipado com seu conteúdo |
t("key", { name }), {{interpolation}}, aninhamento $t(key) | ✅ Mantido |
Plurais key_one / key_other, contexto key_male, returnObjects | ✅ Mantido. Plurais calculados com Intl.PluralRules |
<Trans> com components, tags numeradas <1>...</1>, values | ✅ Mantido |
withTranslation, Translation, I18nContext | ✅ Mantido |
i18n.changeLanguage(), i18n.language, i18n.dir(), on("languageChanged") | ✅ Mantido. changeLanguage controla o idioma do Intlayer |
getFixedT(lng, ns, keyPrefix), i18n.exists(), hasLoadedNamespace() | ✅ Mantido |
i18n.use(Backend).use(LanguageDetector).init({...}) | ⚠️ use() executa o init do plugin e encerra; backends e detectores não têm nada para carregar ou detectar |
init({ resources }), addResourceBundle() | ⚠️ resources é ignorado com alerta de desenvolvimento; remova imports de JSON para obter ganhos reais de bundle |
I18nextProvider i18n={i18n} | ⚠️ Renderiza um IntlayerProvider; a prop i18n é ignorada. No App Router, passe o locale (veja abaixo) |
serverSideTranslations(locale, ["common"]) (next-i18next) | ⚠️ Retorna a estrutura esperada e não carrega nada. Seguro de manter, seguro de remover |
appWithTranslation(App) (next-i18next) | ✅ Mantido |
next-i18next.config.js | ⚠️ Não é lido. Os idiomas são configurados no intlayer.config.ts |
useTranslation() sem namespace | ✅ Opera contra o dicionário geral translation do arquivo inteiro (splitKeys: false) |
O benchmark
O que foi medido
A suite Benchmark Bloom compila a mesma aplicação em cada ambiente: 10 páginas (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 locales (en, fr, es, de, it, pt, zh, ja, ko, ru), componentes idênticos e conteúdo idêntico. As páginas são avaliadas em en e fr.
O next-i18next foi configurado em quatro estratégias de carregamento, desde o JSON de cada idioma importado em resources (static) até um namespace por rota, carregado de forma diferida via backend (scoped-dynamic). O adaptador foi testado sobre os mesmos componentes do setup inicial, com alterações limitadas a next.config.ts, intlayer.config.ts e ao arquivo do provider. Ele não possui variante "scoped" manual: o compilador define o escopo do conteúdo por componente.
Para cada compilação, registram-se:
- Tamanho da lib: tamanho gzip de um componente vazio que apenas importa a biblioteca de i18n.
- JS por página: média de JavaScript gzip transferido por página em todas as rotas e locales.
- % de vazamento de locale: parcela de strings traduzidas no JS que pertence a um idioma que o usuário não está visualizando.
- % de vazamento de página: parcela de strings traduzidas no JS que pertence a uma página em que o usuário não está navegando.
- Média por componente: tamanho médio gzip de cada componente compilado de forma isolada.
- Reatividade E2E: intervalo de tempo real entre selecionar um novo idioma e a alteração de
html[lang]no DOM (Playwright, 5 repetições). - Hidratação: tempo de duração da fase de hidratação do React.
Os dados abaixo resultam da execução de 12/09/2026 comnext-i18next16.3.0 (react-i18next17.0.13,i18next26.4.2) e@intlayer/next-i18next9.5.1. A aplicação de teste foi projetada com escopo enxuto propositalmente (algumas dezenas de strings por idioma), portanto os percentuais de vazamento ilustram um comportamento: expandem-se proporcionalmente ao crescimento do conteúdo enquanto o custo do runtime permanece estático.
Resultados no Next.js
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Setup | Estratégia | Tamanho lib (gz) | Média JS pág (gz) | Vazamento locale | Vazamento pág | Média comp (gz) | Reatividade E2E | Hidratação |
|---|---|---|---|---|---|---|---|---|
| base (sem i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
next-i18next | static | 19.7 KB | 218.5 KB | 0.0% | 89.8% | 78.5 KB | 16.4 ms | 15.6 ms |
next-i18next | dynamic | 19.7 KB | 169.5 KB | 50.0% | 89.8% | 26.1 KB | 15.4 ms | 27.7 ms |
next-i18next | scoped-static | 19.7 KB | 220.1 KB | 0.0% | 89.8% | 78.9 KB | 16.4 ms | 14.7 ms |
next-i18next | scoped-dynamic | 19.7 KB | 163.4 KB | 0.0% | 0.0% | 27.1 KB | 15.9 ms | 15.1 ms |
@intlayer/next-i18next | static | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 10.7 ms | 11.3 ms |
@intlayer/next-i18next | dynamic | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 11.9 ms | 10.6 ms |
next-intlayer (nativo) | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer (nativo) | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
Como interpretar os dados
- 68 KB a menos por página em relação ao setup básico.
resources: { en, fr, ... }despacha todos os idiomas e namespaces para cada rota: 218.5 KB. O build com o adaptador cai para 150.7 KB. Supera também a configuração mais elaborada donext-i18next(163.4 KB, namespace único por rota, carregado sob demanda) em 12.7 KB, pois a própria bibliotecai18nextconsome 19.7 KB contra 9.4 KB. - O vazamento atinge 0% sem intervenção em componentes. Cada configuração do
next-i18next, à exceção da modularizada manualmente, entrega ~90% de strings de rotas distintas. A linhadynamicé pior na prática do que aparenta: preserva o vazamento entre páginas e adiciona 50% de vazamento de idioma, dado que o backend busca todo o namespacetranslationdo locale ativo. O adaptador estabelece 0% / 0% a partir do código original. - Componentes: 8x mais enxutos. Um componente com
useTranslation()isolado consome 78.5 KB comresourcesinlined e 26-27 KB com backend, já quetcontinua preso à store global. No adaptador, a média cai para 9.7 KB. - Hidratação e alternância de idioma aceleradas. A hidratação cai de 15.6 ms para 11.3 ms (e de 27.7 ms no modo
dynamic, no qual o carregamento do backend reside no caminho crítico). A troca de idioma cai de 15-16 ms para 11-12 ms. - O adaptador é diferente do runtime nativo. O
next-intlayercrava 141.3 KB, meros +0.3 KB acima do app sem i18n. O adaptador suporta as particularidades da API doi18next(expressões de interpolação, sufixos de plural e contexto, tags<Trans>) sobre o núcleo do Intlayer: 9.4 KB e +9.4 KB por página em relação ao nativo. Atua como transição, não como destino final.
O adaptadorreact-i18nextno Vite / TanStack Start não constou desta rodada de testes. A medição parareact-i18nextno TanStack Start pode ser verificada em i18next vs Intlayer: 127-184 KB por página e 123-185 ms na troca de idioma com backend sob demanda.
O motivo da mudança nos indicadores
Nenhum arquivo em components/ foi alterado, logo o ganho advém da entidade à qual useTranslation se acopla.
Com o i18next, a ligação é feita na instância global. Qualquer recurso alocado nela (todos os idiomas em static, o namespace completo do idioma ativo em dynamic) torna-se acessível para qualquer componente chamador de useTranslation(). O bundler não consegue fragmentar abaixo do volume contido na instância, e o runtime não é capaz de prever quais chaves serão demandadas em renderização.
Copiar o código para a área de transferência
Com o @intlayer/next-i18next, a ligação é feita diretamente com o dicionário. O plugin syncJSON transforma cada arquivo de namespace em um dicionário; o ciclo de otimização repassa ao componente apenas o dicionário declarado, na forma de import que o empacotador rastreia e separa por página e locale.
Copiar o código para a área de transferência
O arquivo i18n/i18n.ts e sua importação de resources tornam-se código inerte. É daí que procedem os 68 KB de alívio.
Migração em três etapas
Instalação
bashCopiar códigoCopiar o código para a área de transferência
O comando identifica
i18next/react-i18next/next-i18next, instala ointlayer, o pacote do framework (next-intlayeroureact-intlayer), o respectivo adaptador@intlayer/*e o@intlayer/sync-json-plugin, além de preencher ointlayer.config.ts. Conserve as dependências originais instaladas: elas operam como peer dependencies e entregam as tipagens.Aponte o Intlayer para seus arquivos de tradução
intlayer.config.tsCopiar códigoCopiar o código para a área de transferência
Caso você mantenha um único arquivo
translation.jsonpor locale (o namespace padrão do i18next), configuresplitKeys: falsepara que o arquivo integral permaneça como um único dicionário e invocações diretas deuseTranslation()prossigam sem falhas.Adicione o plugin
next.config.tsCopiar códigoCopiar o código para a área de transferência
No App Router, componentes de cliente identificam o idioma pelo segmento
[locale]. OI18nextProviderdo adaptador não aceita locale como propriedade, logo substitua-o uma única vez no arquivo de provider:components/AppProviders.tsxCopiar códigoCopiar o código para a área de transferência
Todos os componentes abaixo continuam invocando
useTranslation().vite.config.tsCopiar códigoCopiar o código para a área de transferência
O
reactI18nextVitePlugin()encapsula ovite-intlayere define os aliases parareact-i18nextei18next. Para projetos sem React,i18nextVitePlugin()do@intlayer/i18next/pluginprovê o alias somente parai18next.
O que você pode remover em seguida
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Arquivo / padrão | Motivo |
|---|---|
resources: { en, fr, ... } e importações JSON | Ignorados pelo adaptador. Era aqui que se concentravam os 68 KB |
i18next-http-backend, i18next-resources-to-backend | Não há nada a carregar dinamicamente |
i18next-browser-languagedetector | A identificação é controlada pelo roteamento do Intlayer (prefixo de URL, cookie, cabeçalho) |
serverSideTranslations() em getStaticProps | Devolve um objeto vazio; inofensivo, mas inútil |
next-i18next.config.js | Não é consultado. Idiomas residem no intlayer.config.ts |
Listas de ns: [...] por página | O compilador detecta os namespaces por componente |
O que você ganha além da redução em bytes
- Tipagem estrita de chaves.
useTranslation("about")valida chaves contra o dicionárioaboutcompilado;t("does.not.exist")gera um erro do compilador TypeScript em vez de retornar a string crua. npx intlayer testbloqueia a integração contínua (CI) se faltar qualquer tradução em qualquer idioma.npx intlayer filltraduz pendências com sua própria chave de provedor (OpenAI, Anthropic, Mistral, Gemini...) e as salva emlocales/{lng}/{ns}.json.- Editor Visual e CMS atuam diretamente no mesmo JSON, permitindo que editores atualizem textos por interface gráfica enquanto os arquivos Git são versionados.
- Migração gradual para
.content.ts. Cada componente pode migrar deuseTranslation("about")parauseIntlayer("about")adotando um arquivo de conteúdo co-localizado. Dicionários JSON e.content.tsoperam juntos harmonicamente.
Limitações importantes antes de iniciar
- Backends e detectores ficam desativados.
i18n.use(HttpBackend)executa o métodoinitdo plugin e encerra. Se seu projeto dependia de buscar traduções em um CMS em tempo de execução, esse fluxo é descontinuado; use o CMS do Intlayer ou os comandosintlayer pull/push. resourcesé descartado, não combinado. Ao contrário de certos adaptadores, o@intlayer/i18nextnão usaresourcesinline como recurso de segurança. Toda chave precisa existir nos dicionários sincronizados, o que é validado porintlayer test.- App Router necessita do ajuste de provider. Apenas um arquivo, apresentado acima. O Pages Router com
appWithTranslationopera sem ajustes adicionais. next-i18next.config.jsnão é aproveitado. Parâmetros comolocalePath,fallbackLngereloadOnPrerendernão são lidos; configurações de idioma e fallback residem emintlayer.config.ts.- O adaptador possui um custo. 9.4 KB de runtime e +9.4 KB por página em relação ao
next-intlayer. Assim que todos os componentes forem convertidos parauseIntlayer, ele pode ser desinstalado.
Quando utilizar cada alternativa?
- Mantenha-se no
i18nextse sua infraestrutura depender de backends dinâmicos em tempo de execução (traduções servidas sob demanda por CMS), de plugins exclusivos ou de um ambiente fora do ecossistema React não atendido pelos adaptadores. - Adote
@intlayer/*se você já opera comreact-i18next/next-i18nexte deseja resgatar 68 KB, atingir componentes 8x menores, eliminar vazamento (0%), obter chaves tipadas e validação na CI sem reescrever seus componentes. É a transição recomendada para bases existentes dei18next. - Prefira o modelo nativo (
next-intlayer/react-intlayer) em projetos novos ou logo após o adaptador consolidar a migração. Trata-se da opção mais rápida (5.5 KB, +0.3 KB por página), liberando Server Components síncronos e arquivos.content.tspor componente.
Comparações relacionadas
- i18next vs Intlayer (comparação das bibliotecas, mesmo benchmark)
- next-intl vs @intlayer/next-intl (mesma série de adaptadores)
- Lingui vs @intlayer/lingui (mesma série de adaptadores)
- vue-i18n vs @intlayer/vue-i18n (mesma série de adaptadores)
- Guias de migração: i18next, react-i18next, next-i18next
- Referência dos adaptadores: i18next, react-i18next, next-i18next
Conclusão
O i18next figura como o runtime mais pesado deste benchmark, e os adaptadores cortam a maior parte dessa carga sem exigir que você abandone sua API habitual. Na mesma aplicação Next.js, isso representa 68 KB a menos por página comparado à configuração inicial, 12.7 KB a menos em relação à opção mais otimizada manualmente, componentes 8x mais leves, 0% de vazamento e 4 ms a menos de hidratação, demandando apenas um arquivo de configuração, uma inclusão de plugin e um ajuste no provider. Backends e detectores tornam-se inócuos, resources é descartado ao invés de incorporado, e a implementação nativa do next-intlayer preserva outros 9 KB de leveza adicional.
A totalidade dos dados brutos, aplicações de teste e scripts encontra-se publicada no repositório do Benchmark Bloom.
Consulte o documento Por que Intlayer? para aprofundar.
Comentários
Ainda sem comentários. Seja o primeiro a compartilhar seus pensamentos.
