@xndrjs/i18n 0.3.3 → 0.5.0-alpha.0

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 (61) hide show
  1. package/README.md +193 -44
  2. package/dist/codegen/index.d.ts +85 -0
  3. package/dist/codegen/index.js +181 -0
  4. package/dist/codegen/index.js.map +1 -0
  5. package/dist/index.d.ts +34 -18
  6. package/dist/index.js +174 -145
  7. package/dist/index.js.map +1 -1
  8. package/dist/validation/index.d.ts +86 -4
  9. package/dist/validation/index.js.map +1 -1
  10. package/package.json +6 -1
  11. package/src/IcuTranslationProviderMulti.test.ts +48 -1
  12. package/src/IcuTranslationProviderMulti.ts +41 -61
  13. package/src/IcuTranslationProviderSingle.test.ts +67 -0
  14. package/src/IcuTranslationProviderSingle.ts +27 -51
  15. package/src/audit/audit-dictionaries.ts +4 -1
  16. package/src/audit/run-audit.test.ts +35 -1
  17. package/src/audit/run-audit.ts +15 -7
  18. package/src/codegen/codegen-config-schema.ts +68 -1
  19. package/src/codegen/config.test.ts +174 -39
  20. package/src/codegen/config.ts +14 -5
  21. package/src/codegen/constants.ts +8 -0
  22. package/src/codegen/delivery-artifacts.test.ts +142 -0
  23. package/src/codegen/delivery-artifacts.ts +124 -0
  24. package/src/codegen/emit/dictionary-file.test.ts +190 -0
  25. package/src/codegen/emit/dictionary-file.ts +165 -2
  26. package/src/codegen/emit/dictionary-schema-file.ts +5 -0
  27. package/src/codegen/emit/instance-file.ts +119 -38
  28. package/src/codegen/emit/namespace-loaders-file.test.ts +176 -0
  29. package/src/codegen/emit/namespace-loaders-file.ts +118 -32
  30. package/src/codegen/emit/types-file.test.ts +114 -0
  31. package/src/codegen/emit/types-file.ts +48 -11
  32. package/src/codegen/generate-i18n-types.test.ts +765 -22
  33. package/src/codegen/generate-i18n-types.ts +111 -58
  34. package/src/codegen/icu-analysis.ts +9 -2
  35. package/src/codegen/locale-fallback.ts +19 -10
  36. package/src/codegen/locale-policy.ts +4 -0
  37. package/src/codegen/paths.ts +9 -5
  38. package/src/codegen/project-locales-set-namespace.test.ts +11 -9
  39. package/src/codegen/read-dictionary.test.ts +474 -2
  40. package/src/codegen/read-dictionary.ts +164 -15
  41. package/src/codegen/write-file-if-changed.test.ts +42 -0
  42. package/src/codegen/write-file-if-changed.ts +20 -0
  43. package/src/codegen-config/build-config.ts +34 -0
  44. package/src/codegen-config/codegen-config.test.ts +32 -0
  45. package/src/codegen-config/index.ts +21 -0
  46. package/src/codegen-config/write-config.ts +8 -0
  47. package/src/deep-freeze.test.ts +13 -0
  48. package/src/deep-freeze.ts +5 -0
  49. package/src/format-core.ts +91 -0
  50. package/src/index.ts +8 -5
  51. package/src/project-locales.test.ts +129 -10
  52. package/src/project-locales.ts +90 -3
  53. package/src/setup/setup-i18n.test.ts +1 -1
  54. package/src/setup/setup-i18n.ts +9 -32
  55. package/src/types.ts +19 -4
  56. package/src/validation/normalize.ts +4 -0
  57. package/dist/types-C1CpXVOJ.d.ts +0 -83
  58. package/src/ensure-namespace.integration.test.ts +0 -66
  59. package/src/ensure-namespace.test.ts +0 -125
  60. package/src/ensure-namespace.ts +0 -70
  61. /package/src/{setup → codegen-config}/type-names.ts +0 -0
package/dist/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { IntlMessageFormat } from 'intl-messageformat';
2
2
 
3
- // src/IcuTranslationProviderSingle.ts
4
-
5
3
  // src/deep-freeze.ts
