@let-value/translate 1.1.6-beta.3 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -73,26 +73,31 @@ const pluralFunc = memo(function pluralFunc(locale) {
73
73
  }
74
74
  });
75
75
  function mergeTranslations(primary, ...others) {
76
+ function copyRecords(source) {
77
+ const copy = {};
78
+ for (const ctx in source) copy[ctx] = { ...source[ctx] };
79
+ return copy;
80
+ }
76
81
  function mergeRecords(target, source) {
77
82
  for (const ctx in source) {
78
- if (!target[ctx]) {
79
- target[ctx] = source[ctx];
83
+ const sourceContext = source[ctx];
84
+ const targetContext = target[ctx];
85
+ if (!targetContext) {
86
+ target[ctx] = { ...sourceContext };
80
87
  continue;
81
88
  }
82
- const targetContext = target[ctx];
83
- const sourceContext = source[ctx];
84
89
  for (const id in sourceContext) if (!targetContext[id]) targetContext[id] = sourceContext[id];
85
90
  }
86
91
  }
87
92
  const result = {
88
93
  charset: primary.charset,
89
94
  headers: { ...primary.headers },
90
- translations: { ...primary.translations },
91
- obsolete: primary.obsolete ? { ...primary.obsolete } : void 0
95
+ translations: copyRecords(primary.translations),
96
+ obsolete: primary.obsolete ? copyRecords(primary.obsolete) : void 0
92
97
  };
93
98
  for (const other of others) {
94
99
  if (other?.translations) mergeRecords(result.translations, other.translations);
95
- if (other?.obsolete) if (!result.obsolete) result.obsolete = other.obsolete;
100
+ if (other?.obsolete) if (!result.obsolete) result.obsolete = copyRecords(other.obsolete);
96
101
  else mergeRecords(result.obsolete, other.obsolete);
97
102
  }
98
103
  return result;
@@ -244,15 +249,44 @@ var Translator = class {
244
249
  translations = {};
245
250
  pending = {};
246
251
  translators = {};
252
+ /**
253
+ * Raw catalogs as resolved, kept around after {@link getLocale} consumes
254
+ * `translations` so they can still be serialized by {@link dehydrate}.
255
+ */
256
+ catalogs = {};
247
257
  constructor(translations, parent) {
248
258
  this.parent = parent;
249
259
  for (const [locale, value] of Object.entries(translations)) {
250
260
  if (!value) continue;
251
261
  if (typeof value === "function") this.loaders[locale] = value;
252
262
  else if ("then" in value) this.loaders[locale] = () => value;
253
- else this.translations[locale] = resolveTranslationModule(value);
263
+ else {
264
+ this.translations[locale] = resolveTranslationModule(value);
265
+ this.catalogs[locale] = this.translations[locale];
266
+ }
254
267
  }
255
268
  }
269
+ /**
270
+ * Seed an already-resolved catalog so {@link getLocale} and {@link fetchLocale}
271
+ * can answer synchronously, without invoking the locale's loader.
272
+ *
273
+ * Used to hydrate a translator from a server-rendered payload before the first
274
+ * client render, so the tree never suspends during hydration. Priming a locale
275
+ * that is already resolved is a no-op.
276
+ */
277
+ prime = (locale, module) => {
278
+ if (this.translators[locale] || this.translations[locale]) return;
279
+ const resolved = resolveTranslationModule(module);
280
+ this.translations[locale] = resolved;
281
+ this.catalogs[locale] = resolved;
282
+ delete this.loaders[locale];
283
+ delete this.pending[locale];
284
+ };
285
+ /**
286
+ * The raw catalog for a resolved locale, or `undefined` when it has not been
287
+ * loaded yet. The counterpart of {@link prime}.
288
+ */
289
+ dehydrate = (locale) => this.catalogs[locale];
256
290
  loadLocale = async (locale, loader) => {
257
291
  this.loaders[locale] = loader ?? this.loaders[locale];
258
292
  return this.fetchLocale(locale);
@@ -286,6 +320,7 @@ var Translator = class {
286
320
  if (loader) {
287
321
  const promise = loader().then((translations) => {
288
322
  this.translations[key] ??= resolveTranslationModule(translations);
323
+ this.catalogs[key] ??= this.translations[key];
289
324
  delete this.pending[key];
290
325
  return this.getLocale(key);
291
326
  });
package/dist/index.d.cts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { GetTextTranslations } from "gettext-parser";
2
-
3
2
  //#region src/locales.d.ts
4
3
  type PluralFormsLocale = "ach" | "af" | "ak" | "am" | "an" | "ar" | "arn" | "ast" | "ay" | "az" | "be" | "bg" | "bn" | "bo" | "br" | "brx" | "bs" | "ca" | "cgg" | "cs" | "csb" | "cy" | "da" | "de" | "doi" | "dz" | "el" | "en" | "eo" | "es" | "et" | "eu" | "fa" | "ff" | "fi" | "fil" | "fo" | "fr" | "fur" | "fy" | "ga" | "gd" | "gl" | "gu" | "gun" | "ha" | "he" | "hi" | "hne" | "hr" | "hu" | "hy" | "id" | "is" | "it" | "ja" | "jbo" | "jv" | "ka" | "kab" | "kk" | "km" | "kn" | "ko" | "ku" | "kw" | "ky" | "lb" | "ln" | "lo" | "lt" | "lv" | "mai" | "mfe" | "mg" | "mi" | "mk" | "ml" | "mn" | "mni" | "mnk" | "mr" | "ms" | "mt" | "my" | "nah" | "nap" | "nb" | "ne" | "nl" | "nn" | "no" | "nso" | "oc" | "or" | "pa" | "pap" | "pl" | "pms" | "ps" | "pt" | "rm" | "ro" | "ru" | "rw" | "sah" | "sat" | "sco" | "sd" | "se" | "si" | "sk" | "sl" | "so" | "son" | "sq" | "sr" | "su" | "sv" | "sw" | "ta" | "te" | "tg" | "th" | "ti" | "tk" | "tr" | "tt" | "ug" | "uk" | "ur" | "uz" | "vi" | "wa" | "wo" | "yo" | "zh";
5
4
  //#endregion
@@ -90,7 +89,7 @@ type TranslationModule = GetTextTranslations | {
90
89
  type TranslationLoader = () => Promise<TranslationModule>;
91
90
  type TranslationEntry = TranslationModule | Promise<TranslationModule> | TranslationLoader;
92
91
  type TranslationRecord = Partial<Record<Locale, TranslationEntry>>;
93
- type SyncLocaleKeys<T> = { [K in keyof T]: T[K] extends TranslationModule ? K : never }[keyof T];
92
+ type SyncLocaleKeys<T> = { [K in keyof T]: T[K] extends TranslationModule ? K : never; }[keyof T];
94
93
  type AnyTranslationMessage = Message | PluralMessage | ContextMessage | ContextPluralMessage;
95
94
  declare class LocaleTranslator {
96
95
  locale: Locale;
@@ -119,7 +118,26 @@ declare class Translator<T extends TranslationRecord = TranslationRecord> {
119
118
  translations: Partial<Record<Locale, GetTextTranslations>>;
120
119
  pending: Partial<Record<Locale, Promise<LocaleTranslator>>>;
121
120
  translators: Partial<Record<Locale, LocaleTranslator>>;
121
+ /**
122
+ * Raw catalogs as resolved, kept around after {@link getLocale} consumes
123
+ * `translations` so they can still be serialized by {@link dehydrate}.
124
+ */
125
+ catalogs: Partial<Record<Locale, GetTextTranslations>>;
122
126
  constructor(translations: T, parent?: Translator);
127
+ /**
128
+ * Seed an already-resolved catalog so {@link getLocale} and {@link fetchLocale}
129
+ * can answer synchronously, without invoking the locale's loader.
130
+ *
131
+ * Used to hydrate a translator from a server-rendered payload before the first
132
+ * client render, so the tree never suspends during hydration. Priming a locale
133
+ * that is already resolved is a no-op.
134
+ */
135
+ prime: (locale: Locale, module: TranslationModule) => void;
136
+ /**
137
+ * The raw catalog for a resolved locale, or `undefined` when it has not been
138
+ * loaded yet. The counterpart of {@link prime}.
139
+ */
140
+ dehydrate: (locale: Locale) => GetTextTranslations | undefined;
123
141
  loadLocale: (locale: Locale, loader?: TranslationLoader) => Promise<LocaleTranslator>;
124
142
  getLocale: <L extends SyncLocaleKeys<T>>(locale: L) => LocaleTranslator;
125
143
  fetchLocale: <L extends keyof T>(locale: L) => LocaleTranslator | Promise<LocaleTranslator>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/locales.ts","../src/config.ts","../src/utils.ts","../src/messages.ts","../src/translator.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/locales.ts","../src/config.ts","../src/utils.ts","../src/messages.ts","../src/translator.ts"],"mappings":";;KAAY;;;KCEP;;;;;EAKD,eAAe;;;;;EAKf,SAAS;;;;;EAKT,WAAW,QAAQ,OAAO,mBAAmB;;;;;;;;UAShC,sBAAsB;;;;;KAQ3B,SAAS;;;KC7BT,QAAQ,GAAG,IAAI,MAAM,iBAAiB,GAAG,2BAA0B,GAAG;KAEtE,mBAAmB,mCAAmC,YAAY,QAAQ,0BAA0B;iBAQhG,KAAK,cAAc,qBAAqB,IAAI,IAAI;iBAahD,WAAW,cAAc;iBAmBzB,mBAAmB;iBAgBnB,sBAAsB,cAAc,sBAAsB;cAmB7D,aAAU,QAAoC,YAAM;iBAmBjD,kBACZ,SAAS,wBACN,SAAS,qCACb;;;UCtGc;EACb;EACA;;UAGa;EACb;EACA;EACA;;UAGa;EACb,OAAO;EACP;;UAGa;EACb;EACA,IAAI;;UAGS;EACb;EACA,IAAI;;KAYI,YAAY,qBACjB,IAAI,mBAAmB,OACvB,YAAY,sBACZ,SAAS,yBAAyB;KAE7B,mBAAmB,qBAAqB,MAAM,YAAY,OAAO;iBAE7D,QAAQ,qBAAqB,MAAM,YAAY,KAAK;KAiBxD,iBAAiB,OAAO,WAAW;iBAE/B,UAAU,MAAM,aAAa;KAWjC,qBAAqB,MAAM,eAAe;KAC1C,aAAa,8BAA8B,WAAW,YAAY;KAClE,eAAe,iBAAiB;KAEhC,0BAA0B,qBAAqB,MAAM,YAAY,OAAO;KAExE,4BAA4B,MAAM,eAAe;UAE5C;EACb,SAAS;EACT,QAAQ;;iBAMI,QAAQ,kBAAkB,SAAS,mBAAmB,KAAK;iBAC3D,QAAQ,SAAS,yBAAyB,kBAAkB;;;KC5EhE,oBAAoB;EAAwB,SAAS;;KACrD,0BAA0B,QAAQ;KAClC,mBAAmB,oBAAoB,QAAQ,qBAAqB;KACpE,oBAAoB,QAAQ,OAAO,QAAQ;KAClD,eAAe,QACf,WAAW,IAAI,EAAE,WAAW,oBAAoB,mBAC7C;KAuCH,wBAAwB,UAAU,gBAAgB,iBAAiB;cAM3D;EACT,QAAQ;EACR,eAAe;EAEH,YAAA,QAAQ,QAAQ,eAAe;EAK3C,iBAAkB,SAAS,SAAS;EAMpC,oBAAqB,SAAS,eAAe;EAa7C,iBAAkB,SAAS;EAgB3B,mBAAoB,kBAAkB,MAAM,YAAY,IAAI;EAK5D,kBAAmB,MAAM,YAAY;EAKrC,YAAa,SAAS,UAAU,gBAAgB,iBAAiB;EAIjE,UAAW,qBAAqB,MAAM,YAAY;EAClD,YAAa,MAAM;EAEnB,UAAW,qBAAqB,OAAO,mBAAmB,OAAO;IAM/C,UAAA,qBAAgB,MAAW,YAAY;IAC/B,YAAA,MAAA;;EAI1B,UAAW,qBAAqB,MAAM,YAAY;EAClD,cAAe,MAAM;EACrB,WAAY,kBAAkB,kBAAkB,SAAS,mBAAmB,OAAO,MAAM,YAAY;EAErG,YAAa,kBAAkB,SAAS,mBAAmB,OAAO,MAAM;;cAI/D,WAAW,UAAU,oBAAoB;EAClD,QAAQ;EACR,SAAS,QAAQ,OAAO,QAAQ;EAChC,cAAc,QAAQ,OAAO,QAAQ;EACrC,SAAS,QAAQ,OAAO,QAAQ,QAAQ;EACxC,aAAa,QAAQ,OAAO,QAAQ;;;;;EAKpC,UAAU,QAAQ,OAAO,QAAQ;EAErB,YAAA,cAAc,GAAG,SAAS;;;;;;;;;EAuBtC,QAAS,QAAQ,QAAQ,QAAQ;;;;;EAejC,YAAa,QAAQ,WAAS;EAE9B,aAAoB,QAAQ,QAAQ,SAAS,sBAAoB,QAAQ;EAMzE,YAAa,UAAU,eAAe,IAAI,QAAQ,MAAI;EA8BtD,cAAe,gBAAgB,GAAG,QAAQ,MAAC,mBAAA,QAAA"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { GetTextTranslations } from "gettext-parser";
2
-
3
2
  //#region src/locales.d.ts
4
3
  type PluralFormsLocale = "ach" | "af" | "ak" | "am" | "an" | "ar" | "arn" | "ast" | "ay" | "az" | "be" | "bg" | "bn" | "bo" | "br" | "brx" | "bs" | "ca" | "cgg" | "cs" | "csb" | "cy" | "da" | "de" | "doi" | "dz" | "el" | "en" | "eo" | "es" | "et" | "eu" | "fa" | "ff" | "fi" | "fil" | "fo" | "fr" | "fur" | "fy" | "ga" | "gd" | "gl" | "gu" | "gun" | "ha" | "he" | "hi" | "hne" | "hr" | "hu" | "hy" | "id" | "is" | "it" | "ja" | "jbo" | "jv" | "ka" | "kab" | "kk" | "km" | "kn" | "ko" | "ku" | "kw" | "ky" | "lb" | "ln" | "lo" | "lt" | "lv" | "mai" | "mfe" | "mg" | "mi" | "mk" | "ml" | "mn" | "mni" | "mnk" | "mr" | "ms" | "mt" | "my" | "nah" | "nap" | "nb" | "ne" | "nl" | "nn" | "no" | "nso" | "oc" | "or" | "pa" | "pap" | "pl" | "pms" | "ps" | "pt" | "rm" | "ro" | "ru" | "rw" | "sah" | "sat" | "sco" | "sd" | "se" | "si" | "sk" | "sl" | "so" | "son" | "sq" | "sr" | "su" | "sv" | "sw" | "ta" | "te" | "tg" | "th" | "ti" | "tk" | "tr" | "tt" | "ug" | "uk" | "ur" | "uz" | "vi" | "wa" | "wo" | "yo" | "zh";
5
4
  //#endregion
@@ -90,7 +89,7 @@ type TranslationModule = GetTextTranslations | {
90
89
  type TranslationLoader = () => Promise<TranslationModule>;
91
90
  type TranslationEntry = TranslationModule | Promise<TranslationModule> | TranslationLoader;
92
91
  type TranslationRecord = Partial<Record<Locale, TranslationEntry>>;
93
- type SyncLocaleKeys<T> = { [K in keyof T]: T[K] extends TranslationModule ? K : never }[keyof T];
92
+ type SyncLocaleKeys<T> = { [K in keyof T]: T[K] extends TranslationModule ? K : never; }[keyof T];
94
93
  type AnyTranslationMessage = Message | PluralMessage | ContextMessage | ContextPluralMessage;
95
94
  declare class LocaleTranslator {
96
95
  locale: Locale;
@@ -119,7 +118,26 @@ declare class Translator<T extends TranslationRecord = TranslationRecord> {
119
118
  translations: Partial<Record<Locale, GetTextTranslations>>;
120
119
  pending: Partial<Record<Locale, Promise<LocaleTranslator>>>;
121
120
  translators: Partial<Record<Locale, LocaleTranslator>>;
121
+ /**
122
+ * Raw catalogs as resolved, kept around after {@link getLocale} consumes
123
+ * `translations` so they can still be serialized by {@link dehydrate}.
124
+ */
125
+ catalogs: Partial<Record<Locale, GetTextTranslations>>;
122
126
  constructor(translations: T, parent?: Translator);
127
+ /**
128
+ * Seed an already-resolved catalog so {@link getLocale} and {@link fetchLocale}
129
+ * can answer synchronously, without invoking the locale's loader.
130
+ *
131
+ * Used to hydrate a translator from a server-rendered payload before the first
132
+ * client render, so the tree never suspends during hydration. Priming a locale
133
+ * that is already resolved is a no-op.
134
+ */
135
+ prime: (locale: Locale, module: TranslationModule) => void;
136
+ /**
137
+ * The raw catalog for a resolved locale, or `undefined` when it has not been
138
+ * loaded yet. The counterpart of {@link prime}.
139
+ */
140
+ dehydrate: (locale: Locale) => GetTextTranslations | undefined;
123
141
  loadLocale: (locale: Locale, loader?: TranslationLoader) => Promise<LocaleTranslator>;
124
142
  getLocale: <L extends SyncLocaleKeys<T>>(locale: L) => LocaleTranslator;
125
143
  fetchLocale: <L extends keyof T>(locale: L) => LocaleTranslator | Promise<LocaleTranslator>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/locales.ts","../src/config.ts","../src/utils.ts","../src/messages.ts","../src/translator.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/locales.ts","../src/config.ts","../src/utils.ts","../src/messages.ts","../src/translator.ts"],"mappings":";;KAAY;;;KCEP;;;;;EAKD,eAAe;;;;;EAKf,SAAS;;;;;EAKT,WAAW,QAAQ,OAAO,mBAAmB;;;;;;;;UAShC,sBAAsB;;;;;KAQ3B,SAAS;;;KC7BT,QAAQ,GAAG,IAAI,MAAM,iBAAiB,GAAG,2BAA0B,GAAG;KAEtE,mBAAmB,mCAAmC,YAAY,QAAQ,0BAA0B;iBAQhG,KAAK,cAAc,qBAAqB,IAAI,IAAI;iBAahD,WAAW,cAAc;iBAmBzB,mBAAmB;iBAgBnB,sBAAsB,cAAc,sBAAsB;cAmB7D,aAAU,QAAoC,YAAM;iBAmBjD,kBACZ,SAAS,wBACN,SAAS,qCACb;;;UCtGc;EACb;EACA;;UAGa;EACb;EACA;EACA;;UAGa;EACb,OAAO;EACP;;UAGa;EACb;EACA,IAAI;;UAGS;EACb;EACA,IAAI;;KAYI,YAAY,qBACjB,IAAI,mBAAmB,OACvB,YAAY,sBACZ,SAAS,yBAAyB;KAE7B,mBAAmB,qBAAqB,MAAM,YAAY,OAAO;iBAE7D,QAAQ,qBAAqB,MAAM,YAAY,KAAK;KAiBxD,iBAAiB,OAAO,WAAW;iBAE/B,UAAU,MAAM,aAAa;KAWjC,qBAAqB,MAAM,eAAe;KAC1C,aAAa,8BAA8B,WAAW,YAAY;KAClE,eAAe,iBAAiB;KAEhC,0BAA0B,qBAAqB,MAAM,YAAY,OAAO;KAExE,4BAA4B,MAAM,eAAe;UAE5C;EACb,SAAS;EACT,QAAQ;;iBAMI,QAAQ,kBAAkB,SAAS,mBAAmB,KAAK;iBAC3D,QAAQ,SAAS,yBAAyB,kBAAkB;;;KC5EhE,oBAAoB;EAAwB,SAAS;;KACrD,0BAA0B,QAAQ;KAClC,mBAAmB,oBAAoB,QAAQ,qBAAqB;KACpE,oBAAoB,QAAQ,OAAO,QAAQ;KAClD,eAAe,QACf,WAAW,IAAI,EAAE,WAAW,oBAAoB,mBAC7C;KAuCH,wBAAwB,UAAU,gBAAgB,iBAAiB;cAM3D;EACT,QAAQ;EACR,eAAe;EAEH,YAAA,QAAQ,QAAQ,eAAe;EAK3C,iBAAkB,SAAS,SAAS;EAMpC,oBAAqB,SAAS,eAAe;EAa7C,iBAAkB,SAAS;EAgB3B,mBAAoB,kBAAkB,MAAM,YAAY,IAAI;EAK5D,kBAAmB,MAAM,YAAY;EAKrC,YAAa,SAAS,UAAU,gBAAgB,iBAAiB;EAIjE,UAAW,qBAAqB,MAAM,YAAY;EAClD,YAAa,MAAM;EAEnB,UAAW,qBAAqB,OAAO,mBAAmB,OAAO;IAM/C,UAAA,qBAAgB,MAAW,YAAY;IAC/B,YAAA,MAAA;;EAI1B,UAAW,qBAAqB,MAAM,YAAY;EAClD,cAAe,MAAM;EACrB,WAAY,kBAAkB,kBAAkB,SAAS,mBAAmB,OAAO,MAAM,YAAY;EAErG,YAAa,kBAAkB,SAAS,mBAAmB,OAAO,MAAM;;cAI/D,WAAW,UAAU,oBAAoB;EAClD,QAAQ;EACR,SAAS,QAAQ,OAAO,QAAQ;EAChC,cAAc,QAAQ,OAAO,QAAQ;EACrC,SAAS,QAAQ,OAAO,QAAQ,QAAQ;EACxC,aAAa,QAAQ,OAAO,QAAQ;;;;;EAKpC,UAAU,QAAQ,OAAO,QAAQ;EAErB,YAAA,cAAc,GAAG,SAAS;;;;;;;;;EAuBtC,QAAS,QAAQ,QAAQ,QAAQ;;;;;EAejC,YAAa,QAAQ,WAAS;EAE9B,aAAoB,QAAQ,QAAQ,SAAS,sBAAoB,QAAQ;EAMzE,YAAa,UAAU,eAAe,IAAI,QAAQ,MAAI;EA8BtD,cAAe,gBAAgB,GAAG,QAAQ,MAAC,mBAAA,QAAA"}
package/dist/index.mjs CHANGED
@@ -72,26 +72,31 @@ const pluralFunc = memo(function pluralFunc(locale) {
72
72
  }
73
73
  });
74
74
  function mergeTranslations(primary, ...others) {
75
+ function copyRecords(source) {
76
+ const copy = {};
77
+ for (const ctx in source) copy[ctx] = { ...source[ctx] };
78
+ return copy;
79
+ }
75
80
  function mergeRecords(target, source) {
76
81
  for (const ctx in source) {
77
- if (!target[ctx]) {
78
- target[ctx] = source[ctx];
82
+ const sourceContext = source[ctx];
83
+ const targetContext = target[ctx];
84
+ if (!targetContext) {
85
+ target[ctx] = { ...sourceContext };
79
86
  continue;
80
87
  }
81
- const targetContext = target[ctx];
82
- const sourceContext = source[ctx];
83
88
  for (const id in sourceContext) if (!targetContext[id]) targetContext[id] = sourceContext[id];
84
89
  }
85
90
  }
86
91
  const result = {
87
92
  charset: primary.charset,
88
93
  headers: { ...primary.headers },
89
- translations: { ...primary.translations },
90
- obsolete: primary.obsolete ? { ...primary.obsolete } : void 0
94
+ translations: copyRecords(primary.translations),
95
+ obsolete: primary.obsolete ? copyRecords(primary.obsolete) : void 0
91
96
  };
92
97
  for (const other of others) {
93
98
  if (other?.translations) mergeRecords(result.translations, other.translations);
94
- if (other?.obsolete) if (!result.obsolete) result.obsolete = other.obsolete;
99
+ if (other?.obsolete) if (!result.obsolete) result.obsolete = copyRecords(other.obsolete);
95
100
  else mergeRecords(result.obsolete, other.obsolete);
96
101
  }
97
102
  return result;
@@ -243,15 +248,44 @@ var Translator = class {
243
248
  translations = {};
244
249
  pending = {};
245
250
  translators = {};
251
+ /**
252
+ * Raw catalogs as resolved, kept around after {@link getLocale} consumes
253
+ * `translations` so they can still be serialized by {@link dehydrate}.
254
+ */
255
+ catalogs = {};
246
256
  constructor(translations, parent) {
247
257
  this.parent = parent;
248
258
  for (const [locale, value] of Object.entries(translations)) {
249
259
  if (!value) continue;
250
260
  if (typeof value === "function") this.loaders[locale] = value;
251
261
  else if ("then" in value) this.loaders[locale] = () => value;
252
- else this.translations[locale] = resolveTranslationModule(value);
262
+ else {
263
+ this.translations[locale] = resolveTranslationModule(value);
264
+ this.catalogs[locale] = this.translations[locale];
265
+ }
253
266
  }
254
267
  }
268
+ /**
269
+ * Seed an already-resolved catalog so {@link getLocale} and {@link fetchLocale}
270
+ * can answer synchronously, without invoking the locale's loader.
271
+ *
272
+ * Used to hydrate a translator from a server-rendered payload before the first
273
+ * client render, so the tree never suspends during hydration. Priming a locale
274
+ * that is already resolved is a no-op.
275
+ */
276
+ prime = (locale, module) => {
277
+ if (this.translators[locale] || this.translations[locale]) return;
278
+ const resolved = resolveTranslationModule(module);
279
+ this.translations[locale] = resolved;
280
+ this.catalogs[locale] = resolved;
281
+ delete this.loaders[locale];
282
+ delete this.pending[locale];
283
+ };
284
+ /**
285
+ * The raw catalog for a resolved locale, or `undefined` when it has not been
286
+ * loaded yet. The counterpart of {@link prime}.
287
+ */
288
+ dehydrate = (locale) => this.catalogs[locale];
255
289
  loadLocale = async (locale, loader) => {
256
290
  this.loaders[locale] = loader ?? this.loaders[locale];
257
291
  return this.fetchLocale(locale);
@@ -285,6 +319,7 @@ var Translator = class {
285
319
  if (loader) {
286
320
  const promise = loader().then((translations) => {
287
321
  this.translations[key] ??= resolveTranslationModule(translations);
322
+ this.catalogs[key] ??= this.translations[key];
288
323
  delete this.pending[key];
289
324
  return this.getLocale(key);
290
325
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["message","buildMessage","buildPlural"],"sources":["../src/utils.ts","../src/messages.ts","../src/translator.ts"],"sourcesContent":["import type { GetTextTranslationRecord, GetTextTranslations } from \"gettext-parser\";\nimport { getNPlurals, getPluralFunc } from \"plural-forms\";\n\nimport type { Locale } from \"./config.ts\";\n\nexport type IsUnion<T, U = T> = (T extends any ? (x: T) => 0 : never) extends (x: U) => 0 ? false : true;\n\nexport type StrictStaticString<T extends string> = string extends T ? never : IsUnion<T> extends true ? never : T;\n\nexport function assert<T>(value: T, message?: string): asserts value is T {\n if (!value) {\n throw new Error(message || \"Assertion failed\");\n }\n}\n\nexport function memo<T extends (...args: any[]) => any>(fn: T): T {\n const cache = new Map<string, ReturnType<T>>();\n return ((...args: Parameters<T>): ReturnType<T> => {\n const key = JSON.stringify(args);\n if (cache.has(key)) {\n return cache.get(key)!;\n }\n const result = fn(...args);\n cache.set(key, result);\n return result;\n }) as T;\n}\n\nexport function substitute(text: string, values: unknown[] = []): string {\n const placeholders: string[] = [];\n\n return text.replace(/\\$\\{([^}]+)\\}/g, (match, placeholder) => {\n if (/^\\d+$/.test(placeholder)) {\n const index = Number(placeholder);\n return index < values.length ? String(values[index]) : match;\n }\n\n let index = placeholders.indexOf(placeholder);\n if (index === -1) {\n index = placeholders.length;\n placeholders.push(placeholder);\n }\n\n return index < values.length ? String(values[index]) : match;\n });\n}\n\nexport function normalizeMessageId(msgid: string): string {\n const placeholders: string[] = [];\n return msgid.replace(/\\$\\{([^}]+)\\}/g, (match, placeholder) => {\n if (/^\\d+$/.test(placeholder)) {\n return match;\n }\n\n let index = placeholders.indexOf(placeholder);\n if (index === -1) {\n index = placeholders.length;\n placeholders.push(placeholder);\n }\n return `\\${${index}}`;\n });\n}\n\nexport function normalizeTranslations(translations: GetTextTranslations): GetTextTranslations {\n const normalized: GetTextTranslations = {\n ...translations,\n translations: {},\n };\n\n for (const [context, messages] of Object.entries(translations.translations)) {\n normalized.translations[context] = {};\n for (const [msgid, entry] of Object.entries(messages)) {\n const normalizedId = normalizeMessageId(msgid);\n normalized.translations[context][normalizedId] = entry;\n }\n }\n\n return normalized;\n}\n\nconst defaultPluralFunc = (n: number) => (n !== 1 ? 1 : 0);\n\nexport const pluralFunc = memo(function pluralFunc(locale: Locale) {\n try {\n const length = Number(getNPlurals(locale));\n if (length === 1) {\n return () => 0;\n }\n const pluralFunc = getPluralFunc(locale);\n const forms = Array.from({ length }, (_, i) => String(i));\n return (n: number) => {\n const idx = Number(pluralFunc(n, forms));\n if (!Number.isFinite(idx) || idx < 0) return 0;\n if (idx >= length) return length - 1;\n return Math.floor(idx);\n };\n } catch {\n return defaultPluralFunc;\n }\n});\n\nexport function mergeTranslations(\n primary: GetTextTranslations,\n ...others: (GetTextTranslations | undefined)[]\n): GetTextTranslations {\n function mergeRecords(target: GetTextTranslationRecord, source: GetTextTranslationRecord): void {\n for (const ctx in source) {\n if (!target[ctx]) {\n target[ctx] = source[ctx];\n continue;\n }\n\n const targetContext = target[ctx];\n const sourceContext = source[ctx];\n for (const id in sourceContext) {\n if (!targetContext[id]) {\n targetContext[id] = sourceContext[id];\n }\n }\n }\n }\n\n const result: GetTextTranslations = {\n charset: primary.charset,\n headers: { ...primary.headers },\n translations: { ...primary.translations },\n obsolete: primary.obsolete ? { ...primary.obsolete } : undefined,\n };\n\n for (const other of others) {\n if (other?.translations) {\n mergeRecords(result.translations, other.translations);\n }\n\n if (other?.obsolete) {\n if (!result.obsolete) {\n result.obsolete = other.obsolete;\n } else {\n mergeRecords(result.obsolete, other.obsolete);\n }\n }\n }\n\n return result;\n}\n","import { assert, type StrictStaticString } from \"./utils.ts\";\n\nexport interface MessageDescriptor {\n id?: string;\n message?: string;\n}\n\nexport interface Message {\n msgid: string;\n msgstr: string;\n values?: any[];\n}\n\nexport interface PluralMessage {\n forms: Message[];\n n: number;\n}\n\nexport interface ContextMessage {\n context: string;\n id: Message;\n}\n\nexport interface ContextPluralMessage {\n context: string;\n id: PluralMessage;\n}\n\nfunction buildFromTemplate(strings: TemplateStringsArray): string {\n let result = \"\";\n for (let i = 0; i < strings.length; i++) {\n result += strings[i];\n if (i < strings.length - 1) result += `\\${${i}}`;\n }\n return result;\n}\n\nexport type MessageArgs<T extends string> =\n | [id: StrictStaticString<T>]\n | [descriptor: MessageDescriptor]\n | [strings: TemplateStringsArray, ...values: unknown[]];\n\nexport type MessageFunction = <T extends string>(...args: MessageArgs<T>) => Message;\n\nexport function message<T extends string>(...args: MessageArgs<T>): Message {\n const [source, ...values] = args as [MessageDescriptor | TemplateStringsArray, ...unknown[]];\n\n if (typeof source === \"string\") {\n return { msgid: source, msgstr: source };\n }\n\n if (typeof source === \"object\" && \"reduce\" in source) {\n const id = buildFromTemplate(source);\n return { msgid: id, msgstr: id, values };\n }\n\n const id = source.id ?? source.message ?? \"\";\n const message = source.message ?? source.id ?? \"\";\n return { msgid: id, msgstr: message };\n}\n\nexport type PluralArgs = [...forms: Message[], n: number];\n\nexport function plural(...args: PluralArgs): PluralMessage {\n assert(args.length > 1, \"At least one plural form and n are required\");\n\n const n = args[args.length - 1] as number;\n assert(typeof n === \"number\", \"The last argument must be a number\");\n\n const forms = args.slice(0, -1) as Message[];\n\n return { forms, n };\n}\n\nexport type PluralFunction = (...args: PluralArgs) => PluralMessage;\nexport type MessageInput<T extends string = string> = [Message] | MessageArgs<T>;\nexport type PluralInput = [PluralMessage] | PluralArgs;\n\nexport type ContextMessageFunction = <T extends string>(...args: MessageArgs<T>) => ContextMessage;\n\nexport type ContextPluralFunction = (...args: PluralArgs) => ContextPluralMessage;\n\nexport interface ContextBuilder {\n message: ContextMessageFunction;\n plural: ContextPluralFunction;\n}\n\nconst baseMessage = message;\nconst basePlural = plural;\n\nexport function context<T extends string>(context: StrictStaticString<T>): ContextBuilder;\nexport function context(strings: TemplateStringsArray, ...values: never[]): ContextBuilder;\nexport function context<T extends string>(\n ...args: [StrictStaticString<T>] | [TemplateStringsArray, ...never[]]\n): ContextBuilder {\n const [source] = args as [StrictStaticString<T> | TemplateStringsArray];\n\n const ctx = typeof source === \"string\" ? source : source[0];\n\n function message<T extends string>(...args: MessageArgs<T>): ContextMessage {\n return { id: baseMessage(...args), context: ctx };\n }\n\n function plural(...forms: PluralArgs): ContextPluralMessage {\n return { id: basePlural(...forms), context: ctx };\n }\n\n return {\n message,\n plural,\n };\n}\n","import type { GetTextTranslations } from \"gettext-parser\";\nimport type { Locale } from \"./config.ts\";\n\nimport {\n message as buildMessage,\n plural as buildPlural,\n type ContextMessage,\n type ContextPluralMessage,\n type Message,\n type MessageArgs,\n type PluralArgs,\n type PluralMessage,\n} from \"./messages.ts\";\nimport { mergeTranslations, normalizeTranslations, pluralFunc, type StrictStaticString, substitute } from \"./utils.ts\";\n\nexport type TranslationModule = GetTextTranslations | { default: GetTextTranslations };\nexport type TranslationLoader = () => Promise<TranslationModule>;\nexport type TranslationEntry = TranslationModule | Promise<TranslationModule> | TranslationLoader;\nexport type TranslationRecord = Partial<Record<Locale, TranslationEntry>>;\ntype SyncLocaleKeys<T> = {\n [K in keyof T]: T[K] extends TranslationModule ? K : never;\n}[keyof T];\n\nfunction selectValues(message: Message | undefined, fallback?: Message): unknown[] | undefined {\n const values = message?.values;\n if (values?.length) {\n return values;\n }\n return fallback?.values;\n}\n\nfunction selectTemplate(preferred: string | undefined, fallback: string): string {\n return preferred?.length ? preferred : fallback;\n}\n\nfunction applyValues(template: string, message: Message | undefined, fallback?: Message): string {\n const values = selectValues(message, fallback);\n return values?.length ? substitute(template, values) : template;\n}\n\nfunction isPluralMessage(value: unknown): value is PluralMessage {\n return Boolean(value) && typeof value === \"object\" && \"forms\" in (value as PluralMessage);\n}\n\nfunction isContextMessage(value: unknown): value is ContextMessage {\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return false;\n }\n const candidate = (value as ContextMessage).id;\n return !isPluralMessage(candidate);\n}\n\nfunction isContextPluralMessage(value: unknown): value is ContextPluralMessage {\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return false;\n }\n const candidate = (value as ContextPluralMessage).id;\n return isPluralMessage(candidate);\n}\n\ntype AnyTranslationMessage = Message | PluralMessage | ContextMessage | ContextPluralMessage;\n\nfunction resolveTranslationModule(module: TranslationModule): GetTextTranslations {\n return \"default\" in module ? module.default : module;\n}\n\nexport class LocaleTranslator {\n locale: Locale;\n translations?: GetTextTranslations;\n\n constructor(locale: Locale, translations?: GetTextTranslations) {\n this.locale = locale;\n this.translations = translations ? normalizeTranslations(translations) : undefined;\n }\n\n resolveMessage = (message: Message, context = \"\"): string => {\n const entry = this.translations?.translations?.[context]?.[message.msgid];\n const template = selectTemplate(entry?.msgstr?.[0], message.msgstr);\n return applyValues(template, message);\n };\n\n resolvePluralForm = (message: PluralMessage, context = \"\"): string => {\n const entry = this.translations?.translations?.[context]?.[message.forms[0].msgid];\n const index = pluralFunc(this.locale)(message.n);\n const forms = message.forms;\n const selectedForm = forms[index] ?? forms[forms.length - 1];\n const translatedForms = entry?.msgstr;\n const templateCandidate = translatedForms?.length\n ? (translatedForms[index] ?? translatedForms[translatedForms.length - 1])\n : undefined;\n const template = selectTemplate(templateCandidate, selectedForm.msgstr);\n return applyValues(template, selectedForm, forms[0]);\n };\n\n translateValue = (message: AnyTranslationMessage): string => {\n if (isContextPluralMessage(message)) {\n return this.resolvePluralForm(message.id, message.context);\n }\n\n if (isContextMessage(message)) {\n return this.resolveMessage(message.id, message.context);\n }\n\n if (isPluralMessage(message)) {\n return this.resolvePluralForm(message);\n }\n\n return this.resolveMessage(message);\n };\n\n translateMessage = <T extends string>(args: MessageArgs<T>, context?: string): string => {\n const message = buildMessage(...args);\n return this.resolveMessage(message, context);\n };\n\n translatePlural = (args: PluralArgs, context?: string): string => {\n const message = buildPlural(...args);\n return this.resolvePluralForm(message, context);\n };\n\n translate = (message: Message | PluralMessage | ContextMessage | ContextPluralMessage): string => {\n return this.translateValue(message);\n };\n\n message = <T extends string>(...args: MessageArgs<T>): string => this.translateMessage(args);\n plural = (...args: PluralArgs): string => this.translatePlural(args);\n\n context = <T extends string>(...args: [StrictStaticString<T>] | [TemplateStringsArray, ...never[]]) => {\n const [source] = args as [StrictStaticString<T> | TemplateStringsArray];\n\n const context = typeof source === \"string\" ? source : source[0];\n\n return {\n message: <U extends string>(...args: MessageArgs<U>): string => this.translateMessage(args, context),\n plural: (...args: PluralArgs): string => this.translatePlural(args, context),\n };\n };\n\n gettext = <T extends string>(...args: MessageArgs<T>): string => this.message(...args);\n ngettext = (...args: PluralArgs): string => this.plural(...args);\n pgettext = <C extends string, T extends string>(context: StrictStaticString<C>, ...args: MessageArgs<T>): string =>\n this.translateMessage(args, context);\n npgettext = <C extends string>(context: StrictStaticString<C>, ...args: PluralArgs): string =>\n this.translatePlural(args, context);\n}\n\nexport class Translator<T extends TranslationRecord = TranslationRecord> {\n parent: Translator | undefined;\n loaders: Partial<Record<Locale, TranslationLoader>> = {};\n translations: Partial<Record<Locale, GetTextTranslations>> = {};\n pending: Partial<Record<Locale, Promise<LocaleTranslator>>> = {};\n translators: Partial<Record<Locale, LocaleTranslator>> = {};\n\n constructor(translations: T, parent?: Translator) {\n this.parent = parent;\n for (const [locale, value] of Object.entries(translations) as [Locale, TranslationEntry][]) {\n if (!value) continue;\n if (typeof value === \"function\") {\n this.loaders[locale] = value;\n } else if (\"then\" in value) {\n this.loaders[locale] = () => value;\n } else {\n this.translations[locale] = resolveTranslationModule(value);\n }\n }\n }\n\n loadLocale = async (locale: Locale, loader?: TranslationLoader): Promise<LocaleTranslator> => {\n this.loaders[locale] = loader ?? this.loaders[locale];\n\n return this.fetchLocale(locale as never);\n };\n\n getLocale = <L extends SyncLocaleKeys<T>>(locale: L): LocaleTranslator => {\n const key = locale as Locale;\n const existing = this.translators[key];\n if (existing) {\n return existing;\n }\n\n const base = this.translations[key];\n if (base) {\n const parentTranslations = this.parent?.getLocale(locale as never)?.translations;\n const translations = mergeTranslations(base, parentTranslations);\n delete this.translations[key];\n\n const translator = new LocaleTranslator(key, translations);\n this.translators[key] = translator;\n return translator;\n }\n\n if (this.pending[key] || this.loaders[key]) {\n console.warn(\n `Translator.getLocale(${key}) called before async locale resolved. Returning untranslated fallback.`,\n );\n this.translators[key] ??= new LocaleTranslator(key);\n return this.translators[key];\n }\n\n this.translators[key] ??= new LocaleTranslator(key);\n return this.translators[key];\n };\n\n fetchLocale = <L extends keyof T>(locale: L) => {\n const key = locale as Locale;\n\n const pending = this.pending[key];\n if (pending) {\n return pending;\n }\n\n const loader = this.loaders[key];\n if (loader) {\n const promise = loader().then((translations) => {\n this.translations[key] ??= resolveTranslationModule(translations);\n delete this.pending[key];\n\n return this.getLocale(key as never);\n });\n this.pending[key] = promise;\n delete this.loaders[key];\n\n return promise;\n }\n\n return this.getLocale(key as never);\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["message","buildMessage","buildPlural"],"sources":["../src/utils.ts","../src/messages.ts","../src/translator.ts"],"sourcesContent":["import type { GetTextTranslationRecord, GetTextTranslations } from \"gettext-parser\";\nimport { getNPlurals, getPluralFunc } from \"plural-forms\";\n\nimport type { Locale } from \"./config.ts\";\n\nexport type IsUnion<T, U = T> = (T extends any ? (x: T) => 0 : never) extends (x: U) => 0 ? false : true;\n\nexport type StrictStaticString<T extends string> = string extends T ? never : IsUnion<T> extends true ? never : T;\n\nexport function assert<T>(value: T, message?: string): asserts value is T {\n if (!value) {\n throw new Error(message || \"Assertion failed\");\n }\n}\n\nexport function memo<T extends (...args: any[]) => any>(fn: T): T {\n const cache = new Map<string, ReturnType<T>>();\n return ((...args: Parameters<T>): ReturnType<T> => {\n const key = JSON.stringify(args);\n if (cache.has(key)) {\n return cache.get(key)!;\n }\n const result = fn(...args);\n cache.set(key, result);\n return result;\n }) as T;\n}\n\nexport function substitute(text: string, values: unknown[] = []): string {\n const placeholders: string[] = [];\n\n return text.replace(/\\$\\{([^}]+)\\}/g, (match, placeholder) => {\n if (/^\\d+$/.test(placeholder)) {\n const index = Number(placeholder);\n return index < values.length ? String(values[index]) : match;\n }\n\n let index = placeholders.indexOf(placeholder);\n if (index === -1) {\n index = placeholders.length;\n placeholders.push(placeholder);\n }\n\n return index < values.length ? String(values[index]) : match;\n });\n}\n\nexport function normalizeMessageId(msgid: string): string {\n const placeholders: string[] = [];\n return msgid.replace(/\\$\\{([^}]+)\\}/g, (match, placeholder) => {\n if (/^\\d+$/.test(placeholder)) {\n return match;\n }\n\n let index = placeholders.indexOf(placeholder);\n if (index === -1) {\n index = placeholders.length;\n placeholders.push(placeholder);\n }\n return `\\${${index}}`;\n });\n}\n\nexport function normalizeTranslations(translations: GetTextTranslations): GetTextTranslations {\n const normalized: GetTextTranslations = {\n ...translations,\n translations: {},\n };\n\n for (const [context, messages] of Object.entries(translations.translations)) {\n normalized.translations[context] = {};\n for (const [msgid, entry] of Object.entries(messages)) {\n const normalizedId = normalizeMessageId(msgid);\n normalized.translations[context][normalizedId] = entry;\n }\n }\n\n return normalized;\n}\n\nconst defaultPluralFunc = (n: number) => (n !== 1 ? 1 : 0);\n\nexport const pluralFunc = memo(function pluralFunc(locale: Locale) {\n try {\n const length = Number(getNPlurals(locale));\n if (length === 1) {\n return () => 0;\n }\n const pluralFunc = getPluralFunc(locale);\n const forms = Array.from({ length }, (_, i) => String(i));\n return (n: number) => {\n const idx = Number(pluralFunc(n, forms));\n if (!Number.isFinite(idx) || idx < 0) return 0;\n if (idx >= length) return length - 1;\n return Math.floor(idx);\n };\n } catch {\n return defaultPluralFunc;\n }\n});\n\nexport function mergeTranslations(\n primary: GetTextTranslations,\n ...others: (GetTextTranslations | undefined)[]\n): GetTextTranslations {\n // Copy every per-context record, not just the outer map. Catalogs come from\n // imported `.po` modules and are shared across translators, so writing into a\n // record we did not create would leak one catalog's messages into another.\n function copyRecords(source: GetTextTranslationRecord): GetTextTranslationRecord {\n const copy: GetTextTranslationRecord = {};\n for (const ctx in source) {\n copy[ctx] = { ...source[ctx] };\n }\n return copy;\n }\n\n function mergeRecords(target: GetTextTranslationRecord, source: GetTextTranslationRecord): void {\n for (const ctx in source) {\n const sourceContext = source[ctx];\n const targetContext = target[ctx];\n\n if (!targetContext) {\n target[ctx] = { ...sourceContext };\n continue;\n }\n\n for (const id in sourceContext) {\n if (!targetContext[id]) {\n targetContext[id] = sourceContext[id];\n }\n }\n }\n }\n\n const result: GetTextTranslations = {\n charset: primary.charset,\n headers: { ...primary.headers },\n translations: copyRecords(primary.translations),\n obsolete: primary.obsolete ? copyRecords(primary.obsolete) : undefined,\n };\n\n for (const other of others) {\n if (other?.translations) {\n mergeRecords(result.translations, other.translations);\n }\n\n if (other?.obsolete) {\n if (!result.obsolete) {\n result.obsolete = copyRecords(other.obsolete);\n } else {\n mergeRecords(result.obsolete, other.obsolete);\n }\n }\n }\n\n return result;\n}\n","import { assert, type StrictStaticString } from \"./utils.ts\";\n\nexport interface MessageDescriptor {\n id?: string;\n message?: string;\n}\n\nexport interface Message {\n msgid: string;\n msgstr: string;\n values?: any[];\n}\n\nexport interface PluralMessage {\n forms: Message[];\n n: number;\n}\n\nexport interface ContextMessage {\n context: string;\n id: Message;\n}\n\nexport interface ContextPluralMessage {\n context: string;\n id: PluralMessage;\n}\n\nfunction buildFromTemplate(strings: TemplateStringsArray): string {\n let result = \"\";\n for (let i = 0; i < strings.length; i++) {\n result += strings[i];\n if (i < strings.length - 1) result += `\\${${i}}`;\n }\n return result;\n}\n\nexport type MessageArgs<T extends string> =\n | [id: StrictStaticString<T>]\n | [descriptor: MessageDescriptor]\n | [strings: TemplateStringsArray, ...values: unknown[]];\n\nexport type MessageFunction = <T extends string>(...args: MessageArgs<T>) => Message;\n\nexport function message<T extends string>(...args: MessageArgs<T>): Message {\n const [source, ...values] = args as [MessageDescriptor | TemplateStringsArray, ...unknown[]];\n\n if (typeof source === \"string\") {\n return { msgid: source, msgstr: source };\n }\n\n if (typeof source === \"object\" && \"reduce\" in source) {\n const id = buildFromTemplate(source);\n return { msgid: id, msgstr: id, values };\n }\n\n const id = source.id ?? source.message ?? \"\";\n const message = source.message ?? source.id ?? \"\";\n return { msgid: id, msgstr: message };\n}\n\nexport type PluralArgs = [...forms: Message[], n: number];\n\nexport function plural(...args: PluralArgs): PluralMessage {\n assert(args.length > 1, \"At least one plural form and n are required\");\n\n const n = args[args.length - 1] as number;\n assert(typeof n === \"number\", \"The last argument must be a number\");\n\n const forms = args.slice(0, -1) as Message[];\n\n return { forms, n };\n}\n\nexport type PluralFunction = (...args: PluralArgs) => PluralMessage;\nexport type MessageInput<T extends string = string> = [Message] | MessageArgs<T>;\nexport type PluralInput = [PluralMessage] | PluralArgs;\n\nexport type ContextMessageFunction = <T extends string>(...args: MessageArgs<T>) => ContextMessage;\n\nexport type ContextPluralFunction = (...args: PluralArgs) => ContextPluralMessage;\n\nexport interface ContextBuilder {\n message: ContextMessageFunction;\n plural: ContextPluralFunction;\n}\n\nconst baseMessage = message;\nconst basePlural = plural;\n\nexport function context<T extends string>(context: StrictStaticString<T>): ContextBuilder;\nexport function context(strings: TemplateStringsArray, ...values: never[]): ContextBuilder;\nexport function context<T extends string>(\n ...args: [StrictStaticString<T>] | [TemplateStringsArray, ...never[]]\n): ContextBuilder {\n const [source] = args as [StrictStaticString<T> | TemplateStringsArray];\n\n const ctx = typeof source === \"string\" ? source : source[0];\n\n function message<T extends string>(...args: MessageArgs<T>): ContextMessage {\n return { id: baseMessage(...args), context: ctx };\n }\n\n function plural(...forms: PluralArgs): ContextPluralMessage {\n return { id: basePlural(...forms), context: ctx };\n }\n\n return {\n message,\n plural,\n };\n}\n","import type { GetTextTranslations } from \"gettext-parser\";\nimport type { Locale } from \"./config.ts\";\n\nimport {\n message as buildMessage,\n plural as buildPlural,\n type ContextMessage,\n type ContextPluralMessage,\n type Message,\n type MessageArgs,\n type PluralArgs,\n type PluralMessage,\n} from \"./messages.ts\";\nimport { mergeTranslations, normalizeTranslations, pluralFunc, type StrictStaticString, substitute } from \"./utils.ts\";\n\nexport type TranslationModule = GetTextTranslations | { default: GetTextTranslations };\nexport type TranslationLoader = () => Promise<TranslationModule>;\nexport type TranslationEntry = TranslationModule | Promise<TranslationModule> | TranslationLoader;\nexport type TranslationRecord = Partial<Record<Locale, TranslationEntry>>;\ntype SyncLocaleKeys<T> = {\n [K in keyof T]: T[K] extends TranslationModule ? K : never;\n}[keyof T];\n\nfunction selectValues(message: Message | undefined, fallback?: Message): unknown[] | undefined {\n const values = message?.values;\n if (values?.length) {\n return values;\n }\n return fallback?.values;\n}\n\nfunction selectTemplate(preferred: string | undefined, fallback: string): string {\n return preferred?.length ? preferred : fallback;\n}\n\nfunction applyValues(template: string, message: Message | undefined, fallback?: Message): string {\n const values = selectValues(message, fallback);\n return values?.length ? substitute(template, values) : template;\n}\n\nfunction isPluralMessage(value: unknown): value is PluralMessage {\n return Boolean(value) && typeof value === \"object\" && \"forms\" in (value as PluralMessage);\n}\n\nfunction isContextMessage(value: unknown): value is ContextMessage {\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return false;\n }\n const candidate = (value as ContextMessage).id;\n return !isPluralMessage(candidate);\n}\n\nfunction isContextPluralMessage(value: unknown): value is ContextPluralMessage {\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return false;\n }\n const candidate = (value as ContextPluralMessage).id;\n return isPluralMessage(candidate);\n}\n\ntype AnyTranslationMessage = Message | PluralMessage | ContextMessage | ContextPluralMessage;\n\nfunction resolveTranslationModule(module: TranslationModule): GetTextTranslations {\n return \"default\" in module ? module.default : module;\n}\n\nexport class LocaleTranslator {\n locale: Locale;\n translations?: GetTextTranslations;\n\n constructor(locale: Locale, translations?: GetTextTranslations) {\n this.locale = locale;\n this.translations = translations ? normalizeTranslations(translations) : undefined;\n }\n\n resolveMessage = (message: Message, context = \"\"): string => {\n const entry = this.translations?.translations?.[context]?.[message.msgid];\n const template = selectTemplate(entry?.msgstr?.[0], message.msgstr);\n return applyValues(template, message);\n };\n\n resolvePluralForm = (message: PluralMessage, context = \"\"): string => {\n const entry = this.translations?.translations?.[context]?.[message.forms[0].msgid];\n const index = pluralFunc(this.locale)(message.n);\n const forms = message.forms;\n const selectedForm = forms[index] ?? forms[forms.length - 1];\n const translatedForms = entry?.msgstr;\n const templateCandidate = translatedForms?.length\n ? (translatedForms[index] ?? translatedForms[translatedForms.length - 1])\n : undefined;\n const template = selectTemplate(templateCandidate, selectedForm.msgstr);\n return applyValues(template, selectedForm, forms[0]);\n };\n\n translateValue = (message: AnyTranslationMessage): string => {\n if (isContextPluralMessage(message)) {\n return this.resolvePluralForm(message.id, message.context);\n }\n\n if (isContextMessage(message)) {\n return this.resolveMessage(message.id, message.context);\n }\n\n if (isPluralMessage(message)) {\n return this.resolvePluralForm(message);\n }\n\n return this.resolveMessage(message);\n };\n\n translateMessage = <T extends string>(args: MessageArgs<T>, context?: string): string => {\n const message = buildMessage(...args);\n return this.resolveMessage(message, context);\n };\n\n translatePlural = (args: PluralArgs, context?: string): string => {\n const message = buildPlural(...args);\n return this.resolvePluralForm(message, context);\n };\n\n translate = (message: Message | PluralMessage | ContextMessage | ContextPluralMessage): string => {\n return this.translateValue(message);\n };\n\n message = <T extends string>(...args: MessageArgs<T>): string => this.translateMessage(args);\n plural = (...args: PluralArgs): string => this.translatePlural(args);\n\n context = <T extends string>(...args: [StrictStaticString<T>] | [TemplateStringsArray, ...never[]]) => {\n const [source] = args as [StrictStaticString<T> | TemplateStringsArray];\n\n const context = typeof source === \"string\" ? source : source[0];\n\n return {\n message: <U extends string>(...args: MessageArgs<U>): string => this.translateMessage(args, context),\n plural: (...args: PluralArgs): string => this.translatePlural(args, context),\n };\n };\n\n gettext = <T extends string>(...args: MessageArgs<T>): string => this.message(...args);\n ngettext = (...args: PluralArgs): string => this.plural(...args);\n pgettext = <C extends string, T extends string>(context: StrictStaticString<C>, ...args: MessageArgs<T>): string =>\n this.translateMessage(args, context);\n npgettext = <C extends string>(context: StrictStaticString<C>, ...args: PluralArgs): string =>\n this.translatePlural(args, context);\n}\n\nexport class Translator<T extends TranslationRecord = TranslationRecord> {\n parent: Translator | undefined;\n loaders: Partial<Record<Locale, TranslationLoader>> = {};\n translations: Partial<Record<Locale, GetTextTranslations>> = {};\n pending: Partial<Record<Locale, Promise<LocaleTranslator>>> = {};\n translators: Partial<Record<Locale, LocaleTranslator>> = {};\n /**\n * Raw catalogs as resolved, kept around after {@link getLocale} consumes\n * `translations` so they can still be serialized by {@link dehydrate}.\n */\n catalogs: Partial<Record<Locale, GetTextTranslations>> = {};\n\n constructor(translations: T, parent?: Translator) {\n this.parent = parent;\n for (const [locale, value] of Object.entries(translations) as [Locale, TranslationEntry][]) {\n if (!value) continue;\n if (typeof value === \"function\") {\n this.loaders[locale] = value;\n } else if (\"then\" in value) {\n this.loaders[locale] = () => value;\n } else {\n this.translations[locale] = resolveTranslationModule(value);\n this.catalogs[locale] = this.translations[locale];\n }\n }\n }\n\n /**\n * Seed an already-resolved catalog so {@link getLocale} and {@link fetchLocale}\n * can answer synchronously, without invoking the locale's loader.\n *\n * Used to hydrate a translator from a server-rendered payload before the first\n * client render, so the tree never suspends during hydration. Priming a locale\n * that is already resolved is a no-op.\n */\n prime = (locale: Locale, module: TranslationModule): void => {\n if (this.translators[locale] || this.translations[locale]) {\n return;\n }\n const resolved = resolveTranslationModule(module);\n this.translations[locale] = resolved;\n this.catalogs[locale] = resolved;\n delete this.loaders[locale];\n delete this.pending[locale];\n };\n\n /**\n * The raw catalog for a resolved locale, or `undefined` when it has not been\n * loaded yet. The counterpart of {@link prime}.\n */\n dehydrate = (locale: Locale): GetTextTranslations | undefined => this.catalogs[locale];\n\n loadLocale = async (locale: Locale, loader?: TranslationLoader): Promise<LocaleTranslator> => {\n this.loaders[locale] = loader ?? this.loaders[locale];\n\n return this.fetchLocale(locale as never);\n };\n\n getLocale = <L extends SyncLocaleKeys<T>>(locale: L): LocaleTranslator => {\n const key = locale as Locale;\n const existing = this.translators[key];\n if (existing) {\n return existing;\n }\n\n const base = this.translations[key];\n if (base) {\n const parentTranslations = this.parent?.getLocale(locale as never)?.translations;\n const translations = mergeTranslations(base, parentTranslations);\n delete this.translations[key];\n\n const translator = new LocaleTranslator(key, translations);\n this.translators[key] = translator;\n return translator;\n }\n\n if (this.pending[key] || this.loaders[key]) {\n console.warn(\n `Translator.getLocale(${key}) called before async locale resolved. Returning untranslated fallback.`,\n );\n this.translators[key] ??= new LocaleTranslator(key);\n return this.translators[key];\n }\n\n this.translators[key] ??= new LocaleTranslator(key);\n return this.translators[key];\n };\n\n fetchLocale = <L extends keyof T>(locale: L) => {\n const key = locale as Locale;\n\n const pending = this.pending[key];\n if (pending) {\n return pending;\n }\n\n const loader = this.loaders[key];\n if (loader) {\n const promise = loader().then((translations) => {\n this.translations[key] ??= resolveTranslationModule(translations);\n this.catalogs[key] ??= this.translations[key];\n delete this.pending[key];\n\n return this.getLocale(key as never);\n });\n this.pending[key] = promise;\n delete this.loaders[key];\n\n return promise;\n }\n\n return this.getLocale(key as never);\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@let-value/translate",
3
- "version": "1.1.6-beta.3",
3
+ "version": "1.2.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/let-value/translate"