@vielzeug/i18nit 2.0.0 → 3.0.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.
Files changed (46) hide show
  1. package/README.md +145 -51
  2. package/dist/format.d.ts +54 -0
  3. package/dist/format.d.ts.map +1 -0
  4. package/dist/i18n.cjs +1 -1
  5. package/dist/i18n.cjs.map +1 -1
  6. package/dist/i18n.d.ts +5 -77
  7. package/dist/i18n.d.ts.map +1 -1
  8. package/dist/i18n.js +156 -202
  9. package/dist/i18n.js.map +1 -1
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +2 -2
  14. package/dist/types.d.ts +62 -83
  15. package/dist/types.d.ts.map +1 -1
  16. package/package.json +11 -12
  17. package/dist/core.cjs +0 -2
  18. package/dist/core.cjs.map +0 -1
  19. package/dist/core.d.ts +0 -35
  20. package/dist/core.d.ts.map +0 -1
  21. package/dist/core.js +0 -53
  22. package/dist/core.js.map +0 -1
  23. package/dist/helpers.cjs +0 -2
  24. package/dist/helpers.cjs.map +0 -1
  25. package/dist/helpers.d.ts +0 -20
  26. package/dist/helpers.d.ts.map +0 -1
  27. package/dist/helpers.js +0 -47
  28. package/dist/helpers.js.map +0 -1
  29. package/dist/i18nit.cjs +0 -2
  30. package/dist/i18nit.cjs.map +0 -1
  31. package/dist/i18nit.d.ts +0 -3
  32. package/dist/i18nit.d.ts.map +0 -1
  33. package/dist/i18nit.js +0 -2
  34. package/dist/i18nit.js.map +0 -1
  35. package/dist/interpolate.cjs +0 -2
  36. package/dist/interpolate.cjs.map +0 -1
  37. package/dist/interpolate.d.ts +0 -11
  38. package/dist/interpolate.d.ts.map +0 -1
  39. package/dist/interpolate.js +0 -13
  40. package/dist/interpolate.js.map +0 -1
  41. package/dist/intl.cjs +0 -2
  42. package/dist/intl.cjs.map +0 -1
  43. package/dist/intl.d.ts +0 -16
  44. package/dist/intl.d.ts.map +0 -1
  45. package/dist/intl.js +0 -65
  46. package/dist/intl.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/i18nit",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -15,16 +15,15 @@
15
15
  "import": "./dist/index.js",
16
16
  "require": "./dist/index.cjs"
17
17
  },
18
- "./core": {
19
- "source": "./src/index.ts",
20
- "types": "./dist/index.d.ts",
21
- "import": "./dist/i18nit.js",
22
- "require": "./dist/i18nit.cjs"
18
+ "./format": {
19
+ "source": "./src/format.ts",
20
+ "types": "./dist/format.d.ts",
21
+ "import": "./dist/format.js",
22
+ "require": "./dist/format.cjs"
23
23
  }
24
24
  },
25
25
  "scripts": {
26
- "build": "vite build && pnpm run build:core && pnpm run build:types",
27
- "build:core": "vite build --config vite.bundle.config.ts",
26
+ "build": "vite build && pnpm run build:types",
28
27
  "build:types": "tsc -p tsconfig.declarations.json",
29
28
  "fix": "eslint --fix src",
30
29
  "lint": "eslint src",
@@ -37,9 +36,9 @@
37
36
  "registry": "https://registry.npmjs.org/"
38
37
  },
39
38
  "devDependencies": {
40
- "@types/node": "^25.5.0",
41
- "typescript": "~6.0.2",
42
- "vite": "^8.0.2",
43
- "vitest": "^4.1.1"
39
+ "@types/node": "^25.8.0",
40
+ "typescript": "~6.0.3",
41
+ "vite": "^8.0.13",
42
+ "vitest": "^4.1.6"
44
43
  }
45
44
  }