6
4
  function deepFreeze(value) {
7
5
  if (value === null || typeof value !== "object") {
8
6
  return value;
9
7
  }
8
+ if (Object.isFrozen(value)) {
9
+ return value;
10
+ }
10
11
  Object.freeze(value);
11
12
  for (const child of Object.values(value)) {
12
13
  deepFreeze(child);
@@ -80,6 +81,68 @@ function formatLocaleFallbackChain(requestedLocale, fallbackMap) {
80
81
  return chain.join(" \u2192 ");
81
82
  }
82
83
 
84
+ // src/format-core.ts
85
+ function formatErrorLabel(context) {
86
+ if (context.namespace !== void 0) {
87
+ return `namespace "${context.namespace}", key "${context.key}"`;
88
+ }
89
+ return `key "${context.key}"`;
90
+ }
91
+ function formatMissingError(context) {
92
+ const chain = formatLocaleFallbackChain(context.locale, context.localeFallback);
93
+ if (context.namespace !== void 0) {
94
+ return `[i18n] Missing key or locale: namespace "${context.namespace}", key "${context.key}" [${context.locale}] (fallback chain: ${chain})`;
95
+ }
96
+ return `[i18n] Missing key or locale: "${context.key}" [${context.locale}] (fallback chain: ${chain})`;
97
+ }
98
+ function resolveMissing(context) {
99
+ const chain = formatLocaleFallbackChain(context.locale, context.localeFallback);
100
+ if (context.onMissing === "key") {
101
+ if (context.namespace !== void 0) {
102
+ return `${context.namespace}.${context.key}`;
103
+ }
104
+ return context.key;
105
+ }
106
+ if (typeof context.onMissing === "function") {
107
+ return context.onMissing({
108
+ ...context.namespace !== void 0 ? { namespace: context.namespace } : {},
109
+ key: context.key,
110
+ locale: context.locale,
111
+ fallbackChain: chain
112
+ });
113
+ }
114
+ throw new Error(formatMissingError(context));
115
+ }
116
+ function resolveAndFormat(options) {
117
+ const { localeByKey, locale, params, getCache, context } = options;
118
+ const resolved = resolveLocaleTemplate(localeByKey, locale, context.localeFallback);
119
+ if (!resolved) {
120
+ return resolveMissing(context);
121
+ }
122
+ const { template, resolvedLocale } = resolved;
123
+ const cache = getCache(resolvedLocale);
124
+ const cacheKey = context.key;
125
+ const label = formatErrorLabel(context);
126
+ if (!cache[cacheKey]) {
127
+ try {
128
+ cache[cacheKey] = new IntlMessageFormat(template, resolvedLocale);
129
+ } catch (err) {
130
+ const message = err instanceof Error ? err.message : String(err);
131
+ throw new Error(
132
+ `[i18n ICU Syntax Error] Dictionary error for ${label} [${resolvedLocale}]: ${message}`
133
+ );
134
+ }
135
+ }
136
+ try {
137
+ return cache[cacheKey].format(params);
138
+ } catch (err) {
139
+ const message = err instanceof Error ? err.message : String(err);
140
+ throw new Error(
141
+ `[i18n Formatting Error] Invalid or missing parameters for ${label} [${resolvedLocale}]: ${message}`
142
+ );
143
+ }
144
+ }
145
+
83
146
  // src/IcuTranslationProviderSingle.ts
84
147
  var IcuTranslationProviderSingleForLocale = class {
85
148
  constructor(provider, locale) {
@@ -89,55 +152,45 @@ var IcuTranslationProviderSingleForLocale = class {
89
152
  provider;
90
153
  locale;
91
154
  get(key, ...args) {
92
- return this.provider.get(key, this.locale, ...args);
155
+ const params = args[0];
156
+ return this.provider.getWithLocale(String(key), this.locale, params);
93
157
  }
94
158
  };
95
159
  var IcuTranslationProviderSingle = class {
96
160
  dictionary;
97
161
  compiledCache = {};
98
162
  localeFallback;
163
+ onMissing;
99
164
  constructor(dictionary, options) {
100
165
  this.dictionary = structuredClone(dictionary);
101
166
  if (options?.localeFallback) {
102
167
  validateLocaleFallback(options.localeFallback);
103
168
  this.localeFallback = options.localeFallback;
104
169
  }
170
+ this.onMissing = options?.onMissing ?? "throw";
105
171
  }
106
172
  get(key, locale, ...args) {
107
173
  const params = args[0];
108
- const resolved = resolveLocaleTemplate(this.dictionary[key], locale, this.localeFallback);
109
- if (!resolved) {
110
- const chain = formatLocaleFallbackChain(locale, this.localeFallback);
111
- throw new Error(
112
- `[i18n] Missing key or locale: "${String(key)}" [${locale}] (fallback chain: ${chain})`
113
- );
114
- }
115
- const { template, resolvedLocale } = resolved;
116
- if (!this.compiledCache[resolvedLocale]) {
117
- this.compiledCache[resolvedLocale] = {};
118
- }
119
- const cacheKey = String(key);
120
- if (!this.compiledCache[resolvedLocale][cacheKey]) {
121
- try {
122
- this.compiledCache[resolvedLocale][cacheKey] = new IntlMessageFormat(
123
- template,
124
- resolvedLocale
125
- );
126
- } catch (err) {
127
- const message = err instanceof Error ? err.message : String(err);
128
- throw new Error(
129
- `[i18n ICU Syntax Error] Dictionary error for key "${String(key)}" [${resolvedLocale}]: ${message}`
130
- );
174
+ return this.getWithLocale(String(key), locale, params);
175
+ }
176
+ getWithLocale(key, locale, params) {
177
+ return resolveAndFormat({
178
+ localeByKey: this.dictionary[key],
179
+ locale,
180
+ params,
181
+ getCache: (resolvedLocale) => {
182
+ if (!this.compiledCache[resolvedLocale]) {
183
+ this.compiledCache[resolvedLocale] = {};
184
+ }
185
+ return this.compiledCache[resolvedLocale];
186
+ },
187
+ context: {
188
+ key,
189
+ locale,
190
+ localeFallback: this.localeFallback,
191
+ onMissing: this.onMissing
131
192
  }
132
- }
133
- try {
134
- return this.compiledCache[resolvedLocale][cacheKey].format(params);
135
- } catch (err) {
136
- const message = err instanceof Error ? err.message : String(err);
137
- throw new Error(
138
- `[i18n Formatting Error] Invalid or missing parameters for key "${String(key)}" [${resolvedLocale}]: ${message}`
139
- );
140
- }
193
+ });
141
194
  }
142
195
  forLocale(locale) {
143
196
  return new IcuTranslationProviderSingleForLocale(this, locale);
@@ -150,6 +203,8 @@ var IcuTranslationProviderSingle = class {
150
203
  this.compiledCache = {};
151
204
  }
152
205
  };
206
+
207
+ // src/IcuTranslationProviderMulti.ts
153
208
  var IcuTranslationProviderMultiForLocale = class {
154
209
  constructor(provider, locale) {
155
210
  this.provider = provider;
@@ -158,13 +213,15 @@ var IcuTranslationProviderMultiForLocale = class {
158
213
  provider;
159
214
  locale;
160
215
  get(namespace, key, ...args) {
161
- return this.provider.get(namespace, key, this.locale, ...args);
216
+ const params = args[0];
217
+ return this.provider.getWithLocale(String(namespace), String(key), this.locale, params);
162
218
  }
163
219
  };
164
220
  var IcuTranslationProviderMulti = class {
165
221
  dictionary;
166
222
  compiledCache = {};
167
223
  localeFallback;
224
+ onMissing;
168
225
  loadedNamespaces;
169
226
  constructor(dictionary, options) {
170
227
  this.dictionary = structuredClone(dictionary);
@@ -173,49 +230,40 @@ var IcuTranslationProviderMulti = class {
173
230
  validateLocaleFallback(options.localeFallback);
174
231
  this.localeFallback = options.localeFallback;
175
232
  }
233
+ this.onMissing = options?.onMissing ?? "throw";
176
234
  }
177
235
  get(namespace, key, locale, ...args) {
236
+ const params = args[0];
237
+ return this.getWithLocale(String(namespace), String(key), locale, params);
238
+ }
239
+ getWithLocale(namespace, key, locale, params) {
178
240
  if (!this.loadedNamespaces.has(namespace)) {
179
241
  throw new Error(
180
- `[i18n] Namespace not loaded: "${String(namespace)}". Call ensureNamespacesLoaded(i18n, ["${String(namespace)}"]) first.`
242
+ `[i18n] Namespace not loaded: "${namespace}". Register it with setNamespace() before calling .get().`
181
243
  );
182
244
  }
183
- const params = args[0];
184
245
  const localeByKey = this.dictionary[namespace]?.[key];
185
- const resolved = resolveLocaleTemplate(localeByKey, locale, this.localeFallback);
186
- if (!resolved) {
187
- const chain = formatLocaleFallbackChain(locale, this.localeFallback);
188
- throw new Error(
189
- `[i18n] Missing key or locale: namespace "${String(namespace)}", key "${String(key)}" [${locale}] (fallback chain: ${chain})`
190
- );
191
- }
192
- const { template, resolvedLocale } = resolved;
193
- if (!this.compiledCache[resolvedLocale]) {
194
- this.compiledCache[resolvedLocale] = {};
195
- }
196
- if (!this.compiledCache[resolvedLocale][namespace]) {
197
- this.compiledCache[resolvedLocale][namespace] = {};
198
- }
199
- const namespaceCache = this.compiledCache[resolvedLocale][namespace];
200
- const cacheKey = String(key);
201
- if (!namespaceCache[cacheKey]) {
202
- try {
203
- namespaceCache[cacheKey] = new IntlMessageFormat(template, resolvedLocale);
204
- } catch (err) {
205
- const message = err instanceof Error ? err.message : String(err);
206
- throw new Error(
207
- `[i18n ICU Syntax Error] namespace "${String(namespace)}", key "${String(key)}" [${resolvedLocale}]: ${message}`
208
- );
246
+ return resolveAndFormat({
247
+ localeByKey,
248
+ locale,
249
+ params,
250
+ getCache: (resolvedLocale) => {
251
+ if (!this.compiledCache[resolvedLocale]) {
252
+ this.compiledCache[resolvedLocale] = {};
253
+ }
254
+ if (!this.compiledCache[resolvedLocale][namespace]) {
255
+ this.compiledCache[resolvedLocale][namespace] = {};
256
+ }
257
+ return this.compiledCache[resolvedLocale][namespace];
258
+ },
259
+ context: {
260
+ namespace,
261
+ key,
262
+ locale,
263
+ localeFallback: this.localeFallback,
264
+ onMissing: this.onMissing
209
265
  }
210
- }
211
- try {
212
- return namespaceCache[cacheKey].format(params);
213
- } catch (err) {
214
- const message = err instanceof Error ? err.message : String(err);
215
- throw new Error(
216
- `[i18n Formatting Error] namespace "${String(namespace)}", key "${String(key)}" [${resolvedLocale}]: ${message}`
217
- );
218
- }
266
+ });
219
267
  }
220
268
  forLocale(locale) {
221
269
  return new IcuTranslationProviderMultiForLocale(this, locale);
@@ -244,6 +292,20 @@ var IcuTranslationProviderMulti = class {
244
292
  };
245
293
 
246
294
  // src/project-locales.ts
295
+ function classifyAreaLocales(areaLocales, localeFallback) {
296
+ const areaSet = new Set(areaLocales);
297
+ const full = [];
298
+ const preserve = [];
299
+ for (const locale of areaLocales) {
300
+ const fallback = localeFallback?.[locale];
301
+ if (fallback !== null && fallback !== void 0 && areaSet.has(fallback)) {
302
+ preserve.push(locale);
303
+ } else {
304
+ full.push(locale);
305
+ }
306
+ }
307
+ return { full, preserve };
308
+ }
247
309
  function projectKeyDictionary(dictionary, locales, localeFallback) {
248
310
  const targetLocales = [...new Set(locales)];
249
311
  const result = {};
@@ -261,97 +323,64 @@ function projectKeyDictionary(dictionary, locales, localeFallback) {
261
323
  }
262
324
  return result;
263
325
  }
264
- function projectLocales(dictionary, locales, localeFallback) {
326
+ function projectNamespaceLocalesCore(dictionary, locales, localeFallback) {
265
327
  return projectKeyDictionary(dictionary, locales, localeFallback);
266
328
  }
267
- function projectNamespacesLocales(dictionary, locales, localeFallback) {
329
+ function projectNamespaceForDeliveryAreaCore(dictionary, areaLocales, localeFallback) {
330
+ const { full, preserve } = classifyAreaLocales(areaLocales, localeFallback);
331
+ const fullProjection = full.length > 0 ? projectKeyDictionary(dictionary, full, localeFallback) : void 0;
332
+ const result = {};
333
+ for (const [key, localesByKey] of Object.entries(dictionary)) {
334
+ const projected = {};
335
+ if (fullProjection !== void 0) {
336
+ const fullEntry = fullProjection[key];
337
+ if (fullEntry !== void 0) {
338
+ Object.assign(projected, fullEntry);
339
+ }
340
+ }
341
+ for (const locale of preserve) {
342
+ const template = localesByKey[locale];
343
+ if (template !== void 0) {
344
+ projected[locale] = template;
345
+ }
346
+ }
347
+ if (Object.keys(projected).length > 0) {
348
+ result[key] = projected;
349
+ }
350
+ }
351
+ return result;
352
+ }
353
+ function projectDictionaryForDeliveryAreaCore(dictionary, areaLocales, localeFallback) {
268
354
  const result = {};
269
355
  for (const namespace of Object.keys(dictionary)) {
270
356
  const namespaceDictionary = dictionary[namespace];
271
357
  if (namespaceDictionary === void 0) {
272
358
  continue;
273
359
  }
274
- result[namespace] = projectKeyDictionary(
360
+ result[namespace] = projectNamespaceForDeliveryAreaCore(
275
361
  namespaceDictionary,
276
- locales,
362
+ areaLocales,
277
363
  localeFallback
278
364
  );
279
365
  }
280
366
  return result;
281
367
  }
282
-
283
- // src/validation/errors.ts
284
- function issueMessage(issue) {
285
- switch (issue.kind) {
286
- case "missing_key":
287
- return `Missing required key at ${issue.path.join(".")}`;
288
- case "invalid_input":
289
- case "invalid_locale_value":
290
- case "icu_syntax_error":
291
- case "locale_args_mismatch":
292
- case "variable_mismatch":
293
- case "variable_type_mismatch":
294
- return issue.message;
295
- }
296
- }
297
- function formatIssues(issues) {
298
- return issues.map((issue) => {
299
- if ("path" in issue && issue.path.length > 0) {
300
- return `[${issue.path.join(".")}] ${issue.kind}: ${issueMessage(issue)}`;
301
- }
302
- return `${issue.kind}: ${issueMessage(issue)}`;
303
- }).join("\n");
304
- }
305
- var DictionaryValidationError = class extends Error {
306
- constructor(issues) {
307
- super(formatIssues(issues));
308
- this.issues = issues;
309
- this.name = "DictionaryValidationError";
310
- }
311
- issues;
312
- };
313
-
314
- // src/ensure-namespace.ts
315
- var inFlightByProvider = /* @__PURE__ */ new WeakMap();
316
- async function ensureOneNamespace(options, namespace) {
317
- if (options.provider.hasNamespace(namespace)) {
318
- return;
319
- }
320
- const providerKey = options.provider;
321
- let inFlight = inFlightByProvider.get(providerKey);
322
- if (!inFlight) {
323
- inFlight = /* @__PURE__ */ new Map();
324
- inFlightByProvider.set(providerKey, inFlight);
325
- }
326
- const existing = inFlight.get(namespace);
327
- if (existing) {
328
- return existing;
329
- }
330
- const promise = (async () => {
331
- try {
332
- if (options.provider.hasNamespace(namespace)) {
333
- return;
334
- }
335
- const raw = await options.resolveLoader(namespace)();
336
- const result = options.validate(namespace, raw);
337
- if (!result.ok) {
338
- throw new DictionaryValidationError(result.issues);
339
- }
340
- options.provider.setNamespace(namespace, result.data);
341
- } finally {
342
- inFlight.delete(namespace);
368
+ function projectDictionaryLocalesCore(dictionary, locales, localeFallback) {
369
+ const result = {};
370
+ for (const namespace of Object.keys(dictionary)) {
371
+ const namespaceDictionary = dictionary[namespace];
372
+ if (namespaceDictionary === void 0) {
373
+ continue;
343
374
  }
344
- })();
345
- inFlight.set(namespace, promise);
346
- return promise;
347
- }
348
- async function ensureNamespacesLoadedImpl(options, namespaces) {
349
- if (namespaces.length === 0) {
350
- return;
375
+ result[namespace] = projectKeyDictionary(
376
+ namespaceDictionary,
377
+ locales,
378
+ localeFallback
379
+ );
351
380
  }
352
- await Promise.all(namespaces.map((namespace) => ensureOneNamespace(options, namespace)));
381
+ return result;
353
382
  }
354
383
 
355
- export { IcuTranslationProviderMulti, IcuTranslationProviderSingle, ensureNamespacesLoadedImpl, formatLocaleFallbackChain, projectLocales, projectNamespacesLocales, resolveLocaleTemplate, validateLocaleFallback };
384
+ export { IcuTranslationProviderMulti, IcuTranslationProviderSingle, formatLocaleFallbackChain, projectDictionaryForDeliveryAreaCore, projectDictionaryLocalesCore, projectNamespaceForDeliveryAreaCore, projectNamespaceLocalesCore, resolveLocaleTemplate, validateLocaleFallback };
356
385
  //# sourceMappingURL=index.js.map
357
386
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/deep-freeze.ts","../src/resolve-locale.ts","../src/IcuTranslationProviderSingle.ts","../src/IcuTranslationProviderMulti.ts","../src/project-locales.ts","../src/validation/errors.ts","../src/ensure-namespace.ts"],"names":["IntlMessageFormat"],"mappings":"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","file":"index.js","sourcesContent":["export function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n\n Object.freeze(value);\n\n for (const child of Object.values(value)) {\n deepFreeze(child);\n }\n\n return value;\n}\n\nexport function cloneAndFreeze<T>(value: T): T {\n return deepFreeze(structuredClone(value));\n}\n","export type LocaleFallbackMap = Record<string, string | null>;\n\nexport interface ResolvedLocaleTemplate {\n template: string;\n resolvedLocale: string;\n fallbackChain: readonly string[];\n}\n\nexport function validateLocaleFallback(map: LocaleFallbackMap): void {\n for (const startLocale of Object.keys(map)) {\n const visited = new Set<string>();\n let current: string | undefined = startLocale;\n\n while (current !== undefined) {\n if (visited.has(current)) {\n throw new Error(`[i18n] Circular locale fallback detected involving \"${current}\"`);\n }\n visited.add(current);\n\n const next: string | null | undefined = map[current];\n if (next === undefined || next === null) {\n break;\n }\n current = next;\n }\n }\n}\n\nexport function resolveLocaleTemplate(\n localeByKey: Record<string, string | undefined> | undefined,\n requestedLocale: string,\n fallbackMap?: LocaleFallbackMap\n): ResolvedLocaleTemplate | undefined {\n const chain: string[] = [requestedLocale];\n let currentLocale = requestedLocale;\n\n while (true) {\n const template = localeByKey?.[currentLocale];\n if (template !== undefined) {\n return { template, resolvedLocale: currentLocale, fallbackChain: chain };\n }\n\n if (!fallbackMap) {\n return undefined;\n }\n\n const fallback = fallbackMap[currentLocale];\n if (fallback === undefined || fallback === null) {\n return undefined;\n }\n\n if (chain.includes(fallback)) {\n throw new Error(\n `[i18n] Circular locale fallback detected: ${[...chain, fallback].join(\" → \")}`\n );\n }\n\n chain.push(fallback);\n currentLocale = fallback;\n }\n}\n\nexport function formatLocaleFallbackChain(\n requestedLocale: string,\n fallbackMap?: LocaleFallbackMap\n): string {\n if (!fallbackMap) {\n return requestedLocale;\n }\n\n const chain: string[] = [requestedLocale];\n let current = requestedLocale;\n\n while (true) {\n const fallback = fallbackMap[current];\n if (fallback === undefined || fallback === null) {\n break;\n }\n if (chain.includes(fallback)) {\n chain.push(fallback);\n break;\n }\n chain.push(fallback);\n current = fallback;\n }\n\n return chain.join(\" → \");\n}\n","import { IntlMessageFormat } from \"intl-messageformat\";\nimport { cloneAndFreeze } from \"./deep-freeze.js\";\nimport {\n formatLocaleFallbackChain,\n resolveLocaleTemplate,\n validateLocaleFallback,\n} from \"./resolve-locale.js\";\nimport type {\n IcuTranslationProviderOptions,\n KeyDictionary,\n LocaleFallbackMap,\n LocaleOfSingle,\n SingleCompiledCache,\n} from \"./types.js\";\n\nexport interface TranslationProviderSingleForLocale<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n Locale extends string,\n> {\n readonly locale: Locale;\n get<K extends keyof Schema & string>(\n key: K,\n ...params: Params[K] extends never ? [] : [params: Params[K]]\n ): string;\n}\n\nexport interface TranslationProviderSingle<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n RequestLocales extends string = LocaleOfSingle<Schema>,\n> {\n get<K extends keyof Schema & string>(\n key: K,\n locale: RequestLocales,\n ...params: Params[K] extends never ? [] : [params: Params[K]]\n ): string;\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): TranslationProviderSingleForLocale<Schema, Params, Locale>;\n getAll(): Schema;\n setAll(values: Schema): void;\n}\n\nexport class IcuTranslationProviderSingleForLocale<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n RequestLocales extends string,\n Locale extends RequestLocales,\n Fallback extends LocaleFallbackMap | undefined,\n> implements TranslationProviderSingleForLocale<Schema, Params, Locale> {\n constructor(\n private readonly provider: IcuTranslationProviderSingle<\n Schema,\n Params,\n RequestLocales,\n Fallback\n >,\n readonly locale: Locale\n ) {}\n\n get<K extends keyof Schema & string>(\n key: K,\n ...args: Params[K] extends never ? [] : [params: Params[K]]\n ): string {\n return (\n this.provider.get as (\n key: K,\n locale: Locale,\n ...params: Params[K] extends never ? [] : [params: Params[K]]\n ) => string\n )(key, this.locale, ...args);\n }\n}\n\nexport class IcuTranslationProviderSingle<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n RequestLocales extends string = LocaleOfSingle<Schema>,\n Fallback extends LocaleFallbackMap | undefined = undefined,\n> implements TranslationProviderSingle<Schema, Params, RequestLocales> {\n private dictionary: Schema;\n private compiledCache: SingleCompiledCache = {};\n private readonly localeFallback?: Fallback;\n\n constructor(dictionary: Schema, options?: IcuTranslationProviderOptions<Fallback>) {\n this.dictionary = structuredClone(dictionary);\n if (options?.localeFallback) {\n validateLocaleFallback(options.localeFallback);\n this.localeFallback = options.localeFallback;\n }\n }\n\n get<K extends keyof Schema & string>(\n key: K,\n locale: RequestLocales,\n ...args: Params[K] extends never ? [] : [params: Params[K]]\n ): string {\n const params = args[0] as Record<string, unknown> | undefined;\n const resolved = resolveLocaleTemplate(this.dictionary[key], locale, this.localeFallback);\n\n if (!resolved) {\n const chain = formatLocaleFallbackChain(locale, this.localeFallback);\n throw new Error(\n `[i18n] Missing key or locale: \"${String(key)}\" [${locale}] (fallback chain: ${chain})`\n );\n }\n\n const { template, resolvedLocale } = resolved;\n\n if (!this.compiledCache[resolvedLocale]) {\n this.compiledCache[resolvedLocale] = {};\n }\n\n const cacheKey = String(key);\n\n if (!this.compiledCache[resolvedLocale][cacheKey]) {\n try {\n this.compiledCache[resolvedLocale][cacheKey] = new IntlMessageFormat(\n template,\n resolvedLocale\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `[i18n ICU Syntax Error] Dictionary error for key \"${String(key)}\" [${resolvedLocale}]: ${message}`\n );\n }\n }\n\n try {\n return this.compiledCache[resolvedLocale][cacheKey].format(params) as string;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `[i18n Formatting Error] Invalid or missing parameters for key \"${String(key)}\" [${resolvedLocale}]: ${message}`\n );\n }\n }\n\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): IcuTranslationProviderSingleForLocale<Schema, Params, RequestLocales, Locale, Fallback> {\n return new IcuTranslationProviderSingleForLocale(this, locale);\n }\n\n getAll(): Schema {\n return cloneAndFreeze(this.dictionary);\n }\n\n setAll(values: Schema): void {\n this.dictionary = structuredClone(values);\n this.compiledCache = {};\n }\n}\n","import { IntlMessageFormat } from \"intl-messageformat\";\nimport { cloneAndFreeze } from \"./deep-freeze.js\";\nimport {\n formatLocaleFallbackChain,\n resolveLocaleTemplate,\n validateLocaleFallback,\n} from \"./resolve-locale.js\";\nimport type {\n IcuTranslationProviderOptions,\n LocaleFallbackMap,\n LocaleOfMulti,\n MultiCompiledCache,\n MultiDictionary,\n} from \"./types.js\";\n\nexport interface TranslationProviderMultiForLocale<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n Locale extends string,\n> {\n readonly locale: Locale;\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n ...params: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string;\n}\n\nexport interface TranslationProviderMulti<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n RequestLocales extends string = LocaleOfMulti<Schema>,\n> {\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n locale: RequestLocales,\n ...params: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string;\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): TranslationProviderMultiForLocale<Schema, Params, Locale>;\n getAll(): Schema;\n hasNamespace<NS extends keyof Schema & string>(namespace: NS): boolean;\n setAll(values: Schema): void;\n setNamespace<NS extends keyof Schema>(namespace: NS, values: Schema[NS]): void;\n}\n\nexport class IcuTranslationProviderMultiForLocale<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n RequestLocales extends string,\n Locale extends RequestLocales,\n Fallback extends LocaleFallbackMap | undefined,\n> implements TranslationProviderMultiForLocale<Schema, Params, Locale> {\n constructor(\n private readonly provider: IcuTranslationProviderMulti<\n Schema,\n Params,\n RequestLocales,\n Fallback\n >,\n readonly locale: Locale\n ) {}\n\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n ...args: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string {\n return (\n this.provider.get as <\n NS extends keyof Schema,\n K extends keyof Schema[NS] & keyof Params[NS] & string,\n >(\n namespace: NS,\n key: K,\n locale: Locale,\n ...params: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ) => string\n )(namespace, key, this.locale, ...args);\n }\n}\n\nexport class IcuTranslationProviderMulti<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n RequestLocales extends string = LocaleOfMulti<Schema>,\n Fallback extends LocaleFallbackMap | undefined = undefined,\n> implements TranslationProviderMulti<Schema, Params, RequestLocales> {\n private dictionary: Schema;\n private compiledCache: MultiCompiledCache = {};\n private readonly localeFallback?: Fallback;\n private loadedNamespaces: Set<string>;\n\n constructor(dictionary: Partial<Schema>, options?: IcuTranslationProviderOptions<Fallback>) {\n this.dictionary = structuredClone(dictionary) as Schema;\n this.loadedNamespaces = new Set(Object.keys(dictionary));\n if (options?.localeFallback) {\n validateLocaleFallback(options.localeFallback);\n this.localeFallback = options.localeFallback;\n }\n }\n\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n locale: RequestLocales,\n ...args: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string {\n if (!this.loadedNamespaces.has(namespace as string)) {\n throw new Error(\n `[i18n] Namespace not loaded: \"${String(namespace)}\". Call ensureNamespacesLoaded(i18n, [\"${String(namespace)}\"]) first.`\n );\n }\n\n const params = args[0] as Record<string, unknown> | undefined;\n const localeByKey = (\n this.dictionary[namespace as string] as Record<string, Record<string, string>>\n )?.[key];\n const resolved = resolveLocaleTemplate(localeByKey, locale, this.localeFallback);\n\n if (!resolved) {\n const chain = formatLocaleFallbackChain(locale, this.localeFallback);\n throw new Error(\n `[i18n] Missing key or locale: namespace \"${String(namespace)}\", key \"${String(key)}\" [${locale}] (fallback chain: ${chain})`\n );\n }\n\n const { template, resolvedLocale } = resolved;\n\n if (!this.compiledCache[resolvedLocale]) {\n this.compiledCache[resolvedLocale] = {};\n }\n\n if (!this.compiledCache[resolvedLocale][namespace as string]) {\n this.compiledCache[resolvedLocale][namespace as string] = {};\n }\n\n const namespaceCache = this.compiledCache[resolvedLocale][namespace as string]!;\n const cacheKey = String(key);\n\n if (!namespaceCache[cacheKey]) {\n try {\n namespaceCache[cacheKey] = new IntlMessageFormat(template, resolvedLocale);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `[i18n ICU Syntax Error] namespace \"${String(namespace)}\", key \"${String(key)}\" [${resolvedLocale}]: ${message}`\n );\n }\n }\n\n try {\n return namespaceCache[cacheKey].format(params) as string;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `[i18n Formatting Error] namespace \"${String(namespace)}\", key \"${String(key)}\" [${resolvedLocale}]: ${message}`\n );\n }\n }\n\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): IcuTranslationProviderMultiForLocale<Schema, Params, RequestLocales, Locale, Fallback> {\n return new IcuTranslationProviderMultiForLocale(this, locale);\n }\n\n getAll(): Schema {\n return cloneAndFreeze(this.dictionary);\n }\n\n hasNamespace<NS extends keyof Schema & string>(namespace: NS): boolean {\n return this.loadedNamespaces.has(namespace);\n }\n\n setAll(values: Schema): void {\n this.dictionary = structuredClone(values);\n this.compiledCache = {};\n this.loadedNamespaces = new Set(Object.keys(values));\n }\n\n setNamespace<NS extends keyof Schema>(namespace: NS, values: Schema[NS]): void {\n this.dictionary = {\n ...this.dictionary,\n [namespace]: structuredClone(values),\n };\n this.loadedNamespaces.add(namespace as string);\n\n for (const locale of Object.keys(this.compiledCache)) {\n delete this.compiledCache[locale]?.[namespace as string];\n }\n }\n}\n","import { resolveLocaleTemplate } from \"./resolve-locale.js\";\nimport type { KeyDictionary, LocaleFallbackMap, MultiDictionary } from \"./types.js\";\n\nfunction projectKeyDictionary<T extends KeyDictionary>(\n dictionary: T,\n locales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n const targetLocales = [...new Set(locales)];\n const result = {} as T;\n\n for (const [key, localesByKey] of Object.entries(dictionary)) {\n const projected: Record<string, string> = {};\n\n for (const locale of targetLocales) {\n const resolved = resolveLocaleTemplate(localesByKey, locale, localeFallback);\n if (resolved !== undefined) {\n projected[locale] = resolved.template;\n }\n }\n\n if (Object.keys(projected).length > 0) {\n result[key as keyof T] = projected as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Builds a dictionary that contains only the requested locales.\n * For each key and target locale, copies the direct template when present;\n * otherwise resolves through `localeFallback` (same rules as `.get()` at runtime).\n */\nexport function projectLocales<T extends KeyDictionary>(\n dictionary: T,\n locales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n return projectKeyDictionary(dictionary, locales, localeFallback);\n}\n\n/**\n * Projects every namespace in a multi-namespace dictionary.\n */\nexport function projectNamespacesLocales<T extends MultiDictionary>(\n dictionary: T,\n locales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n const result = {} as T;\n\n for (const namespace of Object.keys(dictionary) as (keyof T & string)[]) {\n const namespaceDictionary = dictionary[namespace];\n if (namespaceDictionary === undefined) {\n continue;\n }\n\n result[namespace] = projectKeyDictionary(\n namespaceDictionary,\n locales,\n localeFallback\n ) as T[typeof namespace];\n }\n\n return result;\n}\n","import type { ValidationIssue, ValidationResult } from \"./types.js\";\n\nfunction issueMessage(issue: ValidationIssue): string {\n switch (issue.kind) {\n case \"missing_key\":\n return `Missing required key at ${issue.path.join(\".\")}`;\n case \"invalid_input\":\n case \"invalid_locale_value\":\n case \"icu_syntax_error\":\n case \"locale_args_mismatch\":\n case \"variable_mismatch\":\n case \"variable_type_mismatch\":\n return issue.message;\n }\n}\n\nexport function formatIssues(issues: readonly ValidationIssue[]): string {\n return issues\n .map((issue) => {\n if (\"path\" in issue && issue.path.length > 0) {\n return `[${issue.path.join(\".\")}] ${issue.kind}: ${issueMessage(issue)}`;\n }\n return `${issue.kind}: ${issueMessage(issue)}`;\n })\n .join(\"\\n\");\n}\n\nexport class DictionaryValidationError extends Error {\n constructor(public readonly issues: readonly ValidationIssue[]) {\n super(formatIssues(issues));\n this.name = \"DictionaryValidationError\";\n }\n}\n\nexport function assertValidDictionary<T>(\n result: ValidationResult<T>\n): asserts result is { ok: true; data: T } {\n if (!result.ok) {\n throw new DictionaryValidationError(result.issues);\n }\n}\n","import type { MultiDictionary } from \"./types.js\";\nimport type { ValidationResult } from \"./validation/types.js\";\nimport { DictionaryValidationError } from \"./validation/errors.js\";\n\nexport interface EnsureNamespacesLoadedOptions<\n Schema extends MultiDictionary,\n NS extends keyof Schema & string,\n> {\n provider: Pick<\n { hasNamespace(namespace: NS): boolean; setNamespace(namespace: NS, values: Schema[NS]): void },\n \"hasNamespace\" | \"setNamespace\"\n >;\n resolveLoader: (namespace: NS) => () => Promise<unknown>;\n validate: (namespace: NS, raw: unknown) => ValidationResult<Schema[NS]>;\n}\n\nconst inFlightByProvider = new WeakMap<object, Map<string, Promise<void>>>();\n\nasync function ensureOneNamespace<Schema extends MultiDictionary, NS extends keyof Schema & string>(\n options: EnsureNamespacesLoadedOptions<Schema, NS>,\n namespace: NS\n): Promise<void> {\n if (options.provider.hasNamespace(namespace)) {\n return;\n }\n\n const providerKey = options.provider as object;\n let inFlight = inFlightByProvider.get(providerKey);\n if (!inFlight) {\n inFlight = new Map();\n inFlightByProvider.set(providerKey, inFlight);\n }\n\n const existing = inFlight.get(namespace);\n if (existing) {\n return existing;\n }\n\n const promise = (async () => {\n try {\n if (options.provider.hasNamespace(namespace)) {\n return;\n }\n\n const raw = await options.resolveLoader(namespace)();\n const result = options.validate(namespace, raw);\n if (!result.ok) {\n throw new DictionaryValidationError(result.issues);\n }\n\n options.provider.setNamespace(namespace, result.data);\n } finally {\n inFlight!.delete(namespace);\n }\n })();\n\n inFlight.set(namespace, promise);\n return promise;\n}\n\nexport async function ensureNamespacesLoadedImpl<\n Schema extends MultiDictionary,\n NS extends keyof Schema & string,\n>(options: EnsureNamespacesLoadedOptions<Schema, NS>, namespaces: NS[]): Promise<void> {\n if (namespaces.length === 0) {\n return;\n }\n\n await Promise.all(namespaces.map((namespace) => ensureOneNamespace(options, namespace)));\n}\n"]}
1
+ {"version":3,"sources":["../src/deep-freeze.ts","../src/resolve-locale.ts","../src/format-core.ts","../src/IcuTranslationProviderSingle.ts","../src/IcuTranslationProviderMulti.ts","../src/project-locales.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n\n // Guards against infinite recursion on cyclic structures.\n if (Object.isFrozen(value)) {\n return value;\n }\n\n Object.freeze(value);\n\n for (const child of Object.values(value)) {\n deepFreeze(child);\n }\n\n return value;\n}\n\nexport function cloneAndFreeze<T>(value: T): T {\n return deepFreeze(structuredClone(value));\n}\n","export type LocaleFallbackMap = Record<string, string | null>;\n\nexport interface ResolvedLocaleTemplate {\n template: string;\n resolvedLocale: string;\n fallbackChain: readonly string[];\n}\n\nexport function validateLocaleFallback(map: LocaleFallbackMap): void {\n for (const startLocale of Object.keys(map)) {\n const visited = new Set<string>();\n let current: string | undefined = startLocale;\n\n while (current !== undefined) {\n if (visited.has(current)) {\n throw new Error(`[i18n] Circular locale fallback detected involving \"${current}\"`);\n }\n visited.add(current);\n\n const next: string | null | undefined = map[current];\n if (next === undefined || next === null) {\n break;\n }\n current = next;\n }\n }\n}\n\nexport function resolveLocaleTemplate(\n localeByKey: Record<string, string | undefined> | undefined,\n requestedLocale: string,\n fallbackMap?: LocaleFallbackMap\n): ResolvedLocaleTemplate | undefined {\n const chain: string[] = [requestedLocale];\n let currentLocale = requestedLocale;\n\n while (true) {\n const template = localeByKey?.[currentLocale];\n if (template !== undefined) {\n return { template, resolvedLocale: currentLocale, fallbackChain: chain };\n }\n\n if (!fallbackMap) {\n return undefined;\n }\n\n const fallback = fallbackMap[currentLocale];\n if (fallback === undefined || fallback === null) {\n return undefined;\n }\n\n if (chain.includes(fallback)) {\n throw new Error(\n `[i18n] Circular locale fallback detected: ${[...chain, fallback].join(\" → \")}`\n );\n }\n\n chain.push(fallback);\n currentLocale = fallback;\n }\n}\n\nexport function formatLocaleFallbackChain(\n requestedLocale: string,\n fallbackMap?: LocaleFallbackMap\n): string {\n if (!fallbackMap) {\n return requestedLocale;\n }\n\n const chain: string[] = [requestedLocale];\n let current = requestedLocale;\n\n while (true) {\n const fallback = fallbackMap[current];\n if (fallback === undefined || fallback === null) {\n break;\n }\n if (chain.includes(fallback)) {\n chain.push(fallback);\n break;\n }\n chain.push(fallback);\n current = fallback;\n }\n\n return chain.join(\" → \");\n}\n","import { IntlMessageFormat } from \"intl-messageformat\";\nimport { formatLocaleFallbackChain, resolveLocaleTemplate } from \"./resolve-locale.js\";\nimport type { LocaleCache, LocaleFallbackMap, OnMissingTranslation } from \"./types.js\";\n\nexport type FormatCoreContext = {\n key: string;\n namespace?: string | undefined;\n locale: string;\n localeFallback?: LocaleFallbackMap | undefined;\n onMissing: OnMissingTranslation;\n};\n\nexport type ResolveAndFormatOptions = {\n localeByKey: Record<string, string | undefined> | undefined;\n locale: string;\n params?: Record<string, unknown> | undefined;\n getCache: (resolvedLocale: string) => LocaleCache;\n context: FormatCoreContext;\n};\n\nfunction formatErrorLabel(context: Pick<FormatCoreContext, \"key\" | \"namespace\">): string {\n if (context.namespace !== undefined) {\n return `namespace \"${context.namespace}\", key \"${context.key}\"`;\n }\n return `key \"${context.key}\"`;\n}\n\nfunction formatMissingError(context: FormatCoreContext): string {\n const chain = formatLocaleFallbackChain(context.locale, context.localeFallback);\n if (context.namespace !== undefined) {\n return `[i18n] Missing key or locale: namespace \"${context.namespace}\", key \"${context.key}\" [${context.locale}] (fallback chain: ${chain})`;\n }\n return `[i18n] Missing key or locale: \"${context.key}\" [${context.locale}] (fallback chain: ${chain})`;\n}\n\nfunction resolveMissing(context: FormatCoreContext): string {\n const chain = formatLocaleFallbackChain(context.locale, context.localeFallback);\n if (context.onMissing === \"key\") {\n if (context.namespace !== undefined) {\n return `${context.namespace}.${context.key}`;\n }\n return context.key;\n }\n if (typeof context.onMissing === \"function\") {\n return context.onMissing({\n ...(context.namespace !== undefined ? { namespace: context.namespace } : {}),\n key: context.key,\n locale: context.locale,\n fallbackChain: chain,\n });\n }\n throw new Error(formatMissingError(context));\n}\n\n/**\n * Shared runtime path for both ICU providers: resolve locale (with fallback) →\n * compile template (cached) → format with params; handles missing keys via `onMissing`.\n */\nexport function resolveAndFormat(options: ResolveAndFormatOptions): string {\n const { localeByKey, locale, params, getCache, context } = options;\n const resolved = resolveLocaleTemplate(localeByKey, locale, context.localeFallback);\n\n if (!resolved) {\n return resolveMissing(context);\n }\n\n const { template, resolvedLocale } = resolved;\n const cache = getCache(resolvedLocale);\n const cacheKey = context.key;\n const label = formatErrorLabel(context);\n\n if (!cache[cacheKey]) {\n try {\n cache[cacheKey] = new IntlMessageFormat(template, resolvedLocale);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `[i18n ICU Syntax Error] Dictionary error for ${label} [${resolvedLocale}]: ${message}`\n );\n }\n }\n\n try {\n return cache[cacheKey].format(params) as string;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `[i18n Formatting Error] Invalid or missing parameters for ${label} [${resolvedLocale}]: ${message}`\n );\n }\n}\n","import { cloneAndFreeze } from \"./deep-freeze.js\";\nimport { resolveAndFormat } from \"./format-core.js\";\nimport { validateLocaleFallback } from \"./resolve-locale.js\";\nimport type {\n IcuTranslationProviderOptions,\n KeyDictionary,\n LocaleFallbackMap,\n LocaleOfSingle,\n OnMissingTranslation,\n SingleCompiledCache,\n} from \"./types.js\";\n\nexport interface TranslationProviderSingleForLocale<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n Locale extends string,\n> {\n readonly locale: Locale;\n get<K extends keyof Schema & string>(\n key: K,\n ...params: Params[K] extends never ? [] : [params: Params[K]]\n ): string;\n}\n\nexport interface TranslationProviderSingle<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n RequestLocales extends string = LocaleOfSingle<Schema>,\n> {\n get<K extends keyof Schema & string>(\n key: K,\n locale: RequestLocales,\n ...params: Params[K] extends never ? [] : [params: Params[K]]\n ): string;\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): TranslationProviderSingleForLocale<Schema, Params, Locale>;\n getAll(): Schema;\n setAll(values: Schema): void;\n}\n\nexport class IcuTranslationProviderSingleForLocale<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n RequestLocales extends string,\n Locale extends RequestLocales,\n Fallback extends LocaleFallbackMap | undefined,\n> implements TranslationProviderSingleForLocale<Schema, Params, Locale> {\n constructor(\n private readonly provider: IcuTranslationProviderSingle<\n Schema,\n Params,\n RequestLocales,\n Fallback\n >,\n readonly locale: Locale\n ) {}\n\n get<K extends keyof Schema & string>(\n key: K,\n ...args: Params[K] extends never ? [] : [params: Params[K]]\n ): string {\n const params = args[0] as Record<string, unknown> | undefined;\n return this.provider.getWithLocale(String(key), this.locale, params);\n }\n}\n\nexport class IcuTranslationProviderSingle<\n Schema extends KeyDictionary,\n Params extends { [K in keyof Schema]: unknown },\n RequestLocales extends string = LocaleOfSingle<Schema>,\n Fallback extends LocaleFallbackMap | undefined = undefined,\n> implements TranslationProviderSingle<Schema, Params, RequestLocales> {\n private dictionary: Schema;\n private compiledCache: SingleCompiledCache = {};\n private readonly localeFallback?: Fallback;\n private readonly onMissing: OnMissingTranslation;\n\n constructor(dictionary: Schema, options?: IcuTranslationProviderOptions<Fallback>) {\n this.dictionary = structuredClone(dictionary);\n if (options?.localeFallback) {\n validateLocaleFallback(options.localeFallback);\n this.localeFallback = options.localeFallback;\n }\n this.onMissing = options?.onMissing ?? \"throw\";\n }\n\n get<K extends keyof Schema & string>(\n key: K,\n locale: RequestLocales,\n ...args: Params[K] extends never ? [] : [params: Params[K]]\n ): string {\n const params = args[0] as Record<string, unknown> | undefined;\n return this.getWithLocale(String(key), locale, params);\n }\n\n getWithLocale(key: string, locale: string, params?: Record<string, unknown>): string {\n return resolveAndFormat({\n localeByKey: this.dictionary[key],\n locale,\n params,\n getCache: (resolvedLocale) => {\n if (!this.compiledCache[resolvedLocale]) {\n this.compiledCache[resolvedLocale] = {};\n }\n return this.compiledCache[resolvedLocale]!;\n },\n context: {\n key,\n locale,\n localeFallback: this.localeFallback,\n onMissing: this.onMissing,\n },\n });\n }\n\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): IcuTranslationProviderSingleForLocale<Schema, Params, RequestLocales, Locale, Fallback> {\n return new IcuTranslationProviderSingleForLocale(this, locale);\n }\n\n getAll(): Schema {\n return cloneAndFreeze(this.dictionary);\n }\n\n setAll(values: Schema): void {\n this.dictionary = structuredClone(values);\n this.compiledCache = {};\n }\n}\n","import { cloneAndFreeze } from \"./deep-freeze.js\";\nimport { resolveAndFormat } from \"./format-core.js\";\nimport { validateLocaleFallback } from \"./resolve-locale.js\";\nimport type {\n IcuTranslationProviderOptions,\n LocaleFallbackMap,\n LocaleOfMulti,\n MultiCompiledCache,\n MultiDictionary,\n OnMissingTranslation,\n} from \"./types.js\";\n\nexport interface TranslationProviderMultiForLocale<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n Locale extends string,\n> {\n readonly locale: Locale;\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n ...params: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string;\n}\n\nexport interface TranslationProviderMulti<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n RequestLocales extends string = LocaleOfMulti<Schema>,\n> {\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n locale: RequestLocales,\n ...params: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string;\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): TranslationProviderMultiForLocale<Schema, Params, Locale>;\n getAll(): Schema;\n hasNamespace<NS extends keyof Schema & string>(namespace: NS): boolean;\n setAll(values: Schema): void;\n setNamespace<NS extends keyof Schema>(namespace: NS, values: Schema[NS]): void;\n}\n\nexport class IcuTranslationProviderMultiForLocale<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n RequestLocales extends string,\n Locale extends RequestLocales,\n Fallback extends LocaleFallbackMap | undefined,\n> implements TranslationProviderMultiForLocale<Schema, Params, Locale> {\n constructor(\n private readonly provider: IcuTranslationProviderMulti<\n Schema,\n Params,\n RequestLocales,\n Fallback\n >,\n readonly locale: Locale\n ) {}\n\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n ...args: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string {\n const params = args[0] as Record<string, unknown> | undefined;\n return this.provider.getWithLocale(String(namespace), String(key), this.locale, params);\n }\n}\n\nexport class IcuTranslationProviderMulti<\n Schema extends MultiDictionary,\n Params extends { [NS in keyof Schema]: { [K in keyof Schema[NS]]: unknown } },\n RequestLocales extends string = LocaleOfMulti<Schema>,\n Fallback extends LocaleFallbackMap | undefined = undefined,\n> implements TranslationProviderMulti<Schema, Params, RequestLocales> {\n private dictionary: Schema;\n private compiledCache: MultiCompiledCache = {};\n private readonly localeFallback?: Fallback;\n private readonly onMissing: OnMissingTranslation;\n private loadedNamespaces: Set<string>;\n\n constructor(dictionary: Partial<Schema>, options?: IcuTranslationProviderOptions<Fallback>) {\n this.dictionary = structuredClone(dictionary) as Schema;\n this.loadedNamespaces = new Set(Object.keys(dictionary));\n if (options?.localeFallback) {\n validateLocaleFallback(options.localeFallback);\n this.localeFallback = options.localeFallback;\n }\n this.onMissing = options?.onMissing ?? \"throw\";\n }\n\n get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(\n namespace: NS,\n key: K,\n locale: RequestLocales,\n ...args: Params[NS][K] extends never ? [] : [params: Params[NS][K]]\n ): string {\n const params = args[0] as Record<string, unknown> | undefined;\n return this.getWithLocale(String(namespace), String(key), locale, params);\n }\n\n getWithLocale(\n namespace: string,\n key: string,\n locale: string,\n params?: Record<string, unknown>\n ): string {\n if (!this.loadedNamespaces.has(namespace)) {\n throw new Error(\n `[i18n] Namespace not loaded: \"${namespace}\". Register it with setNamespace() before calling .get().`\n );\n }\n\n const localeByKey = (\n this.dictionary[namespace] as Record<string, Record<string, string>> | undefined\n )?.[key];\n\n return resolveAndFormat({\n localeByKey,\n locale,\n params,\n getCache: (resolvedLocale) => {\n if (!this.compiledCache[resolvedLocale]) {\n this.compiledCache[resolvedLocale] = {};\n }\n if (!this.compiledCache[resolvedLocale]![namespace]) {\n this.compiledCache[resolvedLocale]![namespace] = {};\n }\n return this.compiledCache[resolvedLocale]![namespace]!;\n },\n context: {\n namespace,\n key,\n locale,\n localeFallback: this.localeFallback,\n onMissing: this.onMissing,\n },\n });\n }\n\n forLocale<Locale extends RequestLocales>(\n locale: Locale\n ): IcuTranslationProviderMultiForLocale<Schema, Params, RequestLocales, Locale, Fallback> {\n return new IcuTranslationProviderMultiForLocale(this, locale);\n }\n\n getAll(): Schema {\n return cloneAndFreeze(this.dictionary);\n }\n\n hasNamespace<NS extends keyof Schema & string>(namespace: NS): boolean {\n return this.loadedNamespaces.has(namespace);\n }\n\n setAll(values: Schema): void {\n this.dictionary = structuredClone(values);\n this.compiledCache = {};\n this.loadedNamespaces = new Set(Object.keys(values));\n }\n\n setNamespace<NS extends keyof Schema>(namespace: NS, values: Schema[NS]): void {\n this.dictionary = {\n ...this.dictionary,\n [namespace]: structuredClone(values),\n };\n this.loadedNamespaces.add(namespace as string);\n\n for (const locale of Object.keys(this.compiledCache)) {\n delete this.compiledCache[locale]?.[namespace as string];\n }\n }\n}\n","import { resolveLocaleTemplate } from \"./resolve-locale.js\";\nimport type { KeyDictionary, LocaleFallbackMap, MultiDictionary } from \"./types.js\";\n\nfunction classifyAreaLocales(\n areaLocales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): { full: string[]; preserve: string[] } {\n const areaSet = new Set(areaLocales);\n const full: string[] = [];\n const preserve: string[] = [];\n\n for (const locale of areaLocales) {\n const fallback = localeFallback?.[locale];\n if (fallback !== null && fallback !== undefined && areaSet.has(fallback)) {\n preserve.push(locale);\n } else {\n full.push(locale);\n }\n }\n\n return { full, preserve };\n}\n\nfunction projectKeyDictionary<T extends KeyDictionary>(\n dictionary: T,\n locales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n const targetLocales = [...new Set(locales)];\n const result = {} as T;\n\n for (const [key, localesByKey] of Object.entries(dictionary)) {\n const projected: Record<string, string> = {};\n\n for (const locale of targetLocales) {\n const resolved = resolveLocaleTemplate(localesByKey, locale, localeFallback);\n if (resolved !== undefined) {\n projected[locale] = resolved.template;\n }\n }\n\n if (Object.keys(projected).length > 0) {\n result[key as keyof T] = projected as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Builds a namespace dictionary that contains only the requested locales.\n * For each key and target locale, copies the direct template when present;\n * otherwise resolves through `localeFallback` (same rules as `.get()` at runtime).\n */\nexport function projectNamespaceLocalesCore<T extends KeyDictionary>(\n dictionary: T,\n locales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n return projectKeyDictionary(dictionary, locales, localeFallback);\n}\n\n/**\n * Projects a single namespace for a custom delivery area.\n * Full locales resolve through `localeFallback` (e.g. external chains like `it → en-US`);\n * preserve locales copy only their direct canonical entry when present.\n */\nexport function projectNamespaceForDeliveryAreaCore<T extends KeyDictionary>(\n dictionary: T,\n areaLocales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n const { full, preserve } = classifyAreaLocales(areaLocales, localeFallback);\n const fullProjection =\n full.length > 0 ? projectKeyDictionary(dictionary, full, localeFallback) : undefined;\n const result = {} as T;\n\n for (const [key, localesByKey] of Object.entries(dictionary)) {\n const projected: Record<string, string> = {};\n\n if (fullProjection !== undefined) {\n const fullEntry = fullProjection[key as keyof T];\n if (fullEntry !== undefined) {\n Object.assign(projected, fullEntry);\n }\n }\n\n for (const locale of preserve) {\n const template = localesByKey[locale];\n if (template !== undefined) {\n projected[locale] = template;\n }\n }\n\n if (Object.keys(projected).length > 0) {\n result[key as keyof T] = projected as T[keyof T];\n }\n }\n\n return result;\n}\n\n/**\n * Projects a multi-namespace dictionary for a custom delivery area.\n * Each namespace uses the same delivery-area rules as `projectNamespaceForDeliveryAreaCore`.\n */\nexport function projectDictionaryForDeliveryAreaCore<T extends MultiDictionary>(\n dictionary: T,\n areaLocales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n const result = {} as T;\n\n for (const namespace of Object.keys(dictionary) as (keyof T & string)[]) {\n const namespaceDictionary = dictionary[namespace];\n if (namespaceDictionary === undefined) {\n continue;\n }\n\n result[namespace] = projectNamespaceForDeliveryAreaCore(\n namespaceDictionary,\n areaLocales,\n localeFallback\n ) as T[typeof namespace];\n }\n\n return result;\n}\n\n/**\n * Projects every namespace in a multi-namespace dictionary.\n */\nexport function projectDictionaryLocalesCore<T extends MultiDictionary>(\n dictionary: T,\n locales: readonly string[],\n localeFallback?: LocaleFallbackMap\n): T {\n const result = {} as T;\n\n for (const namespace of Object.keys(dictionary) as (keyof T & string)[]) {\n const namespaceDictionary = dictionary[namespace];\n if (namespaceDictionary === undefined) {\n continue;\n }\n\n result[namespace] = projectKeyDictionary(\n namespaceDictionary,\n locales,\n localeFallback\n ) as T[typeof namespace];\n }\n\n return result;\n}\n"]}