@wix/fed-cli-i18next 1.6.42 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -126,43 +126,47 @@ Successful and failed requests are removed from the in-flight cache when they se
126
126
  calls can reload resources or retry failures. Share the loader between i18next instances when
127
127
  they use the same translation resources and should deduplicate concurrent requests.
128
128
 
129
- ### ICU cache options
130
-
131
- `initI18n` accepts these options through `icuOptions`:
132
-
133
- | Option | Default | Behavior |
134
- | ----------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
135
- | `maxCacheSize` | `1000` | Maximum compiled messages across all languages and namespaces in one instance. Least recently used messages are evicted. `0` disables compiled-message caching. |
136
- | `maxFormatterCacheSize` | `100` | Maximum shared number, date/time, and plural formatters combined in one instance. Least recently used formatters are evicted. `0` disables shared-formatter caching. |
137
- | `memoize` | `true` | Set to `false` to disable both caches. |
138
- | `bindI18nStore` | `'added removed'` | Space-separated resource-store events that drop compiled messages for the language and namespace they report. Set to `''` to disable these event bindings. |
139
- | `bindI18n` | `''` | Space-separated i18next events that drop all compiled messages. Set to `'languageChanged'` to drop them on language switches. |
140
-
141
- Cache limits must be non-negative safe integers, or `Infinity` to cache without eviction. Adjust
142
- the limits for your application's working set; eviction trades recompilation work for lower
143
- memory use.
144
-
145
- Resource additions, updates, and removals drop compiled messages for just the language and
146
- namespace they report, so loading one namespace leaves the others compiled. Changes made through
147
- `ICU.addUserDefinedFormats()` drop every compiled message, since compiled messages capture the
148
- format definitions. Shared formatters survive all of these, because nothing a formatter depends on
149
- changes when a translation does. A changed message is recompiled even when its resource update was
150
- silent. Language switches keep cached messages unless configured otherwise. `ICU.clearMessages()`
151
- drops compiled messages; `ICU.clearCache()` drops compiled messages and shared formatters.
152
- Compiled-message storage is private. Replace direct assignments to `ICU.mem` with
153
- `ICU.clearMessages()`.
129
+ ### ICU options
130
+
131
+ `initI18n` creates the [`i18next-icu`](https://github.com/i18next/i18next-icu) plugin and passes
132
+ `icuOptions` to it. Commonly used options:
133
+
134
+ | Option | Default | Behavior |
135
+ | --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
136
+ | `formats` | — | Custom number, date and time styles for [user-defined formats](https://formatjs.io/docs/intl-messageformat#user-defined-formats). |
137
+ | `memoize` | `true` | Caches compiled messages per language, namespace and key. |
138
+ | `bindI18nStore` | `''` | A resource-store event, such as `'added'`, that clears the compiled-message cache. |
139
+ | `bindI18n` | `''` | An i18next event, such as `'languageChanged'`, that clears the compiled-message cache. |
140
+
141
+ Compiled messages are cached by key, so a translation that changes at runtime keeps its old
142
+ compiled form until the cache is cleared. Set `bindI18nStore: 'added'` when you reload or add
143
+ resources after initialization, or call `ICU.clearCache()` yourself:
154
144
 
155
145
  ```ts
156
146
  const i18n = initI18n({
157
147
  locale: 'en',
158
148
  asyncMessagesLoader,
159
- icuOptions: {
160
- maxCacheSize: 1000,
161
- maxFormatterCacheSize: 100,
162
- },
149
+ icuOptions: { bindI18nStore: 'added' },
163
150
  });
164
151
  ```
165
152
 
153
+ ### Migrating to `i18next-icu`
154
+
155
+ This version replaces the package's own copy of the ICU plugin with `i18next-icu` and
156
+ `intl-messageformat` 11 (previously 7). Check your translations and configuration for these changes:
157
+
158
+ - **`select` needs an `other` branch.** `{x, select, 0 {} 1 {, John}}` no longer parses; write
159
+ `{x, select, 1 {, John} other {}}`. Messages that fail to parse go to `parseErrorHandler`, which by
160
+ default returns the raw message.
161
+ - **Resource updates no longer clear compiled messages by default.** Set `bindI18nStore: 'added'`,
162
+ as shown above.
163
+ - **Removed options and methods:** `maxCacheSize`, `maxFormatterCacheSize`, `localeData`,
164
+ `ICU.clearMessages()` and `ICU.addLocaleData()`. Use `ICU.clearCache()` instead of
165
+ `ICU.clearMessages()`. `bindI18nStore` and `bindI18n` take one event name.
166
+ - **Parse errors** passed to `parseErrorHandler` are `intl-messageformat` error classes, such as
167
+ `MissingValueError` with `code: 'MISSING_VALUE'`.
168
+ - **Tags** such as `<0>…</0>` used by `<Trans>` are left as text for react-i18next to replace, as before.
169
+
166
170
  ## Changing language
167
171
 
168
172
  `withTranslation` HOC injects the `i18n` object, which can be used to changes language and other configuration once the application is loaded.
package/dist/i18n.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { IcuConfig } from "./icu.js";
2
1
  import { i18n as i18n$1 } from "i18next";
3
2
  //#region src/i18n.d.ts
4
3
  /** A flat map of translation keys to their translated strings. */
@@ -29,15 +28,6 @@ type I18nFactory = (options: I18nOptions, icuOptions?: {
29
28
  * @returns A configured i18next instance.
30
29
  */
31
30
  declare const i18n: I18nFactory;
32
- /**
33
- * Initializes an i18next instance with ICU MessageFormat support.
34
- * This is the recommended entry point for apps that need ICU pluralization and formatting.
35
- * @returns A configured i18next instance with ICU plugin.
36
- */
37
- declare function initI18n({ icuOptions, ...options }: {
38
- icuOptions?: IcuConfig;
39
- parseErrorHandler?: any;
40
- } & I18nOptions): i18n$1;
41
31
  /**
42
32
  * Initializes an i18next instance without ICU MessageFormat support.
43
33
  * Use when ICU formatting is not needed or when bundle size is a concern.
@@ -45,5 +35,5 @@ declare function initI18n({ icuOptions, ...options }: {
45
35
  */
46
36
  declare function initI18nWithoutICU(options: Omit<I18nOptions, 'icuOptions' | 'parseErrorHandler'>): i18n$1;
47
37
  //#endregion
48
- export { Messages, i18n, initI18n, initI18nWithoutICU };
38
+ export { I18nOptions, Messages, i18n, initI18nWithoutICU };
49
39
  //# sourceMappingURL=i18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","names":["i18nType"],"sources":["../src/i18n.ts"],"mappings":";;;;UAMiB;GACd;;;UAIO;EACR;EACA,uBAAuB,qBAAqB,QAAQ;EACpD,WAAW;EACX;;;;;EAKA;EACA;EACA;;KAGG,eAAe,SAAS,aAAa;EAAe;MAAgBA;;;;;;;cAQ5D,MAAM;;;;;;iBAsEH,WACd,eACG;EAEH,aAAa;EAEb;IACE,cAAWA;;;;;;iBAeC,mBAAmB,SAAS,KAAK,mDAAgDA"}
1
+ {"version":3,"file":"i18n.d.ts","names":["i18nType"],"sources":["../src/i18n.ts"],"mappings":";;;UAIiB;GACd;;;UAIc;EACf;EACA,uBAAuB,qBAAqB,QAAQ;EACpD,WAAW;EACX;;;;;EAKA;EACA;EACA;;KAGG,eAAe,SAAS,aAAa;EAAe;MAAgBA;;;;;;;cAQ5D,MAAM;;;;;;iBAsEH,mBAAmB,SAAS,KAAK,mDAAgDA"}
package/dist/i18n.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"./icu.js";import t from"i18next";const n=({locale:e,asyncMessagesLoader:n,messages:r,useSuspense:i=!1,disableAutoInit:a=!1,bindI18n:o},{icu:s}={})=>{let c={lng:e,fallbackLng:`en`,keySeparator:!1,react:{useSuspense:i,bindI18n:o},_polyfill:{isLoading:!1}},l=t.createInstance(a?c:void 0);return s&&l.use(s),n&&l.use({type:`backend`,read:async(e,t,r)=>{try{return r(null,await n(e))}catch(e){return r(e,null)}}}),r&&(c.resources={[e]:{translation:r}}),a||l.init(c),l};function r({icuOptions:t={},...r}){let{parseErrorHandler:i=void 0}=r,a=new e({parseErrorHandler:i,bindI18n:r.bindI18n,...t});return n(r,{icu:a})}function i(e){return n(e)}export{n as i18n,r as initI18n,i as initI18nWithoutICU};
1
+ import e from"i18next";const t=({locale:t,asyncMessagesLoader:n,messages:r,useSuspense:i=!1,disableAutoInit:a=!1,bindI18n:o},{icu:s}={})=>{let c={lng:t,fallbackLng:`en`,keySeparator:!1,react:{useSuspense:i,bindI18n:o},_polyfill:{isLoading:!1}},l=e.createInstance(a?c:void 0);return s&&l.use(s),n&&l.use({type:`backend`,read:async(e,t,r)=>{try{return r(null,await n(e))}catch(e){return r(e,null)}}}),r&&(c.resources={[t]:{translation:r}}),a||l.init(c),l};function n(e){return t(e)}export{t as i18n,n as initI18nWithoutICU};
2
2
  //# sourceMappingURL=i18n.js.map
package/dist/i18n.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","names":["ICU","i18next","i18n","config","locale","i18nInstance","disableAutoInit","icu","asyncMessagesLoader","callback","language","err","messages","initI18n","options","icuOptions","initI18nWithoutICU"],"sources":["../src/i18n.ts"],"sourcesContent":["import i18next from 'i18next';\nimport type { InitOptions, i18n as i18nType } from 'i18next';\nimport type { IcuConfig } from './icu';\nimport ICU from './icu';\n\n/** A flat map of translation keys to their translated strings. */\nexport interface Messages {\n [key: string]: string;\n}\n\n/** Configuration options for initializing an i18next instance. */\ninterface I18nOptions {\n locale: string;\n asyncMessagesLoader?: (language: string) => Promise<Messages>;\n messages?: Messages;\n useSuspense?: boolean;\n /**\n * @deprecated No-op. The underlying `react.wait` option was removed from\n * react-i18next in v10; use `useSuspense` instead. Kept for backward compatibility.\n */\n wait?: boolean;\n disableAutoInit?: boolean;\n bindI18n?: string;\n}\n\ntype I18nFactory = (options: I18nOptions, icuOptions?: { icu?: any }) => i18nType;\n\n/**\n * Creates and configures an i18next instance with optional ICU support and async message loading.\n * @param options - Locale, messages, and behavior configuration.\n * @param icuOptions - Optional ICU plugin instance for MessageFormat support.\n * @returns A configured i18next instance.\n */\nexport const i18n: I18nFactory = (\n { locale, asyncMessagesLoader, messages, useSuspense = false, disableAutoInit = false, bindI18n },\n { icu } = {},\n) => {\n const config: InitOptions = {\n // Initial language\n lng: locale,\n fallbackLng: 'en',\n\n // Don't use a key separator (no support for nested translation objects)\n keySeparator: false,\n\n react: {\n useSuspense,\n bindI18n,\n },\n\n // Basically when BM can be loaded without this config - you're good to go.\n // oxlint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error _polyfill is a non-standard BM-specific option not in i18next's InitOptions\n _polyfill: { isLoading: false },\n };\n\n const i18nInstance = i18next.createInstance(disableAutoInit ? config : undefined);\n\n // icu is optional since this function can be called from initI18n or initI18nWithoutICU modules\n if (icu) {\n i18nInstance.use(icu);\n }\n\n if (asyncMessagesLoader) {\n i18nInstance.use({\n type: 'backend' as const,\n read: async (\n language: string,\n _namespace: string,\n callback: (error: null | unknown, messages: null | Record<string, string>) => void,\n ) => {\n // We configure how i18next should fetch a translation resource when it\n // needs it: We use Webpack's dynamic imports to fetch resources without\n // increasing our bundle size.\n //\n // See https://webpack.js.org/guides/code-splitting/#dynamic-imports for\n // more information.\n try {\n const translation = await asyncMessagesLoader(language);\n return callback(null, translation);\n } catch (err) {\n return callback(err, null);\n }\n },\n });\n }\n\n if (messages) {\n config.resources = { [locale]: { translation: messages } };\n }\n\n if (!disableAutoInit) {\n i18nInstance.init(config);\n }\n\n return i18nInstance;\n};\n\n/**\n * Initializes an i18next instance with ICU MessageFormat support.\n * This is the recommended entry point for apps that need ICU pluralization and formatting.\n * @returns A configured i18next instance with ICU plugin.\n */\nexport function initI18n({\n icuOptions = {},\n ...options\n}: {\n icuOptions?: IcuConfig;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n parseErrorHandler?: any;\n} & I18nOptions) {\n const { parseErrorHandler = undefined } = options;\n const icu = new ICU({\n parseErrorHandler,\n bindI18n: options.bindI18n,\n ...icuOptions,\n });\n return i18n(options, { icu });\n}\n\n/**\n * Initializes an i18next instance without ICU MessageFormat support.\n * Use when ICU formatting is not needed or when bundle size is a concern.\n * @returns A configured i18next instance without ICU plugin.\n */\nexport function initI18nWithoutICU(options: Omit<I18nOptions, 'icuOptions' | 'parseErrorHandler'>) {\n return i18n(options);\n}\n"],"mappings":"+CAiCA,MAAaE,GACX,CAAE,SAAQ,sBAAqB,WAAU,cAAc,GAAO,kBAAkB,GAAO,YACvF,CAAE,OAAQ,CAAC,IACR,CACH,IAAMC,EAAsB,CAE1B,IAAKC,EACL,YAAa,KAGb,aAAc,GAEd,MAAO,CACL,cACA,UACF,EAKA,UAAW,CAAE,UAAW,EAAM,CAChC,EAEMC,EAAeJ,EAAQ,eAAeK,EAAkBH,EAAS,IAAA,EAAS,EAuChF,OApCII,GACFF,EAAa,IAAIE,CAAG,EAGlBC,GACFH,EAAa,IAAI,CACf,KAAM,UACN,KAAM,MACJ,EACA,EACA,IACG,CAOH,GAAI,CAEF,OAAOI,EAAS,KAAM,MADID,EAAoBE,CAAQ,CACrB,CACnC,OAASC,EAAK,CACZ,OAAOF,EAASE,EAAK,IAAI,CAC3B,CACF,CACF,CAAC,EAGCC,IACF,EAAO,UAAY,EAAGR,GAAS,CAAE,YAAaQ,CAAS,CAAE,GAGtDN,GACHD,EAAa,KAAKF,CAAM,EAGnBE,CACT,EAOA,SAAgBQ,EAAS,CACvB,aAAa,CAAC,EACd,GAAGC,GAKY,CACf,GAAM,CAAE,oBAAoB,IAAA,IAAcA,EACpCP,EAAM,IAAIP,EAAI,CAClB,oBACA,SAAUc,EAAQ,SAClB,GAAGC,CACL,CAAC,EACD,OAAOb,EAAKY,EAAS,CAAE,KAAI,CAAC,CAC9B,CAOA,SAAgBE,EAAmB,EAAgE,CACjG,OAAOd,EAAKY,CAAO,CACrB"}
1
+ {"version":3,"file":"i18n.js","names":["i18next","i18n","config","locale","i18nInstance","disableAutoInit","icu","asyncMessagesLoader","callback","language","err","messages","initI18nWithoutICU","options"],"sources":["../src/i18n.ts"],"sourcesContent":["import i18next from 'i18next';\nimport type { InitOptions, i18n as i18nType } from 'i18next';\n\n/** A flat map of translation keys to their translated strings. */\nexport interface Messages {\n [key: string]: string;\n}\n\n/** Configuration options for initializing an i18next instance. */\nexport interface I18nOptions {\n locale: string;\n asyncMessagesLoader?: (language: string) => Promise<Messages>;\n messages?: Messages;\n useSuspense?: boolean;\n /**\n * @deprecated No-op. The underlying `react.wait` option was removed from\n * react-i18next in v10; use `useSuspense` instead. Kept for backward compatibility.\n */\n wait?: boolean;\n disableAutoInit?: boolean;\n bindI18n?: string;\n}\n\ntype I18nFactory = (options: I18nOptions, icuOptions?: { icu?: any }) => i18nType;\n\n/**\n * Creates and configures an i18next instance with optional ICU support and async message loading.\n * @param options - Locale, messages, and behavior configuration.\n * @param icuOptions - Optional ICU plugin instance for MessageFormat support.\n * @returns A configured i18next instance.\n */\nexport const i18n: I18nFactory = (\n { locale, asyncMessagesLoader, messages, useSuspense = false, disableAutoInit = false, bindI18n },\n { icu } = {},\n) => {\n const config: InitOptions = {\n // Initial language\n lng: locale,\n fallbackLng: 'en',\n\n // Don't use a key separator (no support for nested translation objects)\n keySeparator: false,\n\n react: {\n useSuspense,\n bindI18n,\n },\n\n // Basically when BM can be loaded without this config - you're good to go.\n // oxlint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error _polyfill is a non-standard BM-specific option not in i18next's InitOptions\n _polyfill: { isLoading: false },\n };\n\n const i18nInstance = i18next.createInstance(disableAutoInit ? config : undefined);\n\n // icu is optional since this function can be called from initI18n or initI18nWithoutICU modules\n if (icu) {\n i18nInstance.use(icu);\n }\n\n if (asyncMessagesLoader) {\n i18nInstance.use({\n type: 'backend' as const,\n read: async (\n language: string,\n _namespace: string,\n callback: (error: null | unknown, messages: null | Record<string, string>) => void,\n ) => {\n // We configure how i18next should fetch a translation resource when it\n // needs it: We use Webpack's dynamic imports to fetch resources without\n // increasing our bundle size.\n //\n // See https://webpack.js.org/guides/code-splitting/#dynamic-imports for\n // more information.\n try {\n const translation = await asyncMessagesLoader(language);\n return callback(null, translation);\n } catch (err) {\n return callback(err, null);\n }\n },\n });\n }\n\n if (messages) {\n config.resources = { [locale]: { translation: messages } };\n }\n\n if (!disableAutoInit) {\n i18nInstance.init(config);\n }\n\n return i18nInstance;\n};\n\n/**\n * Initializes an i18next instance without ICU MessageFormat support.\n * Use when ICU formatting is not needed or when bundle size is a concern.\n * @returns A configured i18next instance without ICU plugin.\n */\nexport function initI18nWithoutICU(options: Omit<I18nOptions, 'icuOptions' | 'parseErrorHandler'>) {\n return i18n(options);\n}\n"],"mappings":"uBA+BA,MAAaC,GACX,CAAE,SAAQ,sBAAqB,WAAU,cAAc,GAAO,kBAAkB,GAAO,YACvF,CAAE,OAAQ,CAAC,IACR,CACH,IAAMC,EAAsB,CAE1B,IAAKC,EACL,YAAa,KAGb,aAAc,GAEd,MAAO,CACL,cACA,UACF,EAKA,UAAW,CAAE,UAAW,EAAM,CAChC,EAEMC,EAAeJ,EAAQ,eAAeK,EAAkBH,EAAS,IAAA,EAAS,EAuChF,OApCII,GACFF,EAAa,IAAIE,CAAG,EAGlBC,GACFH,EAAa,IAAI,CACf,KAAM,UACN,KAAM,MACJ,EACA,EACA,IACG,CAOH,GAAI,CAEF,OAAOI,EAAS,KAAM,MADID,EAAoBE,CAAQ,CACrB,CACnC,OAASC,EAAK,CACZ,OAAOF,EAASE,EAAK,IAAI,CAC3B,CACF,CACF,CAAC,EAGCC,IACF,EAAO,UAAY,EAAGR,GAAS,CAAE,YAAaQ,CAAS,CAAE,GAGtDN,GACHD,EAAa,KAAKF,CAAM,EAGnBE,CACT,EAOA,SAAgBQ,EAAmB,EAAgE,CACjG,OAAOX,EAAKY,CAAO,CACrB"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import ICU, { IcuConfig } from "./icu.js";
2
- import { Messages, i18n as i18n$1, initI18n, initI18nWithoutICU } from "./i18n.js";
1
+ import { Messages, i18n as i18n$1, initI18nWithoutICU } from "./i18n.js";
3
2
  import { createAsyncMessagesLoader } from "./create-async-messages-loader.js";
3
+ import { ICU, initI18n } from "./init-i18n.js";
4
4
  import { createRtfFormatter } from "./relative-time-formatting.js";
5
5
  import { TFunction, i18n } from "i18next";
6
6
  import { I18nextProvider, Trans, TransProps, UseTranslationResponse, WithTranslation, WithTranslationProps, useTranslation, withTranslation } from "react-i18next";
7
+ import { IcuConfig } from "i18next-icu";
7
8
  export { I18nextProvider, ICU, type IcuConfig, type Messages, type TFunction, Trans, type TransProps, type UseTranslationResponse, type WithTranslation, type WithTranslationProps, createAsyncMessagesLoader, createRtfFormatter, type i18n, initI18n, i18n$1 as initI18nBase, initI18nWithoutICU, useTranslation, withTranslation };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{createAsyncMessagesLoader as e}from"./create-async-messages-loader.js";import t from"./icu.js";import{i18n as n,initI18n as r,initI18nWithoutICU as i}from"./i18n.js";import{createRtfFormatter as a}from"./relative-time-formatting.js";import{I18nextProvider as o,Trans as s,useTranslation as c,withTranslation as l}from"react-i18next";export{o as I18nextProvider,t as ICU,s as Trans,e as createAsyncMessagesLoader,a as createRtfFormatter,r as initI18n,n as initI18nBase,i as initI18nWithoutICU,c as useTranslation,l as withTranslation};
1
+ import{createAsyncMessagesLoader as e}from"./create-async-messages-loader.js";import{i18n as t,initI18nWithoutICU as n}from"./i18n.js";import{ICU as r,initI18n as i}from"./init-i18n.js";import{createRtfFormatter as a}from"./relative-time-formatting.js";import{I18nextProvider as o,Trans as s,useTranslation as c,withTranslation as l}from"react-i18next";export{o as I18nextProvider,r as ICU,s as Trans,e as createAsyncMessagesLoader,a as createRtfFormatter,i as initI18n,t as initI18nBase,n as initI18nWithoutICU,c as useTranslation,l as withTranslation};
@@ -0,0 +1,15 @@
1
+ import { I18nOptions } from "./i18n.js";
2
+ import ICU, { IcuConfig } from "i18next-icu";
3
+ //#region src/init-i18n.d.ts
4
+ /**
5
+ * Initializes an i18next instance with ICU MessageFormat support.
6
+ * This is the recommended entry point for apps that need ICU pluralization and formatting.
7
+ * @returns A configured i18next instance with ICU plugin.
8
+ */
9
+ declare function initI18n({ icuOptions, ...options }: {
10
+ icuOptions?: IcuConfig;
11
+ parseErrorHandler?: any;
12
+ } & I18nOptions): import("i18next").i18n;
13
+ //#endregion
14
+ export { ICU, initI18n };
15
+ //# sourceMappingURL=init-i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-i18n.d.ts","names":[],"sources":["../src/init-i18n.ts"],"mappings":";;;;;;;;iBAagB,WACd,eACG;EAEH,aAAa;EAEb;IACE,gCAAW"}
@@ -0,0 +1,2 @@
1
+ import{i18n as e}from"./i18n.js";import t from"i18next-icu";function n({icuOptions:n={},...r}){let{parseErrorHandler:i=void 0}=r,a=new t({parseErrorHandler:i,bindI18n:r.bindI18n,...n});return e(r,{icu:a})}export{t as ICU,n as initI18n};
2
+ //# sourceMappingURL=init-i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-i18n.js","names":["ICU","initI18n","options","icu","icuOptions","i18n"],"sources":["../src/init-i18n.ts"],"sourcesContent":["import ICU from 'i18next-icu';\nimport type { IcuConfig } from 'i18next-icu';\nimport { i18n } from './i18n';\nimport type { I18nOptions } from './i18n';\n\n// Keep i18next-icu out of ./i18n: it doesn't declare `sideEffects: false`, so importing it from a\n// module that initI18nWithoutICU shares would pull it and intl-messageformat into every bundle.\n\n/**\n * Initializes an i18next instance with ICU MessageFormat support.\n * This is the recommended entry point for apps that need ICU pluralization and formatting.\n * @returns A configured i18next instance with ICU plugin.\n */\nexport function initI18n({\n icuOptions = {},\n ...options\n}: {\n icuOptions?: IcuConfig;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n parseErrorHandler?: any;\n} & I18nOptions) {\n const { parseErrorHandler = undefined } = options;\n const icu = new ICU({\n parseErrorHandler,\n bindI18n: options.bindI18n,\n ...icuOptions,\n });\n return i18n(options, { icu });\n}\n\nexport { ICU };\n"],"mappings":"4DAaA,SAAgBC,EAAS,CACvB,aAAa,CAAC,EACd,GAAGC,GAKY,CACf,GAAM,CAAE,oBAAoB,IAAA,IAAcA,EACpCC,EAAM,IAAIH,EAAI,CAClB,oBACA,SAAUE,EAAQ,SAClB,GAAGE,CACL,CAAC,EACD,OAAOC,EAAKH,EAAS,CAAE,KAAI,CAAC,CAC9B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/fed-cli-i18next",
3
- "version": "1.6.42",
3
+ "version": "1.7.1",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -28,7 +28,8 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "i18next": "^26.4.2",
31
- "intl-messageformat": "^7.8.4",
31
+ "i18next-icu": "^2.4.5",
32
+ "intl-messageformat": "^11.2.15",
32
33
  "react-i18next": "^15.7.4"
33
34
  },
34
35
  "devDependencies": {
@@ -39,12 +40,12 @@
39
40
  "@wix/fed-cli-oxlint": "1.0.0",
40
41
  "@wix/fed-cli-rolldown": "1.0.0",
41
42
  "oxfmt": "^0.58.0",
42
- "oxlint": "^1.86.0",
43
+ "oxlint": "^1.87.0",
43
44
  "react": "^18.3.1",
44
45
  "react-dom": "^18.3.1",
45
- "rolldown": "^1.2.11",
46
+ "rolldown": "^1.2.12",
46
47
  "typescript": "^6.0.3",
47
- "vite": "^8.3.1",
48
+ "vite": "^8.3.2",
48
49
  "vitest": "^5.0.3"
49
50
  },
50
51
  "peerDependencies": {
@@ -63,5 +64,5 @@
63
64
  ]
64
65
  }
65
66
  },
66
- "falconPackageHash": "bf908b230a4abcdf2d52b53a556d9783258787982cdbd6eb85cf52ff"
67
+ "falconPackageHash": "c01420b378e5d966e7b10dadb60532248036e35051b7ba68aae518ac"
67
68
  }
package/dist/icu.d.ts DELETED
@@ -1,65 +0,0 @@
1
- import { i18n } from "i18next";
2
- //#region src/icu.d.ts
3
- interface IcuFormats {
4
- number?: {
5
- [styleName: string]: Intl.NumberFormatOptions;
6
- };
7
- date?: {
8
- [styleName: string]: Intl.DateTimeFormatOptions;
9
- };
10
- time?: {
11
- [styleName: string]: Intl.DateTimeFormatOptions;
12
- };
13
- }
14
- type StoreEvent = 'added' | 'removed';
15
- interface IcuConfig {
16
- memoize?: boolean;
17
- memoizeFallback?: boolean;
18
- /** Maximum compiled messages per instance. Defaults to 1000; 0 disables this cache, Infinity disables eviction. */
19
- maxCacheSize?: number;
20
- /** Maximum shared Intl formatters per instance. Defaults to 100; 0 disables this cache, Infinity disables eviction. */
21
- maxFormatterCacheSize?: number;
22
- formats?: IcuFormats;
23
- bindI18n?: string;
24
- /** Space-separated resource-store events. Defaults to 'added removed'. */
25
- bindI18nStore?: '' | StoreEvent | 'added removed' | 'removed added';
26
- localeData?: any;
27
- parseErrorHandler?: (err: Error, key: string, res: string, options: object) => string;
28
- parseLngForICU?: (lng: string) => string;
29
- }
30
- /**
31
- * Copied from original ICU source code.
32
- * @source https://github.com/i18next/i18next-icu/blob/7809547c821a7ef3b2bb9ab2610cdbbcfedcb2f9/src/index.js
33
- *
34
- * It's done in order to support `IntlMessageFormat` out of the box.
35
- * `IntlMessageFormat` is adding formatters that are not provided by i18n.
36
- * For example, `select` formatter - https://formatjs.io/docs/core-concepts/icu-syntax#select-format
37
- * It allows to use following translation value: 'Welcome back{inputData, select, 0 {} 1 {, John}}'
38
- * See example in tests: __tests__/i18n.spec.tsx
39
- */
40
- declare class ICU {
41
- options: IcuConfig | undefined;
42
- formats: IcuFormats | undefined;
43
- type: string;
44
- private cacheRoot;
45
- private formatterCache;
46
- private unbindEvents?;
47
- private formatters;
48
- constructor(options: IcuConfig);
49
- init(i18next: i18n | null, options: IcuConfig): void;
50
- addLocaleData(data: any): void;
51
- addUserDefinedFormats(formats: IcuFormats): void;
52
- parse(res: string, options: Record<string, any>, lng: string, ns: string, key: string, info: any): string | undefined;
53
- addLookupKeys(finalKeys: any): any;
54
- /** Drops compiled messages, keeping the shared Intl formatters. */
55
- clearMessages(): void;
56
- /** Drops compiled messages and the shared Intl formatters. */
57
- clearCache(): void;
58
- private clearNamespace;
59
- /** Re-inserts to mark most recently used: Map.set keeps an existing key's position. */
60
- private touch;
61
- private getFormatter;
62
- }
63
- //#endregion
64
- export { IcuConfig, ICU as default };
65
- //# sourceMappingURL=icu.d.ts.map
package/dist/icu.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"icu.d.ts","names":[],"sources":["../src/icu.ts"],"mappings":";;UAIU;EACR;KACG,oBAAoB,KAAK;;EAE5B;KACG,oBAAoB,KAAK;;EAE5B;KACG,oBAAoB,KAAK;;;KAIzB;UASY;EACf;EACA;;EAEA;;EAEA;EACA,UAAU;EACV;;EAEA,qBAAqB;EACrB;EACA,qBAAqB,KAAK,OAAO,aAAa,aAAa;EAC3D,kBAAkB;;;;;;;;;;;;cA2Bd;EACJ,SAAS;EACT,SAAS;EACT;UACQ;UACA;UAIA;UACA;EAMI,YAAA,SAAS;EAMrB,KAAK,SAAS,aAAa,SAAS;EA8CpC,cAAc;EAWd,sBAAsB,SAAS;EAM/B,MACE,aACA,SAAS,qBACT,aACA,YACA,aACA;EAsCF,cAAc;;EAOd;;EAKA;UAKQ;;UAOA;UAKA"}
package/dist/icu.js DELETED
@@ -1,2 +0,0 @@
1
- import{IntlMessageFormat as e}from"intl-messageformat";function t(){return{memoize:!0,memoizeFallback:!1,maxCacheSize:1e3,maxFormatterCacheSize:100,bindI18n:``,bindI18nStore:`added removed`,parseErrorHandler:(e,t,n)=>n}}var n=class{options;formats;type;cacheRoot=/* @__PURE__ */ new Map;formatterCache=/* @__PURE__ */ new Map;unbindEvents;formatters={getNumberFormat:(...e)=>this.getFormatter(`number`,Intl.NumberFormat,e),getDateTimeFormat:(...e)=>this.getFormatter(`dateTime`,Intl.DateTimeFormat,e),getPluralRules:(...e)=>this.getFormatter(`pluralRules`,Intl.PluralRules,e)};constructor(e){this.type=`i18nFormat`,this.init(null,e)}init(n,i){let a=n&&n.options&&n.options.i18nFormat||{};this.options=r(a,i,this.options||{},t());for(let e of[`maxCacheSize`,`maxFormatterCacheSize`]){let t=this.options[e];if(t!==1/0&&(!Number.isSafeInteger(t)||t<0))throw RangeError(`${e} must be a non-negative safe integer or Infinity`)}if(this.formats=this.options?.formats,this.unbindEvents?.(),this.unbindEvents=void 0,this.clearCache(),n){let{bindI18n:t,bindI18nStore:r}=this.options;n.IntlMessageFormat=e,n.ICU=this;let i=()=>this.clearMessages(),a=(e,t)=>this.clearNamespace(e,t),o=n.store,s=t?t.split(` `):[],c=r?r.split(` `):[];for(let e of s)n.on(e,i);for(let e of c)o.on(e,a);this.unbindEvents=()=>{for(let e of s)n.off(e,i);for(let e of c)o.off(e,a)}}this.options?.localeData&&(Object.prototype.toString.apply(this.options.localeData)===`[object Array]`?this.options.localeData.forEach(e=>this.addLocaleData(e)):this.addLocaleData(this.options.localeData))}addLocaleData(t){(Array.isArray(t)?t:[t]).forEach(t=>{t&&t.locale&&e.__addLocaleData(t)})}addUserDefinedFormats(e){this.formats=this.formats?{...this.formats,...e}:e,this.clearMessages()}parse(t,n,r,i,a,o){let s=this.options?.memoize&&this.options.maxCacheSize>0?JSON.stringify([r,i,a]):void 0,c;if(s!==void 0){let e=this.cacheRoot.get(s);e?.source===t&&(c=e.fc,this.touch(s,e))}try{return c||(c=new e(t,r,this.formats,{formatters:this.formatters}),s!==void 0&&(this.options.memoizeFallback||!o||o.resolved?.res)&&(this.touch(s,{lng:r,ns:i,source:t,fc:c}),this.cacheRoot.size>this.options.maxCacheSize&&this.cacheRoot.delete(this.cacheRoot.keys().next().value))),c.format(n)}catch(e){return this.options?.parseErrorHandler?.(e,a,t,n)}}addLookupKeys(e){return e}clearMessages(){this.cacheRoot.clear()}clearCache(){this.clearMessages(),this.formatterCache.clear()}clearNamespace(e,t){for(let[n,r]of this.cacheRoot)r.lng===e&&r.ns===t&&this.cacheRoot.delete(n)}touch(e,t){this.cacheRoot.delete(e),this.cacheRoot.set(e,t)}getFormatter(e,t,n){if(!this.options?.memoize||this.options.maxFormatterCacheSize===0)return new t(...n);let[r,i]=n,a=JSON.stringify([e,r,Object.entries(i??{}).sort(([e],[t])=>e<t?-1:+(e>t))]),o=this.formatterCache.get(a);if(o)return this.formatterCache.delete(a),this.formatterCache.set(a,o),o;let s=new t(...n);return this.formatterCache.set(a,s),this.formatterCache.size>this.options.maxFormatterCacheSize&&this.formatterCache.delete(this.formatterCache.keys().next().value),s}};n.type=`i18nFormat`;function r(e,...t){let n=e;for(let e of t)if(e)for(let[t,r]of Object.entries(e))n[t]===void 0&&(n[t]=r);return e}export{n as default};
2
- //# sourceMappingURL=icu.js.map
package/dist/icu.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"icu.js","names":["getDefaults","res","ICU","args","options","i18nextOptions","i18next","defaults","name","limit","IntlMessageFormat","clearAll","clearChanged","lng","ns","store","i18nEvents","bindI18n","storeEvents","bindI18nStore","event","ld","data","localeData","\"__addLocaleData\"","formats","cacheKey","key","fc","cached","info","err","finalKeys","entry","Formatter","locales","type","a","b","formatter","sources","target","obj","source","value"],"sources":["../src/icu.ts"],"sourcesContent":["import { IntlMessageFormat } from 'intl-messageformat';\nimport type { Formatters } from 'intl-messageformat';\nimport type { i18n } from 'i18next';\n\ninterface IcuFormats {\n number?: {\n [styleName: string]: Intl.NumberFormatOptions;\n };\n date?: {\n [styleName: string]: Intl.DateTimeFormatOptions;\n };\n time?: {\n [styleName: string]: Intl.DateTimeFormatOptions;\n };\n}\n\ntype StoreEvent = 'added' | 'removed';\n\ninterface CachedMessage {\n lng: string;\n ns: string;\n source: string;\n fc: IntlMessageFormat;\n}\n\nexport interface IcuConfig {\n memoize?: boolean;\n memoizeFallback?: boolean;\n /** Maximum compiled messages per instance. Defaults to 1000; 0 disables this cache, Infinity disables eviction. */\n maxCacheSize?: number;\n /** Maximum shared Intl formatters per instance. Defaults to 100; 0 disables this cache, Infinity disables eviction. */\n maxFormatterCacheSize?: number;\n formats?: IcuFormats;\n bindI18n?: string;\n /** Space-separated resource-store events. Defaults to 'added removed'. */\n bindI18nStore?: '' | StoreEvent | 'added removed' | 'removed added';\n localeData?: any;\n parseErrorHandler?: (err: Error, key: string, res: string, options: object) => string;\n parseLngForICU?: (lng: string) => string;\n}\n\nfunction getDefaults(): IcuConfig {\n return {\n memoize: true,\n memoizeFallback: false,\n maxCacheSize: 1000,\n maxFormatterCacheSize: 100,\n bindI18n: '',\n bindI18nStore: 'added removed',\n parseErrorHandler: (_err, _key, res) => {\n return res;\n },\n };\n}\n\n/**\n * Copied from original ICU source code.\n * @source https://github.com/i18next/i18next-icu/blob/7809547c821a7ef3b2bb9ab2610cdbbcfedcb2f9/src/index.js\n *\n * It's done in order to support `IntlMessageFormat` out of the box.\n * `IntlMessageFormat` is adding formatters that are not provided by i18n.\n * For example, `select` formatter - https://formatjs.io/docs/core-concepts/icu-syntax#select-format\n * It allows to use following translation value: 'Welcome back{inputData, select, 0 {} 1 {, John}}'\n * See example in tests: __tests__/i18n.spec.tsx\n */\nclass ICU {\n options: IcuConfig | undefined;\n formats: IcuFormats | undefined;\n type: string;\n private cacheRoot = new Map<string, CachedMessage>();\n private formatterCache = new Map<\n string,\n Intl.NumberFormat | Intl.DateTimeFormat | Intl.PluralRules\n >();\n private unbindEvents?: () => void;\n private formatters: Formatters = {\n getNumberFormat: (...args) => this.getFormatter('number', Intl.NumberFormat, args),\n getDateTimeFormat: (...args) => this.getFormatter('dateTime', Intl.DateTimeFormat, args),\n getPluralRules: (...args) => this.getFormatter('pluralRules', Intl.PluralRules, args),\n };\n\n constructor(options: IcuConfig) {\n this.type = 'i18nFormat';\n\n this.init(null, options);\n }\n\n init(i18next: i18n | null, options: IcuConfig) {\n const i18nextOptions = (i18next && i18next.options && i18next.options.i18nFormat) || {};\n this.options = defaults(i18nextOptions, options, this.options || {}, getDefaults());\n for (const name of ['maxCacheSize', 'maxFormatterCacheSize'] as const) {\n const limit = this.options![name]!;\n if (limit !== Infinity && (!Number.isSafeInteger(limit) || limit < 0)) {\n throw new RangeError(`${name} must be a non-negative safe integer or Infinity`);\n }\n }\n this.formats = this.options?.formats;\n this.unbindEvents?.();\n this.unbindEvents = undefined;\n this.clearCache();\n\n if (i18next) {\n const { bindI18n, bindI18nStore } = this.options!;\n\n // @ts-expect-error fix later\n i18next.IntlMessageFormat = IntlMessageFormat;\n // @ts-expect-error fix later\n i18next.ICU = this;\n\n // Resources can only stale compiled messages, never the shared Intl formatters.\n const clearAll = () => this.clearMessages();\n // Store events report the (lng, ns) that changed, so only that much needs dropping.\n const clearChanged = (lng: string, ns: string) => this.clearNamespace(lng, ns);\n const store = i18next.store;\n const i18nEvents = bindI18n ? bindI18n.split(' ') : [];\n const storeEvents = bindI18nStore ? (bindI18nStore.split(' ') as StoreEvent[]) : [];\n for (const event of i18nEvents) i18next.on(event, clearAll);\n for (const event of storeEvents) store.on(event, clearChanged);\n this.unbindEvents = () => {\n for (const event of i18nEvents) i18next.off(event, clearAll);\n for (const event of storeEvents) store.off(event, clearChanged);\n };\n }\n\n if (this.options?.localeData) {\n if (Object.prototype.toString.apply(this.options.localeData) === '[object Array]') {\n this.options.localeData.forEach((ld: any) => this.addLocaleData(ld));\n } else {\n this.addLocaleData(this.options.localeData);\n }\n }\n }\n\n addLocaleData(data: any) {\n const locales = Array.isArray(data) ? data : [data];\n\n locales.forEach((localeData) => {\n if (localeData && localeData.locale) {\n // Undeclared legacy escape hatch on IntlMessageFormat.\n (IntlMessageFormat as any)['__addLocaleData'](localeData);\n }\n });\n }\n\n addUserDefinedFormats(formats: IcuFormats) {\n this.formats = this.formats ? { ...this.formats, ...formats } : formats;\n // Compiled messages capture `formats`; formatters are keyed by their resolved options.\n this.clearMessages();\n }\n\n parse(\n res: string,\n options: Record<string, any>,\n lng: string,\n ns: string,\n key: string,\n info: any,\n ) {\n // An undefined key means caching is off.\n const cacheKey =\n this.options?.memoize && this.options.maxCacheSize! > 0\n ? JSON.stringify([lng, ns, key])\n : undefined;\n\n let fc: IntlMessageFormat | undefined;\n if (cacheKey !== undefined) {\n const cached = this.cacheRoot.get(cacheKey);\n // A changed source must be recompiled even when no invalidation event fired.\n if (cached?.source === res) {\n fc = cached.fc;\n this.touch(cacheKey, cached);\n }\n }\n\n try {\n if (!fc) {\n fc = new IntlMessageFormat(res, lng, this.formats, { formatters: this.formatters });\n if (\n cacheKey !== undefined &&\n (this.options!.memoizeFallback || !info || info.resolved?.res)\n ) {\n this.touch(cacheKey, { lng, ns, source: res, fc });\n if (this.cacheRoot.size > this.options!.maxCacheSize!) {\n this.cacheRoot.delete(this.cacheRoot.keys().next().value!);\n }\n }\n }\n\n return fc.format(options);\n } catch (err) {\n return this.options?.parseErrorHandler?.(err as Error, key, res, options);\n }\n }\n\n addLookupKeys(finalKeys: any) {\n // no additional keys needed for select or plural\n // so there is no need to add keys to that finalKeys array\n return finalKeys;\n }\n\n /** Drops compiled messages, keeping the shared Intl formatters. */\n clearMessages() {\n this.cacheRoot.clear();\n }\n\n /** Drops compiled messages and the shared Intl formatters. */\n clearCache() {\n this.clearMessages();\n this.formatterCache.clear();\n }\n\n private clearNamespace(lng: string, ns: string) {\n for (const [cacheKey, entry] of this.cacheRoot) {\n if (entry.lng === lng && entry.ns === ns) this.cacheRoot.delete(cacheKey);\n }\n }\n\n /** Re-inserts to mark most recently used: Map.set keeps an existing key's position. */\n private touch(cacheKey: string, entry: CachedMessage) {\n this.cacheRoot.delete(cacheKey);\n this.cacheRoot.set(cacheKey, entry);\n }\n\n private getFormatter<\n T extends Intl.NumberFormat | Intl.DateTimeFormat | Intl.PluralRules,\n Args extends unknown[],\n >(type: string, Formatter: new (...args: Args) => T, args: Args): T {\n if (!this.options?.memoize || this.options.maxFormatterCacheSize === 0) {\n return new Formatter(...args);\n }\n\n const [locales, options] = args;\n // Equivalent option objects should share a formatter regardless of property order.\n const key = JSON.stringify([\n type,\n locales,\n // oxlint-disable-next-line no-array-sort -- Object.entries already returns a fresh array\n Object.entries(options ?? {}).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),\n ]);\n const cached = this.formatterCache.get(key);\n if (cached) {\n this.formatterCache.delete(key);\n this.formatterCache.set(key, cached);\n return cached as T;\n }\n\n const formatter = new Formatter(...args);\n this.formatterCache.set(key, formatter);\n if (this.formatterCache.size > this.options!.maxFormatterCacheSize!) {\n this.formatterCache.delete(this.formatterCache.keys().next().value!);\n }\n return formatter;\n }\n}\n\n// @ts-expect-error fix it later\nICU.type = 'i18nFormat';\n\nexport default ICU;\n\n/** Fills only the keys `obj` leaves undefined, so explicit `undefined` never clobbers a default. */\nfunction defaults(obj: IcuConfig, ...sources: (IcuConfig | undefined)[]): IcuConfig {\n const target = obj as Record<string, unknown>;\n for (const source of sources) {\n if (!source) continue;\n for (const [key, value] of Object.entries(source)) {\n if (target[key] === undefined) target[key] = value;\n }\n }\n return obj;\n}\n"],"mappings":"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"}