@coherent.js/i18n 1.1.2 → 2.0.0-rc.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/types/index.d.ts CHANGED
@@ -45,6 +45,17 @@ export interface TranslatorOptions {
45
45
  fallbackLocale?: string;
46
46
  /** Called instead of returning the key when a translation is missing */
47
47
  missingKeyHandler?: ((key: string, locale: string) => string) | null;
48
+ /**
49
+ * HTML-escape interpolated params (`&`, `<`, `>`, `"`, `'`) on every call;
50
+ * the translation template itself is never escaped. Defaults to `false`.
51
+ * Turn it on when translations are rendered through core's `html:`;
52
+ * `text:` is escaped by core and is the safe default sink.
53
+ */
54
+ escape?: boolean;
55
+ /**
56
+ * Placeholder delimiters, matched literally (not as regex). Merged with the
57
+ * defaults, so overriding one keeps the other.
58
+ */
48
59
  interpolation?: {
49
60
  /** Defaults to `'{{'` */
50
61
  prefix?: string;
@@ -54,6 +65,34 @@ export interface TranslatorOptions {
54
65
  [option: string]: unknown;
55
66
  }
56
67
 
68
+ /** Per-call options for {@link Translator.t}. */
69
+ export interface TranslateOptions {
70
+ /** Locale for this call only; defaults to the current locale */
71
+ locale?: string | null;
72
+ /** HTML-escape the interpolated params; defaults to the translator's `escape` option */
73
+ escape?: boolean;
74
+ }
75
+
76
+ /**
77
+ * A translator bound to one locale, returned by {@link Translator.forLocale}.
78
+ * Safe to use concurrently: it never reads or writes the shared
79
+ * `currentLocale`.
80
+ */
81
+ export interface LocaleTranslator {
82
+ /** The resolved locale this translator is bound to */
83
+ readonly locale: string;
84
+ /** Like {@link Translator.t}, defaulting to the bound locale */
85
+ t(
86
+ key: TranslationKey,
87
+ params?: TranslationParams | null,
88
+ localeOrOptions?: string | null | TranslateOptions
89
+ ): string;
90
+ /** Like {@link Translator.has}, defaulting to the bound locale */
91
+ has(key: TranslationKey, locale?: string | null): boolean;
92
+ /** The bound locale */
93
+ getLocale(): string;
94
+ }
95
+
57
96
  /**
58
97
  * Holds translations per locale and resolves keys with interpolation,
59
98
  * pluralization and fallback.
@@ -78,19 +117,52 @@ export class Translator {
78
117
  /** Recursively merge `source` into `target` */
79
118
  deepMerge(target: TranslationMessages, source: TranslationMessages): TranslationMessages;
80
119
 
81
- /** Switch the active locale */
120
+ /**
121
+ * Loaded locales that can serve `locale`, most specific first: the locale,
122
+ * then its parents with trailing subtags dropped (`zh-Hant-TW` → `zh-Hant`
123
+ * → `zh`). Case-insensitive; `_` is accepted for `-`.
124
+ */
125
+ localeCandidates(locale: string): string[];
126
+
127
+ /** The closest loaded locale (`fr-FR` → `fr`), or `null` */
128
+ resolveLocale(locale: string): string | null;
129
+
130
+ /**
131
+ * Switch the active locale to the closest loaded one (`fr-FR` → `fr`),
132
+ * or to the fallback locale when neither it nor a parent is loaded.
133
+ */
82
134
  setLocale(locale: string): void;
83
135
 
84
136
  /** The active locale */
85
137
  getLocale(): string;
86
138
 
87
139
  /**
88
- * Resolve a key. Falls back to the fallback locale, then to
89
- * `missingKeyHandler`, then to the key itself.
140
+ * A translator bound to `locale` (resolved like `setLocale()`, falling back
141
+ * silently to the fallback locale) that leaves `currentLocale` untouched.
142
+ * Use one per request on the server; `setLocale()` mutates state that every
143
+ * concurrent request shares. `options.escape` sets the escape default for
144
+ * its calls.
145
+ */
146
+ forLocale(locale: string, options?: { escape?: boolean }): LocaleTranslator;
147
+
148
+ /**
149
+ * Resolve a key in the target locale, then its parent locales (`fr-CA` →
150
+ * `fr`), then the fallback locale, then `missingKeyHandler`, then the key
151
+ * itself. Plural forms are chosen with the plural rules of the language the
152
+ * message was found in.
153
+ *
154
+ * The third argument is a locale override, or `{ locale, escape }`.
90
155
  */
91
- t(key: TranslationKey, params?: TranslationParams, locale?: string | null): string;
156
+ t(
157
+ key: TranslationKey,
158
+ params?: TranslationParams | null,
159
+ localeOrOptions?: string | null | TranslateOptions
160
+ ): string;
92
161
 
93
- /** Look a key up in one locale without fallback; `null` if absent */
162
+ /**
163
+ * Look a key up in one locale without fallback; `null` if absent. Only own
164
+ * properties match, so `'constructor'` or `'a.toString'` are absent.
165
+ */
94
166
  getTranslation(
95
167
  key: TranslationKey,
96
168
  locale: string
@@ -99,10 +171,19 @@ export class Translator {
99
171
  /** Pick the plural form matching `count` */
100
172
  selectPlural(pluralObject: PluralForms, count: number, locale: string): string;
101
173
 
102
- /** Substitute `{{param}}` placeholders */
103
- interpolate(str: string, params: TranslationParams): string;
174
+ /**
175
+ * Substitute `{{param}}` placeholders in one pass. Values are inserted
176
+ * literally (`$&` stays `$&`) and are not themselves interpolated;
177
+ * placeholders without a matching param are left as they are.
178
+ * `escape` HTML-escapes the values (never `str`); it defaults to the
179
+ * translator's `escape` option.
180
+ */
181
+ interpolate(str: string, params: TranslationParams, options?: { escape?: boolean }): string;
104
182
 
105
- /** Whether a key resolves in the given (or current) locale */
183
+ /**
184
+ * Whether a key resolves in the given (or current) locale or one of its
185
+ * parents; the fallback locale is not consulted
186
+ */
106
187
  has(key: TranslationKey, locale?: string | null): boolean;
107
188
 
108
189
  /** All messages for a locale, or `{}` */
@@ -128,7 +209,11 @@ export function createScopedTranslator(
128
209
  translator: Translator,
129
210
  namespace: string
130
211
  ): {
131
- t(key: TranslationKey, params?: TranslationParams, locale?: string | null): string;
212
+ t(
213
+ key: TranslationKey,
214
+ params?: TranslationParams | null,
215
+ localeOrOptions?: string | null | TranslateOptions
216
+ ): string;
132
217
  has(key: TranslationKey, locale?: string | null): boolean;
133
218
  getLocale(): string;
134
219
  setLocale(locale: string): void;
@@ -165,7 +250,11 @@ export class DateFormatter {
165
250
  /** Date and time together */
166
251
  dateTime(date: Date | number | string, options?: Intl.DateTimeFormatOptions): string;
167
252
 
168
- /** Relative to now (e.g. `2 hours ago`) */
253
+ /**
254
+ * Relative to now, past or future (e.g. `2 hours ago`, `tomorrow`,
255
+ * `in 3 weeks`), in the largest unit that fits: seconds, minutes, hours,
256
+ * days, weeks (from 7 days), months (from 30 days) or years (from 365 days).
257
+ */
169
258
  relative(date: Date | number | string): string;
170
259
  }
171
260