Ask your question and get a summary of the document by referencing this page and the AI provider of your choice
Version History
- "Add GitHub star comparative"v8.9.818/05/2026
- "Init benchmark"v8.7.1206/01/2026
The content of this page was translated using an AI.
See the last version of the original content in EnglishIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Solid i18n Libraries - 2026 Benchmark Report
This page is a benchmark report for i18n solutions on Solid.
Table of Contents
Interactive Benchmark
Results reference:
See complete benchmark data
See complete benchmark repository here.
Introduction
Internationalisation solutions are among the heaviest dependencies in a Solid app. The main risk is shipping unnecessary content: translations for other pages and other locales in a single route’s bundle.
As your app grows, that problem can quickly blow up the JavaScript sent to the client and slow down navigation.
In practice, for the least optimised implementations, an internationalised page can end up several times heavier than the version without i18n.
The other impact is on developer experience: how you declare content, types, namespace organisation, dynamic loading, and reactivity when the locale changes.
TL;DR
- Intlayer: Recommended choice for professional Solid applications needing advanced features and optimisation (v8.7.12).
- @solid-primitives/i18n: Excellent lightweight alternative for simple projects, though lacks advanced features like lazy loading.
- solid-i18next: Standard but heavy option (~4.7× Intlayer) with same downsides as React i18next.
- Paraglide: Innovative approach but complex DX and tree-shaking issues in some setups.
Test your app
To quickly spot i18n leakage issues, I set up a free scanner available here.
The problem
Two levers are essential to limit the cost of a multilingual app:
- Split content by page / namespace so you do not load whole dictionaries when you do not need them
- Load the right locale dynamically, only when needed
Understanding the technical limitations of these approaches:
Dynamic loading
Without dynamic loading, most solutions keep messages in memory from the first render, which adds significant overhead for apps with many routes and locales.
With dynamic loading, you accept a trade-off: less initial JS, but sometimes an extra request when switching language.
Content splitting
Syntaxes built around t('a.b.c') are very convenient but often encourage keeping large JSON objects at runtime. That model makes tree-shaking hard unless the library offers a real per-page split strategy.
Methodology
For this benchmark, we compared the following libraries:
Base App(No i18n library)solid-intlayer(v8.7.12)@solid-primitives/i18n(v2.2.1)solid-i18next(v17.0.2)@inlang/paraglide-js(v2.17.0)
The framework is Solid with a multilingual app of 10 pages and 10 languages.
We compared four loading strategies:
Open the table in a modal to view all data content clearly
| Strategy | No namespaces (global) | With namespaces (scoped) |
|---|---|---|
| Static loading | Static: Everything in memory at startup. | Scoped static: Split by namespace; everything loaded at startup. |
| Dynamic loading | Dynamic: On-demand loading per locale. | Scoped dynamic: Granular loading per namespace and locale. |
Strategy summary
- Static: Simple; no network latency after the initial load. Downside: large bundle size.
- Dynamic: Reduces initial weight (lazy-loading). Ideal when you have many locales.
- Scoped static: Keeps code organised (logical separation) without complex extra network requests.
- Scoped dynamic: Best approach for code splitting and performance. Minimises memory by loading only what the current view and active locale need.
GitHub STARs
GitHub stars are a strong indicator of a project's popularity, community trust, and long-term relevance. While not a direct measure of technical quality, they reflect how many developers find the project useful, follow its progress, and are likely to adopt it. For estimating the value of a project, stars help compare traction across alternatives and provide insights into ecosystem growth.
Results in detail
1 - Solutions to avoid
No clear solution to avoid in solid ecosystem.
2 - Acceptable solutions
(solid-i18next) ([email protected]):
solid-i18next is probably the most popular option because it was among the first to serve JavaScript app i18n needs. It also has a wide set of community plugins for specific problems.
The package is heavy (~14.6kb, which is about 4.7× solid-intlayer).
Still, it shares the same major downsides as stacks built on t('a.b.c'): optimisations are possible but very time-consuming, and large projects risk bad practices (namespaces + dynamic loading + types).
(@solid-primitives/i18n) (@solid-primitives/[email protected]):
Solid primitive is extremely light and efficient. I recommend that solution for light projects, but it can quickly become lacking features for professional solutions including cookie management, proxy redirection, formatters etc. It also misses lazy loading and scoping namespaces for page size optimisation.
(Paraglide) (@inlang/[email protected]):
Paraglide offers an innovative, well-thought-out approach. Even so, in this benchmark the tree-shaking their company advertises did not work for my implementation. The workflow and DX are also more complex than other options.
Personally I dislike having to regenerate JS files before every push, which creates constant merge conflict risk via PRs.
Finally, in comparison with other solutions, Paraglide does not use a store (e.g. Solid signal) to retrieve the current locale to render the content. For each node parsed, it will request the locale from the localStorage / cookie etc. It leads to execution of unnecessary logic that impacts the component reactivity.
3 - Recommendations
(Intlayer) ([email protected]):
I will not personally judge solid-intlayer for objectivity’s sake, since it is my own solution.
Personal note
This note is personal and does not affect the benchmark results. Still, in the i18n world you often see consensus around a pattern like const t = useTranslation('xx') + <>{t('xx.xx')}</> for translated content.
In Solid apps, injecting a function as a JSX.Element is, in my view, an anti-pattern. It also adds avoidable complexity and JavaScript execution overhead (even if it is barely noticeable).