HomeSandboxShowcaseAppDocBlog
    • EnglishEnglish
      EN
    • русскийRussian
      RU
    • 日本語Japanese
      JA
    • françaisFrench
      FR
    • 한국어Korean
      KO
    • 中文Chinese
      ZH
    • españolSpanish
      ES
    • DeutschGerman
      DE
    • العربيةArabic
      AR
    • italianoItalian
      IT
    • British EnglishBritish English
      EN-GB
    • portuguêsPortuguese
      PT
    • हिन्दीHindi
      HI
    • TürkçeTurkish
      TR
    • polskiPolish
      PL
    • IndonesiaIndonesian
      ID
    • Tiếng ViệtVietnamese
      VI
    • українськаUkrainian
      UK
    /
    Filter docs by framework
    Alt+←
    Why Intlayer ?
    Get Started
    Concept
    • How Intlayer Works
    • Configuration
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • Visual Editor
    • CMS
    • CI/CD Integration
    • TranslationPluralEnumerationConditionGenderInsertionFileNestingMarkdownHTMLFunction Fetching
    • Per Locale File
    • Compiler
    • Auto Fill
    • Testing
    • Bundle Optimization
    Environment
    • Next.js 14 and App Router
      Next.js 15
      Next.js no locale path
      Next.js and Page Router
      Compiler
    • Tanstack Start Solid
    • Astro and React
      Astro and Svelte
      Astro and Vue
      Astro and Solid
      Astro and Preact
      Astro and Lit
      Astro and Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt and Vue
    • Vite and Solid
    • SvelteKit
    • Vite and Preact
    • Vite and Vanilla JS
    • Vite and Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native and Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx and React
    Plugins
    • JSON
    • gettext (.po)
    VS Code Extension
    Agent
    • MCP Server
    • Agent skills
    Releases
    • v8
    • v7
    • v6
    Benchmark
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    Blog
    Ask a question
    1. Documentation
    2. Benchmark
    3. Svelte
    Author: Aymeric PINEAU
    Creation:2026-04-20Last update:2026-05-18
    See the application template on GitHub

    This page has an application template available.

    Reference this doc to your favorite AI assistant
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    Ask your question and get a summary of the document by referencing this page and the AI provider of your choice

    Version History

    1. "Add GitHub star comparative"
      v8.9.85/18/2026
    2. "Init benchmark"
      v8.7.51/6/2026
    Edit this doc

    If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.

    GitHub link to the documentation
    Copy

    Copy doc Markdown to clipboard

    Svelte i18n Libraries - 2026 Benchmark Report

    This page is a benchmark report for i18n solutions on Svelte.

    Table of Contents

    Interactive Benchmark

    Results reference:

    intlayer.org
    See complete benchmark data

    See complete benchmark repository here.

    Introduction

    Internationalization solutions are among the heaviest dependencies in a Svelte 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 optimized implementations, an internationalized 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 organization, dynamic loading, and reactivity when the locale changes.

    TL;DR

    • Intlayer: The most performance-efficient choice (v8.7.12) with the smallest footprint.
    • Paraglide: Strong contender for tree-shaking but has a more complex developer experience and reactivity overhead.
    • svelte-i18n: Feature-complete and standard for Svelte, but carries a much larger bundle weight (~7× Intlayer).

    Test your app

    To quickly spot i18n leakage issues, I set up a free scanner available here.

    intlayer.org

    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)
    • svelte-intlayer (v8.7.12)
    • svelte-i18n (v4.0.1)
    • @inlang/paraglide-js (v2.17.0)

    The framework is Svelte with a multilingual app of 10 pages and 10 languages.

    We compared four loading strategies:

    Show all table content

    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 organized (logical separation) without complex extra network requests.
    • Scoped dynamic: Best approach for code splitting and performance. Minimizes memory by loading only what the current view and active locale need.

    What I measured:

    I ran the same multilingual app in a real browser for every stack, then wrote down what actually showed up on the wire and how long things took. Sizes are reported after normal web compression, because that is closer to what people download than raw source counts.

    • Internationalization library size: After bundling, tree-shaking and minification, the size of the i18n library is the size of the providers + stores code in an empty component. It does not include the loading of translation files. It answers how expensive the library is before your content enters the picture.

    • JavaScript per page: For each benchmark route, how much script the browser pulls in for that visit, averaged across the pages in the suite (and across locales where the report rolls them up). Heavy pages are slow pages.

    • Leakage from other locales: It's the content of the same page but in another language that would be loaded by mistake in the audited page. This content is unnecessary and should be avoided. (e.g. /fr/about page content in /en/about page bundle)

    • Leakage from other routes: The same idea for other screens in the app: whether their copy is riding along when you only opened one page. (e.g. /en/about page content in /en/contact page bundle). A high score hints at weak splitting or over-broad bundles.

    • Average component bundle size: Common UI pieces are measured one at a time instead of hiding inside one giant app number. It shows whether internationalization quietly inflates everyday components. For instance, if your component rerenders, it will load all that data from memory. Attaching a giant JSON to any component is like connecting a big store of unused data that will slow down your components’ performance.

    • Language switch responsiveness: I flip the language using the app’s own control and time how long it takes until the page has clearly switched, what a visitor would notice, not a lab micro-step.

    • Rendering work after a language change: A narrower follow-up: how much effort the interface took to repaint for the new language once the switch is in flight. Useful when the “felt” time and the framework cost diverge.

    • Initial page load time: From navigation to the browser considering the page fully loaded for the scenarios I tested. Good for comparing cold starts.

    • Hydration time: When the app exposes it, how long the client spends turning server HTML into something you can actually click. A dash in the tables means that implementation did not provide a reliable hydration figure in this benchmark.

    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.

    Star History Chart

    Results in detail

    1 - Solutions to avoid

    No clear solution to avoid in svelte ecosystem.

    2 - Acceptable solutions

    (Paraglide) (@inlang/[email protected]):

    Paraglide offers an innovative, well-thought-out approach. In the context of a Vite + Svelte app, the tree-shaking their company advertises works as expected, which is great. But in the case of a React + TanStack Start, the tree-shaking did not work as expected, same for Next.js. That said, I would be double-checking the usage of Paraglide in a Svelte and TanStack Start project. 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. The tool also seems more focused on Vite than on Next.js. Finally, in comparison with other solutions, Paraglide does not use a store (e.g. Svelte store) 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.

    Note on paraglide: the solution inject code in your codebase to import, as a result the metric 'lib size' in the benchmark report is almost 0. Code gen is a good think, because the function used will include only the necessary logic (prefix all vs no prefix, cookie vs storage etc). In comparison Intlayer process to this filtering using env variables injection during the build to force the bundler to tree shake the content depending of the logic. Thanks to this, paraglide and intlayer end up being solution 6-10 times lighter than i18next or next-intl.

    (svelte-i18n) ([email protected]):

    This solution answers all needs for i18n in a Svelte project. But as it's the case for i18next or other main i18n solutions it's a bit heavy (~15.9kb, which is about 7× svelte-intlayer).

    3 - Recommendations

    (Intlayer) ([email protected]):

    I will not personally judge svelte-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 Svelte apps, injecting a function as a Slot is, in my view, an anti-pattern. It also adds avoidable complexity and JavaScript execution overhead (even if it is barely noticeable).

    Solid
    Alt+→

    In this page

      Discussions are anonymous and regularly reviewed to address common issues. Feel free to share feature ideas, feedback on the documentation, or anything related to Intlayer, we use this input to shape our roadmap and improve the product.

      Dynamic JSON loading

      Lazy-loads translations at runtime

      Scoped JSON (namespacing)

      Per-page translation namespaces

      I18n Performance Benchmark

      No data available

      What is this metric?

      The total gzip-compressed size of the internationalization library bundle. It only includes the provider and content retrieval logic after tree-shaking and minification.

      Why is it important?

      A smaller library size reduces the initial JavaScript payload, leading to faster download and execution times on the client.

      View as