intor-translator 1.5.0 → 1.6.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.
package/dist/index.cjs CHANGED
@@ -50,6 +50,162 @@ var BaseTranslator = class {
50
50
  }
51
51
  };
52
52
 
53
+ // src/formatter/utils/to-cache-key.ts
54
+ function toCacheKey(locale, options) {
55
+ if (!options || Object.keys(options).length === 0) return locale;
56
+ const normalized = Object.entries(options).filter(([, value]) => value !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}:${String(value)}`).join("|");
57
+ return `${locale}__${normalized}`;
58
+ }
59
+
60
+ // src/formatter/date/create-date-time-formatter.ts
61
+ function createDateTimeFormatter() {
62
+ const cache = /* @__PURE__ */ new Map();
63
+ return (locale, options) => {
64
+ const key = toCacheKey(locale, options);
65
+ const cached = cache.get(key);
66
+ if (cached) return cached;
67
+ const formatter = new Intl.DateTimeFormat(locale, options);
68
+ cache.set(key, formatter);
69
+ return formatter;
70
+ };
71
+ }
72
+
73
+ // src/formatter/display-name/create-display-names.ts
74
+ function createDisplayNames() {
75
+ const cache = /* @__PURE__ */ new Map();
76
+ return (locale, options) => {
77
+ const key = toCacheKey(locale, options);
78
+ const cached = cache.get(key);
79
+ if (cached) return cached;
80
+ const displayNames = new Intl.DisplayNames(locale, options);
81
+ cache.set(key, displayNames);
82
+ return displayNames;
83
+ };
84
+ }
85
+
86
+ // src/formatter/list/create-list-formatter.ts
87
+ function createListFormatter() {
88
+ const cache = /* @__PURE__ */ new Map();
89
+ return (locale, options) => {
90
+ const key = toCacheKey(locale, options);
91
+ const cached = cache.get(key);
92
+ if (cached) return cached;
93
+ const formatter = new Intl.ListFormat(locale, options);
94
+ cache.set(key, formatter);
95
+ return formatter;
96
+ };
97
+ }
98
+
99
+ // src/formatter/number/create-number-formatter.ts
100
+ function createNumberFormatter() {
101
+ const cache = /* @__PURE__ */ new Map();
102
+ return (locale, options) => {
103
+ const key = toCacheKey(locale, options);
104
+ const cached = cache.get(key);
105
+ if (cached) return cached;
106
+ const formatter = new Intl.NumberFormat(locale, options);
107
+ cache.set(key, formatter);
108
+ return formatter;
109
+ };
110
+ }
111
+
112
+ // src/formatter/plural/create-plural-rules.ts
113
+ function createPluralRules() {
114
+ const cache = /* @__PURE__ */ new Map();
115
+ return (locale, options) => {
116
+ const key = toCacheKey(locale, options);
117
+ const cached = cache.get(key);
118
+ if (cached) return cached;
119
+ const rules = new Intl.PluralRules(locale, options);
120
+ cache.set(key, rules);
121
+ return rules;
122
+ };
123
+ }
124
+
125
+ // src/formatter/relative-time/create-relative-time-formatter.ts
126
+ function createRelativeTimeFormatter() {
127
+ const cache = /* @__PURE__ */ new Map();
128
+ return (locale, options) => {
129
+ const key = toCacheKey(locale, options);
130
+ const cached = cache.get(key);
131
+ if (cached) return cached;
132
+ const formatter = new Intl.RelativeTimeFormat(locale, options);
133
+ cache.set(key, formatter);
134
+ return formatter;
135
+ };
136
+ }
137
+
138
+ // src/formatter/create-formatter.ts
139
+ function createFormatter({
140
+ getLocale,
141
+ formatDefaults
142
+ }) {
143
+ const getDateTimeFormatter = createDateTimeFormatter();
144
+ const getListFormatter = createListFormatter();
145
+ const getRelativeTimeFormatter = createRelativeTimeFormatter();
146
+ const getNumberFormatter = createNumberFormatter();
147
+ const getDisplayNames = createDisplayNames();
148
+ const getPluralRules = createPluralRules();
149
+ return {
150
+ number(value, options) {
151
+ return getNumberFormatter(getLocale(), {
152
+ ...formatDefaults?.number,
153
+ ...options
154
+ }).format(value);
155
+ },
156
+ currency(value, currency, options) {
157
+ const resolvedCurrency = currency ?? formatDefaults?.currencyCode;
158
+ if (!resolvedCurrency) {
159
+ throw new Error("[intor-translator] currency is required");
160
+ }
161
+ return getNumberFormatter(getLocale(), {
162
+ ...formatDefaults?.currency,
163
+ ...options,
164
+ style: "currency",
165
+ currency: resolvedCurrency
166
+ }).format(value);
167
+ },
168
+ date(value, options) {
169
+ return getDateTimeFormatter(getLocale(), {
170
+ ...formatDefaults?.date,
171
+ ...formatDefaults?.timeZone ? { timeZone: formatDefaults.timeZone } : {},
172
+ ...options
173
+ }).format(value);
174
+ },
175
+ relativeTime(value, unit, options) {
176
+ return getRelativeTimeFormatter(getLocale(), {
177
+ ...formatDefaults?.relativeTime,
178
+ ...options
179
+ }).format(value, unit);
180
+ },
181
+ list(values, options) {
182
+ return getListFormatter(getLocale(), {
183
+ ...formatDefaults?.list,
184
+ ...options
185
+ }).format(values);
186
+ },
187
+ displayName(value, options) {
188
+ const resolvedOptions = {
189
+ ...formatDefaults?.displayName,
190
+ ...options
191
+ };
192
+ if (!resolvedOptions.type) {
193
+ throw new Error("[intor-translator] displayName type is required");
194
+ }
195
+ return getDisplayNames(
196
+ getLocale(),
197
+ resolvedOptions
198
+ ).of(value);
199
+ },
200
+ plural(value, options) {
201
+ return getPluralRules(getLocale(), {
202
+ ...formatDefaults?.plural,
203
+ ...options
204
+ }).select(value);
205
+ }
206
+ };
207
+ }
208
+
53
209
  // src/shared/utils/resolve-candidate-locales.ts
54
210
  var resolveCandidateLocales = (locale, fallbackLocalesMap) => {
55
211
  const fallbacks = fallbackLocalesMap?.[locale] || [];
@@ -266,14 +422,27 @@ var CoreTranslator = class extends BaseTranslator {
266
422
  [...DEFAULT_HOOKS],
267
423
  { name: "Intor Translator" }
268
424
  );
425
+ /** Locale-aware formatting helpers. */
426
+ format;
269
427
  constructor(options) {
270
- const { locale, messages, isLoading, hooks, ...translateConfig } = options;
428
+ const {
429
+ locale,
430
+ messages,
431
+ isLoading,
432
+ hooks,
433
+ formatDefaults,
434
+ ...translateConfig
435
+ } = options;
271
436
  super({
272
437
  locale,
273
438
  ...messages !== void 0 && { messages },
274
439
  ...isLoading !== void 0 && { isLoading }
275
440
  });
276
441
  this.translateConfig = translateConfig;
442
+ this.format = createFormatter({
443
+ getLocale: () => this.locale,
444
+ ...formatDefaults !== void 0 && { formatDefaults }
445
+ });
277
446
  if (hooks) for (const hook of hooks) this.use(hook);
278
447
  }
279
448
  /** Registers a pipeline hook. */
@@ -328,6 +497,8 @@ var ScopeTranslator = class extends CoreTranslator {
328
497
  /** Create a scoped translator with a prefix key for resolving nested message paths. */
329
498
  scoped(preKey) {
330
499
  return {
500
+ /** Locale-aware formatting helpers. */
501
+ format: this.format,
331
502
  /** Checks whether a translation key exists. */
332
503
  hasKey: (key, targetLocale) => {
333
504
  const fullKey = getFullKey(preKey, key);