Задайте питання та отримайте підсумок документа, вказавши цю сторінку та обраного вами постачальника штучного інтелекту
Вміст цієї сторінки перекладено за допомогою штучного інтелекту.
Переглянути останню версію оригінального вмісту англійськоюЯкщо у вас є ідея щодо покращення цієї документації, будь ласка, долучіться, надіславши pull request на GitHub.
Посилання на документацію на GitHubСкопіювати документацію у форматі Markdown в буфер обміну
vue-i18n VS Intlayer | Vue Internationalization (i18n) Benchmark
vue-i18n is the reference i18n library for Vue. Intlayer is a compiler-based, component-scoped alternative with a Vue integration (vue-intlayer). We already compared their features and developer experience. This article looks at what each one costs once the app is built.
The data comes from Benchmark Bloom, an open-source suite that builds the same application with each library and records what the browser actually downloads and executes.
tl;dr: On the same Vite + Vue 3 app,vue-i18nships 134.9 KB of gzipped JavaScript per page against 41.3 KB for the app without i18n. Intlayer ships 57.1 KB. Thevue-i18nruntime alone weighs 24.3 KB gzip (6x Intlayer's 3.9 KB), every page carries 90% of foreign-page strings, and a component compiled in isolation drags in 196 KB because it is bound to the global message tree. The@intlayer/vue-i18nadapter keeps thevue-i18nAPI and measured 47.0 KB per page.
In short
- vue-i18n - The de-facto i18n library for Vue 2 / Vue 3 and the core of
@nuxtjs/i18n. ICU-style messages, SFC<i18n>blocks,v-tdirective,d()/n()formatters, large ecosystem. Messages are registered on a global instance atcreateI18n(); lazy loading per locale is a manualsetLocaleMessage()pattern, and per-route splitting is yours to build. - Intlayer - Component-centric content model.
.content.tsdictionaries sit next to the component they serve, a build-time compiler (vite-intlayer) tree-shakes and lazy-loads them per component and per locale, strict TypeScript types are generated from your content, and missing translations fail at build time. Ships router / SEO helpers, a Visual Editor / CMS and AI-assisted translation.
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
Badges update automatically. Snapshots will vary over time.
Side-by-side feature comparison
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
| Feature | vue-intlayer (Intlayer) | vue-i18n |
|---|---|---|
| Translations near components | ✅ Yes, .content.ts collocated with each component | ✅ Via SFC <i18n> blocks (optional); global catalogs are the common setup |
| TypeScript integration | ✅ Strict types auto-generated from content | ✅ Good typings; strict key safety needs schema typing and discipline |
| Missing translation detection | ✅ TypeScript error + build-time error/warning | ⚠️ Runtime fallback + console warning |
| Rich content (components / Markdown) | ✅ Direct support | ⚠️ <i18n-t> component interpolation; Markdown via external plugins |
| ICU support | ⚠️ WIP | ✅ Yes |
| Formatting (dates, numbers, currencies) | ✅ Intl-based formatters | ✅ d() / n() with datetimeFormats / numberFormats |
| Localized routing | ✅ Helpers for Vue Router / Nuxt, getMultilingualUrls | ⚠️ Not core (@nuxtjs/i18n or custom router setup) |
| SEO helpers (hreflang, sitemap, robots) | ✅ Built-in helpers | ❌ Not core |
| Tree-shaking (ship only used content) | ✅ Per component, per locale, automated by the compiler | ⚠️ Manual: split catalogs, setLocaleMessage() per route |
| Lazy loading | ✅ importMode: 'dynamic' (one line of config) | ✅ Manual import() + setLocaleMessage() |
| Purge unused content | ✅ Dead dictionaries are dropped at build time | ❌ Not built-in |
| Testing missing translations (CLI / CI) | ✅ npx intlayer content test | ⚠️ Third-party (vue-i18n-extract) |
| AI-powered translation | ✅ Built-in, uses your own provider keys | ❌ No |
| Visual Editor / CMS | ✅ Free Visual Editor + optional CMS | ❌ No (external localization platforms) |
| MCP server & Agent Skills | ✅ Yes | ❌ No |
| Ecosystem / community | ⚠️ Smaller but growing fast | ✅ Large and mature in the Vue ecosystem |
The benchmark
What was measured
The Benchmark Bloom suite builds the same Vite + Vue 3 application with each library: 10 pages (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 locales (en, fr, es, de, it, pt, zh, ja, ko, ru), identical components and identical content. Pages are measured in en and fr.
Both libraries were tested in the static configuration, the one most Vue projects ship: for vue-i18n, every locale's JSON imported and passed to createI18n({ messages }); for Intlayer, the default importMode: 'static'. In that mode Intlayer bundles every locale too, but the compiler still scopes content per component, so a page only carries the dictionaries of the components it renders.
For each build, the suite records:
- Lib size: gzip size of an empty component that only imports the i18n library. The fixed cost of the runtime.
- Page JS: gzip JavaScript downloaded per page, averaged over all pages and locales.
- Locale leak %: share of translated strings found in the downloaded JS that belong to a locale the user is not viewing (fingerprinted on
enandfr, so 50% means "the other measured locale is fully present"; with 10 locales bundled, the real waste is higher). - Page leak %: share of translated strings found in the downloaded JS that belong to a page the user is not on.
- Component avg: average gzip size of each component compiled in isolation. Shows how much i18n runtime and catalog a single component drags in.
- E2E reactivity: wall-clock time between selecting a new locale and
html[lang]updating in the DOM (Playwright, 5 iterations). - Page load:
PerformanceNavigationTiming.duration.
Numbers below come from the run dated 2026-09-12 withvue-i18n11.4.0 andintlayer9.5.0 / 9.5.1. The test application is deliberately small (a few dozen strings per locale), so leakage percentages describe a pattern: they grow with your content while the runtime cost stays fixed.
Results on Vite + Vue 3
Відкрийте таблицю в модальному вікні, щоб чітко переглянути всі дані
| Library | Strategy | Lib size (gz) | Lib size (min) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Page load |
|---|---|---|---|---|---|---|---|---|---|
| base (no 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 |
The base app's page-leak column is left blank: with no i18n library, the fingerprinting picks up hard-coded strings in shared chunks and the number is not meaningful.
How to read it
- Runtime cost.
vue-i18nis one of the heaviest runtimes in the whole benchmark: 24.3 KB gzip / 83.2 KB minified for an empty component that only imports it.vue-intlayercosts 3.9 KB gzip. That gap is paid on every page regardless of how many strings you have. - Per-page JavaScript. The app without i18n weighs 41.3 KB.
vue-i18nmore than triples it to 134.9 KB; Intlayer lands at 57.1 KB, +15.8 KB, most of which is the ten bundled locales (see the next point). - Leakage. With
createI18n({ messages: { en, fr, ... } }), every page ships every locale and every page's strings: 50% locale leakage (on the two fingerprinted locales) and 90% page leakage. Intlayer'sstaticmode also bundles every locale (hence the comparable locale-leak figure) but has 0% page leakage: a page only pulls the dictionaries of the components it renders. Switching toimportMode: 'dynamic'removes the locale leakage as well; that configuration was not part of this Vue run. - Component size is where the architecture shows. A component calling
useI18n()compiles to 196 KB on average, becauset()is bound to the global instance that holds every message of every locale. The same component withuseIntlayer()compiles to 7.7 KB: it only reaches its own dictionary. - Reactivity is a non-issue for both (2-5 ms). Vue's reactivity system makes locale switching cheap once the messages are in memory.
@intlayer/vue-i18n, the drop-in adapter, keeps thevue-i18nAPI and measured 47.0 KB per page and 8.4 KB per component, with the application code untouched.
For reference, the same run measured fluent-vue at 171.8 KB per page, 29.7 KB of runtime and 217 KB per component.
Why the gap? Global instance vs. compiled dictionaries
vue-i18n is a runtime. createI18n() builds a global instance holding a message tree per locale; useI18n() binds each component to it; t("footer.github") looks the key up at render time. This is what makes SFC <i18n> blocks, v-t, and runtime message loading possible, and it is also why every component's dependency graph includes the whole tree:
Скопіюйте код у буфер обміну
Optimizing means you split en.json into per-route files, you call setLocaleMessage() in a router guard, and you keep the route-to-file map correct as components move. The runtime can't do it for you because it has no idea which keys a component will ask for.
Intlayer moves that knowledge to the build. Content is declared next to the component, and vite-intlayer resolves which component imports which dictionary:
Скопіюйте код у буфер обміну
The compiler emits, per dictionary and per locale, exactly the JSON that component needs, and drops dictionaries nothing imports. Per-route scoping is a consequence of per-component scoping, not a task.
To also drop the unused locales, setdictionary.importMode: 'dynamic'inintlayer.config.ts. See the bundle optimization doc.
Developer experience
Setup
vue-i18n
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
Intlayer
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
Component
vue-i18n
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
t('counter.label') is a string until you type the message schema yourself; a typo renders the key.
Intlayer
Скопіюйте код у буфер обміну
Скопіюйте код у буфер обміну
label and increment are typed; a typo is a TypeScript error, a missing French value is a build error.
Lazy loading per locale
vue-i18n
Скопіюйте код у буфер обміну
Then call loadLocaleMessages() from a router guard, and split locales/{locale}.json by route yourself if you want per-page scoping.
Intlayer
Скопіюйте код у буфер обміну
Keep the vue-i18n API, get Intlayer's output
@intlayer/vue-i18n is a drop-in adapter: useI18n(), t(), d(), n(), {name} and {0} interpolation, pipe plurals ("car | cars"), v-t and i18n.global.locale keep working, served from Intlayer dictionaries compiled by vite-intlayer.
Скопіюйте код у буфер обміну
In the benchmark, the compat build of the same app went from 134.9 KB to 47.0 KB per page and from 196 KB to 8.4 KB per component, with the components untouched. Your existing locales/{locale}.json can stay the source of truth through the JSON sync plugin.
See the vue-i18n migration guide and the compatibility doc. Nuxt users have the same path through @nuxtjs/i18n compatibility.
When to choose which?
- Choose vue-i18n if you want the standard Vue approach, you rely on ICU messages or SFC
<i18n>blocks, you already use@nuxtjs/i18n, or a translation platform expects centralized JSON. Budget the time to split catalogs and lazy-load per route if bundle size matters. - Choose Intlayer if you want component-scoped content, strict TypeScript, build-time missing-key errors, zero-effort tree-shaking and lazy loading, and built-in editorial tooling (Visual Editor, CMS, AI translation, MCP server). Especially relevant for large, modular Vue / Nuxt codebases and design systems.
- Choose
@intlayer/vue-i18nif you are already onvue-i18nand want the bundle gains without a rewrite.
Related comparisons
- next-intl vs Intlayer (same benchmark)
- i18next vs Intlayer (same benchmark)
- Lingui vs Intlayer (same benchmark)
- vue-i18n vs Intlayer (features & DX)
- Is vue-i18n outdated?
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.
Conclusion
vue-i18n is mature, flexible and deeply integrated with Vue. The benchmark shows what its runtime-first design costs on a Vite build: a 24 KB gzip runtime, 134.9 KB per page for an app that weighs 41 KB without i18n, 90% foreign-page content on every page, and components that each reach 196 KB because they hang off the global message tree.
Intlayer moves the work into the compiler. Per-component dictionaries and dead-content purging are build outputs, not conventions. On the same app: 3.9 KB runtime, 57.1 KB per page, 0% page leakage, components 25x smaller. And if a rewrite isn't on the table, @intlayer/vue-i18n gets most of the way there with the components untouched.
All the raw data, the test apps and the scripts are in the Benchmark Bloom repository. Run it yourself.
Refer to the 'Why Intlayer?' doc for more details.
Коментарі
Поки що немає коментарів. Будьте першим, хто поділиться своїми думками.
