- BREAKING: drop
cross-fetchdependency.i18next-http-backendnow requires a host-providedfetch. This is available in Node ≥ 18 (stable since Node 21), all modern browsers, Deno, and Bun. For runtimes without nativefetch, install a ponyfill yourself and inject it viaoptions.alternateFetch, or stay on v3.x. - BREAKING: minimum Node version is now 18 (
engines.node = ">=18"). - chore: simplified environment detection in
lib/request.js— usesglobalThis(withglobal/windowfallbacks for legacy embedded runtimes) instead of separateglobal.*/window.*branches per API. XHR / ActiveXObject are still picked up if the host provides them, but no longer polyfilled. - chore: declared
"sideEffects": falsefor better tree-shaking by downstream bundlers. - build: replaced babel + browserify + uglify-js with
tsdown(rolldown + oxc). One config produces ESM, CJS, and the IIFE browser bundles. Drops@babel/cli,@babel/core,@babel/preset-env,babel-plugin-add-module-exports,browserify,uglify-js, thefixcjsrewrite hack, and the--ignore cross-fetchbrowserify flag. Side benefit: minified browser bundle shrinks from ~13 KB to ~6.8 KB (oxc minifier + no babel runtime helpers). - build: ESM and CJS outputs are now bundled into a single
index.jsper format (previously one file perlib/*.jsmodule). The package'sexportsmap is unchanged, so this is invisible to consumers using documented entry points. - lint: replaced
eslint-config-standard(+ five plugins) withneostandardand migrated to ESLint 9 flat config (eslint.config.mjs). Removed deprecatedtslintanddtslint—test:typescriptnow runstsc --noEmitplustsd. - chore: tightened
.npmignore— published tarball no longer includes the sourcelib/, the build configs (tsdown.config.ts,eslint.config.mjs,tsconfig.json), or the rootindex.jsre-export shim. Drops from 21.3 KB → ~17 KB packed. - docs:
alternateFetchis now documented in the README options block as the supported escape hatch for fetch ponyfills, test mocking, and request interception. v4 migration note added to "Getting started".
- fix: allow forward slashes in
nsvalues so nested namespace names (mapping to URL layouts such as/locales/en/a/b.json) fetch correctly again. 3.0.5's security fix applied the same strict URL-segment check to bothlngandns, which was correct forlng(no BCP-47 shape contains/) but over-strict forns— nested namespaces containing/were never officially supported, but the behaviour fell out of the implicit string-substitution semantics ofloadPathand is common enough in the wild to be worth accommodating.isSafeUrlSegmentis now split intoisSafeLangUrlSegment(strict — still rejects/) andisSafeNsUrlSegment(loose — allows/but still rejects..,\, URL-structure characters, control chars, prototype keys, and oversized inputs).isSafeUrlSegmentis kept as a backwards-compatible alias for the strict check. The 3.0.5 security fix remains in force for every concrete attack pattern from the original advisory.
Security release — all issues found via an internal audit. See published advisory GHSA-q89c-q3h5-w34g.
- security: refuse to build request URLs when
lngornsvalues contain path-traversal, URL-structure (?,#,%,@, whitespace), path separators, control characters, prototype keys, or exceed 128 chars. Prevents path traversal / SSRF / URL injection via attacker-controlled language-code values.isSafeUrlSegmentis permissive for legitimate i18next language codes (any BCP-47-like shape, underscores, hyphens, dots,+-joined multi-language requests) (GHSA-q89c-q3h5-w34g) - security: per-instance
omitFetchOptions— the fetch-options-stripping fallback is now scoped to a single backend instance viaoptions._omitFetchOptionsinstead of a module-level boolean. One instance hitting a "not implemented" fetch error no longer permanently stripsrequestOptions(includingcredentials,mode,cache) from every other backend instance in the same process - security: strip CR/LF/NUL and other C0/C1 control characters from
lng/ns/ URL values before they appear in error-callback strings (CWE-117 log forging) - security: redact
user:passwordcredentials from URLs before including them in error-callback strings — prevents leaking basic-auth credentials embedded inloadPath/addPath - security: iterate own enumerable keys only (
Object.keys+ prototype-key guard) inaddQueryStringand in thecustomHeadersloop in XHR mode — prevents prototype-pollution amplification into the URL and request headers - chore: ignore
.env*and*.pem/*.keyfiles in.gitignore
- use own interpolation function for loadPath and addPath instead of relying on i18next's interpolator i18next#2420 — this means only
{{lng}}and{{ns}}placeholders are supported; custom interpolation prefix/suffix from i18next config no longer applies to backend paths
- optimize fetchApi selector
- try to get rid of top-level await
- fix for Deno 2 and removal of unnecessary .cjs file
- for esm build environments not supporting top-level await, you should import the
i18next-http-backend/cjsexport or stay at v2.6.2 or v2.7.1
- optimize fetchApi selector [backported]
- same as 2.6.2
- deprecated, same as v3.0.0
- improve network error detection across browsers 152
- optimize "Failed to fetch" retry case 147
- fix "Failed to fetch" retry case 147
- dereference timers in node.js so that the process may exit when finished 139
- fix: remove typeof window.document === 'undefined' check which deopt bundle optimization 137
- added fetch interceptor to the Backend Options 133
- fix: overriding options
- fix: mjs typings export
- fix: separate cjs and mjs typings
- fix for browser usage
- update deps
- hack for debug mode in react-native
- fix for types moduleResolution "node16"
- parseLoadPayload for POST request 110
- regression fix for saveMissing signature 1890
- typescript: export the backend options type 105
- typescript: static type prop
- fix if url starts with file:// 100
- typescript: update for major i18next version