@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 +33 -29
- package/dist/i18n.d.ts +1 -11
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +1 -1
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/init-i18n.d.ts +15 -0
- package/dist/init-i18n.d.ts.map +1 -0
- package/dist/init-i18n.js +2 -0
- package/dist/init-i18n.js.map +1 -0
- package/package.json +7 -6
- package/dist/icu.d.ts +0 -65
- package/dist/icu.d.ts.map +0 -1
- package/dist/icu.js +0 -2
- package/dist/icu.js.map +0 -1
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
|
|
130
|
-
|
|
131
|
-
`initI18n`
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
| `
|
|
137
|
-
| `memoize`
|
|
138
|
-
| `bindI18nStore`
|
|
139
|
-
| `bindI18n`
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
the
|
|
143
|
-
|
|
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,
|
|
38
|
+
export { I18nOptions, Messages, i18n, initI18nWithoutICU };
|
|
49
39
|
//# sourceMappingURL=i18n.d.ts.map
|
package/dist/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","names":["i18nType"],"sources":["../src/i18n.ts"],"mappings":"
|
|
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"
|
|
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":["
|
|
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
|
|
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"./
|
|
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 @@
|
|
|
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.
|
|
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
|
-
"
|
|
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.
|
|
43
|
+
"oxlint": "^1.87.0",
|
|
43
44
|
"react": "^18.3.1",
|
|
44
45
|
"react-dom": "^18.3.1",
|
|
45
|
-
"rolldown": "^1.2.
|
|
46
|
+
"rolldown": "^1.2.12",
|
|
46
47
|
"typescript": "^6.0.3",
|
|
47
|
-
"vite": "^8.3.
|
|
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": "
|
|
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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"}
|