package/dist/core.cjs DELETED
@@ -1,2 +0,0 @@
1
- var e=class e{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}get locale(){return this.#t??this.#e.getLocale()}#r(e){return this.#n?`${this.#n}.${e}`:e}t(e,t){return this.#e.translate(this.#r(e),t,this.locale)}has(e){return this.#e.findMessage(this.#r(e),this.locale)!==void 0}hasOwn(e){return this.#e.checkOwn(this.#r(e),this.locale)}number(e,t){return this.#e.formatNumber(e,t,this.locale)}date(e,t){return this.#e.formatDate(e,t,this.locale)}list(e,t=`and`){return this.#e.formatList(e,this.locale,t)}relative(e,t,n){return this.#e.formatRelative(e,t,n,this.locale)}currency(e,t,n){return this.#e.formatNumber(e,{...n,currency:t,style:`currency`},this.locale)}scope(t){return new e(this.#e,this.#t,this.#n?`${this.#n}.${String(t)}`:String(t))}withLocale(t){return new e(this.#e,t,this.#n)}};exports.BoundView=e;
2
- //# sourceMappingURL=core.cjs.map
package/dist/core.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.cjs","names":["#core","#fixedLocale","#prefix","#key"],"sources":["../src/core.ts"],"sourcesContent":["import type { BoundI18n, Locale, MessageValue, Messages, NamespaceKeys, TranslationKeyParam, Vars } from './types';\n\n/* -------------------- I18nCore -------------------- */\n\n/**\n * Module-private interface given to every `BoundView` — exposes only the operations views need.\n * Created once per `I18n` instance so `scope()` / `withLocale()` allocate no closures per call.\n */\nexport type I18nCore = {\n checkOwn(key: string, locale: Locale): boolean;\n findMessage(key: string, locale: Locale): MessageValue | undefined;\n formatDate(value: Date | number, options: Intl.DateTimeFormatOptions | undefined, locale: Locale): string;\n formatList(items: unknown[], locale: string, type: 'and' | 'or'): string;\n formatNumber(value: number, options: Intl.NumberFormatOptions | undefined, locale: Locale): string;\n formatRelative(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options: Intl.RelativeTimeFormatOptions | undefined,\n locale: Locale,\n ): string;\n getLocale(): Locale;\n translate(key: string, vars: Vars | undefined, locale: Locale): string;\n};\n\n/* -------------------- BoundView -------------------- */\n\n/**\n * Lightweight view over an `I18n` instance, fixed to a locale and/or key namespace prefix.\n * All methods live on the prototype — no closures are allocated per `scope()` / `withLocale()` call.\n */\nexport class BoundView<T extends Messages = Messages> implements BoundI18n<T> {\n readonly #core: I18nCore;\n readonly #fixedLocale: Locale | null;\n readonly #prefix: string | undefined;\n\n constructor(core: I18nCore, fixedLocale: Locale | null, prefix?: string) {\n this.#core = core;\n this.#fixedLocale = fixedLocale;\n this.#prefix = prefix;\n }\n\n get locale(): Locale {\n return this.#fixedLocale ?? this.#core.getLocale();\n }\n\n #key(key: string): string {\n return this.#prefix ? `${this.#prefix}.${key}` : key;\n }\n\n t(key: TranslationKeyParam<T>, vars?: Vars): string {\n return this.#core.translate(this.#key(key as string), vars, this.locale);\n }\n\n has(key: string): boolean {\n return this.#core.findMessage(this.#key(key), this.locale) !== undefined;\n }\n\n hasOwn(key: string): boolean {\n return this.#core.checkOwn(this.#key(key), this.locale);\n }\n\n number(value: number, options?: Intl.NumberFormatOptions): string {\n return this.#core.formatNumber(value, options, this.locale);\n }\n\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string {\n return this.#core.formatDate(value, options, this.locale);\n }\n\n list(items: unknown[], type: 'and' | 'or' = 'and'): string {\n return this.#core.formatList(items, this.locale, type);\n }\n\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string {\n return this.#core.formatRelative(value, unit, options, this.locale);\n }\n\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string {\n return this.#core.formatNumber(value, { ...options, currency, style: 'currency' }, this.locale);\n }\n\n scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages> {\n return new BoundView(\n this.#core,\n this.#fixedLocale,\n this.#prefix ? `${this.#prefix}.${String(ns)}` : String(ns),\n ) as BoundI18n<T[K] & Messages>;\n }\n\n withLocale(locale: Locale): BoundI18n<T> {\n return new BoundView<T>(this.#core, locale, this.#prefix);\n }\n}\n"],"mappings":"AA8BA,IAAa,EAAb,MAAa,CAAiE,CAC5E,GACA,GACA,GAEA,YAAY,EAAgB,EAA4B,EAAiB,CACvE,MAAA,EAAa,EACb,MAAA,EAAoB,EACpB,MAAA,EAAe,EAGjB,IAAI,QAAiB,CACnB,OAAO,MAAA,GAAqB,MAAA,EAAW,WAAW,CAGpD,GAAK,EAAqB,CACxB,OAAO,MAAA,EAAe,GAAG,MAAA,EAAa,GAAG,IAAQ,EAGnD,EAAE,EAA6B,EAAqB,CAClD,OAAO,MAAA,EAAW,UAAU,MAAA,EAAU,EAAc,CAAE,EAAM,KAAK,OAAO,CAG1E,IAAI,EAAsB,CACxB,OAAO,MAAA,EAAW,YAAY,MAAA,EAAU,EAAI,CAAE,KAAK,OAAO,GAAK,IAAA,GAGjE,OAAO,EAAsB,CAC3B,OAAO,MAAA,EAAW,SAAS,MAAA,EAAU,EAAI,CAAE,KAAK,OAAO,CAGzD,OAAO,EAAe,EAA4C,CAChE,OAAO,MAAA,EAAW,aAAa,EAAO,EAAS,KAAK,OAAO,CAG7D,KAAK,EAAsB,EAA8C,CACvE,OAAO,MAAA,EAAW,WAAW,EAAO,EAAS,KAAK,OAAO,CAG3D,KAAK,EAAkB,EAAqB,MAAe,CACzD,OAAO,MAAA,EAAW,WAAW,EAAO,KAAK,OAAQ,EAAK,CAGxD,SAAS,EAAe,EAAmC,EAAkD,CAC3G,OAAO,MAAA,EAAW,eAAe,EAAO,EAAM,EAAS,KAAK,OAAO,CAGrE,SAAS,EAAe,EAAkB,EAAwE,CAChH,OAAO,MAAA,EAAW,aAAa,EAAO,CAAE,GAAG,EAAS,WAAU,MAAO,WAAY,CAAE,KAAK,OAAO,CAGjG,MAAkC,EAAmC,CACnE,OAAO,IAAI,EACT,MAAA,EACA,MAAA,EACA,MAAA,EAAe,GAAG,MAAA,EAAa,GAAG,OAAO,EAAG,GAAK,OAAO,EAAG,CAC5D,CAGH,WAAW,EAA8B,CACvC,OAAO,IAAI,EAAa,MAAA,EAAY,EAAQ,MAAA,EAAa"}
package/dist/core.d.ts DELETED
@@ -1,35 +0,0 @@
1
- import type { BoundI18n, Locale, MessageValue, Messages, NamespaceKeys, TranslationKeyParam, Vars } from './types';
2
- /**
3
- * Module-private interface given to every `BoundView` — exposes only the operations views need.
4
- * Created once per `I18n` instance so `scope()` / `withLocale()` allocate no closures per call.
5
- */
6
- export type I18nCore = {
7
- checkOwn(key: string, locale: Locale): boolean;
8
- findMessage(key: string, locale: Locale): MessageValue | undefined;
9
- formatDate(value: Date | number, options: Intl.DateTimeFormatOptions | undefined, locale: Locale): string;
10
- formatList(items: unknown[], locale: string, type: 'and' | 'or'): string;
11
- formatNumber(value: number, options: Intl.NumberFormatOptions | undefined, locale: Locale): string;
12
- formatRelative(value: number, unit: Intl.RelativeTimeFormatUnit, options: Intl.RelativeTimeFormatOptions | undefined, locale: Locale): string;
13
- getLocale(): Locale;
14
- translate(key: string, vars: Vars | undefined, locale: Locale): string;
15
- };
16
- /**
17
- * Lightweight view over an `I18n` instance, fixed to a locale and/or key namespace prefix.
18
- * All methods live on the prototype — no closures are allocated per `scope()` / `withLocale()` call.
19
- */
20
- export declare class BoundView<T extends Messages = Messages> implements BoundI18n<T> {
21
- #private;
22
- constructor(core: I18nCore, fixedLocale: Locale | null, prefix?: string);
23
- get locale(): Locale;
24
- t(key: TranslationKeyParam<T>, vars?: Vars): string;
25
- has(key: string): boolean;
26
- hasOwn(key: string): boolean;
27
- number(value: number, options?: Intl.NumberFormatOptions): string;
28
- date(value: Date | number, options?: Intl.DateTimeFormatOptions): string;
29
- list(items: unknown[], type?: 'and' | 'or'): string;
30
- relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string;
31
- currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string;
32
- scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages>;
33
- withLocale(locale: Locale): BoundI18n<T>;
34
- }
35
- //# sourceMappingURL=core.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAInH;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IACnE,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,qBAAqB,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1G,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;IACzE,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,mBAAmB,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACnG,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,CAAC,sBAAsB,EACjC,OAAO,EAAE,IAAI,CAAC,yBAAyB,GAAG,SAAS,EACnD,MAAM,EAAE,MAAM,GACb,MAAM,CAAC;IACV,SAAS,IAAI,MAAM,CAAC;IACpB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACxE,CAAC;AAIF;;;GAGG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,CAAE,YAAW,SAAS,CAAC,CAAC,CAAC;;gBAK/D,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM;IAMvE,IAAI,MAAM,IAAI,MAAM,CAEnB;IAMD,CAAC,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM;IAInD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,GAAG,MAAM;IAIjE,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAAG,MAAM;IAIxE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,GAAE,KAAK,GAAG,IAAY,GAAG,MAAM;IAI1D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,yBAAyB,GAAG,MAAM;IAI5G,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG,MAAM;IAIjH,KAAK,CAAC,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;IAQpE,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAGzC"}
package/dist/core.js DELETED
@@ -1,53 +0,0 @@
1
- //#region src/core.ts
2
- var e = class e {
3
- #e;
4
- #t;
5
- #n;
6
- constructor(e, t, n) {
7
- this.#e = e, this.#t = t, this.#n = n;
8
- }
9
- get locale() {
10
- return this.#t ?? this.#e.getLocale();
11
- }
12
- #r(e) {
13
- return this.#n ? `${this.#n}.${e}` : e;
14
- }
15
- t(e, t) {
16
- return this.#e.translate(this.#r(e), t, this.locale);
17
- }
18
- has(e) {
19
- return this.#e.findMessage(this.#r(e), this.locale) !== void 0;
20
- }
21
- hasOwn(e) {
22
- return this.#e.checkOwn(this.#r(e), this.locale);
23
- }
24
- number(e, t) {
25
- return this.#e.formatNumber(e, t, this.locale);
26
- }
27
- date(e, t) {
28
- return this.#e.formatDate(e, t, this.locale);
29
- }
30
- list(e, t = "and") {
31
- return this.#e.formatList(e, this.locale, t);
32
- }
33
- relative(e, t, n) {
34
- return this.#e.formatRelative(e, t, n, this.locale);
35
- }
36
- currency(e, t, n) {
37
- return this.#e.formatNumber(e, {
38
- ...n,
39
- currency: t,
40
- style: "currency"
41
- }, this.locale);
42
- }
43
- scope(t) {
44
- return new e(this.#e, this.#t, this.#n ? `${this.#n}.${String(t)}` : String(t));
45
- }
46
- withLocale(t) {
47
- return new e(this.#e, t, this.#n);
48
- }
49
- };
50
- //#endregion
51
- export { e as BoundView };
52
-
53
- //# sourceMappingURL=core.js.map
package/dist/core.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.js","names":["#core","#fixedLocale","#prefix","#key"],"sources":["../src/core.ts"],"sourcesContent":["import type { BoundI18n, Locale, MessageValue, Messages, NamespaceKeys, TranslationKeyParam, Vars } from './types';\n\n/* -------------------- I18nCore -------------------- */\n\n/**\n * Module-private interface given to every `BoundView` — exposes only the operations views need.\n * Created once per `I18n` instance so `scope()` / `withLocale()` allocate no closures per call.\n */\nexport type I18nCore = {\n checkOwn(key: string, locale: Locale): boolean;\n findMessage(key: string, locale: Locale): MessageValue | undefined;\n formatDate(value: Date | number, options: Intl.DateTimeFormatOptions | undefined, locale: Locale): string;\n formatList(items: unknown[], locale: string, type: 'and' | 'or'): string;\n formatNumber(value: number, options: Intl.NumberFormatOptions | undefined, locale: Locale): string;\n formatRelative(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options: Intl.RelativeTimeFormatOptions | undefined,\n locale: Locale,\n ): string;\n getLocale(): Locale;\n translate(key: string, vars: Vars | undefined, locale: Locale): string;\n};\n\n/* -------------------- BoundView -------------------- */\n\n/**\n * Lightweight view over an `I18n` instance, fixed to a locale and/or key namespace prefix.\n * All methods live on the prototype — no closures are allocated per `scope()` / `withLocale()` call.\n */\nexport class BoundView<T extends Messages = Messages> implements BoundI18n<T> {\n readonly #core: I18nCore;\n readonly #fixedLocale: Locale | null;\n readonly #prefix: string | undefined;\n\n constructor(core: I18nCore, fixedLocale: Locale | null, prefix?: string) {\n this.#core = core;\n this.#fixedLocale = fixedLocale;\n this.#prefix = prefix;\n }\n\n get locale(): Locale {\n return this.#fixedLocale ?? this.#core.getLocale();\n }\n\n #key(key: string): string {\n return this.#prefix ? `${this.#prefix}.${key}` : key;\n }\n\n t(key: TranslationKeyParam<T>, vars?: Vars): string {\n return this.#core.translate(this.#key(key as string), vars, this.locale);\n }\n\n has(key: string): boolean {\n return this.#core.findMessage(this.#key(key), this.locale) !== undefined;\n }\n\n hasOwn(key: string): boolean {\n return this.#core.checkOwn(this.#key(key), this.locale);\n }\n\n number(value: number, options?: Intl.NumberFormatOptions): string {\n return this.#core.formatNumber(value, options, this.locale);\n }\n\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string {\n return this.#core.formatDate(value, options, this.locale);\n }\n\n list(items: unknown[], type: 'and' | 'or' = 'and'): string {\n return this.#core.formatList(items, this.locale, type);\n }\n\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string {\n return this.#core.formatRelative(value, unit, options, this.locale);\n }\n\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string {\n return this.#core.formatNumber(value, { ...options, currency, style: 'currency' }, this.locale);\n }\n\n scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages> {\n return new BoundView(\n this.#core,\n this.#fixedLocale,\n this.#prefix ? `${this.#prefix}.${String(ns)}` : String(ns),\n ) as BoundI18n<T[K] & Messages>;\n }\n\n withLocale(locale: Locale): BoundI18n<T> {\n return new BoundView<T>(this.#core, locale, this.#prefix);\n }\n}\n"],"mappings":";AA8BA,IAAa,IAAb,MAAa,EAAiE;CAC5E;CACA;CACA;CAEA,YAAY,GAAgB,GAA4B,GAAiB;AAGvE,EAFA,MAAA,IAAa,GACb,MAAA,IAAoB,GACpB,MAAA,IAAe;;CAGjB,IAAI,SAAiB;AACnB,SAAO,MAAA,KAAqB,MAAA,EAAW,WAAW;;CAGpD,GAAK,GAAqB;AACxB,SAAO,MAAA,IAAe,GAAG,MAAA,EAAa,GAAG,MAAQ;;CAGnD,EAAE,GAA6B,GAAqB;AAClD,SAAO,MAAA,EAAW,UAAU,MAAA,EAAU,EAAc,EAAE,GAAM,KAAK,OAAO;;CAG1E,IAAI,GAAsB;AACxB,SAAO,MAAA,EAAW,YAAY,MAAA,EAAU,EAAI,EAAE,KAAK,OAAO,KAAK,KAAA;;CAGjE,OAAO,GAAsB;AAC3B,SAAO,MAAA,EAAW,SAAS,MAAA,EAAU,EAAI,EAAE,KAAK,OAAO;;CAGzD,OAAO,GAAe,GAA4C;AAChE,SAAO,MAAA,EAAW,aAAa,GAAO,GAAS,KAAK,OAAO;;CAG7D,KAAK,GAAsB,GAA8C;AACvE,SAAO,MAAA,EAAW,WAAW,GAAO,GAAS,KAAK,OAAO;;CAG3D,KAAK,GAAkB,IAAqB,OAAe;AACzD,SAAO,MAAA,EAAW,WAAW,GAAO,KAAK,QAAQ,EAAK;;CAGxD,SAAS,GAAe,GAAmC,GAAkD;AAC3G,SAAO,MAAA,EAAW,eAAe,GAAO,GAAM,GAAS,KAAK,OAAO;;CAGrE,SAAS,GAAe,GAAkB,GAAwE;AAChH,SAAO,MAAA,EAAW,aAAa,GAAO;GAAE,GAAG;GAAS;GAAU,OAAO;GAAY,EAAE,KAAK,OAAO;;CAGjG,MAAkC,GAAmC;AACnE,SAAO,IAAI,EACT,MAAA,GACA,MAAA,GACA,MAAA,IAAe,GAAG,MAAA,EAAa,GAAG,OAAO,EAAG,KAAK,OAAO,EAAG,CAC5D;;CAGH,WAAW,GAA8B;AACvC,SAAO,IAAI,EAAa,MAAA,GAAY,GAAQ,MAAA,EAAa"}
package/dist/helpers.cjs DELETED
@@ -1,2 +0,0 @@
1
- function e(e,t){if(t in e)return e[t];let n=t.match(/[^.[\]]+/gu)??[],r=e;for(let e of n){if(typeof r!=`object`||!r)return;r=r[e]}return r}var t=new Set([`zero`,`one`,`two`,`few`,`many`,`other`]);function n(e){if(typeof e==`string`)return!0;if(typeof e!=`object`||!e||Array.isArray(e))return!1;let n=e;if(!(`other`in n))return!1;let r=Object.keys(n);return r.length>t.size?!1:r.every(e=>t.has(e))&&Object.values(n).every(e=>typeof e==`string`)}function r(e,t){let i={...e};for(let[e,a]of Object.entries(t)){let t=i[e];!n(a)&&!n(t)&&typeof t==`object`&&t?i[e]=r(t,a):i[e]=typeof a==`object`&&a?{...a}:a}return i}var i=class extends Map{#e;constructor(e){super(),this.#e=e}set(e,t){return!this.has(e)&&this.size>=this.#e&&this.delete(this.keys().next().value),super.set(e,t)}};exports.BoundedMap=i,exports.deepMerge=r,exports.isMessageValue=n,exports.resolvePath=e;
2
- //# sourceMappingURL=helpers.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.cjs","names":["#cap"],"sources":["../src/helpers.ts"],"sourcesContent":["import type { MessageValue, Messages } from './types';\n\n/* -------------------- Path Resolution -------------------- */\n\n/**\n * Resolves nested properties using dot notation and bracket notation.\n * Supports: 'user.name', 'items[0]', 'user.items[0].name'\n */\nexport function resolvePath(obj: Record<string, unknown>, path: string): unknown {\n // Try direct access first (handles keys with literal dots)\n if (path in obj) return obj[path];\n\n const parts = path.match(/[^.[\\]]+/gu) ?? [];\n let value: unknown = obj;\n\n for (const part of parts) {\n if (value == null || typeof value !== 'object') return undefined;\n\n value = (value as Record<string, unknown>)[part];\n }\n\n return value;\n}\n\n/* -------------------- Message Value Guard -------------------- */\n\nexport const PLURAL_FORMS = new Set<string>(['zero', 'one', 'two', 'few', 'many', 'other']);\n\nexport function isMessageValue(value: unknown): value is MessageValue {\n if (typeof value === 'string') return true;\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n\n const obj = value as Record<string, unknown>;\n\n if (!('other' in obj)) return false;\n\n const keys = Object.keys(obj);\n\n if (keys.length > PLURAL_FORMS.size) return false;\n\n return keys.every((k) => PLURAL_FORMS.has(k)) && Object.values(obj).every((v) => typeof v === 'string');\n}\n\n/* -------------------- Deep Merge -------------------- */\n\nexport function deepMerge(target: Messages, source: Messages): Messages {\n const result = { ...target };\n\n for (const [key, val] of Object.entries(source)) {\n const existing = result[key];\n\n if (!isMessageValue(val) && !isMessageValue(existing) && typeof existing === 'object' && existing !== null) {\n result[key] = deepMerge(existing as Messages, val as Messages);\n } else {\n // Clone PluralMessages objects to prevent external mutations from corrupting the catalog.\n result[key] = typeof val === 'object' && val !== null ? ({ ...(val as object) } as MessageValue) : val;\n }\n }\n\n return result;\n}\n\n/* -------------------- BoundedMap -------------------- */\n\n/**\n * Size-bounded Map that evicts the oldest entry (insertion order) when the cap is reached.\n * Used by I18n's chain cache to prevent unbounded growth in long-lived SSR singletons when\n * locale tags are derived from arbitrary user input (e.g. Accept-Language headers).\n */\nexport class BoundedMap<K, V> extends Map<K, V> {\n readonly #cap: number;\n\n constructor(cap: number) {\n super();\n this.#cap = cap;\n }\n\n override set(key: K, value: V): this {\n if (!this.has(key) && this.size >= this.#cap) {\n this.delete(this.keys().next().value as K);\n }\n\n return super.set(key, value);\n }\n}\n"],"mappings":"AAQA,SAAgB,EAAY,EAA8B,EAAuB,CAE/E,GAAI,KAAQ,EAAK,OAAO,EAAI,GAE5B,IAAM,EAAQ,EAAK,MAAM,aAAa,EAAI,EAAE,CACxC,EAAiB,EAErB,IAAK,IAAM,KAAQ,EAAO,CACxB,GAAqB,OAAO,GAAU,WAAlC,EAA4C,OAEhD,EAAS,EAAkC,GAG7C,OAAO,EAKT,IAAa,EAAe,IAAI,IAAY,CAAC,OAAQ,MAAO,MAAO,MAAO,OAAQ,QAAQ,CAAC,CAE3F,SAAgB,EAAe,EAAuC,CACpE,GAAI,OAAO,GAAU,SAAU,MAAO,GAEtC,GAAI,OAAO,GAAU,WAAY,GAAkB,MAAM,QAAQ,EAAM,CAAE,MAAO,GAEhF,IAAM,EAAM,EAEZ,GAAI,EAAE,UAAW,GAAM,MAAO,GAE9B,IAAM,EAAO,OAAO,KAAK,EAAI,CAI7B,OAFI,EAAK,OAAS,EAAa,KAAa,GAErC,EAAK,MAAO,GAAM,EAAa,IAAI,EAAE,CAAC,EAAI,OAAO,OAAO,EAAI,CAAC,MAAO,GAAM,OAAO,GAAM,SAAS,CAKzG,SAAgB,EAAU,EAAkB,EAA4B,CACtE,IAAM,EAAS,CAAE,GAAG,EAAQ,CAE5B,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,EAAO,CAAE,CAC/C,IAAM,EAAW,EAAO,GAEpB,CAAC,EAAe,EAAI,EAAI,CAAC,EAAe,EAAS,EAAI,OAAO,GAAa,UAAY,EACvF,EAAO,GAAO,EAAU,EAAsB,EAAgB,CAG9D,EAAO,GAAO,OAAO,GAAQ,UAAY,EAAgB,CAAE,GAAI,EAAgB,CAAoB,EAIvG,OAAO,EAUT,IAAa,EAAb,cAAsC,GAAU,CAC9C,GAEA,YAAY,EAAa,CACvB,OAAO,CACP,MAAA,EAAY,EAGd,IAAa,EAAQ,EAAgB,CAKnC,MAJI,CAAC,KAAK,IAAI,EAAI,EAAI,KAAK,MAAQ,MAAA,GACjC,KAAK,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,MAAW,CAGrC,MAAM,IAAI,EAAK,EAAM"}
package/dist/helpers.d.ts DELETED
@@ -1,20 +0,0 @@
1
- import type { MessageValue, Messages } from './types';
2
- /**
3
- * Resolves nested properties using dot notation and bracket notation.
4
- * Supports: 'user.name', 'items[0]', 'user.items[0].name'
5
- */
6
- export declare function resolvePath(obj: Record<string, unknown>, path: string): unknown;
7
- export declare const PLURAL_FORMS: Set<string>;
8
- export declare function isMessageValue(value: unknown): value is MessageValue;
9
- export declare function deepMerge(target: Messages, source: Messages): Messages;
10
- /**
11
- * Size-bounded Map that evicts the oldest entry (insertion order) when the cap is reached.
12
- * Used by I18n's chain cache to prevent unbounded growth in long-lived SSR singletons when
13
- * locale tags are derived from arbitrary user input (e.g. Accept-Language headers).
14
- */
15
- export declare class BoundedMap<K, V> extends Map<K, V> {
16
- #private;
17
- constructor(cap: number);
18
- set(key: K, value: V): this;
19
- }
20
- //# sourceMappingURL=helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAItD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAc/E;AAID,eAAO,MAAM,YAAY,aAAkE,CAAC;AAE5F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAcpE;AAID,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAetE;AAID;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;;gBAGjC,GAAG,EAAE,MAAM;IAKd,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;CAOrC"}
package/dist/helpers.js DELETED
@@ -1,47 +0,0 @@
1
- //#region src/helpers.ts
2
- function e(e, t) {
3
- if (t in e) return e[t];
4
- let n = t.match(/[^.[\]]+/gu) ?? [], r = e;
5
- for (let e of n) {
6
- if (typeof r != "object" || !r) return;
7
- r = r[e];
8
- }
9
- return r;
10
- }
11
- var t = new Set([
12
- "zero",
13
- "one",
14
- "two",
15
- "few",
16
- "many",
17
- "other"
18
- ]);
19
- function n(e) {
20
- if (typeof e == "string") return !0;
21
- if (typeof e != "object" || !e || Array.isArray(e)) return !1;
22
- let n = e;
23
- if (!("other" in n)) return !1;
24
- let r = Object.keys(n);
25
- return r.length > t.size ? !1 : r.every((e) => t.has(e)) && Object.values(n).every((e) => typeof e == "string");
26
- }
27
- function r(e, t) {
28
- let i = { ...e };
29
- for (let [e, a] of Object.entries(t)) {
30
- let t = i[e];
31
- !n(a) && !n(t) && typeof t == "object" && t ? i[e] = r(t, a) : i[e] = typeof a == "object" && a ? { ...a } : a;
32
- }
33
- return i;
34
- }
35
- var i = class extends Map {
36
- #e;
37
- constructor(e) {
38
- super(), this.#e = e;
39
- }
40
- set(e, t) {
41
- return !this.has(e) && this.size >= this.#e && this.delete(this.keys().next().value), super.set(e, t);
42
- }
43
- };
44
- //#endregion
45
- export { i as BoundedMap, r as deepMerge, n as isMessageValue, e as resolvePath };
46
-
47
- //# sourceMappingURL=helpers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.js","names":["#cap"],"sources":["../src/helpers.ts"],"sourcesContent":["import type { MessageValue, Messages } from './types';\n\n/* -------------------- Path Resolution -------------------- */\n\n/**\n * Resolves nested properties using dot notation and bracket notation.\n * Supports: 'user.name', 'items[0]', 'user.items[0].name'\n */\nexport function resolvePath(obj: Record<string, unknown>, path: string): unknown {\n // Try direct access first (handles keys with literal dots)\n if (path in obj) return obj[path];\n\n const parts = path.match(/[^.[\\]]+/gu) ?? [];\n let value: unknown = obj;\n\n for (const part of parts) {\n if (value == null || typeof value !== 'object') return undefined;\n\n value = (value as Record<string, unknown>)[part];\n }\n\n return value;\n}\n\n/* -------------------- Message Value Guard -------------------- */\n\nexport const PLURAL_FORMS = new Set<string>(['zero', 'one', 'two', 'few', 'many', 'other']);\n\nexport function isMessageValue(value: unknown): value is MessageValue {\n if (typeof value === 'string') return true;\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n\n const obj = value as Record<string, unknown>;\n\n if (!('other' in obj)) return false;\n\n const keys = Object.keys(obj);\n\n if (keys.length > PLURAL_FORMS.size) return false;\n\n return keys.every((k) => PLURAL_FORMS.has(k)) && Object.values(obj).every((v) => typeof v === 'string');\n}\n\n/* -------------------- Deep Merge -------------------- */\n\nexport function deepMerge(target: Messages, source: Messages): Messages {\n const result = { ...target };\n\n for (const [key, val] of Object.entries(source)) {\n const existing = result[key];\n\n if (!isMessageValue(val) && !isMessageValue(existing) && typeof existing === 'object' && existing !== null) {\n result[key] = deepMerge(existing as Messages, val as Messages);\n } else {\n // Clone PluralMessages objects to prevent external mutations from corrupting the catalog.\n result[key] = typeof val === 'object' && val !== null ? ({ ...(val as object) } as MessageValue) : val;\n }\n }\n\n return result;\n}\n\n/* -------------------- BoundedMap -------------------- */\n\n/**\n * Size-bounded Map that evicts the oldest entry (insertion order) when the cap is reached.\n * Used by I18n's chain cache to prevent unbounded growth in long-lived SSR singletons when\n * locale tags are derived from arbitrary user input (e.g. Accept-Language headers).\n */\nexport class BoundedMap<K, V> extends Map<K, V> {\n readonly #cap: number;\n\n constructor(cap: number) {\n super();\n this.#cap = cap;\n }\n\n override set(key: K, value: V): this {\n if (!this.has(key) && this.size >= this.#cap) {\n this.delete(this.keys().next().value as K);\n }\n\n return super.set(key, value);\n }\n}\n"],"mappings":";AAQA,SAAgB,EAAY,GAA8B,GAAuB;AAE/E,KAAI,KAAQ,EAAK,QAAO,EAAI;CAE5B,IAAM,IAAQ,EAAK,MAAM,aAAa,IAAI,EAAE,EACxC,IAAiB;AAErB,MAAK,IAAM,KAAQ,GAAO;AACxB,MAAqB,OAAO,KAAU,aAAlC,EAA4C;AAEhD,MAAS,EAAkC;;AAG7C,QAAO;;AAKT,IAAa,IAAe,IAAI,IAAY;CAAC;CAAQ;CAAO;CAAO;CAAO;CAAQ;CAAQ,CAAC;AAE3F,SAAgB,EAAe,GAAuC;AACpE,KAAI,OAAO,KAAU,SAAU,QAAO;AAEtC,KAAI,OAAO,KAAU,aAAY,KAAkB,MAAM,QAAQ,EAAM,CAAE,QAAO;CAEhF,IAAM,IAAM;AAEZ,KAAI,EAAE,WAAW,GAAM,QAAO;CAE9B,IAAM,IAAO,OAAO,KAAK,EAAI;AAI7B,QAFI,EAAK,SAAS,EAAa,OAAa,KAErC,EAAK,OAAO,MAAM,EAAa,IAAI,EAAE,CAAC,IAAI,OAAO,OAAO,EAAI,CAAC,OAAO,MAAM,OAAO,KAAM,SAAS;;AAKzG,SAAgB,EAAU,GAAkB,GAA4B;CACtE,IAAM,IAAS,EAAE,GAAG,GAAQ;AAE5B,MAAK,IAAM,CAAC,GAAK,MAAQ,OAAO,QAAQ,EAAO,EAAE;EAC/C,IAAM,IAAW,EAAO;AAExB,EAAI,CAAC,EAAe,EAAI,IAAI,CAAC,EAAe,EAAS,IAAI,OAAO,KAAa,YAAY,IACvF,EAAO,KAAO,EAAU,GAAsB,EAAgB,GAG9D,EAAO,KAAO,OAAO,KAAQ,YAAY,IAAgB,EAAE,GAAI,GAAgB,GAAoB;;AAIvG,QAAO;;AAUT,IAAa,IAAb,cAAsC,IAAU;CAC9C;CAEA,YAAY,GAAa;AAEvB,EADA,OAAO,EACP,MAAA,IAAY;;CAGd,IAAa,GAAQ,GAAgB;AAKnC,SAJI,CAAC,KAAK,IAAI,EAAI,IAAI,KAAK,QAAQ,MAAA,KACjC,KAAK,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,MAAW,EAGrC,MAAM,IAAI,GAAK,EAAM"}
package/dist/i18nit.cjs DELETED
@@ -1,2 +0,0 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class e{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}get locale(){return this.#t??this.#e.getLocale()}#r(e){return this.#n?`${this.#n}.${e}`:e}t(e,t){return this.#e.translate(this.#r(e),t,this.locale)}has(e){return this.#e.findMessage(this.#r(e),this.locale)!==void 0}hasOwn(e){return this.#e.checkOwn(this.#r(e),this.locale)}number(e,t){return this.#e.formatNumber(e,t,this.locale)}date(e,t){return this.#e.formatDate(e,t,this.locale)}list(e,t=`and`){return this.#e.formatList(e,this.locale,t)}relative(e,t,n){return this.#e.formatRelative(e,t,n,this.locale)}currency(e,t,n){return this.#e.formatNumber(e,{...n,currency:t,style:`currency`},this.locale)}scope(t){return new e(this.#e,this.#t,this.#n?`${this.#n}.${String(t)}`:String(t))}withLocale(t){return new e(this.#e,t,this.#n)}};function t(e,t){if(t in e)return e[t];let n=t.match(/[^.[\]]+/gu)??[],r=e;for(let e of n){if(typeof r!=`object`||!r)return;r=r[e]}return r}var n=new Set([`zero`,`one`,`two`,`few`,`many`,`other`]);function r(e){if(typeof e==`string`)return!0;if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e;if(!(`other`in t))return!1;let r=Object.keys(t);return r.length>n.size?!1:r.every(e=>n.has(e))&&Object.values(t).every(e=>typeof e==`string`)}function i(e,t){let n={...e};for(let[e,a]of Object.entries(t)){let t=n[e];!r(a)&&!r(t)&&typeof t==`object`&&t?n[e]=i(t,a):n[e]=typeof a==`object`&&a?{...a}:a}return n}var a=class extends Map{#e;constructor(e){super(),this.#e=e}set(e,t){return!this.has(e)&&this.size>=this.#e&&this.delete(this.keys().next().value),super.set(e,t)}};function o(){return{dateFormat:new Map,listFormat:new Map,numberFormat:new Map,pluralRules:new Map,relativeTimeFormat:new Map}}function s(e,t,n){let r=e.get(t);return r||(r=n(),e.set(t,r)),r}function c(e,t){return t?`${e}:${JSON.stringify(t,Object.keys(t).sort())}`:e}function l(e,t,n,r){let i=c(r,n);try{return s(e.numberFormat,i,()=>new Intl.NumberFormat(r,n)).format(t)}catch{return String(t)}}function u(e,t,n,r){let i=typeof t==`number`?new Date(t):t,a=c(r,n);try{return s(e.dateFormat,a,()=>new Intl.DateTimeFormat(r,n)).format(i)}catch{return i.toString()}}function d(e,t,n,r,i){let a=c(i,r);try{return s(e.relativeTimeFormat,a,()=>new Intl.RelativeTimeFormat(i,r)).format(t,n)}catch{return String(t)}}function f(e,t,n,r){if(t.length===0)return``;let i=t.map(String),a=r===`and`?`conjunction`:`disjunction`;try{return s(e.listFormat,`${n}:${a}`,()=>new Intl.ListFormat(n,{style:`long`,type:a})).format(i)}catch{return i.length===1?i[0]:i.length===2?`${i[0]} ${r} ${i[1]}`:`${i.slice(0,-1).join(`, `)} ${r} ${i.at(-1)}`}}function p(e,t,n){let r=Math.floor(Math.abs(n));try{return s(e.pluralRules,t,()=>new Intl.PluralRules(t)).select(r)}catch{return r===1?`one`:`other`}}function m(e,t,n,r){return t==null?``:Array.isArray(t)?n===`and`?f(e,t,r,`and`):n===`or`?f(e,t,r,`or`):n===void 0?t.map(String).join(`, `):t.map(String).join(n):typeof t==`number`?l(e,t,void 0,r):String(t)}function h(e,n,r,i){return e.includes(`{`)?e.replace(/\{([\p{ID_Continue}\-.[\]]+)(?:\|([^}]+))?\}/gu,(e,a,o)=>m(i,t(n,a),o,r)):e}var g=class{#e;#t;#n=new Map;#r=new Map;#i=new Map;#a=new Set;#o=new a(128);#s;#c;#l=null;#u=null;#d=!1;#f=0;#p=null;#m;#h=o();#g;constructor({fallback:n,loaders:i,locale:a=`en`,messages:o,onDiagnostic:s,onMissing:c}={}){if(this.#e=a,this.#t=Array.isArray(n)?n:n?[n]:[],this.#s=c,this.#c=s,o)for(let[e,t]of Object.entries(o))this.#n.set(e,structuredClone(t));if(i)for(let[e,t]of Object.entries(i))this.#r.set(e,t);this.#m={checkOwn:(e,n)=>{let i=this.#n.get(n);if(!i)return!1;let a=t(i,e);return a!==void 0&&r(a)},findMessage:(e,t)=>this.#b(e,t),formatDate:(e,t,n)=>u(this.#h,e,t,n),formatList:(e,t,n)=>f(this.#h,e,t,n),formatNumber:(e,t,n)=>l(this.#h,e,t,n),formatRelative:(e,t,n,r)=>d(this.#h,e,t,n,r),getLocale:()=>this.#e,translate:(e,t,n)=>this.#S(e,t,n)},this.#g=new e(this.#m,null)}get locale(){return this.#e}get locales(){return this.#l??=[...this.#n.keys()],this.#l}set locale(e){this.#e!==e&&(this.#e=e,this.#y(`locale-change`))}async setLocale(e){e!==this.#e&&(await this.load(e),this.locale=e)}add(e,t){let n=this.#n.get(e)??{};this.#n.set(e,i(n,t)),this.#l=null,this.#x(this.#e).includes(e)&&this.#y(`catalog-update`)}replace(e,t){this.#n.set(e,structuredClone(t)),this.#l=null,this.#x(this.#e).includes(e)&&this.#y(`catalog-update`)}has(e){return this.#g.has(e)}hasOwn(e){return this.#g.hasOwn(e)}hasLocale(e){return this.#n.has(e)}async load(...e){await Promise.all(e.map(e=>this.#C(e)))}async reload(e){this.#r.has(e)&&(this.#n.delete(e),this.#l=null,await this.#C(e))}registerLoader(e,t){this.#r.set(e,t),this.#u=null}get loadableLocales(){return this.#u??=[...this.#r.keys()],this.#u}t(e,t){return this.#g.t(e,t)}number(e,t){return this.#g.number(e,t)}date(e,t){return this.#g.date(e,t)}list(e,t=`and`){return this.#g.list(e,t)}relative(e,t,n){return this.#g.relative(e,t,n)}currency(e,t,n){return this.#g.currency(e,t,n)}withLocale(e){return this.#g.withLocale(e)}scope(e){return this.#g.scope(e)}batch(e){this.#f++;try{e()}finally{if(this.#f--,this.#f===0&&this.#p!==null){let e=this.#p;this.#p=null,this.#y(e)}}}subscribe(e,t){if(this.#a.add(e),t)try{e({locale:this.#e,reason:`locale-change`})}catch(e){this.#_(e)}return()=>this.#a.delete(e)}dispose(){this.#d=!0,this.#a.clear(),this.#n.clear(),this.#r.clear(),this.#i.clear(),this.#o.clear(),this.#l=null,this.#u=null}[Symbol.dispose](){this.dispose()}async[Symbol.asyncDispose](){await Promise.allSettled([...this.#i.values()]),this.dispose()}#_(e){this.#c?this.#c({error:e,kind:`subscriber-error`}):console.error(`[i18nit] Subscriber threw:`,e)}#v(e,t){this.#c?this.#c({error:e,kind:`loader-error`,locale:t}):console.warn(`[i18nit] Loader error:`,e)}#y(e){if(this.#f>0){this.#p!==`locale-change`&&(this.#p=e);return}let t={locale:this.#e,reason:e};for(let e of this.#a)try{e(t)}catch(e){this.#_(e)}}#b(e,n){for(let i of this.#x(n)){let n=this.#n.get(i);if(!n)continue;let a=t(n,e);if(a!==void 0&&r(a))return a}}#x(e){let t=this.#o.get(e);if(t)return t;let n=new Set,r=e=>{n.add(e);let t=e.split(`-`);for(let e=t.length-1;e>0;e--)n.add(t.slice(0,e).join(`-`))};r(e);for(let e of this.#t)r(e);let i=[...n];return this.#o.set(e,i),i}#S(e,t,n){let r=this.#b(e,n);if(r===void 0)return this.#s?.(e,n)??e;if(typeof r==`string`)return h(r,t??{},n,this.#h);let i=t??{},a=Number(i.count??0);return h(r[a===0&&r.zero!==void 0?`zero`:p(this.#h,n,a)]??r.other,i,n,this.#h)}#C(e){if(this.#i.has(e))return this.#i.get(e);if(this.#n.has(e))return Promise.resolve();let t=this.#r.get(e);if(!t)return Promise.resolve();let n=(async()=>{try{let n=await t(e);this.#d||this.replace(e,n)}catch(t){throw this.#v(t,e),t}finally{this.#i.delete(e)}})();return this.#i.set(e,n),n}};function _(e){return new g(e)}exports.I18n=g,exports.createI18n=_;
2
- //# sourceMappingURL=i18nit.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18nit.cjs","names":["#core","#fixedLocale","#prefix","#key","#cap","#caches","#view","#locale","#fallbacks","#onMissing","#onDiagnostic","#catalogs","#loaders","#core","#findMessage","#translate","#localesCache","#notify","#getLocaleChain","#loadOne","#loadersCache","#batchDepth","#pendingNotify","#subscribers","#diagnoseSubscriber","#disposed","#loading","#chainCache","#diagnoseLoader"],"sources":["../src/core.ts","../src/helpers.ts","../src/intl.ts","../src/interpolate.ts","../src/i18n.ts"],"sourcesContent":["import type { BoundI18n, Locale, MessageValue, Messages, NamespaceKeys, TranslationKeyParam, Vars } from './types';\n\n/* -------------------- I18nCore -------------------- */\n\n/**\n * Module-private interface given to every `BoundView` — exposes only the operations views need.\n * Created once per `I18n` instance so `scope()` / `withLocale()` allocate no closures per call.\n */\nexport type I18nCore = {\n checkOwn(key: string, locale: Locale): boolean;\n findMessage(key: string, locale: Locale): MessageValue | undefined;\n formatDate(value: Date | number, options: Intl.DateTimeFormatOptions | undefined, locale: Locale): string;\n formatList(items: unknown[], locale: string, type: 'and' | 'or'): string;\n formatNumber(value: number, options: Intl.NumberFormatOptions | undefined, locale: Locale): string;\n formatRelative(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options: Intl.RelativeTimeFormatOptions | undefined,\n locale: Locale,\n ): string;\n getLocale(): Locale;\n translate(key: string, vars: Vars | undefined, locale: Locale): string;\n};\n\n/* -------------------- BoundView -------------------- */\n\n/**\n * Lightweight view over an `I18n` instance, fixed to a locale and/or key namespace prefix.\n * All methods live on the prototype — no closures are allocated per `scope()` / `withLocale()` call.\n */\nexport class BoundView<T extends Messages = Messages> implements BoundI18n<T> {\n readonly #core: I18nCore;\n readonly #fixedLocale: Locale | null;\n readonly #prefix: string | undefined;\n\n constructor(core: I18nCore, fixedLocale: Locale | null, prefix?: string) {\n this.#core = core;\n this.#fixedLocale = fixedLocale;\n this.#prefix = prefix;\n }\n\n get locale(): Locale {\n return this.#fixedLocale ?? this.#core.getLocale();\n }\n\n #key(key: string): string {\n return this.#prefix ? `${this.#prefix}.${key}` : key;\n }\n\n t(key: TranslationKeyParam<T>, vars?: Vars): string {\n return this.#core.translate(this.#key(key as string), vars, this.locale);\n }\n\n has(key: string): boolean {\n return this.#core.findMessage(this.#key(key), this.locale) !== undefined;\n }\n\n hasOwn(key: string): boolean {\n return this.#core.checkOwn(this.#key(key), this.locale);\n }\n\n number(value: number, options?: Intl.NumberFormatOptions): string {\n return this.#core.formatNumber(value, options, this.locale);\n }\n\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string {\n return this.#core.formatDate(value, options, this.locale);\n }\n\n list(items: unknown[], type: 'and' | 'or' = 'and'): string {\n return this.#core.formatList(items, this.locale, type);\n }\n\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string {\n return this.#core.formatRelative(value, unit, options, this.locale);\n }\n\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string {\n return this.#core.formatNumber(value, { ...options, currency, style: 'currency' }, this.locale);\n }\n\n scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages> {\n return new BoundView(\n this.#core,\n this.#fixedLocale,\n this.#prefix ? `${this.#prefix}.${String(ns)}` : String(ns),\n ) as BoundI18n<T[K] & Messages>;\n }\n\n withLocale(locale: Locale): BoundI18n<T> {\n return new BoundView<T>(this.#core, locale, this.#prefix);\n }\n}\n","import type { MessageValue, Messages } from './types';\n\n/* -------------------- Path Resolution -------------------- */\n\n/**\n * Resolves nested properties using dot notation and bracket notation.\n * Supports: 'user.name', 'items[0]', 'user.items[0].name'\n */\nexport function resolvePath(obj: Record<string, unknown>, path: string): unknown {\n // Try direct access first (handles keys with literal dots)\n if (path in obj) return obj[path];\n\n const parts = path.match(/[^.[\\]]+/gu) ?? [];\n let value: unknown = obj;\n\n for (const part of parts) {\n if (value == null || typeof value !== 'object') return undefined;\n\n value = (value as Record<string, unknown>)[part];\n }\n\n return value;\n}\n\n/* -------------------- Message Value Guard -------------------- */\n\nexport const PLURAL_FORMS = new Set<string>(['zero', 'one', 'two', 'few', 'many', 'other']);\n\nexport function isMessageValue(value: unknown): value is MessageValue {\n if (typeof value === 'string') return true;\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n\n const obj = value as Record<string, unknown>;\n\n if (!('other' in obj)) return false;\n\n const keys = Object.keys(obj);\n\n if (keys.length > PLURAL_FORMS.size) return false;\n\n return keys.every((k) => PLURAL_FORMS.has(k)) && Object.values(obj).every((v) => typeof v === 'string');\n}\n\n/* -------------------- Deep Merge -------------------- */\n\nexport function deepMerge(target: Messages, source: Messages): Messages {\n const result = { ...target };\n\n for (const [key, val] of Object.entries(source)) {\n const existing = result[key];\n\n if (!isMessageValue(val) && !isMessageValue(existing) && typeof existing === 'object' && existing !== null) {\n result[key] = deepMerge(existing as Messages, val as Messages);\n } else {\n // Clone PluralMessages objects to prevent external mutations from corrupting the catalog.\n result[key] = typeof val === 'object' && val !== null ? ({ ...(val as object) } as MessageValue) : val;\n }\n }\n\n return result;\n}\n\n/* -------------------- BoundedMap -------------------- */\n\n/**\n * Size-bounded Map that evicts the oldest entry (insertion order) when the cap is reached.\n * Used by I18n's chain cache to prevent unbounded growth in long-lived SSR singletons when\n * locale tags are derived from arbitrary user input (e.g. Accept-Language headers).\n */\nexport class BoundedMap<K, V> extends Map<K, V> {\n readonly #cap: number;\n\n constructor(cap: number) {\n super();\n this.#cap = cap;\n }\n\n override set(key: K, value: V): this {\n if (!this.has(key) && this.size >= this.#cap) {\n this.delete(this.keys().next().value as K);\n }\n\n return super.set(key, value);\n }\n}\n","import type { Locale, PluralForm } from './types';\n\n/* -------------------- Cache Container -------------------- */\n\n/** Holds all Intl formatter caches for one I18n instance — GC'd with the instance. */\nexport type IntlCaches = {\n dateFormat: Map<string, Intl.DateTimeFormat>;\n listFormat: Map<string, Intl.ListFormat>;\n numberFormat: Map<string, Intl.NumberFormat>;\n pluralRules: Map<string, Intl.PluralRules>;\n relativeTimeFormat: Map<string, Intl.RelativeTimeFormat>;\n};\n\nexport function makeIntlCaches(): IntlCaches {\n return {\n dateFormat: new Map(),\n listFormat: new Map(),\n numberFormat: new Map(),\n pluralRules: new Map(),\n relativeTimeFormat: new Map(),\n };\n}\n\n/* -------------------- Cache Helpers -------------------- */\n\nfunction intlFmt<F extends object>(cache: Map<string, F>, key: string, build: () => F): F {\n let fmt = cache.get(key);\n\n if (!fmt) {\n fmt = build();\n cache.set(key, fmt);\n }\n\n return fmt;\n}\n\n/**\n * Builds a stable string key for an Intl formatter cache.\n * Call this once per formatter construction path — not on every format call — so key\n * serialization cost is paid only on cache misses.\n */\nfunction intlKey(locale: string, options?: object): string {\n return options ? `${locale}:${JSON.stringify(options, Object.keys(options).sort())}` : locale;\n}\n\n/* -------------------- Format Functions -------------------- */\n\nexport function formatNumber(\n caches: IntlCaches,\n value: number,\n options: Intl.NumberFormatOptions | undefined,\n locale: Locale,\n): string {\n const key = intlKey(locale, options);\n\n try {\n return intlFmt(caches.numberFormat, key, () => new Intl.NumberFormat(locale, options)).format(value);\n } catch {\n return String(value);\n }\n}\n\nexport function formatDate(\n caches: IntlCaches,\n value: Date | number,\n options: Intl.DateTimeFormatOptions | undefined,\n locale: Locale,\n): string {\n const d = typeof value === 'number' ? new Date(value) : value;\n const key = intlKey(locale, options);\n\n try {\n return intlFmt(caches.dateFormat, key, () => new Intl.DateTimeFormat(locale, options)).format(d);\n } catch {\n return d.toString();\n }\n}\n\nexport function formatRelative(\n caches: IntlCaches,\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options: Intl.RelativeTimeFormatOptions | undefined,\n locale: Locale,\n): string {\n const key = intlKey(locale, options);\n\n try {\n return intlFmt(caches.relativeTimeFormat, key, () => new Intl.RelativeTimeFormat(locale, options)).format(\n value,\n unit,\n );\n } catch {\n return String(value);\n }\n}\n\nexport function formatList(caches: IntlCaches, items: unknown[], locale: string, type: 'and' | 'or'): string {\n if (items.length === 0) return '';\n\n const stringItems = items.map(String);\n const intlType = type === 'and' ? 'conjunction' : 'disjunction';\n\n try {\n return intlFmt(\n caches.listFormat,\n `${locale}:${intlType}`,\n () => new Intl.ListFormat(locale, { style: 'long', type: intlType }),\n ).format(stringItems);\n } catch {\n // Fallback for environments without Intl.ListFormat\n if (stringItems.length === 1) return stringItems[0];\n\n if (stringItems.length === 2) return `${stringItems[0]} ${type} ${stringItems[1]}`;\n\n return `${stringItems.slice(0, -1).join(', ')} ${type} ${stringItems.at(-1)}`;\n }\n}\n\nexport function getPluralForm(caches: IntlCaches, locale: Locale, count: number): PluralForm {\n const n = Math.floor(Math.abs(count));\n\n try {\n return intlFmt(caches.pluralRules, locale, () => new Intl.PluralRules(locale)).select(n) as PluralForm;\n } catch {\n return n === 1 ? 'one' : 'other';\n }\n}\n","import type { Vars } from './types';\n\nimport { resolvePath } from './helpers';\nimport { type IntlCaches, formatList, formatNumber } from './intl';\n\n/* -------------------- Token Resolution -------------------- */\n\nfunction resolveToken(caches: IntlCaches, value: unknown, separator: string | undefined, locale: string): string {\n if (value == null) return '';\n\n if (Array.isArray(value)) {\n if (separator === 'and') return formatList(caches, value, locale, 'and');\n\n if (separator === 'or') return formatList(caches, value, locale, 'or');\n\n if (separator !== undefined) return value.map(String).join(separator);\n\n return value.map(String).join(', ');\n }\n\n if (typeof value === 'number') {\n return formatNumber(caches, value, undefined, locale);\n }\n\n return String(value);\n}\n\n/* -------------------- Interpolation -------------------- */\n\n/**\n * Interpolates variables into a template string. Supports Unicode variable names\n * via `\\p{ID_Continue}` so non-ASCII identifiers like `{prénom}` or `{名前}` work correctly.\n *\n * Supported formats: `{name}` · `{user.name}` · `{items[0]}` · `{items}` ·\n * `{items|and}` · `{items|or}` · `{items| - }` · `{items.length}`\n */\nexport function interpolate(template: string, vars: Vars, locale: string, caches: IntlCaches): string {\n if (!template.includes('{')) return template;\n\n return template.replace(/\\{([\\p{ID_Continue}\\-.[\\]]+)(?:\\|([^}]+))?\\}/gu, (_match, key: string, separator?: string) =>\n resolveToken(caches, resolvePath(vars, key), separator, locale),\n );\n}\n","import type {\n BoundI18n,\n DiagnosticEvent,\n I18nOptions,\n Loader,\n Locale,\n LocaleChangeEvent,\n LocaleChangeReason,\n MessageValue,\n Messages,\n NamespaceKeys,\n TranslationKeyParam,\n Unsubscribe,\n Vars,\n} from './types';\n\nimport { BoundView, type I18nCore } from './core';\nimport { BoundedMap, deepMerge, isMessageValue, resolvePath } from './helpers';\nimport { interpolate } from './interpolate';\nimport {\n type IntlCaches,\n formatDate,\n formatList,\n formatNumber,\n formatRelative,\n getPluralForm,\n makeIntlCaches,\n} from './intl';\n\nexport class I18n<T extends Messages = Messages> implements BoundI18n<T> {\n #locale: Locale;\n #fallbacks: Locale[];\n #catalogs = new Map<Locale, Messages>();\n #loaders = new Map<Locale, Loader>();\n #loading = new Map<Locale, Promise<void>>();\n #subscribers = new Set<(event: LocaleChangeEvent) => void>();\n /** Bounded at 128 entries — prevents unbounded growth when locale tags come from user input. */\n #chainCache = new BoundedMap<Locale, Locale[]>(128);\n #onMissing?: (key: string, locale: Locale) => string | undefined;\n #onDiagnostic?: (event: DiagnosticEvent) => void;\n #localesCache: Locale[] | null = null;\n #loadersCache: Locale[] | null = null;\n #disposed = false;\n #batchDepth = 0;\n #pendingNotify: LocaleChangeReason | null = null;\n #core: I18nCore;\n\n // Instance-scoped Intl caches — GC'd with the instance (important for SSR with many locales).\n readonly #caches: IntlCaches = makeIntlCaches();\n\n /** Internal BoundView — I18n delegates its BoundI18n surface here to avoid duplicating every method. */\n readonly #view: BoundView<T>;\n\n constructor({ fallback, loaders, locale = 'en', messages, onDiagnostic, onMissing }: I18nOptions<T> = {}) {\n this.#locale = locale;\n this.#fallbacks = Array.isArray(fallback) ? fallback : fallback ? [fallback] : [];\n this.#onMissing = onMissing;\n this.#onDiagnostic = onDiagnostic;\n\n if (messages) {\n for (const [l, m] of Object.entries(messages)) {\n // Deep-clone at init so external mutations to the source object can't corrupt the catalog.\n this.#catalogs.set(l, structuredClone(m) as Messages);\n }\n }\n\n if (loaders) for (const [l, fn] of Object.entries(loaders)) this.#loaders.set(l, fn);\n\n this.#core = {\n checkOwn: (key: string, locale: Locale) => {\n const catalog = this.#catalogs.get(locale);\n\n if (!catalog) return false;\n\n const value = resolvePath(catalog, key);\n\n return value !== undefined && isMessageValue(value);\n },\n findMessage: (key: string, locale: Locale) => this.#findMessage(key, locale),\n formatDate: (value, options, locale) => formatDate(this.#caches, value, options, locale),\n formatList: (items, locale, type) => formatList(this.#caches, items, locale, type),\n formatNumber: (value, options, locale) => formatNumber(this.#caches, value, options, locale),\n formatRelative: (value, unit, options, locale) => formatRelative(this.#caches, value, unit, options, locale),\n getLocale: () => this.#locale,\n translate: (key, vars, locale) => this.#translate(key, vars, locale),\n };\n\n this.#view = new BoundView<T>(this.#core, null);\n }\n\n /* -------------------- Locale -------------------- */\n\n get locale(): Locale {\n return this.#locale;\n }\n\n get locales(): Locale[] {\n this.#localesCache ??= [...this.#catalogs.keys()];\n\n return this.#localesCache;\n }\n\n set locale(value: Locale) {\n if (this.#locale === value) return;\n\n if (import.meta.env?.DEV && !this.#catalogs.has(value) && this.#loaders.has(value)) {\n console.warn(\n `[i18nit] locale \"${value}\" has a registered loader but is not loaded. ` +\n 'Use setLocale() to load and switch atomically.',\n );\n }\n\n this.#locale = value;\n this.#notify('locale-change');\n }\n\n async setLocale(locale: Locale): Promise<void> {\n if (locale === this.#locale) return;\n\n await this.load(locale);\n this.locale = locale;\n }\n\n /* -------------------- Message Management -------------------- */\n\n /** Deep-merges messages into an existing locale catalog. */\n add(locale: Locale, messages: Messages): void {\n const existing = this.#catalogs.get(locale) ?? {};\n\n this.#catalogs.set(locale, deepMerge(existing, messages));\n this.#localesCache = null;\n\n if (this.#getLocaleChain(this.#locale).includes(locale)) this.#notify('catalog-update');\n }\n\n /** Replaces the entire locale catalog for `locale` with a deep clone of `messages`. */\n replace(locale: Locale, messages: Messages): void {\n this.#catalogs.set(locale, structuredClone(messages));\n this.#localesCache = null;\n\n if (this.#getLocaleChain(this.#locale).includes(locale)) this.#notify('catalog-update');\n }\n\n has(key: string): boolean {\n return this.#view.has(key);\n }\n\n /** Like `has()`, but only checks the exact locale without walking the fallback chain. */\n hasOwn(key: string): boolean {\n return this.#view.hasOwn(key);\n }\n\n hasLocale(locale: Locale): boolean {\n return this.#catalogs.has(locale);\n }\n\n /* -------------------- Async Loaders -------------------- */\n\n async load(...locales: Locale[]): Promise<void> {\n await Promise.all(locales.map((locale) => this.#loadOne(locale)));\n }\n\n /**\n * Force-reloads a locale catalog even if already populated. Useful for hot-reload and forced bundle refresh.\n * No-op (with a dev warning) when no loader is registered for the locale, to prevent silently clearing the catalog.\n */\n async reload(locale: Locale): Promise<void> {\n if (!this.#loaders.has(locale)) {\n if (import.meta.env?.DEV) {\n console.warn(`[i18nit] reload(\"${locale}\") skipped — no loader registered for this locale.`);\n }\n\n return;\n }\n\n this.#catalogs.delete(locale);\n this.#localesCache = null;\n await this.#loadOne(locale);\n }\n\n registerLoader(locale: Locale, loader: Loader): void {\n this.#loaders.set(locale, loader);\n this.#loadersCache = null;\n }\n\n /** Returns the locale keys for which a loader has been registered. */\n get loadableLocales(): Locale[] {\n this.#loadersCache ??= [...this.#loaders.keys()];\n\n return this.#loadersCache;\n }\n\n /* -------------------- BoundI18n surface (delegated to #view) -------------------- */\n\n /**\n * Translates a key with optional interpolation variables.\n * Locale must be loaded first via `load()` or provided via `messages` in config.\n * For a per-call locale override use `withLocale(locale).t(key, vars)`.\n */\n t(key: TranslationKeyParam<T>, vars?: Vars): string {\n return this.#view.t(key, vars);\n }\n\n number(value: number, options?: Intl.NumberFormatOptions): string {\n return this.#view.number(value, options);\n }\n\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string {\n return this.#view.date(value, options);\n }\n\n list(items: unknown[], type: 'and' | 'or' = 'and'): string {\n return this.#view.list(items, type);\n }\n\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string {\n return this.#view.relative(value, unit, options);\n }\n\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string {\n return this.#view.currency(value, currency, options);\n }\n\n /**\n * Returns a bound interface that translates in the given locale without\n * changing the active locale on the instance. Useful for SSR and\n * multi-locale rendering in a single pass.\n */\n withLocale(locale: Locale): BoundI18n<T> {\n return this.#view.withLocale(locale);\n }\n\n /**\n * Returns a translator scoped to a key namespace prefix. Reacts to locale changes on the\n * instance. When `T` is a concrete message type, the returned `BoundI18n` is narrowed to\n * the subtree type so `t()` autocomplete works within the scope.\n * Only keys whose values are nested message objects are valid scope targets.\n */\n scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages> {\n return this.#view.scope(ns);\n }\n\n /* -------------------- Subscriptions -------------------- */\n\n /**\n * Executes `fn` while deferring subscriber notifications. A single notification fires\n * after `fn` completes, collapsing any number of `add()` / `replace()` calls made within.\n * Nested `batch()` calls are supported; notification fires when the outermost batch exits.\n * If both a locale change and a catalog update are triggered, `'locale-change'` takes priority.\n *\n * @remarks\n * `batch()` is synchronous. Async operations (e.g. `load()`) started inside `fn` complete\n * after the batch exits and will notify subscribers individually. To batch-load multiple\n * locales and notify once, await `load()` before entering the batch:\n * ```ts\n * await i18n.load('fr', 'de');\n * i18n.batch(() => { i18n.locale = 'fr'; });\n * ```\n */\n batch(fn: () => void): void {\n this.#batchDepth++;\n\n try {\n fn();\n } finally {\n this.#batchDepth--;\n\n if (this.#batchDepth === 0 && this.#pendingNotify !== null) {\n const reason = this.#pendingNotify;\n\n this.#pendingNotify = null;\n this.#notify(reason);\n }\n }\n }\n\n subscribe(listener: (event: LocaleChangeEvent) => void, immediate?: boolean): Unsubscribe {\n this.#subscribers.add(listener);\n\n if (immediate) {\n try {\n listener({ locale: this.#locale, reason: 'locale-change' });\n } catch (err) {\n this.#diagnoseSubscriber(err);\n }\n }\n\n return () => this.#subscribers.delete(listener);\n }\n\n /** Releases all resources held by this instance. */\n dispose(): void {\n this.#disposed = true;\n this.#subscribers.clear();\n this.#catalogs.clear();\n this.#loaders.clear();\n this.#loading.clear();\n this.#chainCache.clear();\n this.#localesCache = null;\n this.#loadersCache = null;\n }\n\n /** Enables `using i18n = createI18n(...)` for deterministic resource release. */\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Awaits any in-flight `load()` calls and then releases all resources.\n * Enables `await using i18n = createI18n(...)` in environments that support `Symbol.asyncDispose`.\n */\n async [Symbol.asyncDispose](): Promise<void> {\n await Promise.allSettled([...this.#loading.values()]);\n this.dispose();\n }\n\n /* -------------------- Private -------------------- */\n\n #diagnoseSubscriber(error: unknown): void {\n if (this.#onDiagnostic) {\n this.#onDiagnostic({ error, kind: 'subscriber-error' });\n } else {\n console.error('[i18nit] Subscriber threw:', error);\n }\n }\n\n #diagnoseLoader(error: unknown, locale: Locale): void {\n if (this.#onDiagnostic) {\n this.#onDiagnostic({ error, kind: 'loader-error', locale });\n } else {\n console.warn('[i18nit] Loader error:', error);\n }\n }\n\n #notify(reason: LocaleChangeReason): void {\n if (this.#batchDepth > 0) {\n // 'locale-change' takes priority over 'catalog-update' if both occur in one batch\n if (this.#pendingNotify !== 'locale-change') this.#pendingNotify = reason;\n\n return;\n }\n\n const event: LocaleChangeEvent = { locale: this.#locale, reason };\n\n for (const listener of this.#subscribers) {\n try {\n listener(event);\n } catch (err) {\n this.#diagnoseSubscriber(err);\n }\n }\n }\n\n #findMessage(key: string, locale: Locale): MessageValue | undefined {\n for (const loc of this.#getLocaleChain(locale)) {\n const messages = this.#catalogs.get(loc);\n\n if (!messages) continue;\n\n const value = resolvePath(messages, key);\n\n if (value !== undefined && isMessageValue(value)) return value;\n }\n\n return undefined;\n }\n\n #getLocaleChain(locale: Locale): Locale[] {\n const cached = this.#chainCache.get(locale);\n\n if (cached) return cached;\n\n const seen = new Set<Locale>();\n const push = (l: Locale) => {\n seen.add(l);\n\n const parts = l.split('-');\n\n for (let i = parts.length - 1; i > 0; i--) {\n seen.add(parts.slice(0, i).join('-'));\n }\n };\n\n push(locale);\n for (const fallback of this.#fallbacks) push(fallback);\n\n const chain = [...seen];\n\n this.#chainCache.set(locale, chain);\n\n return chain;\n }\n\n #translate(key: string, vars: Vars | undefined, locale: Locale): string {\n const message = this.#findMessage(key, locale);\n\n if (message === undefined) return this.#onMissing?.(key, locale) ?? key;\n\n if (typeof message === 'string') return interpolate(message, vars ?? {}, locale, this.#caches);\n\n const v = vars ?? {};\n\n if (import.meta.env?.DEV && v.count === undefined) {\n console.warn(`[i18nit] Key \"${key}\" is a plural message but vars.count is missing. Defaulting to 0.`);\n }\n\n const count = Number(v.count ?? 0);\n const form = count === 0 && message.zero !== undefined ? 'zero' : getPluralForm(this.#caches, locale, count);\n\n return interpolate(message[form] ?? message.other, v, locale, this.#caches);\n }\n\n #loadOne(locale: Locale): Promise<void> {\n if (this.#loading.has(locale)) return this.#loading.get(locale)!;\n\n if (this.#catalogs.has(locale)) return Promise.resolve();\n\n const loader = this.#loaders.get(locale);\n\n if (!loader) return Promise.resolve();\n\n const promise = (async () => {\n try {\n const messages = await loader(locale);\n\n // Use replace() so the loader result is the authoritative catalog for this locale,\n // not merged on top of any pre-seeded static messages.\n if (!this.#disposed) this.replace(locale, messages);\n } catch (error) {\n this.#diagnoseLoader(error, locale);\n throw error;\n } finally {\n this.#loading.delete(locale);\n }\n })();\n\n this.#loading.set(locale, promise);\n\n return promise;\n }\n}\n\nexport function createI18n<T extends Messages = Messages>(config?: I18nOptions<T>): I18n<T> {\n return new I18n<T>(config);\n}\n"],"mappings":"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"}
package/dist/i18nit.d.ts DELETED
@@ -1,3 +0,0 @@
1
- /** Compatibility re-export — the implementation has moved to domain modules. */
2
- export * from './index';
3
- //# sourceMappingURL=i18nit.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18nit.d.ts","sourceRoot":"","sources":["../src/i18nit.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,cAAc,SAAS,CAAC"}
package/dist/i18nit.js DELETED
@@ -1,2 +0,0 @@
1
- var e=class e{#e;#t;#n;constructor(e,t,n){this.#e=e,this.#t=t,this.#n=n}get locale(){return this.#t??this.#e.getLocale()}#r(e){return this.#n?`${this.#n}.${e}`:e}t(e,t){return this.#e.translate(this.#r(e),t,this.locale)}has(e){return this.#e.findMessage(this.#r(e),this.locale)!==void 0}hasOwn(e){return this.#e.checkOwn(this.#r(e),this.locale)}number(e,t){return this.#e.formatNumber(e,t,this.locale)}date(e,t){return this.#e.formatDate(e,t,this.locale)}list(e,t=`and`){return this.#e.formatList(e,this.locale,t)}relative(e,t,n){return this.#e.formatRelative(e,t,n,this.locale)}currency(e,t,n){return this.#e.formatNumber(e,{...n,currency:t,style:`currency`},this.locale)}scope(t){return new e(this.#e,this.#t,this.#n?`${this.#n}.${String(t)}`:String(t))}withLocale(t){return new e(this.#e,t,this.#n)}};function t(e,t){if(t in e)return e[t];let n=t.match(/[^.[\]]+/gu)??[],r=e;for(let e of n){if(typeof r!=`object`||!r)return;r=r[e]}return r}var n=new Set([`zero`,`one`,`two`,`few`,`many`,`other`]);function r(e){if(typeof e==`string`)return!0;if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e;if(!(`other`in t))return!1;let r=Object.keys(t);return r.length>n.size?!1:r.every(e=>n.has(e))&&Object.values(t).every(e=>typeof e==`string`)}function i(e,t){let n={...e};for(let[e,a]of Object.entries(t)){let t=n[e];!r(a)&&!r(t)&&typeof t==`object`&&t?n[e]=i(t,a):n[e]=typeof a==`object`&&a?{...a}:a}return n}var a=class extends Map{#e;constructor(e){super(),this.#e=e}set(e,t){return!this.has(e)&&this.size>=this.#e&&this.delete(this.keys().next().value),super.set(e,t)}};function o(){return{dateFormat:new Map,listFormat:new Map,numberFormat:new Map,pluralRules:new Map,relativeTimeFormat:new Map}}function s(e,t,n){let r=e.get(t);return r||(r=n(),e.set(t,r)),r}function c(e,t){return t?`${e}:${JSON.stringify(t,Object.keys(t).sort())}`:e}function l(e,t,n,r){let i=c(r,n);try{return s(e.numberFormat,i,()=>new Intl.NumberFormat(r,n)).format(t)}catch{return String(t)}}function u(e,t,n,r){let i=typeof t==`number`?new Date(t):t,a=c(r,n);try{return s(e.dateFormat,a,()=>new Intl.DateTimeFormat(r,n)).format(i)}catch{return i.toString()}}function d(e,t,n,r,i){let a=c(i,r);try{return s(e.relativeTimeFormat,a,()=>new Intl.RelativeTimeFormat(i,r)).format(t,n)}catch{return String(t)}}function f(e,t,n,r){if(t.length===0)return``;let i=t.map(String),a=r===`and`?`conjunction`:`disjunction`;try{return s(e.listFormat,`${n}:${a}`,()=>new Intl.ListFormat(n,{style:`long`,type:a})).format(i)}catch{return i.length===1?i[0]:i.length===2?`${i[0]} ${r} ${i[1]}`:`${i.slice(0,-1).join(`, `)} ${r} ${i.at(-1)}`}}function p(e,t,n){let r=Math.floor(Math.abs(n));try{return s(e.pluralRules,t,()=>new Intl.PluralRules(t)).select(r)}catch{return r===1?`one`:`other`}}function m(e,t,n,r){return t==null?``:Array.isArray(t)?n===`and`?f(e,t,r,`and`):n===`or`?f(e,t,r,`or`):n===void 0?t.map(String).join(`, `):t.map(String).join(n):typeof t==`number`?l(e,t,void 0,r):String(t)}function h(e,n,r,i){return e.includes(`{`)?e.replace(/\{([\p{ID_Continue}\-.[\]]+)(?:\|([^}]+))?\}/gu,(e,a,o)=>m(i,t(n,a),o,r)):e}var g=class{#e;#t;#n=new Map;#r=new Map;#i=new Map;#a=new Set;#o=new a(128);#s;#c;#l=null;#u=null;#d=!1;#f=0;#p=null;#m;#h=o();#g;constructor({fallback:n,loaders:i,locale:a=`en`,messages:o,onDiagnostic:s,onMissing:c}={}){if(this.#e=a,this.#t=Array.isArray(n)?n:n?[n]:[],this.#s=c,this.#c=s,o)for(let[e,t]of Object.entries(o))this.#n.set(e,structuredClone(t));if(i)for(let[e,t]of Object.entries(i))this.#r.set(e,t);this.#m={checkOwn:(e,n)=>{let i=this.#n.get(n);if(!i)return!1;let a=t(i,e);return a!==void 0&&r(a)},findMessage:(e,t)=>this.#b(e,t),formatDate:(e,t,n)=>u(this.#h,e,t,n),formatList:(e,t,n)=>f(this.#h,e,t,n),formatNumber:(e,t,n)=>l(this.#h,e,t,n),formatRelative:(e,t,n,r)=>d(this.#h,e,t,n,r),getLocale:()=>this.#e,translate:(e,t,n)=>this.#S(e,t,n)},this.#g=new e(this.#m,null)}get locale(){return this.#e}get locales(){return this.#l??=[...this.#n.keys()],this.#l}set locale(e){this.#e!==e&&(this.#e=e,this.#y(`locale-change`))}async setLocale(e){e!==this.#e&&(await this.load(e),this.locale=e)}add(e,t){let n=this.#n.get(e)??{};this.#n.set(e,i(n,t)),this.#l=null,this.#x(this.#e).includes(e)&&this.#y(`catalog-update`)}replace(e,t){this.#n.set(e,structuredClone(t)),this.#l=null,this.#x(this.#e).includes(e)&&this.#y(`catalog-update`)}has(e){return this.#g.has(e)}hasOwn(e){return this.#g.hasOwn(e)}hasLocale(e){return this.#n.has(e)}async load(...e){await Promise.all(e.map(e=>this.#C(e)))}async reload(e){this.#r.has(e)&&(this.#n.delete(e),this.#l=null,await this.#C(e))}registerLoader(e,t){this.#r.set(e,t),this.#u=null}get loadableLocales(){return this.#u??=[...this.#r.keys()],this.#u}t(e,t){return this.#g.t(e,t)}number(e,t){return this.#g.number(e,t)}date(e,t){return this.#g.date(e,t)}list(e,t=`and`){return this.#g.list(e,t)}relative(e,t,n){return this.#g.relative(e,t,n)}currency(e,t,n){return this.#g.currency(e,t,n)}withLocale(e){return this.#g.withLocale(e)}scope(e){return this.#g.scope(e)}batch(e){this.#f++;try{e()}finally{if(this.#f--,this.#f===0&&this.#p!==null){let e=this.#p;this.#p=null,this.#y(e)}}}subscribe(e,t){if(this.#a.add(e),t)try{e({locale:this.#e,reason:`locale-change`})}catch(e){this.#_(e)}return()=>this.#a.delete(e)}dispose(){this.#d=!0,this.#a.clear(),this.#n.clear(),this.#r.clear(),this.#i.clear(),this.#o.clear(),this.#l=null,this.#u=null}[Symbol.dispose](){this.dispose()}async[Symbol.asyncDispose](){await Promise.allSettled([...this.#i.values()]),this.dispose()}#_(e){this.#c?this.#c({error:e,kind:`subscriber-error`}):console.error(`[i18nit] Subscriber threw:`,e)}#v(e,t){this.#c?this.#c({error:e,kind:`loader-error`,locale:t}):console.warn(`[i18nit] Loader error:`,e)}#y(e){if(this.#f>0){this.#p!==`locale-change`&&(this.#p=e);return}let t={locale:this.#e,reason:e};for(let e of this.#a)try{e(t)}catch(e){this.#_(e)}}#b(e,n){for(let i of this.#x(n)){let n=this.#n.get(i);if(!n)continue;let a=t(n,e);if(a!==void 0&&r(a))return a}}#x(e){let t=this.#o.get(e);if(t)return t;let n=new Set,r=e=>{n.add(e);let t=e.split(`-`);for(let e=t.length-1;e>0;e--)n.add(t.slice(0,e).join(`-`))};r(e);for(let e of this.#t)r(e);let i=[...n];return this.#o.set(e,i),i}#S(e,t,n){let r=this.#b(e,n);if(r===void 0)return this.#s?.(e,n)??e;if(typeof r==`string`)return h(r,t??{},n,this.#h);let i=t??{},a=Number(i.count??0);return h(r[a===0&&r.zero!==void 0?`zero`:p(this.#h,n,a)]??r.other,i,n,this.#h)}#C(e){if(this.#i.has(e))return this.#i.get(e);if(this.#n.has(e))return Promise.resolve();let t=this.#r.get(e);if(!t)return Promise.resolve();let n=(async()=>{try{let n=await t(e);this.#d||this.replace(e,n)}catch(t){throw this.#v(t,e),t}finally{this.#i.delete(e)}})();return this.#i.set(e,n),n}};function _(e){return new g(e)}export{g as I18n,_ as createI18n};
2
- //# sourceMappingURL=i18nit.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"i18nit.js","names":["#core","#fixedLocale","#prefix","#key","#cap","#caches","#view","#locale","#fallbacks","#onMissing","#onDiagnostic","#catalogs","#loaders","#core","#findMessage","#translate","#localesCache","#notify","#getLocaleChain","#loadOne","#loadersCache","#batchDepth","#pendingNotify","#subscribers","#diagnoseSubscriber","#disposed","#loading","#chainCache","#diagnoseLoader"],"sources":["../src/core.ts","../src/helpers.ts","../src/intl.ts","../src/interpolate.ts","../src/i18n.ts"],"sourcesContent":["import type { BoundI18n, Locale, MessageValue, Messages, NamespaceKeys, TranslationKeyParam, Vars } from './types';\n\n/* -------------------- I18nCore -------------------- */\n\n/**\n * Module-private interface given to every `BoundView` — exposes only the operations views need.\n * Created once per `I18n` instance so `scope()` / `withLocale()` allocate no closures per call.\n */\nexport type I18nCore = {\n checkOwn(key: string, locale: Locale): boolean;\n findMessage(key: string, locale: Locale): MessageValue | undefined;\n formatDate(value: Date | number, options: Intl.DateTimeFormatOptions | undefined, locale: Locale): string;\n formatList(items: unknown[], locale: string, type: 'and' | 'or'): string;\n formatNumber(value: number, options: Intl.NumberFormatOptions | undefined, locale: Locale): string;\n formatRelative(\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options: Intl.RelativeTimeFormatOptions | undefined,\n locale: Locale,\n ): string;\n getLocale(): Locale;\n translate(key: string, vars: Vars | undefined, locale: Locale): string;\n};\n\n/* -------------------- BoundView -------------------- */\n\n/**\n * Lightweight view over an `I18n` instance, fixed to a locale and/or key namespace prefix.\n * All methods live on the prototype — no closures are allocated per `scope()` / `withLocale()` call.\n */\nexport class BoundView<T extends Messages = Messages> implements BoundI18n<T> {\n readonly #core: I18nCore;\n readonly #fixedLocale: Locale | null;\n readonly #prefix: string | undefined;\n\n constructor(core: I18nCore, fixedLocale: Locale | null, prefix?: string) {\n this.#core = core;\n this.#fixedLocale = fixedLocale;\n this.#prefix = prefix;\n }\n\n get locale(): Locale {\n return this.#fixedLocale ?? this.#core.getLocale();\n }\n\n #key(key: string): string {\n return this.#prefix ? `${this.#prefix}.${key}` : key;\n }\n\n t(key: TranslationKeyParam<T>, vars?: Vars): string {\n return this.#core.translate(this.#key(key as string), vars, this.locale);\n }\n\n has(key: string): boolean {\n return this.#core.findMessage(this.#key(key), this.locale) !== undefined;\n }\n\n hasOwn(key: string): boolean {\n return this.#core.checkOwn(this.#key(key), this.locale);\n }\n\n number(value: number, options?: Intl.NumberFormatOptions): string {\n return this.#core.formatNumber(value, options, this.locale);\n }\n\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string {\n return this.#core.formatDate(value, options, this.locale);\n }\n\n list(items: unknown[], type: 'and' | 'or' = 'and'): string {\n return this.#core.formatList(items, this.locale, type);\n }\n\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string {\n return this.#core.formatRelative(value, unit, options, this.locale);\n }\n\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string {\n return this.#core.formatNumber(value, { ...options, currency, style: 'currency' }, this.locale);\n }\n\n scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages> {\n return new BoundView(\n this.#core,\n this.#fixedLocale,\n this.#prefix ? `${this.#prefix}.${String(ns)}` : String(ns),\n ) as BoundI18n<T[K] & Messages>;\n }\n\n withLocale(locale: Locale): BoundI18n<T> {\n return new BoundView<T>(this.#core, locale, this.#prefix);\n }\n}\n","import type { MessageValue, Messages } from './types';\n\n/* -------------------- Path Resolution -------------------- */\n\n/**\n * Resolves nested properties using dot notation and bracket notation.\n * Supports: 'user.name', 'items[0]', 'user.items[0].name'\n */\nexport function resolvePath(obj: Record<string, unknown>, path: string): unknown {\n // Try direct access first (handles keys with literal dots)\n if (path in obj) return obj[path];\n\n const parts = path.match(/[^.[\\]]+/gu) ?? [];\n let value: unknown = obj;\n\n for (const part of parts) {\n if (value == null || typeof value !== 'object') return undefined;\n\n value = (value as Record<string, unknown>)[part];\n }\n\n return value;\n}\n\n/* -------------------- Message Value Guard -------------------- */\n\nexport const PLURAL_FORMS = new Set<string>(['zero', 'one', 'two', 'few', 'many', 'other']);\n\nexport function isMessageValue(value: unknown): value is MessageValue {\n if (typeof value === 'string') return true;\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n\n const obj = value as Record<string, unknown>;\n\n if (!('other' in obj)) return false;\n\n const keys = Object.keys(obj);\n\n if (keys.length > PLURAL_FORMS.size) return false;\n\n return keys.every((k) => PLURAL_FORMS.has(k)) && Object.values(obj).every((v) => typeof v === 'string');\n}\n\n/* -------------------- Deep Merge -------------------- */\n\nexport function deepMerge(target: Messages, source: Messages): Messages {\n const result = { ...target };\n\n for (const [key, val] of Object.entries(source)) {\n const existing = result[key];\n\n if (!isMessageValue(val) && !isMessageValue(existing) && typeof existing === 'object' && existing !== null) {\n result[key] = deepMerge(existing as Messages, val as Messages);\n } else {\n // Clone PluralMessages objects to prevent external mutations from corrupting the catalog.\n result[key] = typeof val === 'object' && val !== null ? ({ ...(val as object) } as MessageValue) : val;\n }\n }\n\n return result;\n}\n\n/* -------------------- BoundedMap -------------------- */\n\n/**\n * Size-bounded Map that evicts the oldest entry (insertion order) when the cap is reached.\n * Used by I18n's chain cache to prevent unbounded growth in long-lived SSR singletons when\n * locale tags are derived from arbitrary user input (e.g. Accept-Language headers).\n */\nexport class BoundedMap<K, V> extends Map<K, V> {\n readonly #cap: number;\n\n constructor(cap: number) {\n super();\n this.#cap = cap;\n }\n\n override set(key: K, value: V): this {\n if (!this.has(key) && this.size >= this.#cap) {\n this.delete(this.keys().next().value as K);\n }\n\n return super.set(key, value);\n }\n}\n","import type { Locale, PluralForm } from './types';\n\n/* -------------------- Cache Container -------------------- */\n\n/** Holds all Intl formatter caches for one I18n instance — GC'd with the instance. */\nexport type IntlCaches = {\n dateFormat: Map<string, Intl.DateTimeFormat>;\n listFormat: Map<string, Intl.ListFormat>;\n numberFormat: Map<string, Intl.NumberFormat>;\n pluralRules: Map<string, Intl.PluralRules>;\n relativeTimeFormat: Map<string, Intl.RelativeTimeFormat>;\n};\n\nexport function makeIntlCaches(): IntlCaches {\n return {\n dateFormat: new Map(),\n listFormat: new Map(),\n numberFormat: new Map(),\n pluralRules: new Map(),\n relativeTimeFormat: new Map(),\n };\n}\n\n/* -------------------- Cache Helpers -------------------- */\n\nfunction intlFmt<F extends object>(cache: Map<string, F>, key: string, build: () => F): F {\n let fmt = cache.get(key);\n\n if (!fmt) {\n fmt = build();\n cache.set(key, fmt);\n }\n\n return fmt;\n}\n\n/**\n * Builds a stable string key for an Intl formatter cache.\n * Call this once per formatter construction path — not on every format call — so key\n * serialization cost is paid only on cache misses.\n */\nfunction intlKey(locale: string, options?: object): string {\n return options ? `${locale}:${JSON.stringify(options, Object.keys(options).sort())}` : locale;\n}\n\n/* -------------------- Format Functions -------------------- */\n\nexport function formatNumber(\n caches: IntlCaches,\n value: number,\n options: Intl.NumberFormatOptions | undefined,\n locale: Locale,\n): string {\n const key = intlKey(locale, options);\n\n try {\n return intlFmt(caches.numberFormat, key, () => new Intl.NumberFormat(locale, options)).format(value);\n } catch {\n return String(value);\n }\n}\n\nexport function formatDate(\n caches: IntlCaches,\n value: Date | number,\n options: Intl.DateTimeFormatOptions | undefined,\n locale: Locale,\n): string {\n const d = typeof value === 'number' ? new Date(value) : value;\n const key = intlKey(locale, options);\n\n try {\n return intlFmt(caches.dateFormat, key, () => new Intl.DateTimeFormat(locale, options)).format(d);\n } catch {\n return d.toString();\n }\n}\n\nexport function formatRelative(\n caches: IntlCaches,\n value: number,\n unit: Intl.RelativeTimeFormatUnit,\n options: Intl.RelativeTimeFormatOptions | undefined,\n locale: Locale,\n): string {\n const key = intlKey(locale, options);\n\n try {\n return intlFmt(caches.relativeTimeFormat, key, () => new Intl.RelativeTimeFormat(locale, options)).format(\n value,\n unit,\n );\n } catch {\n return String(value);\n }\n}\n\nexport function formatList(caches: IntlCaches, items: unknown[], locale: string, type: 'and' | 'or'): string {\n if (items.length === 0) return '';\n\n const stringItems = items.map(String);\n const intlType = type === 'and' ? 'conjunction' : 'disjunction';\n\n try {\n return intlFmt(\n caches.listFormat,\n `${locale}:${intlType}`,\n () => new Intl.ListFormat(locale, { style: 'long', type: intlType }),\n ).format(stringItems);\n } catch {\n // Fallback for environments without Intl.ListFormat\n if (stringItems.length === 1) return stringItems[0];\n\n if (stringItems.length === 2) return `${stringItems[0]} ${type} ${stringItems[1]}`;\n\n return `${stringItems.slice(0, -1).join(', ')} ${type} ${stringItems.at(-1)}`;\n }\n}\n\nexport function getPluralForm(caches: IntlCaches, locale: Locale, count: number): PluralForm {\n const n = Math.floor(Math.abs(count));\n\n try {\n return intlFmt(caches.pluralRules, locale, () => new Intl.PluralRules(locale)).select(n) as PluralForm;\n } catch {\n return n === 1 ? 'one' : 'other';\n }\n}\n","import type { Vars } from './types';\n\nimport { resolvePath } from './helpers';\nimport { type IntlCaches, formatList, formatNumber } from './intl';\n\n/* -------------------- Token Resolution -------------------- */\n\nfunction resolveToken(caches: IntlCaches, value: unknown, separator: string | undefined, locale: string): string {\n if (value == null) return '';\n\n if (Array.isArray(value)) {\n if (separator === 'and') return formatList(caches, value, locale, 'and');\n\n if (separator === 'or') return formatList(caches, value, locale, 'or');\n\n if (separator !== undefined) return value.map(String).join(separator);\n\n return value.map(String).join(', ');\n }\n\n if (typeof value === 'number') {\n return formatNumber(caches, value, undefined, locale);\n }\n\n return String(value);\n}\n\n/* -------------------- Interpolation -------------------- */\n\n/**\n * Interpolates variables into a template string. Supports Unicode variable names\n * via `\\p{ID_Continue}` so non-ASCII identifiers like `{prénom}` or `{名前}` work correctly.\n *\n * Supported formats: `{name}` · `{user.name}` · `{items[0]}` · `{items}` ·\n * `{items|and}` · `{items|or}` · `{items| - }` · `{items.length}`\n */\nexport function interpolate(template: string, vars: Vars, locale: string, caches: IntlCaches): string {\n if (!template.includes('{')) return template;\n\n return template.replace(/\\{([\\p{ID_Continue}\\-.[\\]]+)(?:\\|([^}]+))?\\}/gu, (_match, key: string, separator?: string) =>\n resolveToken(caches, resolvePath(vars, key), separator, locale),\n );\n}\n","import type {\n BoundI18n,\n DiagnosticEvent,\n I18nOptions,\n Loader,\n Locale,\n LocaleChangeEvent,\n LocaleChangeReason,\n MessageValue,\n Messages,\n NamespaceKeys,\n TranslationKeyParam,\n Unsubscribe,\n Vars,\n} from './types';\n\nimport { BoundView, type I18nCore } from './core';\nimport { BoundedMap, deepMerge, isMessageValue, resolvePath } from './helpers';\nimport { interpolate } from './interpolate';\nimport {\n type IntlCaches,\n formatDate,\n formatList,\n formatNumber,\n formatRelative,\n getPluralForm,\n makeIntlCaches,\n} from './intl';\n\nexport class I18n<T extends Messages = Messages> implements BoundI18n<T> {\n #locale: Locale;\n #fallbacks: Locale[];\n #catalogs = new Map<Locale, Messages>();\n #loaders = new Map<Locale, Loader>();\n #loading = new Map<Locale, Promise<void>>();\n #subscribers = new Set<(event: LocaleChangeEvent) => void>();\n /** Bounded at 128 entries — prevents unbounded growth when locale tags come from user input. */\n #chainCache = new BoundedMap<Locale, Locale[]>(128);\n #onMissing?: (key: string, locale: Locale) => string | undefined;\n #onDiagnostic?: (event: DiagnosticEvent) => void;\n #localesCache: Locale[] | null = null;\n #loadersCache: Locale[] | null = null;\n #disposed = false;\n #batchDepth = 0;\n #pendingNotify: LocaleChangeReason | null = null;\n #core: I18nCore;\n\n // Instance-scoped Intl caches — GC'd with the instance (important for SSR with many locales).\n readonly #caches: IntlCaches = makeIntlCaches();\n\n /** Internal BoundView — I18n delegates its BoundI18n surface here to avoid duplicating every method. */\n readonly #view: BoundView<T>;\n\n constructor({ fallback, loaders, locale = 'en', messages, onDiagnostic, onMissing }: I18nOptions<T> = {}) {\n this.#locale = locale;\n this.#fallbacks = Array.isArray(fallback) ? fallback : fallback ? [fallback] : [];\n this.#onMissing = onMissing;\n this.#onDiagnostic = onDiagnostic;\n\n if (messages) {\n for (const [l, m] of Object.entries(messages)) {\n // Deep-clone at init so external mutations to the source object can't corrupt the catalog.\n this.#catalogs.set(l, structuredClone(m) as Messages);\n }\n }\n\n if (loaders) for (const [l, fn] of Object.entries(loaders)) this.#loaders.set(l, fn);\n\n this.#core = {\n checkOwn: (key: string, locale: Locale) => {\n const catalog = this.#catalogs.get(locale);\n\n if (!catalog) return false;\n\n const value = resolvePath(catalog, key);\n\n return value !== undefined && isMessageValue(value);\n },\n findMessage: (key: string, locale: Locale) => this.#findMessage(key, locale),\n formatDate: (value, options, locale) => formatDate(this.#caches, value, options, locale),\n formatList: (items, locale, type) => formatList(this.#caches, items, locale, type),\n formatNumber: (value, options, locale) => formatNumber(this.#caches, value, options, locale),\n formatRelative: (value, unit, options, locale) => formatRelative(this.#caches, value, unit, options, locale),\n getLocale: () => this.#locale,\n translate: (key, vars, locale) => this.#translate(key, vars, locale),\n };\n\n this.#view = new BoundView<T>(this.#core, null);\n }\n\n /* -------------------- Locale -------------------- */\n\n get locale(): Locale {\n return this.#locale;\n }\n\n get locales(): Locale[] {\n this.#localesCache ??= [...this.#catalogs.keys()];\n\n return this.#localesCache;\n }\n\n set locale(value: Locale) {\n if (this.#locale === value) return;\n\n if (import.meta.env?.DEV && !this.#catalogs.has(value) && this.#loaders.has(value)) {\n console.warn(\n `[i18nit] locale \"${value}\" has a registered loader but is not loaded. ` +\n 'Use setLocale() to load and switch atomically.',\n );\n }\n\n this.#locale = value;\n this.#notify('locale-change');\n }\n\n async setLocale(locale: Locale): Promise<void> {\n if (locale === this.#locale) return;\n\n await this.load(locale);\n this.locale = locale;\n }\n\n /* -------------------- Message Management -------------------- */\n\n /** Deep-merges messages into an existing locale catalog. */\n add(locale: Locale, messages: Messages): void {\n const existing = this.#catalogs.get(locale) ?? {};\n\n this.#catalogs.set(locale, deepMerge(existing, messages));\n this.#localesCache = null;\n\n if (this.#getLocaleChain(this.#locale).includes(locale)) this.#notify('catalog-update');\n }\n\n /** Replaces the entire locale catalog for `locale` with a deep clone of `messages`. */\n replace(locale: Locale, messages: Messages): void {\n this.#catalogs.set(locale, structuredClone(messages));\n this.#localesCache = null;\n\n if (this.#getLocaleChain(this.#locale).includes(locale)) this.#notify('catalog-update');\n }\n\n has(key: string): boolean {\n return this.#view.has(key);\n }\n\n /** Like `has()`, but only checks the exact locale without walking the fallback chain. */\n hasOwn(key: string): boolean {\n return this.#view.hasOwn(key);\n }\n\n hasLocale(locale: Locale): boolean {\n return this.#catalogs.has(locale);\n }\n\n /* -------------------- Async Loaders -------------------- */\n\n async load(...locales: Locale[]): Promise<void> {\n await Promise.all(locales.map((locale) => this.#loadOne(locale)));\n }\n\n /**\n * Force-reloads a locale catalog even if already populated. Useful for hot-reload and forced bundle refresh.\n * No-op (with a dev warning) when no loader is registered for the locale, to prevent silently clearing the catalog.\n */\n async reload(locale: Locale): Promise<void> {\n if (!this.#loaders.has(locale)) {\n if (import.meta.env?.DEV) {\n console.warn(`[i18nit] reload(\"${locale}\") skipped — no loader registered for this locale.`);\n }\n\n return;\n }\n\n this.#catalogs.delete(locale);\n this.#localesCache = null;\n await this.#loadOne(locale);\n }\n\n registerLoader(locale: Locale, loader: Loader): void {\n this.#loaders.set(locale, loader);\n this.#loadersCache = null;\n }\n\n /** Returns the locale keys for which a loader has been registered. */\n get loadableLocales(): Locale[] {\n this.#loadersCache ??= [...this.#loaders.keys()];\n\n return this.#loadersCache;\n }\n\n /* -------------------- BoundI18n surface (delegated to #view) -------------------- */\n\n /**\n * Translates a key with optional interpolation variables.\n * Locale must be loaded first via `load()` or provided via `messages` in config.\n * For a per-call locale override use `withLocale(locale).t(key, vars)`.\n */\n t(key: TranslationKeyParam<T>, vars?: Vars): string {\n return this.#view.t(key, vars);\n }\n\n number(value: number, options?: Intl.NumberFormatOptions): string {\n return this.#view.number(value, options);\n }\n\n date(value: Date | number, options?: Intl.DateTimeFormatOptions): string {\n return this.#view.date(value, options);\n }\n\n list(items: unknown[], type: 'and' | 'or' = 'and'): string {\n return this.#view.list(items, type);\n }\n\n relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string {\n return this.#view.relative(value, unit, options);\n }\n\n currency(value: number, currency: string, options?: Omit<Intl.NumberFormatOptions, 'style' | 'currency'>): string {\n return this.#view.currency(value, currency, options);\n }\n\n /**\n * Returns a bound interface that translates in the given locale without\n * changing the active locale on the instance. Useful for SSR and\n * multi-locale rendering in a single pass.\n */\n withLocale(locale: Locale): BoundI18n<T> {\n return this.#view.withLocale(locale);\n }\n\n /**\n * Returns a translator scoped to a key namespace prefix. Reacts to locale changes on the\n * instance. When `T` is a concrete message type, the returned `BoundI18n` is narrowed to\n * the subtree type so `t()` autocomplete works within the scope.\n * Only keys whose values are nested message objects are valid scope targets.\n */\n scope<K extends NamespaceKeys<T>>(ns: K): BoundI18n<T[K] & Messages> {\n return this.#view.scope(ns);\n }\n\n /* -------------------- Subscriptions -------------------- */\n\n /**\n * Executes `fn` while deferring subscriber notifications. A single notification fires\n * after `fn` completes, collapsing any number of `add()` / `replace()` calls made within.\n * Nested `batch()` calls are supported; notification fires when the outermost batch exits.\n * If both a locale change and a catalog update are triggered, `'locale-change'` takes priority.\n *\n * @remarks\n * `batch()` is synchronous. Async operations (e.g. `load()`) started inside `fn` complete\n * after the batch exits and will notify subscribers individually. To batch-load multiple\n * locales and notify once, await `load()` before entering the batch:\n * ```ts\n * await i18n.load('fr', 'de');\n * i18n.batch(() => { i18n.locale = 'fr'; });\n * ```\n */\n batch(fn: () => void): void {\n this.#batchDepth++;\n\n try {\n fn();\n } finally {\n this.#batchDepth--;\n\n if (this.#batchDepth === 0 && this.#pendingNotify !== null) {\n const reason = this.#pendingNotify;\n\n this.#pendingNotify = null;\n this.#notify(reason);\n }\n }\n }\n\n subscribe(listener: (event: LocaleChangeEvent) => void, immediate?: boolean): Unsubscribe {\n this.#subscribers.add(listener);\n\n if (immediate) {\n try {\n listener({ locale: this.#locale, reason: 'locale-change' });\n } catch (err) {\n this.#diagnoseSubscriber(err);\n }\n }\n\n return () => this.#subscribers.delete(listener);\n }\n\n /** Releases all resources held by this instance. */\n dispose(): void {\n this.#disposed = true;\n this.#subscribers.clear();\n this.#catalogs.clear();\n this.#loaders.clear();\n this.#loading.clear();\n this.#chainCache.clear();\n this.#localesCache = null;\n this.#loadersCache = null;\n }\n\n /** Enables `using i18n = createI18n(...)` for deterministic resource release. */\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n /**\n * Awaits any in-flight `load()` calls and then releases all resources.\n * Enables `await using i18n = createI18n(...)` in environments that support `Symbol.asyncDispose`.\n */\n async [Symbol.asyncDispose](): Promise<void> {\n await Promise.allSettled([...this.#loading.values()]);\n this.dispose();\n }\n\n /* -------------------- Private -------------------- */\n\n #diagnoseSubscriber(error: unknown): void {\n if (this.#onDiagnostic) {\n this.#onDiagnostic({ error, kind: 'subscriber-error' });\n } else {\n console.error('[i18nit] Subscriber threw:', error);\n }\n }\n\n #diagnoseLoader(error: unknown, locale: Locale): void {\n if (this.#onDiagnostic) {\n this.#onDiagnostic({ error, kind: 'loader-error', locale });\n } else {\n console.warn('[i18nit] Loader error:', error);\n }\n }\n\n #notify(reason: LocaleChangeReason): void {\n if (this.#batchDepth > 0) {\n // 'locale-change' takes priority over 'catalog-update' if both occur in one batch\n if (this.#pendingNotify !== 'locale-change') this.#pendingNotify = reason;\n\n return;\n }\n\n const event: LocaleChangeEvent = { locale: this.#locale, reason };\n\n for (const listener of this.#subscribers) {\n try {\n listener(event);\n } catch (err) {\n this.#diagnoseSubscriber(err);\n }\n }\n }\n\n #findMessage(key: string, locale: Locale): MessageValue | undefined {\n for (const loc of this.#getLocaleChain(locale)) {\n const messages = this.#catalogs.get(loc);\n\n if (!messages) continue;\n\n const value = resolvePath(messages, key);\n\n if (value !== undefined && isMessageValue(value)) return value;\n }\n\n return undefined;\n }\n\n #getLocaleChain(locale: Locale): Locale[] {\n const cached = this.#chainCache.get(locale);\n\n if (cached) return cached;\n\n const seen = new Set<Locale>();\n const push = (l: Locale) => {\n seen.add(l);\n\n const parts = l.split('-');\n\n for (let i = parts.length - 1; i > 0; i--) {\n seen.add(parts.slice(0, i).join('-'));\n }\n };\n\n push(locale);\n for (const fallback of this.#fallbacks) push(fallback);\n\n const chain = [...seen];\n\n this.#chainCache.set(locale, chain);\n\n return chain;\n }\n\n #translate(key: string, vars: Vars | undefined, locale: Locale): string {\n const message = this.#findMessage(key, locale);\n\n if (message === undefined) return this.#onMissing?.(key, locale) ?? key;\n\n if (typeof message === 'string') return interpolate(message, vars ?? {}, locale, this.#caches);\n\n const v = vars ?? {};\n\n if (import.meta.env?.DEV && v.count === undefined) {\n console.warn(`[i18nit] Key \"${key}\" is a plural message but vars.count is missing. Defaulting to 0.`);\n }\n\n const count = Number(v.count ?? 0);\n const form = count === 0 && message.zero !== undefined ? 'zero' : getPluralForm(this.#caches, locale, count);\n\n return interpolate(message[form] ?? message.other, v, locale, this.#caches);\n }\n\n #loadOne(locale: Locale): Promise<void> {\n if (this.#loading.has(locale)) return this.#loading.get(locale)!;\n\n if (this.#catalogs.has(locale)) return Promise.resolve();\n\n const loader = this.#loaders.get(locale);\n\n if (!loader) return Promise.resolve();\n\n const promise = (async () => {\n try {\n const messages = await loader(locale);\n\n // Use replace() so the loader result is the authoritative catalog for this locale,\n // not merged on top of any pre-seeded static messages.\n if (!this.#disposed) this.replace(locale, messages);\n } catch (error) {\n this.#diagnoseLoader(error, locale);\n throw error;\n } finally {\n this.#loading.delete(locale);\n }\n })();\n\n this.#loading.set(locale, promise);\n\n return promise;\n }\n}\n\nexport function createI18n<T extends Messages = Messages>(config?: I18nOptions<T>): I18n<T> {\n return new I18n<T>(config);\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- const e=require(`./helpers.cjs`),t=require(`./intl.cjs`);function n(e,n,r,i){return n==null?``:Array.isArray(n)?r===`and`?t.formatList(e,n,i,`and`):r===`or`?t.formatList(e,n,i,`or`):r===void 0?n.map(String).join(`, `):n.map(String).join(r):typeof n==`number`?t.formatNumber(e,n,void 0,i):String(n)}function r(t,r,i,a){return t.includes(`{`)?t.replace(/\{([\p{ID_Continue}\-.[\]]+)(?:\|([^}]+))?\}/gu,(t,o,s)=>n(a,e.resolvePath(r,o),s,i)):t}exports.interpolate=r;
2
- //# sourceMappingURL=interpolate.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interpolate.cjs","names":[],"sources":["../src/interpolate.ts"],"sourcesContent":["import type { Vars } from './types';\n\nimport { resolvePath } from './helpers';\nimport { type IntlCaches, formatList, formatNumber } from './intl';\n\n/* -------------------- Token Resolution -------------------- */\n\nfunction resolveToken(caches: IntlCaches, value: unknown, separator: string | undefined, locale: string): string {\n if (value == null) return '';\n\n if (Array.isArray(value)) {\n if (separator === 'and') return formatList(caches, value, locale, 'and');\n\n if (separator === 'or') return formatList(caches, value, locale, 'or');\n\n if (separator !== undefined) return value.map(String).join(separator);\n\n return value.map(String).join(', ');\n }\n\n if (typeof value === 'number') {\n return formatNumber(caches, value, undefined, locale);\n }\n\n return String(value);\n}\n\n/* -------------------- Interpolation -------------------- */\n\n/**\n * Interpolates variables into a template string. Supports Unicode variable names\n * via `\\p{ID_Continue}` so non-ASCII identifiers like `{prénom}` or `{名前}` work correctly.\n *\n * Supported formats: `{name}` · `{user.name}` · `{items[0]}` · `{items}` ·\n * `{items|and}` · `{items|or}` · `{items| - }` · `{items.length}`\n */\nexport function interpolate(template: string, vars: Vars, locale: string, caches: IntlCaches): string {\n if (!template.includes('{')) return template;\n\n return template.replace(/\\{([\\p{ID_Continue}\\-.[\\]]+)(?:\\|([^}]+))?\\}/gu, (_match, key: string, separator?: string) =>\n resolveToken(caches, resolvePath(vars, key), separator, locale),\n );\n}\n"],"mappings":"yDAOA,SAAS,EAAa,EAAoB,EAAgB,EAA+B,EAAwB,CAiB/G,OAhBI,GAAS,KAAa,GAEtB,MAAM,QAAQ,EAAM,CAClB,IAAc,MAAc,EAAA,WAAW,EAAQ,EAAO,EAAQ,MAAM,CAEpE,IAAc,KAAa,EAAA,WAAW,EAAQ,EAAO,EAAQ,KAAK,CAElE,IAAc,IAAA,GAEX,EAAM,IAAI,OAAO,CAAC,KAAK,KAAK,CAFC,EAAM,IAAI,OAAO,CAAC,KAAK,EAAU,CAKnE,OAAO,GAAU,SACZ,EAAA,aAAa,EAAQ,EAAO,IAAA,GAAW,EAAO,CAGhD,OAAO,EAAM,CAYtB,SAAgB,EAAY,EAAkB,EAAY,EAAgB,EAA4B,CAGpG,OAFK,EAAS,SAAS,IAAI,CAEpB,EAAS,QAAQ,kDAAmD,EAAQ,EAAa,IAC9F,EAAa,EAAQ,EAAA,YAAY,EAAM,EAAI,CAAE,EAAW,EAAO,CAChE,CAJmC"}
@@ -1,11 +0,0 @@
1
- import type { Vars } from './types';
2
- import { type IntlCaches } from './intl';
3
- /**
4
- * Interpolates variables into a template string. Supports Unicode variable names
5
- * via `\p{ID_Continue}` so non-ASCII identifiers like `{prénom}` or `{名前}` work correctly.
6
- *
7
- * Supported formats: `{name}` · `{user.name}` · `{items[0]}` · `{items}` ·
8
- * `{items|and}` · `{items|or}` · `{items| - }` · `{items.length}`
9
- */
10
- export declare function interpolate(template: string, vars: Vars, locale: string, caches: IntlCaches): string;
11
- //# sourceMappingURL=interpolate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interpolate.d.ts","sourceRoot":"","sources":["../src/interpolate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAGpC,OAAO,EAAE,KAAK,UAAU,EAA4B,MAAM,QAAQ,CAAC;AA0BnE;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAMpG"}
@@ -1,13 +0,0 @@
1
- import { resolvePath as e } from "./helpers.js";
2
- import { formatList as t, formatNumber as n } from "./intl.js";
3
- //#region src/interpolate.ts
4
- function r(e, r, i, a) {
5
- return r == null ? "" : Array.isArray(r) ? i === "and" ? t(e, r, a, "and") : i === "or" ? t(e, r, a, "or") : i === void 0 ? r.map(String).join(", ") : r.map(String).join(i) : typeof r == "number" ? n(e, r, void 0, a) : String(r);
6
- }
7
- function i(t, n, i, a) {
8
- return t.includes("{") ? t.replace(/\{([\p{ID_Continue}\-.[\]]+)(?:\|([^}]+))?\}/gu, (t, o, s) => r(a, e(n, o), s, i)) : t;
9
- }
10
- //#endregion
11
- export { i as interpolate };
12
-
13
- //# sourceMappingURL=interpolate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interpolate.js","names":[],"sources":["../src/interpolate.ts"],"sourcesContent":["import type { Vars } from './types';\n\nimport { resolvePath } from './helpers';\nimport { type IntlCaches, formatList, formatNumber } from './intl';\n\n/* -------------------- Token Resolution -------------------- */\n\nfunction resolveToken(caches: IntlCaches, value: unknown, separator: string | undefined, locale: string): string {\n if (value == null) return '';\n\n if (Array.isArray(value)) {\n if (separator === 'and') return formatList(caches, value, locale, 'and');\n\n if (separator === 'or') return formatList(caches, value, locale, 'or');\n\n if (separator !== undefined) return value.map(String).join(separator);\n\n return value.map(String).join(', ');\n }\n\n if (typeof value === 'number') {\n return formatNumber(caches, value, undefined, locale);\n }\n\n return String(value);\n}\n\n/* -------------------- Interpolation -------------------- */\n\n/**\n * Interpolates variables into a template string. Supports Unicode variable names\n * via `\\p{ID_Continue}` so non-ASCII identifiers like `{prénom}` or `{名前}` work correctly.\n *\n * Supported formats: `{name}` · `{user.name}` · `{items[0]}` · `{items}` ·\n * `{items|and}` · `{items|or}` · `{items| - }` · `{items.length}`\n */\nexport function interpolate(template: string, vars: Vars, locale: string, caches: IntlCaches): string {\n if (!template.includes('{')) return template;\n\n return template.replace(/\\{([\\p{ID_Continue}\\-.[\\]]+)(?:\\|([^}]+))?\\}/gu, (_match, key: string, separator?: string) =>\n resolveToken(caches, resolvePath(vars, key), separator, locale),\n );\n}\n"],"mappings":";;;AAOA,SAAS,EAAa,GAAoB,GAAgB,GAA+B,GAAwB;AAiB/G,QAhBI,KAAS,OAAa,KAEtB,MAAM,QAAQ,EAAM,GAClB,MAAc,QAAc,EAAW,GAAQ,GAAO,GAAQ,MAAM,GAEpE,MAAc,OAAa,EAAW,GAAQ,GAAO,GAAQ,KAAK,GAElE,MAAc,KAAA,IAEX,EAAM,IAAI,OAAO,CAAC,KAAK,KAAK,GAFC,EAAM,IAAI,OAAO,CAAC,KAAK,EAAU,GAKnE,OAAO,KAAU,WACZ,EAAa,GAAQ,GAAO,KAAA,GAAW,EAAO,GAGhD,OAAO,EAAM;;AAYtB,SAAgB,EAAY,GAAkB,GAAY,GAAgB,GAA4B;AAGpG,QAFK,EAAS,SAAS,IAAI,GAEpB,EAAS,QAAQ,mDAAmD,GAAQ,GAAa,MAC9F,EAAa,GAAQ,EAAY,GAAM,EAAI,EAAE,GAAW,EAAO,CAChE,GAJmC"}
package/dist/intl.cjs DELETED
@@ -1,2 +0,0 @@
1
- function e(){return{dateFormat:new Map,listFormat:new Map,numberFormat:new Map,pluralRules:new Map,relativeTimeFormat:new Map}}function t(e,t,n){let r=e.get(t);return r||(r=n(),e.set(t,r)),r}function n(e,t){return t?`${e}:${JSON.stringify(t,Object.keys(t).sort())}`:e}function r(e,r,i,a){let o=n(a,i);try{return t(e.numberFormat,o,()=>new Intl.NumberFormat(a,i)).format(r)}catch{return String(r)}}function i(e,r,i,a){let o=typeof r==`number`?new Date(r):r,s=n(a,i);try{return t(e.dateFormat,s,()=>new Intl.DateTimeFormat(a,i)).format(o)}catch{return o.toString()}}function a(e,r,i,a,o){let s=n(o,a);try{return t(e.relativeTimeFormat,s,()=>new Intl.RelativeTimeFormat(o,a)).format(r,i)}catch{return String(r)}}function o(e,n,r,i){if(n.length===0)return``;let a=n.map(String),o=i===`and`?`conjunction`:`disjunction`;try{return t(e.listFormat,`${r}:${o}`,()=>new Intl.ListFormat(r,{style:`long`,type:o})).format(a)}catch{return a.length===1?a[0]:a.length===2?`${a[0]} ${i} ${a[1]}`:`${a.slice(0,-1).join(`, `)} ${i} ${a.at(-1)}`}}function s(e,n,r){let i=Math.floor(Math.abs(r));try{return t(e.pluralRules,n,()=>new Intl.PluralRules(n)).select(i)}catch{return i===1?`one`:`other`}}exports.formatDate=i,exports.formatList=o,exports.formatNumber=r,exports.formatRelative=a,exports.getPluralForm=s,exports.makeIntlCaches=e;
2
- //# sourceMappingURL=intl.cjs.map