i18next-icu

An i18next format plugin that swaps i18next's interpolation syntax for full ICU MessageFormat, powered by intl-messageformat.

Library
npm
v2.4.4
98stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
51/100Fair
Development Activity68
Maintenance24
Community40
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
58/100Fair
Architecture70
Code Quality72
Innovation40
Learning Curve50

i18next-icu is an official i18next plugin that replaces i18next’s own interpolation/pluralization engine with the ICU MessageFormat spec, delegating all parsing to formatjs’s intl-messageformat library. Instead of i18next’s {{variable}} interpolation and _plural key suffixes, translators write standard ICU syntax such as {count, plural, one {# item} other {# items}}, giving locale-correct plural, select, and gender rules plus ICU number/date formatting for every language Intl supports.

The plugin is a thin adapter: it implements i18next’s i18nFormat interface (init, parse, addLookupKeys, clearCache) and forwards each translation lookup to IntlMessageFormat, with an internal memoization cache keyed by language/namespace/key so repeated t() calls for the same string don’t re-parse the ICU pattern. A recent addition hardens the internal path-walking utilities against prototype-pollution style keys (__proto__, constructor, prototype) and adds an optional escapeVariables mode that HTML-escapes interpolated values before they reach the ICU parser, guarding against strings like user:< breaking parsing or producing unexpected output.

Because only the ICU format is respected once the plugin is active, i18next’s own interpolation and plural helpers stop applying to translations using this plugin — teams adopt it specifically when they want a single, standards-based message format across an app’s translations rather than i18next’s homegrown syntax.

What You Get

  • A single ICU class you pass to i18next.use() that fully replaces i18next’s built-in interpolation and plural resolution with ICU MessageFormat parsing.
  • Per-key memoization of compiled ICU message formatters, with configurable cache-clearing on i18next or resource-store events (bindI18n / bindI18nStore).
  • A parseErrorHandler hook that lets you supply a fallback string (instead of throwing) whenever a translation fails to parse as valid ICU.
  • A parseLngForICU hook to remap i18next language codes (e.g. pseudo-locales like en-ZZ) to a locale ICU can format correctly.
  • An escapeVariables option that HTML-escapes interpolated variable values before ICU parsing, plus prototype-pollution-safe path handling in the internal cache utilities.
  • TypeScript type definitions, including guidance for opting translation-key extraction out of i18next’s default {{variable}} interpolation parser so ICU’s single-brace plural syntax doesn’t produce phantom variables.

Common Use Cases

  • Apps that need correct plural/gender rules across many locales (Arabic’s six plural categories, Slavic language plurals, etc.) without hand-writing per-language plural logic.
  • Teams migrating translation content from a FormatJS/react-intl-based stack onto i18next, where translators already write ICU MessageFormat strings.
  • Products embedding locale-sensitive number, date, and currency formatting directly inside translation strings instead of pre-formatting values in application code.
  • React apps combining react-i18next’s <Trans> component with ICU-formatted strings, relying on the plugin’s ignoreTag handling so <0></0> child placeholders don’t conflict with ICU parsing.

Under The Hood

Architecture The package is a single-responsibility adapter: src/index.js exports an ICU class that satisfies i18next’s i18nFormat plugin contract (init, parse, addLookupKeys, clearCache), so i18next can swap its own interpolation/pluralization engine for this one at i18next.use(ICU).init(...) time. Each parse() call resolves options through a small defaults()-merge chain (i18nextOptions over caller-supplied options over prior instance options over library defaults), lazily compiles an IntlMessageFormat instance for the given translation string and language, and memoizes it in an internal mem object keyed by language.namespace.key via a custom setPath/getPath object-path walker in src/utils.js. That walker is deliberately hardened against __proto__/constructor/prototype path segments, so a maliciously-shaped translation key can’t be used to pollute Object.prototype through the cache. There is no other internal layering — one class, one utility module, and a direct dependency on intl-messageformat for the actual ICU parsing/formatting.

Tech Stack Written in plain ES2015+ JavaScript, published as dual ESM/CommonJS builds (dist/es, dist/commonjs) plus a UMD bundle (i18nextICU.js / .min.js) produced via Babel and Rollup, with intl-messageformat (>=10.3.3 <12.0.0) declared as the sole peer dependency the plugin wraps. Type definitions ship as a hand-written index.d.ts module declaration rather than being compiler-generated. Development tooling includes Jest for tests, ESLint with the Airbnb config, and tsc --noEmit run as part of npm test purely for type-checking the surface against consumers’ TypeScript configs — there is no separate build-time type emission step.

Code Quality The repo carries two focused Jest spec files: icu.spec.js covers core ICU parsing behavior (plurals across locales including Arabic’s six categories, custom number formats, error-handler fallback behavior, and react-i18next <Trans> placeholder compatibility), and a dedicated security.spec.js explicitly tests the prototype-pollution guards in the path-walking utilities. Coverage is tracked via Coveralls (.coveralls.yml). tsc --noEmit type-checks the codebase against index.d.ts as part of the test script, and ESLint (Airbnb ruleset) is configured for style enforcement. No GitHub Actions workflow file was present in this shallow clone, so CI configuration beyond the local test/lint scripts couldn’t be directly confirmed.

What Makes It Unique The library itself is a thin, standard integration — it doesn’t reimplement ICU MessageFormat, it delegates entirely to intl-messageformat — so its value is less technical novelty and more filling a specific gap in i18next’s plugin surface for teams that want ICU-standard message syntax instead of i18next’s own interpolation dialect. The one genuinely deliberate technical choice is defensive: an escapeVariables option that HTML-escapes interpolated values before they reach the ICU parser, paired with the prototype-pollution-safe cache key walker, both added specifically to harden a plugin that sits in the path of user-supplied translation variables.

Used by 5 apps in this directory

TypeScript
99%
Other

Activepieces

Automation · AI Assistants

24,298

Open-source AI automation platform that converts 280+ workflow integrations into MCP servers for LLMs, with no-code builders and TypeScript extensibility.

View details
92
Repo Health
85
Technical
64
Dependency
Built with
TypeScript99%
Updated today
TypeScript
97%
Other

Formbricks

Forms Surveys · Marketing · Analytics

12,897

Open-source experience management platform for in-app, website, email, and link surveys — privacy-first and fully self-hostable.

View details
93
Repo Health
81
Technical
70
Dependency
Built with
TypeScript97%
Updated yesterday
TypeScript
91%
AGPL 3.0

PeerTube

Social Media

15,316

A federated, ActivityPub-based video hosting platform built by Framasoft — self-hostable instances interconnect into a network with no vendor lock-in, P2P-assisted streaming, and no ads.

View details
95
Repo Health
75
Technical
70
Dependency
Built with
TypeScript91%
Updated 1 weeks ago
TypeScript
70%
AGPL 3.0

Plane

Productivity · Project Management · Collaboration

58,977

Open-source project management platform to replace Jira, Linear, and ClickUp — with built-in cycles, real-time collaborative docs, and full self-hosting.

View details
89
Repo Health
82
Technical
77
Dependency
Built with
TypeScript70%
Python27%
Updated 3 days ago
TypeScript
96%
AGPL 3.0

Rallly

Scheduling

5,248

Self-hostable group scheduling polls that eliminate back-and-forth emails and find the best meeting time for everyone.

View details
91
Repo Health
75
Technical
67
Dependency
Built with
TypeScript96%
Updated yesterday

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search