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
vue-i18n VS Intlayer: Benchmark de internacionalização (i18n) para Vue
vue-i18n é a biblioteca i18n de referência para Vue. Intlayer é uma alternativa baseada em compilador, com conteúdo delimitado por componente, com uma integração Vue (vue-intlayer). Este artigo analisa quanto cada uma custa depois que a app é compilada.
Os dados vêm do Benchmark Bloom, uma suíte open-source que compila a mesma aplicação com cada biblioteca e registra o que o navegador realmente baixa e executa.
tl;dr: Na mesma app Vite + Vue 3,vue-i18nentrega 134,9 KB de JavaScript gzipado por página contra 41,3 KB para a app sem i18n. Intlayer entrega 57,1 KB. O runtime dovue-i18nsozinho pesa 24,3 KB gzip (6x os 3,9 KB do Intlayer), cada página carrega 90% das strings de outras páginas, e um componente compilado isoladamente arrasta 196 KB porque está preso à árvore global de mensagens. O adaptador@intlayer/vue-i18nmantém a API dovue-i18ne mediu 47,0 KB por página.
Em resumo
- vue-i18n - A biblioteca i18n de facto para Vue 2 / Vue 3 e o núcleo do
@nuxtjs/i18n. Mensagens no estilo ICU, blocos<i18n>em SFC, diretivav-t, formatadoresd()/n(), grande ecossistema. As mensagens são registradas em uma instância global nocreateI18n(); o lazy loading por locale é um padrão manual comsetLocaleMessage(), e a divisão por rota fica por sua conta. - Intlayer - Modelo de conteúdo centrado em componentes. Os dicionários
.content.tsficam ao lado do componente que servem, um compilador em tempo de build (vite-intlayer) faz tree-shaking e lazy loading por componente e por locale, tipos TypeScript estritos são gerados a partir do seu conteúdo, e traduções ausentes falham no build. Inclui helpers de roteamento / SEO, um Visual Editor / CMS e tradução assistida por IA.
Abrir a tabela em um modal para ver todo o conteúdo claramente
Os badges são atualizados automaticamente. Os snapshots vão variar com o tempo.
Comparação de funcionalidades lado a lado
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Funcionalidade | vue-intlayer (Intlayer) | vue-i18n |
|---|---|---|
| Traduções perto dos componentes | ✅ Sim, .content.ts colocado junto a cada componente | ✅ Via blocos SFC <i18n> (opcional); catálogos globais são a configuração comum |
| Integração TypeScript | ✅ Tipos estritos gerados automaticamente do conteúdo | ✅ Boas tipagens; segurança estrita de chaves exige schema tipado e disciplina |
| Detecção de traduções ausentes | ✅ Erro TypeScript + erro/aviso em tempo de build | ⚠️ Fallback em runtime + aviso no console |
| Conteúdo rico (componentes / Markdown) | ✅ Suporte direto | ⚠️ Interpolação de componentes <i18n-t>; Markdown via plugins externos |
| Suporte a ICU | ⚠️ Em andamento | ✅ Sim |
| Formatação (datas, números, moedas) | ✅ Formatadores baseados em Intl | ✅ d() / n() com datetimeFormats / numberFormats |
| Roteamento localizado | ✅ Helpers para Vue Router / Nuxt, getMultilingualUrls | ⚠️ Não é core (@nuxtjs/i18n ou configuração de roteador personalizada) |
| Helpers de SEO (hreflang, sitemap, robots) | ✅ Helpers integrados | ❌ Não é core |
| Tree-shaking (entregar só o conteúdo usado) | ✅ Por componente, por locale, automatizado pelo compilador | ⚠️ Manual: dividir catálogos, setLocaleMessage() por rota |
| Lazy loading | ✅ importMode: 'dynamic' (uma linha de config) | ✅ import() manual + setLocaleMessage() |
| Purga de conteúdo não usado | ✅ Dicionários mortos são descartados no build | ❌ Não integrado |
| Teste de traduções ausentes (CLI / CI) | ✅ npx intlayer content test | ⚠️ De terceiros (vue-i18n-extract) |
| Tradução com IA | ✅ Integrada, usa suas próprias chaves de provedor | ❌ Não |
| Visual Editor / CMS | ✅ Visual Editor gratuito + CMS opcional | ❌ Não (plataformas externas de localização) |
| Servidor MCP e Agent Skills | ✅ Sim | ❌ Não |
| Ecossistema / comunidade | ⚠️ Menor mas crescendo rápido | ✅ Grande e maduro no ecossistema Vue |
O benchmark
O que foi medido
A suíte Benchmark Bloom compila a mesma aplicação Vite + Vue 3 com cada biblioteca: 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 medidas em en e fr.
Ambas as bibliotecas foram testadas na configuração static, a que a maioria dos projetos Vue entrega: para vue-i18n, o JSON de cada locale importado e passado para createI18n({ messages }); para Intlayer, o importMode: 'static' padrão. Nesse modo o Intlayer também empacota todos os locales, mas o compilador ainda delimita o conteúdo por componente, então uma página só carrega os dicionários dos componentes que renderiza.
Para cada build, a suíte registra:
- Lib size: tamanho gzip de um componente vazio que só importa a biblioteca i18n. O custo fixo do runtime.
- Page JS: JavaScript gzip baixado por página, em média sobre todas as páginas e locales.
- Locale leak %: parcela de strings traduzidas encontradas no JS baixado que pertencem a um locale que o usuário não está vendo (fingerprint em
enefr, então 50% significa "o outro locale medido está totalmente presente"; com 10 locales empacotados, o desperdício real é maior). - Page leak %: parcela de strings traduzidas encontradas no JS baixado que pertencem a uma página em que o usuário não está.
- Component avg: tamanho gzip médio de cada componente compilado isoladamente. Mostra quanto runtime i18n e catálogo um único componente arrasta.
- E2E reactivity: tempo real entre selecionar um novo locale e
html[lang]ser atualizado no DOM (Playwright, 5 iterações). - Page load:
PerformanceNavigationTiming.duration.
Os números abaixo vêm da execução datada de 2026-09-12 comvue-i18n11.4.0 eintlayer9.5.0 / 9.5.1. A aplicação de teste é deliberadamente pequena (algumas dezenas de strings por locale), então as porcentagens de vazamento descrevem um padrão: elas crescem com o seu conteúdo enquanto o custo do runtime permanece fixo.
Resultados em Vite + Vue 3
Escolha as métricas e as bibliotecas que lhe interessam:
Métrica
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
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
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Biblioteca | Estratégia | Lib size (gz) | Lib size (min) | Page JS méd. (gz) | Locale leak | Page leak | Component méd. (gz) | Reatividade E2E | Page load |
|---|---|---|---|---|---|---|---|---|---|
| base (sem i18n) | - | 0,0 KB | 0,0 KB | 41,3 KB | 0,0% | - | 1,1 KB | 1,8 ms | 10,8 ms |
vue-i18n | static | 24,3 KB | 83,2 KB | 134,9 KB | 50,0% | 90,0% | 196,0 KB | 2,8 ms | 13,6 ms |
vue-intlayer | static | 3,9 KB | 11,1 KB | 57,1 KB | 56,8% | 0,0% | 7,7 KB | 4,5 ms | 13,8 ms |
@intlayer/vue-i18n (compat) | static | 7,9 KB | 23,2 KB | 47,0 KB | 15,0% | 0,0% | 8,4 KB | 1,5 ms | 9,3 ms |
A coluna page-leak da app base é deixada em branco: sem biblioteca i18n, o fingerprinting captura strings hard-coded em chunks compartilhados e o número não é significativo.
Como ler
- Custo do runtime.
vue-i18né um dos runtimes mais pesados de todo o benchmark: 24,3 KB gzip / 83,2 KB minificado para um componente vazio que apenas o importa.vue-intlayercusta 3,9 KB gzip. Essa diferença é paga em cada página, independentemente de quantas strings você tem. - JavaScript por página. A app sem i18n pesa 41,3 KB.
vue-i18nmais que triplica para 134,9 KB; Intlayer fica em 57,1 KB, +15,8 KB, a maior parte vinda dos dez locales empacotados (veja o próximo ponto). - Vazamento. Com
createI18n({ messages: { en, fr, ... } }), cada página entrega todos os locales e as strings de todas as páginas: 50% de vazamento de locale (nos dois locales com fingerprint) e 90% de vazamento de página. O modostaticdo Intlayer também empacota todos os locales (daí o número comparável de vazamento de locale) mas tem 0% de vazamento de página: uma página só puxa os dicionários dos componentes que renderiza. Trocar paraimportMode: 'dynamic'remove também o vazamento de locale; essa configuração não fez parte desta execução Vue. - O tamanho dos componentes é onde a arquitetura aparece. Um componente que chama
useI18n()compila para 196 KB em média, porquet()está preso à instância global que contém todas as mensagens de todos os locales. O mesmo componente comuseIntlayer()compila para 7,7 KB: ele só alcança o seu próprio dicionário. - Reatividade não é problema para nenhum dos dois (2-5 ms). O sistema de reatividade do Vue torna a troca de locale barata uma vez que as mensagens estão em memória.
@intlayer/vue-i18n, o adaptador drop-in, mantém a API dovue-i18ne mediu 47,0 KB por página e 8,4 KB por componente, com o código da aplicação intocado.
Para referência, a mesma execução mediu fluent-vue em 171,8 KB por página, 29,7 KB de runtime e 217 KB por componente.
Tabela completa, com todas as bibliotecas e todas as estratégias, no relatório de benchmark do Vue.
Por que a diferença? Instância global vs. dicionários compilados
vue-i18n é um runtime. createI18n() constrói uma instância global que contém uma árvore de mensagens por locale; useI18n() vincula cada componente a ela; t("footer.github") procura a chave no momento do render. É isso que torna possíveis os blocos SFC <i18n>, v-t e o carregamento de mensagens em runtime, e é também por isso que o grafo de dependências de cada componente inclui a árvore inteira:
Copiar o código para a área de transferência
Otimizar significa que você divide en.json em arquivos por rota, você chama setLocaleMessage() em um guard do roteador, e você mantém o mapa rota-arquivo correto conforme os componentes se movem. O runtime não pode fazer isso por você porque não faz ideia de quais chaves um componente vai pedir.
Intlayer move esse conhecimento para o build. O conteúdo é declarado ao lado do componente, e vite-intlayer resolve qual componente importa qual dicionário:
Copiar o código para a área de transferência
O compilador emite, por dicionário e por locale, exatamente o JSON de que aquele componente precisa, e descarta os dicionários que nada importa. A delimitação por rota é uma consequência da delimitação por componente, não uma tarefa.
Para descartar também os locales não usados, definadictionary.importMode: 'dynamic'emintlayer.config.ts. Veja a doc de otimização de bundle.
Experiência de desenvolvimento
Configuração
vue-i18n
Copiar o código para a área de transferência
Copiar o código para a área de transferência
Intlayer
Copiar o código para a área de transferência
Copiar o código para a área de transferência
Copiar o código para a área de transferência
Componente
vue-i18n
Copiar o código para a área de transferência
Copiar o código para a área de transferência
t('counter.label') é uma string até que você mesmo tipe o schema de mensagens; um erro de digitação renderiza a chave.
Intlayer
Copiar o código para a área de transferência
Copiar o código para a área de transferência
label e increment são tipados; um erro de digitação é um erro TypeScript, um valor em francês ausente é um erro de build.
Lazy loading por locale
vue-i18n
Copiar o código para a área de transferência
Depois chame loadLocaleMessages() a partir de um guard do roteador, e divida você mesmo locales/{locale}.json por rota se quiser delimitação por página.
Intlayer
Copiar o código para a área de transferência
Mantenha a API do vue-i18n, obtenha a saída do Intlayer
@intlayer/vue-i18n é um adaptador drop-in: useI18n(), t(), d(), n(), a interpolação {name} e {0}, plurais com pipe ("car | cars"), v-t e i18n.global.locale continuam funcionando, servidos a partir de dicionários Intlayer compilados pelo vite-intlayer.
Copiar o código para a área de transferência
No benchmark, o build compat da mesma app passou de 134,9 KB para 47,0 KB por página e de 196 KB para 8,4 KB por componente, com os componentes intocados. Seus locales/{locale}.json existentes podem continuar sendo a fonte de verdade através do plugin de sincronização JSON.
Veja o guia de migração do vue-i18n e a doc de compatibilidade. Usuários de Nuxt têm o mesmo caminho pela compatibilidade @nuxtjs/i18n.
Quando escolher qual?
- Escolha vue-i18n se você quer a abordagem Vue padrão, depende de mensagens ICU ou blocos SFC
<i18n>, já usa@nuxtjs/i18n, ou uma plataforma de tradução espera JSON centralizado. Reserve tempo para dividir catálogos e fazer lazy loading por rota se o tamanho do bundle importa. - Escolha Intlayer se você quer conteúdo delimitado por componente, TypeScript estrito, erros de chaves ausentes em tempo de build, tree-shaking e lazy loading sem esforço, e ferramentas editoriais integradas (Visual Editor, CMS, tradução por IA, servidor MCP). Especialmente relevante para bases de código Vue / Nuxt grandes e modulares e para design systems.
- Escolha
@intlayer/vue-i18nse você já está novue-i18ne quer os ganhos de bundle sem uma reescrita.
FAQ
Ambos, dependendo de como você o adota. O vue-intlayer é um runtime nativo com seu próprio composable useIntlayer(). O @intlayer/vue-i18n é um adaptador de compatibilidade que mantém a API do vue-i18n e substitui o que está vinculado a ela, permitindo migrar sem alterar componentes e avançar arquivo por arquivo depois.
O adaptador não os lê. Mova essas mensagens para seu JSON de idioma, ou para um .content.ts ao lado do componente, o que representa a mesma ideia com tipos gerados. Esse é o único recurso do vue-i18n que não é suportado.
Sim. Intlayer com Nuxt cobre roteamento multilíngue, middleware de detecção de idioma e geração de sitemaps. Se você usa @nuxtjs/i18n, o adaptador de compatibilidade Nuxt i18n é o caminho de migração.
Sim. O plugin de sincronização JSON os lê no dialeto do vue-i18n ({name}, {0}, plurais em pipe "car | cars") e grava as traduções de volta quando a CLI ou o CMS os atualiza.
O suporte nativo a ICU está em desenvolvimento. O adaptador @intlayer/vue-i18n resolve a sintaxe de mensagens do próprio vue-i18n, incluindo plurais em pipe e interpolação nomeada e de lista. Para o modelo de pluralização do Intlayer, consulte conteúdo de enumeração.
Comparações relacionadas
Documentação de referência:
Relatórios de benchmark:
Para entender de onde vêm essas bibliotecas, leia a história do i18n em JavaScript.
Estrelas no GitHub
As estrelas no GitHub são um forte indicador da popularidade de um projeto, da confiança da comunidade e da relevância a longo prazo. Embora não sejam uma medida direta da qualidade técnica, refletem quantos desenvolvedores acham o projeto útil, acompanham seu progresso e tendem a adotá-lo.
Atividade de commits
As estrelas mostram popularidade. Os commits mostram quanto trabalho é investido num projeto. No momento em que este texto foi escrito, o Intlayer soma cerca de 7.500 commits, mais do que a maioria das bibliotecas comparadas aqui e cerca de 5 vezes mais do que next-intl ou next-i18next.
- intlify/vue-i18n
- aymericzip/intlayer
Commits no branch padrão, fonte: API do GitHub.
O Intlayer é um monorepo, então o total inclui cada pacote de framework, a CLI e a documentação. Leia os commits como um sinal de atividade, não de qualidade.
Downloads no npm
- vue-i18n
- vue-intlayer
Fonte: API de downloads do registro npm.
Os downloads recompensam as soluções mais antigas, não as melhores. Uma biblioteca lançada há anos continua sendo instalada por cada projeto que a escolheu na época, por cada execução de CI e por cada pacote que depende dela. O número mede a inércia mais do que uma escolha atual.
Os assistentes de IA amplificam o efeito. next-intl, i18next e vue-i18n estão por toda parte no código com que foram treinados, então eles os sugerem por padrão, sem comparar as alternativas. Cada sugestão gera downloads, que alimentam a próxima sugestão. Compare pelo benchmark, não pelo número de downloads.
Conclusão
vue-i18n é maduro, flexível e profundamente integrado ao Vue. O benchmark mostra o que seu design runtime-first custa em um build Vite: um runtime de 24 KB gzip, 134,9 KB por página para uma app que pesa 41 KB sem i18n, 90% de conteúdo de outras páginas em cada página, e componentes que chegam cada um a 196 KB porque dependem da árvore global de mensagens.
Intlayer move o trabalho para o compilador. Dicionários por componente e purga de conteúdo morto são saídas do build, não convenções. Na mesma app: 3,9 KB de runtime, 57,1 KB por página, 0% de vazamento de página, componentes 25x menores. E se uma reescrita não está na mesa, @intlayer/vue-i18n chega à maior parte do caminho com os componentes intocados.
Todos os dados brutos, as apps de teste e os scripts estão no repositório Benchmark Bloom. Execute você mesmo.
Consulte a doc "Por que Intlayer?" para mais detalhes.
Comentários
Ainda sem comentários. Seja o primeiro a compartilhar seus pensamentos.
