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
- "Adicionar comparativo de estrelas do GitHub"v8.9.818/05/2026
- "Inicialização do benchmark"v8.7.1206/01/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
Bibliotecas i18n para Solid - Relatório de Benchmark 2026
Esta página é um relatório de benchmark para soluções i18n no Solid.
Índice
Benchmark Interativo
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
Referência de resultados:
Ver dados completos do benchmark
Veja o repositório completo do benchmark aqui.
Introdução
As soluções de internacionalização estão entre as dependências mais pesadas em um app Solid. O principal risco é enviar conteúdo desnecessário: traduções para outras páginas e outros locais no bundle de uma única rota.
À medida que seu app cresce, esse problema pode rapidamente explodir o JavaScript enviado ao cliente e tornar a navegação lenta.
Na prática, para as implementações menos otimizadas, uma página internacionalizada pode acabar sendo várias vezes mais pesada do que a versão sem i18n.
O outro impacto é na experiência do desenvolvedor (DX): como você declara conteúdo, tipos, organização de namespaces, carregamento dinâmico e reatividade quando o local muda.
TL;DR
- Intlayer: Escolha recomendada para aplicações Solid profissionais que precisam de recursos avançados e otimização (v8.7.12).
- @solid-primitives/i18n: Excelente alternativa leve para projetos simples, embora careça de recursos avançados como lazy loading.
- solid-i18next: Opção padrão, mas pesada (~4.7× o Intlayer) com os mesmos pontos negativos do React i18next.
- Paraglide: Abordagem inovadora, mas DX complexa e problemas de tree-shaking em algumas configurações.
Teste seu app
Para identificar rapidamente problemas de vazamento de i18n, configurei um scanner gratuito disponível aqui.
O problema
Duas alavancas são essenciais para limitar o custo de um app multilíngue:
- Dividir o conteúdo por página / namespace para não carregar dicionários inteiros quando não for necessário.
- Carregar o local correto dinamicamente, apenas quando necessário.
Entendendo as limitações técnicas dessas abordagens:
Carregamento dinâmico
Sem carregamento dinâmico, a maioria das soluções mantém as mensagens na memória desde o primeiro render, o que adiciona um overhead significativo para apps com muitas rotas e locais.
Com carregamento dinâmico, você aceita uma troca: menos JS inicial, mas às vezes uma requisição extra ao trocar de idioma.
Divisão de conteúdo (Splitting)
Sintaxes construídas em torno de t('a.b.c') são muito convenientes, mas frequentemente incentivam a manutenção de grandes objetos JSON em tempo de execução. Esse modelo torna o tree-shaking difícil, a menos que a biblioteca ofereça uma estratégia real de divisão por página.
Metodologia
Para este benchmark, comparamos as seguintes bibliotecas:
Base App(Sem biblioteca i18n)solid-intlayer(v8.7.12)@solid-primitives/i18n(v2.2.1)solid-i18next(v17.0.2)@inlang/paraglide-js(v2.17.0)
O framework é Solid com um app multilíngue de 10 páginas e 10 idiomas.
Comparamos quatro estratégias de carregamento:
Abrir a tabela em um modal para ver todo o conteúdo claramente
| Estratégia | Sem namespaces (global) | Com namespaces (scoped) |
|---|---|---|
| Carregamento estático | Static: Tudo na memória ao iniciar. | Scoped static: Dividido por namespace; tudo carregado ao iniciar. |
| Carregamento dinâmico | Dynamic: Carregamento sob demanda por local. | Scoped dynamic: Carregamento granular por namespace e local. |
Resumo das estratégias
- Static: Simples; sem latência de rede após o carregamento inicial. Desvantagem: grande tamanho de bundle.
- Dynamic: Reduz o peso inicial (lazy-loading). Ideal quando você tem muitos locais.
- Scoped static: Mantém o código organizado (separação lógica) sem requisições de rede extras complexas.
- Scoped dynamic: Melhor abordagem para code splitting e desempenho. Minimiza a memória carregando apenas o que a view atual e o local ativo precisam.
O que medi:
Executei o mesmo aplicativo multilíngue em um navegador real para cada stack e anotei o que realmente aparecia na rede e quanto tempo levava. Os tamanhos são relatados após compressão web normal, porque isso se aproxima mais do que as pessoas fazem download do que contagens de código-fonte bruto.
Tamanho da biblioteca de internacionalização: Após bundling, tree-shaking e minificação, o tamanho da biblioteca i18n é o tamanho dos providers + código de hooks/primitives em um componente vazio. Não inclui o carregamento de arquivos de tradução. Responde o quão caro é a biblioteca antes de seu conteúdo entrar na história.
JavaScript por página: Para cada rota de benchmark, quanto script o navegador extrai para essa visita, em média nas páginas do conjunto (e entre idiomas onde o relatório os agrega). Páginas pesadas são páginas lentas.
Vazamento de outros idiomas: É o conteúdo da mesma página mas em outro idioma que seria carregado por engano na página auditada. Este conteúdo é desnecessário e deve ser evitado. (ex. conteúdo da página
/fr/aboutno bundle da página/en/about)Vazamento de outras rotas: A mesma ideia para outras telas no aplicativo: se sua cópia está viajando junto quando você abriu apenas uma página. (ex. conteúdo da página
/en/aboutno bundle da página/en/contact). Uma pontuação alta sugere divisão fraca ou bundles muito amplos.Tamanho médio do bundle do componente: Peças de UI comuns são medidas uma de cada vez em vez de se esconder dentro de um número gigante de aplicativo. Mostra se a internacionalização silenciosamente infla componentes cotidianos. Por exemplo, se seu componente é renderizado novamente, ele carregará todos esses dados da memória. Anexar um JSON gigante a qualquer componente é como conectar um grande armazenamento de dados não utilizados que desacelerará o desempenho de seus componentes.
Responsividade da troca de idioma: Mudo o idioma usando o controle do próprio aplicativo e cronometro quanto tempo leva até a página ter claramente trocado, o que um visitante notaria, não um micro-passo de laboratório.
Trabalho de renderização após uma mudança de idioma: Um acompanhamento mais estreito: quanto esforço a interface levou para redesenhar o novo idioma uma vez que a troca está em andamento. Útil quando o tempo "sentido" e o custo do framework divergem.
Tempo de carregamento da página inicial: Da navegação até o navegador considerar a página totalmente carregada para os cenários que testei. Bom para comparar inícios frios.
Tempo de hidratação: Quando o aplicativo o expõe, quanto tempo o cliente gasta transformando HTML do servidor em algo que você pode realmente clicar. Um travessão nas tabelas significa que a implementação não forneceu uma figura de hidratação confiável neste benchmark.
Estrelas do GitHub
As estrelas do 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, elas refletem quantos desenvolvedores consideram o projeto útil, acompanham seu progresso e têm probabilidade de adotá-lo. Para estimar o valor de um projeto, as estrelas ajudam a comparar a tração entre as alternativas e fornecem insights sobre o crescimento do ecossistema.
Resultados em detalhes
1 - Soluções a evitar
Nenhuma solução clara a evitar no ecossistema Solid.
2 - Soluções aceitáveis
(solid-i18next) (solid-i18next@17.0.2):
O solid-i18next é provavelmente a opção mais popular porque foi uma das primeiras a atender às necessidades de i18n de apps JavaScript. Também possui um amplo conjunto de plugins da comunidade para problemas específicos.
O pacote é pesado (~14.6kb, o que é cerca de 4.7× o solid-intlayer).
Ainda assim, compartilha as mesmas principais desvantagens das stacks construídas sobre o t('a.b.c'): otimizações são possíveis, mas consomem muito tempo, e grandes projetos correm o risco de más práticas (namespaces + carregamento dinâmico + tipos).
(@solid-primitives/i18n) (@solid-primitives/i18n@2.2.1):
O Solid primitive é extremamente leve e eficiente. Recomendo essa solução para projetos leves, mas pode rapidamente carecer de recursos para soluções profissionais que incluam gerenciamento de cookies, redirecionamento de proxy, formatadores etc. Também carece de lazy loading e scoping de namespaces para otimização do tamanho da página.
(Paraglide) (@inlang/paraglide-js@2.17.0):
O Paraglide oferece uma abordagem inovadora e bem pensada. Ainda assim, neste benchmark, o tree-shaking que a empresa anuncia não funcionou para minha implementação. O fluxo de trabalho e a DX também são mais complexos do que outras opções.
Pessoalmente, não gosto de ter que regenerar arquivos JS antes de cada push, o que cria um risco constante de conflito de merge através de PRs.
Finalmente, em comparação com outras soluções, o Paraglide não usa um store (ex: Solid signal) para recuperar o local atual para renderizar o conteúdo. Para cada nó analisado, ele solicitará o local do localStorage / cookie etc. Isso leva à execução de lógica desnecessária que impacta a reatividade do componente.
3 - Recomendações
(Intlayer) (solid-intlayer@8.7.12):
Eu não julgarei pessoalmente o solid-intlayer por uma questão de objetividade, já que é minha própria solução.
Nota pessoal
Esta nota é pessoal e não afeta os resultados do benchmark. Ainda assim, no mundo do i18n, você costuma ver consenso em torno de um padrão como const t = useTranslation('xx') + <>{t('xx.xx')}</> para o conteúdo traduzido.
Em apps Solid, injetar uma função como um JSX.Element é, na minha opinião, um antipadrão. Também adiciona complexidade evitável e overhead de execução de JavaScript (mesmo que seja quase imperceptível).
