Repository navigation
Update dependency i18next to v26.5.8 - #12166
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
Contributor
Author
|
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
from
October 21, 2026 16:54
c328053 to
0c2fa5a
Compare
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
6 times, most recently
from
October 22, 2026 15:58
8f9c658 to
c545bcf
Compare
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
from
October 22, 2026 23:15
c545bcf to
f7b58c7
Compare
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
10 times, most recently
from
October 23, 2026 17:49
f765083 to
4ac054d
Compare
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
6 times, most recently
from
October 23, 2026 21:09
b7bfed3 to
921cd4b
Compare
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
2 times, most recently
from
October 24, 2026 06:44
c4728f6 to
bea3fec
Compare
renovate
Bot
force-pushed
the
renovate/i18next-26.x
branch
from
October 24, 2026 08:45
bea3fec to
87560f9
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
26.4.4→26.5.8Release Notes
i18next/i18next (i18next)
v26.5.8Compare Source
joinArraysnow get the same resolved details as strings. The joined value was extended withlastKeyin the place of the resolved lookup, so withpostProcessPassResolveda post processor got nousedLng,usedNSorexactUsedKey(t('steps', { joinArrays: ' / ' })reportedundefined/undefined:undefined). This affected the subliminal post processor used by the locize InContext editor, which could not map a joined array to its key. The nesting recursion guard did not get the parent key either, so arrays that nest each other (listA: ['a', '$t(listB)'],listB: ['b', '$t(listA)']) threwMaximum call stack size exceeded. They now stop at the guard, as strings do. Ani18nFormatplugin withhandleAsObjectandparsealso no longer throwsCannot read properties of undefined (reading 'usedNS')on joined arrays. Thanks @nk-batman21 (#2458).v26.5.7Compare Source
cacheInBuiltFormats: true, built-in formats now also work when thet()options contain a BigInt or a circular object. The cache key was built withJSON.stringifyover all options, including the interpolation values, which throws on those, so every built-in format in that call returned the raw value:t('num', { val: 12345678901234567890n })with'Total: {{val, number}}'returned'Total: 12345678901234567890'instead of'Total: 12,345,678,901,234,567,890', and passing an object with a back-reference (like an ORM entity) left all numbers, dates and lists of that call unformatted. When the key cannot be built, the value is now formatted without the cache, as withcacheInBuiltFormats: false. This also applies to formatters added withaddCached. Other calls still use the cache as before. Thanks @nk-batman21 (#2457).v26.5.6Compare Source
cloneInstance({ forkResourceStore: true })now copies the resources at every level. It copied them only down to the namespace objects, so nested keys and arrays stayed shared with the original instance:addResource()with a nested key (fork.addResource('en', 'translation', 'greeting.hello', 'Hi')) or a deepaddResourceBundle()on the fork also changed the original instance and every other fork. Flat keys were already isolated. Forking a large store takes a bit longer: with 300k keys in nested groups, about 11 ms instead of 3 ms per fork. Clones withoutforkResourceStorestill share the store as before. Thanks @nk-batman21 (#2456, follow-up to #2270).v26.5.5Compare Source
skipOnVariables: true, a{{placeholder}}inside a value inserted with an unescaped{{- var}}now stays literal, as it already did for{{var}}. The escape pass ran after the unescaped values were written and scanned them again, sot('{{- a}}', { a: '{{b}}', b: 'c' })returned'c'instead of'{{b}}'. With pre-built HTML that carries user text, liket('You may contact {{name}} at {{- emailHTML}}.', { name, emailHTML }), that text could pull another variable of the samet()call into the output. Results withskipOnVariables: false, and values without placeholders, are unchanged. Compatibility note: a{{- var}}value whose placeholders were meant to be filled from the samet()call now keeps them literally;skipOnVariables: falserestores the old behavior. Thanks @nk-batman21 (#2455, reported in #1595).v26.5.4Compare Source
skipOnVariables: true, a{{placeholder}}inside an interpolated value now stays literal also when the same placeholder appears later in the translation. Each value was written withString.replace, which replaces the first copy of the placeholder text, and that could be the copy inside an earlier value:t('{{name}} has {{count}} items', { name: '{{count}}', count: 5 })returned'5 has {{count}} items'instead of'{{count}} has 5 items'. The value is now written at the position of the matched placeholder. Results withskipOnVariables: falseare unchanged. Thanks @nk-batman21 (#2454, reported in #1595).useRawValueToEscape: true, a non-string value in an unescaped{{- var}}placeholder or withescapeValue: falseno longer throwsval.replace is not a function; it is converted to a string like any other value.v26.5.3Compare Source
countalso when the call passes an explicitns.t(($) => $.item)already failed withoutcount, butt(($) => $.item, { ns: 'items' })compiled, although at runtime it looks upiteminstead ofitem_one/item_otherand returns the key. It now fails the same way, also withordinal: true,defaultValue, annsarray, a key prefix andi18n.t. Calls withcount,context,returnObjects: trueand arrays of selectors, as well as return types, are unchanged. Thanks @nyarthan (#2452).v26.5.2Compare Source
t()call with a missing, misspelled or wrongly typed option now reports that option again (Property 'album' is missing,Type 'string' is not assignable to type 'number'), as TypeScript 5 and 6 do. TypeScript 7 elaborated the error against the default-value signature instead and ended in'{ count: 3; albm: "Summer"; }' is not assignable to type 'string': on a failed call TypeScript explains the last of the equally matching signatures, and TypeScript 7 sorts the 3-element[key, defaultValue, options?]last. It is now written as two signatures,[key, defaultValue]and[key, defaultValue, options]. This affects the default key checks with i18next{{name}}messages as well asparseInterpolation: 'icu'and'mf2'. Which calls compile, their return types and the error positions are unchanged on TypeScript 5.9, 6 and 7.v26.5.1Compare Source
t()calls against a large namespace is no longer quadratic in the number of keys. TypeScript does not cachekeyofof an object type, and the types rebuilt the union of all keys of a namespace once per key while building the key union, and again in everyt()call to look up the return type. Both now use a cached key union, and a literal key is looked up directly instead of being intersected with every key. With 5,000 keys in one namespace and one call per key, the check time went from 14.8s to 1.1s (TypeScript 6); with 1,000 keys from 0.75s to 0.27s. Keys, return types and errors are unchanged.enableSelector: true/'strict') withcontextis no longer quadratic in the size of an object. To decide which keys a context keeps, the types scanned all keys of the object once for every key, also when TypeScript checks the selector withcontextwidened tostring. With 1,000 keys plus one context variant each, a namespace took 18.7s and failed with "Type instantiation is excessively deep and possibly infinite" (TS2589); 2,500 and more ran out of memory. The context variants of an object are now collected once, in one pass over its keys: 1,000 keys check in 0.69s, 5,000 in 3.1s. Long keys (whole sentences withkeySeparator: false) work as before. Selected values and errors are unchanged.v26.5.0Compare Source
parseInterpolation: 'icu'andparseInterpolation: 'mf2'typet()options from the message's ICU MessageFormat arguments (i18next-icu) or MessageFormat 2 variables (i18next-mf2), so ICU and MF2 users no longer needparseInterpolation: falseand lose argument checking. Missing, misspelled and wrongly typed arguments fail, and so does leaving out the options for a message with arguments (t('greeting')); that error names the missing arguments. Opt-in, defaulttrueis unchanged.{name}takesstring | number,{n, number},pluralandselectordinaltakenumber,{d, date}and{t, time}takeDate,selecttakes its case keys or any string (forother), and arguments nested in cases are required too.#and tags are not arguments, apostrophe quoting is read like intl-messageformat does.{$name}takesstring | number, a variable annotated with:number,:integer,:currency,:percentor:unit(inline or through.input/.local) takesnumber,:datetime,:dateand:timetakeDate,:stringtakesstring, option and markup variables (minimumFractionDigits=$digits,{#link href=$url}) are required too,.localvariables are not arguments, and|quoted literals|and\{escapes are skipped.interpolationFormatTypeMapoverrides a type by ICU format or MF2 function name, e.g.date: Date | numberor a customuppercase: string.t(),getFixedT(),i18n.t, key prefixes, namespaces, the selector API and react-i18next'sTransvalues. Messages need literal types, as the resources file from i18next-cli'stypescommand has them.false(TypeScript 6), 0.5s instead of 0.26s with TypeScript 7. Messages that no call uses cost nothing.Property 'name' is missing) instead of'{ nmae: string }' is not assignable to type 'string'from the default-value overload.v26.4.7Compare Source
cloneInstance()no longer inheritspreload.loadResources()adds everypreloadlanguage to each load, and clones copiedpreloadfrom the parent, so a clone'sinit()and everychangeLanguage()walked all preloaded languages × all namespaces throughqueueLoad()/hasResourceBundle(), although the parent had already loaded them into the shared store. With i18next-http-middleware (one clone +changeLanguage()per request), 25 preloaded languages and 20 namespaces, that was most of the per-request CPU: the reproduction from the issue went from ~90 µs to ~10 µs per request, the same as with a single language. A clone now only loads what it uses itself: itschangeLanguage()no longer waits for parent preload languages that are still loading (the parent's owninit()still does), andclone.loadNamespaces()loads the new namespace for the clone's language and fallbacks instead of every preloaded language.clone.loadLanguages()works as before, the parent instance is unchanged, and passingpreloadtocloneInstance()keeps the old behavior. Thanks @theMostCuriousHomunculus for the detailed report (#2451).v26.4.6Compare Source
toResolveHierarchy()checked the rawfallbackLngvalue against the list, but the list holds formatted codes, so any fallback written differently from its formatted form slipped through:lng: 'de-CH'withfallbackLng: 'de-ch'gavelanguages['de-CH', 'de', 'de-CH'], and the same happened withfallbackLng: 'EN'+cleanCode,lowerCaseLng, and Intl aliases (iw-IL→he-IL). Missing keys were looked up in the same language twice. Only exact duplicates are removed; the order is unchanged. Thanks @lprnmns (#2450).v26.4.5Compare Source
hasLoadedNamespace(ns, { lng })no longer staysfalseforever when the passed inlngis loaded under another code, or not at all. It checked the load state of the rawlng, butloadLanguages()stores a language under its resolved code (de-ch→de-CH,de-CH→dewithload: 'languageOnly') and skips alngoutsidesupportedLngsentirely (only the fallback gets loaded), so that state never got set. react-i18next'suseTranslation(ns, { lng })then never became ready: withuseSuspenseit kept throwing an already resolved promise and React retried forever (100% CPU, SSR never finished), without it the load effect re-rendered in a loop. It now checks the code the language is actually loaded under, and for alngoutsidesupportedLngsonly waits for the fallback, which is also whatt()resolves to. Calls withoutlngand theprecheck(react-i18next'sbindI18n: 'languageChanging') are unchanged (react-i18next#1934).Configuration
📅 Schedule: (UTC)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.