# i18next changelog > i18next release notes. - Vendor: i18next - Category: Frameworks & Libraries - Official site: https://www.i18next.com/ - Tracked by: What's New (https://whatsnew.fyi/product/i18next) - Harvested from: GitHub (i18next/i18next) - Entries below: 10 (newest first) What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. ## Releases ### v26.3.6 - Date: 2026-07-09 - Version: v26.3.6 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.6 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.6 - fix: allow TypeScript 7 in the optional `typescript` peer dependency range (`^5 || ^6 || ^7`). With `typescript@7.0.2` in a project, `npm install` failed with an `ERESOLVE` peer conflict. The published types are TS7-compatible as-is: every `test/typescript` suite produces identical results under 6.0 and 7.0.2. Reported in [react-i18next#1927](https://github.com/i18next/react-i18next/issues/1927), thanks @andikapradanaarif. ### v26.3.5 - Date: 2026-07-08 - Version: v26.3.5 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.5 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.5 - fix: `$t()` nesting options blocks that span multiple lines are now parsed. `nest()` decided where the nested key ends by testing `match[1]` with `/{.*}/`, whose dot does not cross line breaks — so a `$t(key, { ... })` options object containing a newline was treated as having no options, mis-split as formatters, and the nested lookup ran without its options (placeholders stayed unresolved). The nesting regexp itself already matches newlines inside `$t(...)`; adding the `s` (dotAll) flag makes multiline options behave like the single-line form. Thanks @spokodev ([#2440](https://github.com/i18next/i18next/pull/2440)). - fix: `getUsedParamsDetails` (the `returnDetails: true` path) no longer mutates the passed `replace` object. It wrote `count` straight onto `options.replace` so the returned `usedParams` would include it — a caller reusing one `replace` object across `t()` calls then carried a stale `count` into later interpolations (e.g. a previous call's `count: 5` rendered instead of the current call's value). The details are now built from a copy; `usedParams` still includes `count`. Thanks @spokodev ([#2441](https://github.com/i18next/i18next/pull/2441)). - fix: with the default `skipOnVariables: true` + `escapeValue: true`, a `{{placeholder}}` carried inside an interpolated value now stays literal even when the value contains escapable characters. The skip logic advanced the regex `lastIndex` by the raw value length, but the escaped text written into the string is longer, so `lastIndex` landed inside the inserted value and a trailing `{{placeholder}}` in it got interpolated — leaking another in-scope variable that should have stayed literal (values without escapable characters were already skipped correctly). The advance now uses the escaped length that is actually written, and the regex-safe `$`-doubling is applied only at the `String.replace` call so it can't distort the length arithmetic. Thanks @spokodev ([#2442](https://github.com/i18next/i18next/pull/2442)). ### v26.3.4 - Date: 2026-06-30 - Version: v26.3.4 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.4 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.4 - fix(security): `deepExtend` (used by `addResourceBundle(..., deep, overwrite)`) no longer recurses into inherited properties. It checked key existence with the `in` operator, which walks the prototype chain, so a source key matching an inherited built-in (e.g. `hasOwnProperty`, `toString`) caused recursion into the shared `Object.prototype` function and, with `overwrite: true`, could overwrite e.g. `Object.prototype.hasOwnProperty.call` with a non-callable value — corrupting a shared built-in process-wide (DoS). Existence is now checked with `Object.prototype.hasOwnProperty.call`, so such keys are copied as plain own data instead. This complements the existing `__proto__`/`constructor` guard and is also strictly more correct for an own-property merge. Only affects applications that pass attacker-controlled data with `deep: true` and `overwrite: true`; no standard backend/integration does this. Distinct from CVE-2026-48713 / CVE-2026-48714 (different packages, `setPath` mechanism). Thanks to zx (Jace) for the responsible disclosure. ### v26.3.3 - Date: 2026-06-26 - Version: v26.3.3 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.3 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.3 - fix(types): selector `t($ => $.arr, { returnObjects: true, context })` on a JSON array of **heterogeneous** objects now preserves each element's full shape (e.g. `{ transKey1: string; transKey2: string }[]`) instead of collapsing to a union of partial element types. Two type-level causes: (1) `FilterKeys` evaluated the whole array element type at once, so `keyof (A | B)` only saw the keys common to every element — it now distributes over the object union and filters each element independently; (2) when TypeScript merges mismatched array element types it injects phantom optional `undefined` keys (e.g. `transKey1_withContext?: undefined` on elements that don't define it), which the context-detection helpers mistook for real context variants — they now skip keys typed as `undefined`. Also adds a dedicated `context` + `returnObjects: true` selector overload using `const Fn` + `ReturnType`, so `Target` is no longer collapsed to `unknown` via `ApplyTarget`. Resolves Problem 1 of #2398 (Problem 2 was already fixed on master). Thanks @sauravgupta-dotcom ([#2438](https://github.com/i18next/i18next/pull/2438)). Fixes [#2398](https://github.com/i18next/i18next/issues/2398). ### v26.3.2 - Date: 2026-06-24 - Version: v26.3.2 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.2 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.2 - fix: chained formatters with a parenthesised option that contains the format separator (e.g. `join(separator: ', ')`) now work at **any** position in the chain, not just first. Previously the comma-in-parens reassembly only repaired `formats[0]`, so `{{v, uppercase, join(separator: ', ')}}` split the `join(...)` option on the inner comma and never rejoined it, producing corrupt output. Replaced the first-position-only repair with a position-independent pass that re-joins fragments until each open paren closes. Thanks @spokodev ([#2437](https://github.com/i18next/i18next/pull/2437)). ### v26.3.1 - Date: 2026-06-03 - Version: v26.3.1 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.1 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.1 - fix(types): `t()` with a `keyPrefix` no longer pollutes its return type with sibling keys' values. A regression in 26.3.0 — the `[Res] extends [never]` guards added to `KeysBuilderWithReturnObjects` / `KeysBuilderWithoutReturnObjects` turned the builders into deferred conditional types, so `KeyPrefix` stopped resolving to a literal union and `keyPrefix` inference widened to the whole namespace. Symptom: `useTranslation(ns, { keyPrefix: 'a.b' })` then `t('title')` would resolve to `'.title' | '.title' | ...` instead of just the scoped value. Affected every `react-i18next` user using `keyPrefix`. Restored to the eager 26.2.0 form. The same-namespace conflict handling from #2434 still works via `_DropConflictKeys` at the merge layer (in `options.d.ts`). Thanks @aaronrosenthal ([#2436](https://github.com/i18next/i18next/pull/2436)). ### v26.3.0 - Date: 2026-05-26 - Version: v26.3.0 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.3.0 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.3.0 - feat(types): introduce `ResourceNamespaceMap` — a separate mergeable augmentation surface for namespace resource types, designed for monorepos where multiple packages each want to contribute their own namespaces. Previously, every package had to coordinate on a single `CustomTypeOptions.resources` declaration (or fall back to typing dependency namespaces as `any`) because `resources` is a single property of an interface and TypeScript reports TS2717 when two declarations of the same property disagree. The new interface merges naturally across `declare module 'i18next'` blocks, so each package can ship its own `i18next.d.ts` independently. Per-property merge handles same-namespace contributions from multiple packages, and same-key/different-literal conflicts are silently dropped to avoid poisoning `t()` overload resolution. Fully backwards-compatible — existing `CustomTypeOptions.resources` augmentations continue to work, and both surfaces can coexist. Scalar options (`defaultNS`, `returnNull`, `enableSelector`, etc.) still belong on `CustomTypeOptions`. Thanks @sh3xu ([#2434](https://github.com/i18next/i18next/pull/2434)). Fixes [#2409](https://github.com/i18next/i18next/issues/2409). ### v26.2.0 - Date: 2026-05-14 - Version: v26.2.0 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.2.0 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.2.0 - feat(types): new `parseInterpolation` TypeOption (default `true`). When set to `false` in `CustomTypeOptions`, the type-level extractor stops parsing translation strings for `{{variable}}` patterns. Required by `i18next-icu` users — the default extractor mistakes ICU MessageFormat nested-brace plurals like `{count, plural, one {{count} row} other {{count} rows}}` for an interpolation block and demands a phantom variable name. The flag is type-only; runtime interpolation is governed by `InterpolationOptions` and is unaffected. Fixes [i18next-icu#85](https://github.com/i18next/i18next-icu/issues/85). - fix(types): expose `enableSelector` on `InitOptions` so `i18next.init({ enableSelector: 'strict' })` typechecks without a module augmentation. The runtime already reads `opts?.enableSelector` from init options; this lands the matching type declaration next to the other selector-resolution knobs. Accepts `false | true | 'optimize' | 'strict'`. Thanks @Faithfinder ([#2431](https://github.com/i18next/i18next/pull/2431)) ### v26.1.0 - Date: 2026-05-11 - Version: v26.1.0 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.1.0 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.1.0 - feat: `enableSelector: 'strict'` (TypeOptions + runtime option). Opt-in mode that drops the flattened-primary form from `NsResource` at the type level — every namespace (primary included) is exposed only under its own key on `$`, uniformly across single- and multi-ns hooks. At runtime, a leading selector path segment matching the scope's namespace list is always rewritten as a namespace prefix, including the primary. Eliminates the silent-miss surface area where `t($ => $.primary.foo)` typechecks but doesn't resolve under the default mode (see [#2429](https://github.com/i18next/i18next/issues/2429)). Backward-compatible: default `enableSelector: false | true | 'optimize'` behavior is unchanged. Note: strict mode is incompatible with the [#2405](https://github.com/i18next/i18next/issues/2405) pattern (keys whose names match sibling namespaces) — those users should stay on default mode. ### v26.0.10 - Date: 2026-05-07 - Version: v26.0.10 - Original notes: https://github.com/i18next/i18next/releases/tag/v26.0.10 - Permalink: https://whatsnew.fyi/product/i18next/releases/v26.0.10 - feat: `getFixedT` accepts a fourth optional `fixedOpts` argument carrying `scopeNs` — the full namespace list the bound `t` was created for. The selector API uses `scopeNs` to detect when a path's first segment is a namespace prefix, **without** changing resolution scope. Resolution still uses the bound `ns` (a single primary string in the typical react-i18next setup), so plain `t('key')` lookups stay isolated to the primary namespace exactly as before — only `t($ => $.secondaryNs.foo)` selectors now route correctly under `useTranslation([nsA, nsB])`. Fixes the runtime side of [#2429](https://github.com/i18next/i18next/issues/2429) for the `react-i18next` default-`nsMode` case. The 4th argument is opt-in: existing 3-arg `getFixedT(lng, ns, keyPrefix)` callers see no behavior change.