Skip to content

ilingo vs. i18next

i18next is the most widely-used i18n library in the JavaScript ecosystem — mature (since 2011), framework-agnostic at its core, and surrounded by a large plugin ecosystem (backends, language detection, ICU, react-i18next, …). It's an excellent library and the closest functional peer to ilingo.

This page is an honest side-by-side: where ilingo is the better fit, where i18next is, and how the two map onto each other. No FUD — the numbers are sourced and the tradeoffs are real.

The one-paragraph version. ilingo is a smaller, faster, ESM/TypeScript-first core with batteries — lazy-loading stores, a file-system backend, locale negotiation — in the box. i18next is a larger, battle-tested ecosystem with a synchronous API, full ICU MessageFormat (via plugin), and first-party React bindings. Pick ilingo for a lean modern stack across Node / edge / browser / Vue; pick i18next for ecosystem depth, React, or full ICU.

What they share

It's worth clearing this up first, because it's a common misconception: modern i18next is not "non-standard" under the hood. Since v21 it selects plural forms with Intl.PluralRules, and since v21.3 it formats numbers / dates / lists with the Intl.* APIs — exactly like ilingo. So the difference is not "Intl-native vs. not". The real differences are bundle size, architecture, and the shape of the API.

Bundle size

Core packages, no plugins, measured with bundlephobia (minified, then min + gzip):

LibraryMinifiedMin + gzipRuntime deps
ilingo — full barrel~15.3 kB~6.0 kB2 (pathtrace, smob)
ilingoIlingo + MemoryStore~3.3 kB¹
i18next — core~42.4 kB~13.2 kB0

¹ ilingo's own CI-enforced budget (brotli) — see .size-limit.json and Performance → Bundle size.

ilingo's core is less than half i18next's core, gzipped — and the gap widens in a real app. A typical i18next deployment adds plugins: i18next-http-backend (loading), i18next-browser-languagedetector (negotiation), each shipping more bytes. ilingo's equivalents — LoaderStore, negotiateLocale / parseAcceptLanguage — are already counted inside that 6 kB. Tree-shaking goes further still: a defineCatalog-only import is ~1.2 kB.

ilingo declares "sideEffects": false, so a bundler drops every export you don't import.

Throughput

ilingo runs 1.6× – 2.3× faster than i18next per call across four representative workloads — despite ilingo's async get() paying a microtask per call. Full table, methodology, and hardware are on the Performance page; the ratios:

Workloadilingo / i18next
Cache hit, simple string leaf2.03×
Plural lookup (count = 5)2.05×
Cache miss + 3-deep fallback chain2.33×
Template + Intl.NumberFormat modifier1.63×

These are micro-benchmarks — read the caveats. Per-call speed almost never dominates a real app (render and hydration do); treat it as evidence of a short resolution path, not a reason to switch on its own.

Feature by feature

ilingoi18next
Maturitynewer, smaller communitysince 2011, very large community
Core size (min + gzip)~6.0 kB~13.2 kB
Module formatESM-onlyESM + CJS
TypeScriptfirst-party (TS source)first-party types
Plural rulesIntl.PluralRulesIntl.PluralRules (v21+)
Number / date / list formatIntl.*, built-inIntl.*, built-in (v21.3+)
Full ICU MessageFormat (select, nested)✗ — ICU-lite (plurals + {{var, formatter}})✓ via i18next-icu
Fallback chainBCP-47 walk, built-infallbackLng, built-in
Pluggable storageIStore port — memory / fs / lazy loader / customplugin backends
Lazy / code-split loadingLoaderStore, in-corei18next-http-backend (plugin)
File-system backend@ilingo/fs, in-corei18next-fs-backend (plugin)
Locale negotiationnegotiateLocale / parseAcceptLanguage, in-corei18next-browser-languagedetector (plugin)
Translate callasyncget() returns a Promisesynct() returns a string
Vue@ilingo/vue (first-party)i18next-vue (official)
React— (framework-agnostic core is usable)react-i18next (first-party)
Plugin ecosystemsmall, younglarge, mature

Two rows are the actual decision points — far more than bundle bytes:

  • Sync vs. async. i18next's t() is synchronous: call it in render, get a string back. ilingo's get() returns a Promise. That async surface is precisely what lets any store be lazy- or network-backed without an API break — it's what powers LoaderStore and FSStore. The cost is friction if you want a bare synchronous translate in a hot path. In Vue it's a non-issue: @ilingo/vue's useTranslation hides the await behind a reactive Ref.
  • ICU MessageFormat. i18next + i18next-icu supports the full ICU grammar (select, nested plurals, ordinals). ilingo is ICU-lite: CLDR plural categories via definePlural plus Intl formatters via {{value, number(...)}} — but no select / nested message grammar. If your translators rely on full ICU, stay on i18next.

Concept mapping

Porting a mental model — or a codebase — from i18next:

i18nextilingo
t('common:greeting')get({ namespace: 'common', key: 'greeting' })
t('key', { name }){{name}} in the message + data: { name }
key_one / key_other suffixesdefinePlural({ one, other })
namespaces (ns)namespace argument / defineNamespace
fallbackLng: ['de', 'en']fallback option (BCP-47 chain)
i18next-http-backendLoaderStore (loader: (l, ns) => import(...))
i18next-fs-backend@ilingo/fs FSStore
i18next-browser-languagedetectornegotiateLocale(supported, navigator.languages)
addResourceBundle(...)registerStore(new MemoryStore(...))

See Catalog Design, Stores, and Locales & Fallback for the details.

When not to choose ilingo

Honest disqualifiers — reach for i18next (or FormatJS) instead if:

  • You have a large existing i18next codebase. The migration cost rarely pays back; both are good libraries.
  • You need full ICU MessageFormat (select, gender, nested plurals) — use i18next-icu or FormatJS.
  • You're React-first and want the most-used, best-documented bindings — react-i18next has no ilingo equivalent today.
  • You depend on a specific i18next plugin (e.g. a locize workflow or a particular backend connector) with no ilingo store yet.
  • You want a fully synchronous translate function with no async surface anywhere in your stack.

If none of those apply — and a small bundle and a framework-agnostic, modern core matter to you — ilingo is built for exactly that. Start with the Quick Start.

Released under the MIT License.