@mmstack/translate 20.5.10 → 20.5.12

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/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import * as i0 from '@angular/core';
2
- import { Signal, WritableSignal, Provider } from '@angular/core';
1
+ import * as _angular_core from '@angular/core';
2
+ import { Signal, Provider, WritableSignal } from '@angular/core';
3
+ import * as _mmstack_translate from '@mmstack/translate';
3
4
  import { ResolveFn, ActivatedRouteSnapshot, CanMatchFn } from '@angular/router';
4
5
  import * as _formatjs_intl from '@formatjs/intl';
5
6
  import { IntlConfig } from '@formatjs/intl';
@@ -23,7 +24,28 @@ type extractParams<T extends string> = T extends `${infer _Start}{${infer Var}}$
23
24
  type mergeParams<TExtracted extends [string, any]> = {
24
25
  [K in TExtracted as K[0]]: K[1];
25
26
  };
26
- type flattenParams<TKey extends string, TVal> = TVal extends UnknownStringKeyObject ? inferParamTupples<TVal, `${TKey}.`> : TVal extends string ? extractParams<TVal> extends never ? [TKey] : [TKey, mergeParams<extractParams<TVal>>] : never;
27
+ declare const PARAM_BRAND: unique symbol;
28
+ /**
29
+ * Branded string type produced by `withParams<P>(message)`. The brand carries
30
+ * both the declared parameter shape `P` and the original literal message `S` —
31
+ * the literal lives inside the brand (not just on the intersection) so the
32
+ * inference machinery can recover it without going through template-literal
33
+ * pattern matching on a branded intersection (which widens `infer` slots to
34
+ * `string` and breaks auto-extraction). Module-local `unique symbol`, so the
35
+ * brand is not constructible outside this package.
36
+ */
37
+ type WithParams<P extends Record<string, unknown>, S extends string = string> = S & {
38
+ readonly [PARAM_BRAND]: {
39
+ params: P;
40
+ literal: S;
41
+ };
42
+ };
43
+ type flattenParams<TKey extends string, TVal> = TVal extends {
44
+ readonly [PARAM_BRAND]: {
45
+ params: infer P;
46
+ literal: infer S extends string;
47
+ };
48
+ } ? P extends Record<string, unknown> ? extractParams<S> extends never ? [TKey, P] : [TKey, Omit<mergeParams<extractParams<S>>, keyof P> & P] : [TKey] : TVal extends UnknownStringKeyObject ? inferParamTupples<TVal, `${TKey}.`> : TVal extends string ? extractParams<TVal> extends never ? [TKey] : [TKey, mergeParams<extractParams<TVal>>] : never;
27
49
  type inferParamTupples<T extends UnknownStringKeyObject, TPrefix extends string = ''> = Simplify<{
28
50
  [K in keyof T]: K extends string ? flattenParams<`${TPrefix}${K}`, T[K]> : never;
29
51
  }[keyof T]>;
@@ -35,7 +57,9 @@ type TypeEnsuringAllPlaceholders<PlaceholdersUnion extends string> = StringConta
35
57
  type extractParamString<T extends string> = T extends `${infer _Start}{${infer Var}}${infer End}` ? Var extends `${infer VarName},${string}` ? `{${VarName}, ${string}}` | extractParamString<End> : `{${Var}}` | extractParamString<End> : never;
36
58
  type inferParamsFromValue<V extends string> = extractParamString<V> extends never ? string : TypeEnsuringAllPlaceholders<extractParamString<V>>;
37
59
  type inferTranslationShape<T extends UnknownStringKeyObject> = {
38
- [K in keyof T]: T[K] extends UnknownStringKeyObject ? inferTranslationShape<T[K]> : T[K] extends string ? inferParamsFromValue<T[K]> : never;
60
+ [K in keyof T]: T[K] extends {
61
+ readonly [PARAM_BRAND]: any;
62
+ } ? string : T[K] extends UnknownStringKeyObject ? inferTranslationShape<T[K]> : T[K] extends string ? inferParamsFromValue<T[K]> : never;
39
63
  };
40
64
 
41
65
  declare const INTERNAL_SYMBOL: unique symbol;
@@ -67,7 +91,48 @@ type TranslationNamespace<TNS extends string, T extends CompiledTranslation<Unkn
67
91
  };
68
92
  declare function createNamespace<const T extends UnknownStringKeyObject, TNS extends string>(ns: TNS, translation: T): TranslationNamespace<TNS, CompiledTranslation<T, TNS, string>, inferTranslationShape<T>>;
69
93
 
70
- declare const FORMAT_PRESETS: Record<string, Intl.DateTimeFormatOptions>;
94
+ declare const FORMAT_PRESETS: {
95
+ short: {
96
+ dateStyle: "short";
97
+ timeStyle: "short";
98
+ };
99
+ medium: {
100
+ dateStyle: "medium";
101
+ timeStyle: "medium";
102
+ };
103
+ long: {
104
+ dateStyle: "long";
105
+ timeStyle: "long";
106
+ };
107
+ full: {
108
+ dateStyle: "full";
109
+ timeStyle: "full";
110
+ };
111
+ shortDate: {
112
+ dateStyle: "short";
113
+ };
114
+ mediumDate: {
115
+ dateStyle: "medium";
116
+ };
117
+ longDate: {
118
+ dateStyle: "long";
119
+ };
120
+ fullDate: {
121
+ dateStyle: "full";
122
+ };
123
+ shortTime: {
124
+ timeStyle: "short";
125
+ };
126
+ mediumTime: {
127
+ timeStyle: "medium";
128
+ };
129
+ longTime: {
130
+ timeStyle: "long";
131
+ };
132
+ fullTime: {
133
+ timeStyle: "full";
134
+ };
135
+ };
71
136
  type DateFormat = keyof typeof FORMAT_PRESETS;
72
137
  /**
73
138
  * Supported date inputs
@@ -85,21 +150,43 @@ type FormatDateOptions = {
85
150
  * Format to use for formatting
86
151
  * @default 'medium'
87
152
  */
88
- format?: DateFormat;
153
+ format?: DateFormat | Intl.DateTimeFormatOptions;
89
154
  /**
90
- * Locale to use for formatting, opts out to dynamic locale changes
155
+ * Locale to use for formatting
91
156
  */
157
+ locale: string;
158
+ };
159
+ /**
160
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
161
+ */
162
+ type UnsafeFormatDateOptions = Omit<FormatDateOptions, 'locale'> & {
163
+ /** Optional locale string falling back to the legacy global signal */
92
164
  locale?: string;
93
165
  };
94
166
  /**
95
- * Format a date using the current or provided locale & timezone
96
- * By default it is reactive to the global dynamic locale, works best when wrapped in a computed() if you need to react to locale changes
97
- *
98
- * @param date - Date to format
99
- * @param opt - Options for formatting
100
- * @returns Formatted date string
167
+ * @example formatDate(this.date, this.locale)
168
+ */
169
+ declare function formatDate(date: SupportedDateInput | Signal<SupportedDateInput>, locale: string | Signal<string>): string;
170
+ /**
171
+ * @example formatDate(this.date, { locale: 'sl-SI', format: 'shortDate' })
172
+ */
173
+ declare function formatDate(date: SupportedDateInput | Signal<SupportedDateInput>, opt: FormatDateOptions | Signal<FormatDateOptions>): string;
174
+ /**
175
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
176
+ * Use `injectFormatDate()` instead, or pass locale explicitly.
177
+ * @example formatDate(this.date)
178
+ */
179
+ declare function formatDate(date: SupportedDateInput | Signal<SupportedDateInput>, opt?: UnsafeFormatDateOptions | Signal<UnsafeFormatDateOptions>): string;
180
+ declare const provideFormatDateDefaults: (valueOrFn: Omit<Partial<FormatDateOptions>, "locale"> | (() => Omit<Partial<FormatDateOptions>, "locale"> | Signal<Omit<Partial<FormatDateOptions>, "locale">>)) => _angular_core.Provider;
181
+
182
+ /**
183
+ * Inject a context-safe date formatting function tied to the current injector.
184
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
185
+ * @example
186
+ * const formatDate = injectFormatDate();
187
+ * readonly displayDate = computed(() => formatDate(this.date()));
101
188
  */
102
- declare function formatDate(date: SupportedDateInput | Signal<SupportedDateInput>, opt?: FormatDateOptions | Signal<FormatDateOptions>): string;
189
+ declare function injectFormatDate(): (date: SupportedDateInput | Signal<SupportedDateInput>, optOrLocale?: Partial<FormatDateOptions> | Signal<Partial<FormatDateOptions>> | string | Signal<string>) => string;
103
190
 
104
191
  /**
105
192
  * Options for formatting a display name
@@ -107,24 +194,46 @@ declare function formatDate(date: SupportedDateInput | Signal<SupportedDateInput
107
194
  type FormatDisplayNameOptions = {
108
195
  /**
109
196
  * The display style for the result set
197
+ * @default 'long'
110
198
  */
111
- style: Intl.RelativeTimeFormatStyle;
199
+ style?: Intl.RelativeTimeFormatStyle;
112
200
  /**
113
- * Locale to use for formatting, opts out to dynamic locale changes
201
+ * Locale to use for formatting
114
202
  */
203
+ locale: string;
204
+ };
205
+ /**
206
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
207
+ */
208
+ type UnsafeFormatDisplayNameOptions = Omit<FormatDisplayNameOptions, 'locale'> & {
209
+ /** Optional locale string falling back to the legacy global signal */
115
210
  locale?: string;
116
211
  };
117
212
  type SupportedCode = string | null | undefined;
118
213
  /**
119
- * Format a display name using the current or provided locale
120
- * By default it is reactive to the global dynamic locale, works best when wrapped in a computed() if you need to react to locale changes
121
- *
122
- * @param value - The code to format
123
- * @param type - The type of display name to format
124
- * @param opt - Options for formatting
125
- * @returns Formatted display name string
214
+ * @example formatDisplayName(this.value, 'region', this.locale)
215
+ */
216
+ declare function formatDisplayName(value: SupportedCode | Signal<SupportedCode>, type: Intl.DisplayNamesType | Signal<Intl.DisplayNamesType>, locale: string | Signal<string>): string;
217
+ /**
218
+ * @example formatDisplayName(this.value, 'region', {locale: 'en-US', style: 'long'})
219
+ */
220
+ declare function formatDisplayName(value: SupportedCode | Signal<SupportedCode>, type: Intl.DisplayNamesType | Signal<Intl.DisplayNamesType>, opt: FormatDisplayNameOptions | Signal<FormatDisplayNameOptions>): string;
221
+ /**
222
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
223
+ * Use `injectFormatDisplayName()` instead, or pass locale explicitly.
224
+ * @example formatDisplayName(this.value)
225
+ */
226
+ declare function formatDisplayName(value: SupportedCode | Signal<SupportedCode>, type: Intl.DisplayNamesType | Signal<Intl.DisplayNamesType>, opt?: UnsafeFormatDisplayNameOptions | Signal<UnsafeFormatDisplayNameOptions>): string;
227
+ declare const provideFormatDisplayNameDefaults: (valueOrFn: Omit<Partial<FormatDisplayNameOptions>, "locale"> | (() => Omit<Partial<FormatDisplayNameOptions>, "locale"> | Signal<Omit<Partial<FormatDisplayNameOptions>, "locale">>)) => _angular_core.Provider;
228
+
229
+ /**
230
+ * Inject a context-safe date formatting function tied to the current injector.
231
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
232
+ * @example
233
+ * const formatDisplayName = injectFormatDisplayName();
234
+ * readonly region = computed(() => formatDisplayName('US', 'region'));
126
235
  */
127
- declare function formatDisplayName(value: SupportedCode | Signal<SupportedCode>, type: Intl.DisplayNamesType | Signal<Intl.DisplayNamesType>, opt?: FormatDisplayNameOptions | Signal<FormatDisplayNameOptions>): string;
236
+ declare function injectFormatDisplayName(): (value: SupportedCode | Signal<SupportedCode>, type: Intl.DisplayNamesType | Signal<Intl.DisplayNamesType>, localeOrOpt?: FormatDisplayNameOptions | Signal<FormatDisplayNameOptions> | string | Signal<string>) => string;
128
237
 
129
238
  type ListType = 'conjunction' | 'disjunction' | 'unit';
130
239
  type ListStyle = 'long' | 'short' | 'narrow';
@@ -135,26 +244,50 @@ type SupportedListInput = string[] | null | undefined;
135
244
  type FormatListOptions = {
136
245
  /**
137
246
  * The type of list to format
247
+ * @default 'conjunction'
138
248
  */
139
249
  type?: ListType;
140
250
  /**
141
251
  * The style of list to format
252
+ * @default 'long'
142
253
  */
143
254
  style?: ListStyle;
144
255
  /**
145
- * Locale to use for formatting, opts out to dynamic locale changes
256
+ * Locale to use for formatting
146
257
  */
258
+ locale: string;
259
+ };
260
+ /**
261
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
262
+ */
263
+ type UnsafeFormatListOptions = Omit<FormatListOptions, 'locale'> & {
264
+ /** Optional locale string falling back to the legacy global signal */
147
265
  locale?: string;
148
266
  };
149
267
  /**
150
- * Format a list using the current or provided locale
151
- * By default it is reactive to the global dynamic locale, works best when wrapped in a computed() if you need to react to locale changes
152
- *
153
- * @param value - The list to format
154
- * @param opt - Options for formatting
155
- * @returns Formatted list string
268
+ * @example formatList(this.items, this.locale)
156
269
  */
157
- declare function formatList(value: SupportedListInput | Signal<SupportedListInput>, opt?: FormatListOptions | Signal<FormatListOptions>): string;
270
+ declare function formatList(value: SupportedListInput | Signal<SupportedListInput>, locale: string | Signal<string>): string;
271
+ /**
272
+ * @example formatList(this.items, { locale: 'sl-SI', type: 'disjunction' })
273
+ */
274
+ declare function formatList(value: SupportedListInput | Signal<SupportedListInput>, opt: FormatListOptions | Signal<FormatListOptions>): string;
275
+ /**
276
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
277
+ * Use `injectFormatList()` instead, or pass locale explicitly.
278
+ * @example formatList(this.items)
279
+ */
280
+ declare function formatList(value: SupportedListInput | Signal<SupportedListInput>, opt?: UnsafeFormatListOptions | Signal<UnsafeFormatListOptions>): string;
281
+ declare const provideFormatListDefaults: (valueOrFn: Omit<Partial<FormatListOptions>, "locale"> | (() => Omit<Partial<FormatListOptions>, "locale"> | Signal<Omit<Partial<FormatListOptions>, "locale">>)) => _angular_core.Provider;
282
+
283
+ /**
284
+ * Inject a context-safe list formatting function tied to the current injector.
285
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
286
+ * @example
287
+ * const formatList = injectFormatList();
288
+ * readonly displayList = computed(() => formatList(this.items()));
289
+ */
290
+ declare function injectFormatList(): (value: SupportedListInput | Signal<SupportedListInput>, optOrLocale?: Partial<FormatListOptions> | Signal<Partial<FormatListOptions>> | string | Signal<string>) => string;
158
291
 
159
292
  type NumberNotation = 'standard' | 'scientific' | 'engineering' | 'compact';
160
293
  type SupportedNumberValue = number | null | undefined;
@@ -164,6 +297,7 @@ type SupportedNumberValue = number | null | undefined;
164
297
  type FormatNumberOptions = {
165
298
  /**
166
299
  * The notation to use for formatting
300
+ * @default 'standard'
167
301
  */
168
302
  notation?: NumberNotation;
169
303
  /**
@@ -176,27 +310,50 @@ type FormatNumberOptions = {
176
310
  maxFractionDigits?: number;
177
311
  /**
178
312
  * Whether to use grouping
313
+ * @default true
179
314
  */
180
315
  useGrouping?: boolean;
181
- /**
182
- * Locale to use for formatting, opts out to dynamic locale changes
183
- */
184
- locale?: string;
185
316
  /**
186
317
  * If the number is not a valid number, return formatted 0. By default formatter returns an empty string
187
318
  * @default false
188
319
  */
189
320
  fallbackToZero?: boolean;
321
+ /**
322
+ * Locale to use for formatting
323
+ */
324
+ locale: string;
190
325
  };
191
326
  /**
192
- * Format a number using the current or provided locale
193
- * By default it is reactive to the global dynamic locale, works best when wrapped in a computed() if you need to react to locale changes
194
- *
195
- * @param number - Number to format
196
- * @param opt - Options for formatting
197
- * @returns Formatted number string
327
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
328
+ */
329
+ type UnsafeFormatNumberOptions = Omit<FormatNumberOptions, 'locale'> & {
330
+ /** Optional locale string falling back to the legacy global signal */
331
+ locale?: string;
332
+ };
333
+ /**
334
+ * @example formatNumber(this.value, this.locale)
335
+ */
336
+ declare function formatNumber(value: SupportedNumberValue | Signal<SupportedNumberValue>, locale: string | Signal<string>): string;
337
+ /**
338
+ * @example formatNumber(this.value, { locale: 'de-DE', notation: 'compact' })
339
+ */
340
+ declare function formatNumber(value: SupportedNumberValue | Signal<SupportedNumberValue>, opt: FormatNumberOptions | Signal<FormatNumberOptions>): string;
341
+ /**
342
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
343
+ * Use `injectFormatNumber()` instead, or pass locale explicitly.
344
+ * @example formatNumber(this.value)
345
+ */
346
+ declare function formatNumber(value: SupportedNumberValue | Signal<SupportedNumberValue>, opt?: UnsafeFormatNumberOptions | Signal<UnsafeFormatNumberOptions>): string;
347
+ declare const provideFormatNumberDefaults: (valueOrFn: Omit<Partial<FormatNumberOptions>, "locale"> | (() => Omit<Partial<FormatNumberOptions>, "locale"> | Signal<Omit<Partial<FormatNumberOptions>, "locale">>)) => _angular_core.Provider;
348
+
349
+ /**
350
+ * Inject a context-safe number formatting function tied to the current injector.
351
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
352
+ * @example
353
+ * const formatNumber = injectFormatNumber();
354
+ * readonly display = computed(() => formatNumber(this.value()));
198
355
  */
199
- declare function formatNumber(value: SupportedNumberValue | Signal<SupportedNumberValue>, opt?: FormatNumberOptions | Signal<FormatNumberOptions>): string;
356
+ declare function injectFormatNumber(): (value: SupportedNumberValue | Signal<SupportedNumberValue>, optOrLocale?: Partial<FormatNumberOptions> | Signal<Partial<FormatNumberOptions>> | string | Signal<string>) => string;
200
357
  /**
201
358
  * Options for formatting a percentage value
202
359
  */
@@ -209,42 +366,97 @@ type FormatPercentOptions = {
209
366
  * Maximum number of fraction digits to use
210
367
  */
211
368
  maxFractionDigits?: number;
212
- /**
213
- * Locale to use for formatting, opts out to dynamic locale changes
214
- */
215
- locale?: string;
216
369
  /**
217
370
  * If the number is not a valid number, return formatted 0. By default formatter returns an empty string
218
371
  * @default false
219
372
  */
220
373
  fallbackToZero?: boolean;
374
+ /**
375
+ * Locale to use for formatting
376
+ */
377
+ locale: string;
221
378
  };
222
379
  /**
223
- * Format a percentage using the current or provided locale
224
- * By default it is reactive to the global dynamic locale, works best when wrapped in a computed() if you need to react to locale changes
225
- *
226
- * @param number - Number to format
227
- * @param opt - Options for formatting
228
- * @returns Formatted percentage string
380
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
229
381
  */
230
- declare function formatPercent(value: SupportedNumberValue | Signal<SupportedNumberValue>, opt?: FormatPercentOptions | Signal<FormatPercentOptions>): string;
382
+ type UnsafeFormatPercentOptions = Omit<FormatPercentOptions, 'locale'> & {
383
+ /** Optional locale string falling back to the legacy global signal */
384
+ locale?: string;
385
+ };
386
+ /**
387
+ * @example formatPercent(this.value, this.locale)
388
+ */
389
+ declare function formatPercent(value: SupportedNumberValue | Signal<SupportedNumberValue>, locale: string | Signal<string>): string;
390
+ /**
391
+ * @example formatPercent(this.value, { locale: 'de-DE', maxFractionDigits: 2 })
392
+ */
393
+ declare function formatPercent(value: SupportedNumberValue | Signal<SupportedNumberValue>, opt: FormatPercentOptions | Signal<FormatPercentOptions>): string;
394
+ /**
395
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
396
+ * Use `injectFormatPercent()` instead, or pass locale explicitly.
397
+ * @example formatPercent(this.value)
398
+ */
399
+ declare function formatPercent(value: SupportedNumberValue | Signal<SupportedNumberValue>, opt?: UnsafeFormatPercentOptions | Signal<UnsafeFormatPercentOptions>): string;
400
+ declare const provideFormatPercentDefaults: (valueOrFn: Omit<Partial<FormatPercentOptions>, "locale"> | (() => Omit<Partial<FormatPercentOptions>, "locale"> | Signal<Omit<Partial<FormatPercentOptions>, "locale">>)) => _angular_core.Provider;
401
+
402
+ /**
403
+ * Inject a context-safe percent formatting function tied to the current injector.
404
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
405
+ */
406
+ declare function injectFormatPercent(): (value: SupportedNumberValue | Signal<SupportedNumberValue>, optOrLocale?: Partial<FormatPercentOptions> | Signal<Partial<FormatPercentOptions>> | string | Signal<string>) => string;
231
407
  type CurrencyDisplay = 'symbol' | 'narrowSymbol' | 'code' | 'name';
232
408
  /**
233
409
  * Options for formatting a currency
234
410
  */
235
411
  type FormatCurrencyOptions = {
236
- display?: CurrencyDisplay;
237
412
  /**
238
- * Locale to use for formatting, opts out to dynamic locale changes
413
+ * The display type for the currency format
414
+ * @default 'symbol'
239
415
  */
240
- locale?: string;
416
+ display?: CurrencyDisplay;
241
417
  /**
242
418
  * If the number is not a valid number, return formatted 0. By default formatter returns an empty string
243
419
  * @default false
244
420
  */
245
421
  fallbackToZero?: boolean;
422
+ /**
423
+ * Locale to use for formatting
424
+ */
425
+ locale: string;
246
426
  };
247
- declare function formatCurrency(value: SupportedNumberValue | Signal<SupportedNumberValue>, currency: string | Signal<string>, opt?: FormatCurrencyOptions | Signal<FormatCurrencyOptions>): string;
427
+ /**
428
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
429
+ */
430
+ type UnsafeFormatCurrencyOptions = Omit<FormatCurrencyOptions, 'locale'> & {
431
+ /** Optional locale string falling back to the legacy global signal */
432
+ locale?: string;
433
+ };
434
+ /**
435
+ * @example formatCurrency(this.value, 'USD', this.locale)
436
+ */
437
+ declare function formatCurrency(value: SupportedNumberValue | Signal<SupportedNumberValue>, currency: string | Signal<string>, locale: string | Signal<string>): string;
438
+ /**
439
+ * @example formatCurrency(this.value, 'EUR', { locale: 'de-DE', display: 'code' })
440
+ */
441
+ declare function formatCurrency(value: SupportedNumberValue | Signal<SupportedNumberValue>, currency: string | Signal<string>, opt: FormatCurrencyOptions | Signal<FormatCurrencyOptions>): string;
442
+ /**
443
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
444
+ * Use `injectFormatCurrency()` instead, or pass locale explicitly.
445
+ * @example formatCurrency(this.value, 'USD')
446
+ */
447
+ declare function formatCurrency(value: SupportedNumberValue | Signal<SupportedNumberValue>, currency: string | Signal<string>, opt?: UnsafeFormatCurrencyOptions | Signal<UnsafeFormatCurrencyOptions>): string;
448
+ declare const provideFormatCurrencyDefaults: (valueOrFn: Omit<Partial<FormatCurrencyOptions>, "locale"> | (() => Omit<Partial<FormatCurrencyOptions>, "locale"> | Signal<Omit<Partial<FormatCurrencyOptions>, "locale">>)) => _angular_core.Provider;
449
+
450
+ /**
451
+ * Inject a context-safe currency formatting function tied to the current injector.
452
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
453
+ */
454
+ declare function injectFormatCurrency(): (value: SupportedNumberValue | Signal<SupportedNumberValue>, currency: string | Signal<string>, optOrLocale?: Partial<FormatCurrencyOptions> | Signal<Partial<FormatCurrencyOptions>> | string | Signal<string>) => string;
455
+
456
+ declare function createFormatterProvider<T extends {
457
+ locale: string;
458
+ }>(formatterName: string, libraryDefaults: Omit<T, 'locale'>, nonLocaleEqual: (a: Omit<T, 'locale'>, b: Omit<T, 'locale'>) => boolean): readonly [(valueOrFn: Omit<Partial<T>, "locale"> | (() => Omit<Partial<T>, "locale"> | Signal<Omit<Partial<T>, "locale">>)) => Provider, () => Signal<T>];
459
+ type inferProvideParameter<T extends ReturnType<typeof createFormatterProvider>[0]> = Parameters<T>[0];
248
460
 
249
461
  /**
250
462
  * Options for formatting a relative time value
@@ -261,22 +473,63 @@ type FormatRelativeTimeOptions = {
261
473
  */
262
474
  numeric?: Intl.RelativeTimeFormatNumeric;
263
475
  /**
264
- * Locale to use for formatting, opts out to dynamic locale changes
476
+ * Locale to use for formatting
265
477
  */
478
+ locale: string;
479
+ };
480
+ /**
481
+ * @deprecated UNSAFE FOR SSR/EDGE. Omiting the locale property forces a fallback to a process-level global singleton.
482
+ */
483
+ type UnsafeFormatRelativeTimeOptions = Omit<FormatRelativeTimeOptions, 'locale'> & {
484
+ /** Optional locale string falling back to the legacy global signal */
266
485
  locale?: string;
267
486
  };
268
487
  type RelativeTimeUnit = Intl.RelativeTimeFormatUnit;
269
488
  type SupportedRelativeTimeInput = number | null | undefined;
270
489
  /**
271
- * Format a relative time using the current or provided locale
272
- * By default it is reactive to the global dynamic locale, works best when wrapped in a computed() if you need to react to locale changes
273
- *
274
- * @param value - The numeric value to use in the relative time internationalization message
275
- * @param unit - The unit to use in the relative time internationalization message
276
- * @param opt - Options for formatting
277
- * @returns Formatted relative time string
490
+ * @example formatRelativeTime(this.value, this.unit, this.locale)
491
+ */
492
+ declare function formatRelativeTime(value: SupportedRelativeTimeInput | Signal<SupportedRelativeTimeInput>, unit: RelativeTimeUnit | Signal<RelativeTimeUnit>, locale: string | Signal<string>): string;
493
+ /**
494
+ * @example formatRelativeTime(this.value, 'day', { locale: 'sl-SI', numeric: 'auto' })
495
+ */
496
+ declare function formatRelativeTime(value: SupportedRelativeTimeInput | Signal<SupportedRelativeTimeInput>, unit: RelativeTimeUnit | Signal<RelativeTimeUnit>, opt: FormatRelativeTimeOptions | Signal<FormatRelativeTimeOptions>): string;
497
+ /**
498
+ * @deprecated UNSAFE FOR SSR/EDGE. This signature reads from a process-level global singleton, will be fully removed when Angular 23 drops
499
+ * Use `injectFormatRelativeTime()` instead, or pass locale explicitly.
500
+ * @example formatRelativeTime(this.value, 'day')
278
501
  */
279
- declare function formatRelativeTime(value: SupportedRelativeTimeInput | Signal<SupportedRelativeTimeInput>, unit: RelativeTimeUnit | Signal<RelativeTimeUnit>, opt?: FormatRelativeTimeOptions | Signal<FormatRelativeTimeOptions>): string;
502
+ declare function formatRelativeTime(value: SupportedRelativeTimeInput | Signal<SupportedRelativeTimeInput>, unit: RelativeTimeUnit | Signal<RelativeTimeUnit>, opt?: UnsafeFormatRelativeTimeOptions | Signal<UnsafeFormatRelativeTimeOptions>): string;
503
+ declare const provideFormatRelativeTimeDefaults: (valueOrFn: Omit<Partial<FormatRelativeTimeOptions>, "locale"> | (() => Omit<Partial<FormatRelativeTimeOptions>, "locale"> | Signal<Omit<Partial<FormatRelativeTimeOptions>, "locale">>)) => _angular_core.Provider;
504
+
505
+ /**
506
+ * Inject a context-safe relative time formatting function tied to the current injector.
507
+ * Uses the libraries locale signal & provided default configuration to react to locale/config changes
508
+ * @example
509
+ * const formatRelativeTime = injectFormatRelativeTime();
510
+ * readonly relativeAge = computed(() => formatRelativeTime(this.delta(), 'day'));
511
+ */
512
+ declare function injectFormatRelativeTime(): (value: SupportedRelativeTimeInput | Signal<SupportedRelativeTimeInput>, unit: RelativeTimeUnit | Signal<RelativeTimeUnit>, optOrLocale?: Partial<FormatRelativeTimeOptions> | Signal<Partial<FormatRelativeTimeOptions>> | string | Signal<string>) => string;
513
+
514
+ type FormatDefaults = {
515
+ date?: inferProvideParameter<typeof provideFormatDateDefaults>;
516
+ displayName?: inferProvideParameter<typeof provideFormatDisplayNameDefaults>;
517
+ list?: inferProvideParameter<typeof provideFormatListDefaults>;
518
+ relativeTime?: inferProvideParameter<typeof provideFormatRelativeTimeDefaults>;
519
+ number?: inferProvideParameter<typeof provideFormatNumberDefaults>;
520
+ percent?: inferProvideParameter<typeof provideFormatPercentDefaults>;
521
+ currency?: inferProvideParameter<typeof provideFormatCurrencyDefaults>;
522
+ };
523
+ declare function provideFormatDefaults(cfg: FormatDefaults): Provider[];
524
+ declare function injectFormatters(): {
525
+ date: (date: _mmstack_translate.SupportedDateInput | _angular_core.Signal<_mmstack_translate.SupportedDateInput>, optOrLocale?: Partial<_mmstack_translate.FormatDateOptions> | _angular_core.Signal<Partial<_mmstack_translate.FormatDateOptions>> | string | _angular_core.Signal<string>) => string;
526
+ displayName: (value: (string | null | undefined) | _angular_core.Signal<string | null | undefined>, type: Intl.DisplayNamesType | _angular_core.Signal<Intl.DisplayNamesType>, localeOrOpt?: _mmstack_translate.FormatDisplayNameOptions | _angular_core.Signal<_mmstack_translate.FormatDisplayNameOptions> | string | _angular_core.Signal<string>) => string;
527
+ list: (value: _mmstack_translate.SupportedListInput | _angular_core.Signal<_mmstack_translate.SupportedListInput>, optOrLocale?: Partial<_mmstack_translate.FormatListOptions> | _angular_core.Signal<Partial<_mmstack_translate.FormatListOptions>> | string | _angular_core.Signal<string>) => string;
528
+ relativeTime: (value: (number | null | undefined) | _angular_core.Signal<number | null | undefined>, unit: _mmstack_translate.RelativeTimeUnit | _angular_core.Signal<_mmstack_translate.RelativeTimeUnit>, optOrLocale?: Partial<_mmstack_translate.FormatRelativeTimeOptions> | _angular_core.Signal<Partial<_mmstack_translate.FormatRelativeTimeOptions>> | string | _angular_core.Signal<string>) => string;
529
+ number: (value: (number | null | undefined) | _angular_core.Signal<number | null | undefined>, optOrLocale?: Partial<_mmstack_translate.FormatNumberOptions> | _angular_core.Signal<Partial<_mmstack_translate.FormatNumberOptions>> | string | _angular_core.Signal<string>) => string;
530
+ percent: (value: (number | null | undefined) | _angular_core.Signal<number | null | undefined>, optOrLocale?: Partial<_mmstack_translate.FormatPercentOptions> | _angular_core.Signal<Partial<_mmstack_translate.FormatPercentOptions>> | string | _angular_core.Signal<string>) => string;
531
+ currency: (value: (number | null | undefined) | _angular_core.Signal<number | null | undefined>, currency: string | _angular_core.Signal<string>, optOrLocale?: Partial<_mmstack_translate.FormatCurrencyOptions> | _angular_core.Signal<Partial<_mmstack_translate.FormatCurrencyOptions>> | string | _angular_core.Signal<string>) => string;
532
+ };
280
533
 
281
534
  type BaseConfig = Omit<IntlConfig, 'locale' | 'messages'> & {
282
535
  /** Checks next locale is in provided array before switching locales */
@@ -326,6 +579,24 @@ declare function injectIntl(): Signal<_formatjs_intl.IntlShape<string>>;
326
579
  declare function injectDynamicLocale(): WritableSignal<string> & {
327
580
  isLoading: Signal<boolean>;
328
581
  };
582
+ /**
583
+ * Power-user escape hatch for adding translations imperatively (e.g. content
584
+ * loaded from a remote API after bootstrap). Returns a function that registers
585
+ * a flat per-locale map of keys under a given namespace
586
+ *
587
+ * Pair with {@link injectUnsafeT} to read the added keys without compile-time
588
+ * constraints.
589
+ *
590
+ * @example
591
+ * ```ts
592
+ * const addTranslations = injectAddTranslations();
593
+ * addTranslations('remote', {
594
+ * 'en-US': { greeting: 'Hi {name}' },
595
+ * 'sl-SI': { greeting: 'Zdravo {name}' },
596
+ * });
597
+ * ```
598
+ */
599
+ declare function injectAddTranslations(): (ns: string, translations: Record<string, Record<string, string>>) => void;
329
600
 
330
601
  type TFunction<TMap extends AnyStringRecord> = <TKey extends keyof TMap & string>(key: TKey, ...args: TMap[TKey] extends void ? [] : [TMap[TKey]]) => string;
331
602
  type SignalTFunction<TMap extends AnyStringRecord> = <TKey extends keyof TMap & string>(key: TKey, ...args: TMap[TKey] extends void ? [] : [() => TMap[TKey]]) => Signal<string>;
@@ -348,6 +619,23 @@ declare function registerRemoteNamespace<TNS extends string>(ns: TNS, defaultTra
348
619
  injectNamespaceT: () => UntypedTFunction<TNS>;
349
620
  resolveNamespaceTranslation: ResolveFn<void>;
350
621
  };
622
+ /**
623
+ * Power-user escape hatch that returns a fully untyped translation function.
624
+ * Intended for use alongside {@link injectAddTranslations} when translations
625
+ * are added imperatively (e.g. from a remote API), or for cross-namespace
626
+ * lookups where the typed API would be impractical.
627
+ *
628
+ * @example
629
+ * ```ts
630
+ * const t = injectUnsafeT();
631
+ * t('any.namespace.key', { name: 'Alice', count: 3 });
632
+ * const sig = t.asSignal('any.namespace.key', () => ({ name: name() }));
633
+ * ```
634
+ */
635
+ declare function injectUnsafeT(): {
636
+ (key: string, params?: Record<string, string | number>): string;
637
+ asSignal(key: string, params?: () => Record<string, string | number>): Signal<string>;
638
+ };
351
639
 
352
640
  declare function injectResolveParamLocale(snapshot: ActivatedRouteSnapshot): string;
353
641
 
@@ -426,10 +714,10 @@ declare function provideMockTranslations(options?: MockTranslationOptions): Prov
426
714
 
427
715
  declare abstract class Translate<TInput extends string, T extends CompiledTranslation<UnknownStringKeyObject, string>, TMap extends inferCompiledTranslationMap<T> = inferCompiledTranslationMap<T>, TKey extends TInput & keyof TMap & string = TInput & keyof TMap & string> {
428
716
  private readonly t;
429
- readonly translate: i0.InputSignal<TMap[TKey] extends void ? TKey | [key: TKey] : [key: TKey, vars: TMap[TKey]]>;
717
+ readonly translate: _angular_core.InputSignal<TMap[TKey] extends void ? TKey | [key: TKey] : [key: TKey, vars: TMap[TKey]]>;
430
718
  constructor();
431
- static ɵfac: i0.ɵɵFactoryDeclaration<Translate<any, any, any, any>, never>;
432
- static ɵdir: i0.ɵɵDirectiveDeclaration<Translate<any, any, any, any>, never, never, { "translate": { "alias": "translate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
719
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<Translate<any, any, any, any>, never>;
720
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Translate<any, any, any, any>, never, never, { "translate": { "alias": "translate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
433
721
  }
434
722
 
435
723
  type TransformTFn<T extends CompiledTranslation<UnknownStringKeyObject, string>, TMap extends inferCompiledTranslationMap<T>> = <TKey extends keyof TMap & string>(key: TKey, ...args: TMap[TKey] extends void ? [locale?: string] : [TMap[TKey], locale?: string]) => string;
@@ -438,5 +726,30 @@ declare abstract class Translator<T extends CompiledTranslation<UnknownStringKey
438
726
  transform: TransformTFn<T, TMap>;
439
727
  }
440
728
 
441
- export { Translate, Translator, canMatchLocale, compileTranslation, createNamespace, formatCurrency, formatDate, formatDisplayName, formatList, formatNumber, formatPercent, formatRelativeTime, injectDynamicLocale, injectIntl, injectResolveParamLocale, injectSupportedLocales, provideIntlConfig, provideMockTranslations, registerNamespace, registerRemoteNamespace };
442
- export type { CompiledTranslation, FormatCurrencyOptions, FormatDateOptions, FormatDisplayNameOptions, FormatListOptions, FormatNumberOptions, FormatPercentOptions, FormatRelativeTimeOptions, RelativeTimeUnit, SupportedDateInput, SupportedListInput, inferCompiledTranslationMap, inferCompiledTranslationNamespace, inferCompiledTranslationShape, mergeTranslationMaps };
729
+ /**
730
+ * Power-user escape hatch for ICU messages whose parameters can't be inferred
731
+ * from the message string — typically variables nested inside `plural` /
732
+ * `select` / `selectordinal` arms, which the type-level extractor skips.
733
+ *
734
+ * Declared params are merged with auto-extracted ones; on key conflict, the
735
+ * declared params win. Non-default locales for a key wrapped with `withParams`
736
+ * may be plain strings — they don't need to repeat the wrapper.
737
+ *
738
+ * @example
739
+ * ```ts
740
+ * const ns = createNamespace('quote', {
741
+ * // auto-extracts `count`; `name` is declared explicitly because it
742
+ * // lives inside the plural arms and can't be inferred
743
+ * stats: withParams<{ name: string }>(
744
+ * '{count, plural, one {1 quote from {name}} other {# quotes from {name}}}',
745
+ * ),
746
+ * });
747
+ *
748
+ * // t inferred as: (key, { count: number; name: string }) => string
749
+ * t('quote.stats', { count: 3, name: 'Alice' });
750
+ * ```
751
+ */
752
+ declare function withParams<const P extends Record<string, unknown>, const S extends string = string>(message: S): WithParams<P, S>;
753
+
754
+ export { Translate, Translator, canMatchLocale, compileTranslation, createNamespace, formatCurrency, formatDate, formatDisplayName, formatList, formatNumber, formatPercent, formatRelativeTime, injectAddTranslations, injectDynamicLocale, injectFormatCurrency, injectFormatDate, injectFormatDisplayName, injectFormatList, injectFormatNumber, injectFormatPercent, injectFormatRelativeTime, injectFormatters, injectIntl, injectResolveParamLocale, injectSupportedLocales, injectUnsafeT, provideFormatCurrencyDefaults, provideFormatDateDefaults, provideFormatDefaults, provideFormatDisplayNameDefaults, provideFormatListDefaults, provideFormatNumberDefaults, provideFormatPercentDefaults, provideFormatRelativeTimeDefaults, provideIntlConfig, provideMockTranslations, registerNamespace, registerRemoteNamespace, withParams };
755
+ export type { CompiledTranslation, FormatCurrencyOptions, FormatDateOptions, FormatDisplayNameOptions, FormatListOptions, FormatNumberOptions, FormatPercentOptions, FormatRelativeTimeOptions, RelativeTimeUnit, SupportedDateInput, SupportedListInput, UnsafeFormatCurrencyOptions, UnsafeFormatDateOptions, UnsafeFormatDisplayNameOptions, UnsafeFormatListOptions, UnsafeFormatNumberOptions, UnsafeFormatPercentOptions, UnsafeFormatRelativeTimeOptions, inferCompiledTranslationMap, inferCompiledTranslationNamespace, inferCompiledTranslationShape, mergeTranslationMaps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/translate",
3
- "version": "20.5.10",
3
+ "version": "20.5.12",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "localize",