intor-translator 1.4.7 → 1.4.9
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 +4 -4
- package/dist/index.d.cts +88 -116
- package/dist/index.d.ts +88 -116
- package/dist/index.js +4 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -295,7 +295,7 @@ var CoreTranslator = class extends BaseTranslator {
|
|
|
295
295
|
});
|
|
296
296
|
};
|
|
297
297
|
/** Get the translated message for a key, with optional replacements. */
|
|
298
|
-
t = (key,
|
|
298
|
+
t = (key, replacements) => {
|
|
299
299
|
return translate({
|
|
300
300
|
hooks: this.hooks,
|
|
301
301
|
messages: this._messages,
|
|
@@ -303,7 +303,7 @@ var CoreTranslator = class extends BaseTranslator {
|
|
|
303
303
|
isLoading: this._isLoading,
|
|
304
304
|
translateConfig: this.translateConfig,
|
|
305
305
|
key,
|
|
306
|
-
replacements
|
|
306
|
+
replacements
|
|
307
307
|
});
|
|
308
308
|
};
|
|
309
309
|
};
|
|
@@ -332,7 +332,7 @@ var ScopeTranslator = class extends CoreTranslator {
|
|
|
332
332
|
targetLocale
|
|
333
333
|
});
|
|
334
334
|
},
|
|
335
|
-
t: (key,
|
|
335
|
+
t: (key, replacements) => {
|
|
336
336
|
const fullKey = getFullKey(preKey, key);
|
|
337
337
|
return translate({
|
|
338
338
|
hooks: this.hooks,
|
|
@@ -341,7 +341,7 @@ var ScopeTranslator = class extends CoreTranslator {
|
|
|
341
341
|
isLoading: this._isLoading,
|
|
342
342
|
translateConfig: this.translateConfig,
|
|
343
343
|
key: fullKey,
|
|
344
|
-
replacements
|
|
344
|
+
replacements
|
|
345
345
|
});
|
|
346
346
|
}
|
|
347
347
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -88,182 +88,156 @@ type FallbackLocalesMap<L extends string = string> = Partial<Record<L, L[]>>;
|
|
|
88
88
|
*/
|
|
89
89
|
type DefaultDepth = 15;
|
|
90
90
|
/** Countdown tuple for limiting recursive depth (up to 15 levels). */
|
|
91
|
-
type
|
|
91
|
+
type PrevDepth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
92
|
+
/** Detects `any` to prevent infinite type recursion. */
|
|
93
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
94
|
+
/** Detects `never` for safe conditional branching in type pipelines. */
|
|
95
|
+
type IsNever<T> = [T] extends [never] ? true : false;
|
|
92
96
|
/**
|
|
93
|
-
*
|
|
97
|
+
* Expands a single object property into its dot-separated path form.
|
|
94
98
|
*
|
|
95
99
|
* @example
|
|
96
100
|
* ```ts
|
|
97
|
-
*
|
|
101
|
+
* ExpandPath<"user", { name: string }>; // => "user" | "user.name"
|
|
98
102
|
* ```
|
|
103
|
+
*
|
|
99
104
|
*/
|
|
100
|
-
type
|
|
101
|
-
[K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}` | `${K & string}.${NodeKeys<M[K], Prev[D]>}` : never;
|
|
102
|
-
}[keyof M] : never;
|
|
105
|
+
type ExpandPath<K extends PropertyKey, V, IncludeSelf extends boolean = true, D extends number = DefaultDepth> = V extends MessageLeaf ? `${K & string}` : V extends MessageObject ? IncludeSelf extends true ? `${K & string}` | `${K & string}.${GeneratePaths<V, IncludeSelf, PrevDepth[D]>}` : `${K & string}.${GeneratePaths<V, IncludeSelf, PrevDepth[D]>}` : never;
|
|
103
106
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
107
|
+
* Generates dot-separated path strings from a nested message object.
|
|
106
108
|
* @example
|
|
107
109
|
* ```ts
|
|
108
|
-
*
|
|
110
|
+
* GeneratePaths<{ user: { name: "Ivan" } }>; // => "user" | "user.name"
|
|
109
111
|
* ```
|
|
110
112
|
*/
|
|
111
|
-
type
|
|
112
|
-
[K in keyof M]:
|
|
113
|
+
type GeneratePaths<M, IncludeSelf extends boolean = true, D extends number = DefaultDepth> = IsAny<M> extends true ? never : [D] extends [never] ? never : M extends MessageObject ? {
|
|
114
|
+
[K in keyof M]: ExpandPath<K, M[K], IncludeSelf, D>;
|
|
113
115
|
}[keyof M] : never;
|
|
114
116
|
/**
|
|
115
|
-
* Resolves the
|
|
116
|
-
* within a nested message object.
|
|
117
|
+
* Resolves the type located at a dot-separated path.
|
|
117
118
|
*
|
|
118
119
|
* @example
|
|
119
120
|
* ```ts
|
|
120
|
-
*
|
|
121
|
+
* AtPath<{ a: { b: { c: string } } }, "a.b">; // => { c: string };
|
|
121
122
|
* ```
|
|
122
123
|
*/
|
|
123
|
-
type
|
|
124
|
+
type AtPath<MessageSchema, PK extends string> = PK extends `${infer Head}.${infer Tail}` ? Head extends keyof MessageSchema ? AtPath<MessageSchema[Head], Tail> : never : PK extends keyof MessageSchema ? MessageSchema[PK] : never;
|
|
125
|
+
/** Conditional helper for branching on `LocaleMessages`. */
|
|
126
|
+
type IfLocaleMessages<T, Then, Else> = T extends LocaleMessages ? Then : Else;
|
|
127
|
+
/** Narrows a type to `MessageObject`, otherwise resolves to never. */
|
|
128
|
+
type IfMessageObject<T> = T extends MessageObject ? T : never;
|
|
129
|
+
|
|
124
130
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* The resolved type may be a subtree or a leaf value.
|
|
131
|
+
* Dot-separated leaf keys derived from a single message object.
|
|
128
132
|
*
|
|
129
133
|
* @example
|
|
130
134
|
* ```ts
|
|
131
|
-
*
|
|
132
|
-
* AtPath<typeof messages, "a">; // → { b: { c: string }; z: string };
|
|
133
|
-
* AtPath<typeof messages, "a.b">; // → { c: string };
|
|
135
|
+
* Key<{ a: { b: { c: string }; z: string } }>; // => "a.z" | "a.b.c"
|
|
134
136
|
* ```
|
|
135
137
|
*/
|
|
136
|
-
type
|
|
137
|
-
|
|
138
|
+
type Key<M> = GeneratePaths<M, false>;
|
|
138
139
|
/**
|
|
139
|
-
*
|
|
140
|
-
* of a specified locale (or union of locales).
|
|
140
|
+
* Leaf keys resolved from localized messages (union of all locales).
|
|
141
141
|
*
|
|
142
142
|
* @example
|
|
143
143
|
* ```ts
|
|
144
|
-
*
|
|
145
|
-
* en: { greeting: { morning: "morning" } },
|
|
146
|
-
* zh: { greeting: { evening: "晚上好" } },
|
|
147
|
-
* };
|
|
148
|
-
*
|
|
149
|
-
* // 1. Union of all locales
|
|
150
|
-
* LocalizedNodeKeys<typeof messages> // → "greeting" | "greeting.morning" | "greeting.evening"
|
|
151
|
-
*
|
|
152
|
-
* // 2. For a specified locale
|
|
153
|
-
* LocalizedNodeKeys<typeof messages, "en"> // → "greeting" | "greeting.morning"
|
|
154
|
-
* LocalizedNodeKeys<typeof messages, "zh"> // → "greeting" | "greeting.evening"
|
|
155
|
-
*
|
|
156
|
-
* // 3. Fallback when M is not LocaleMessages
|
|
157
|
-
* LocalizedNodeKeys // → string
|
|
144
|
+
* LocalizedKey<{ en: { a: { b: { c: string }; z: string } } }>; // => "a.z" | "a.b.c"
|
|
158
145
|
* ```
|
|
159
146
|
*/
|
|
160
|
-
type
|
|
147
|
+
type LocalizedKey<M> = IfLocaleMessages<M, Key<IfMessageObject<M[keyof M]>>, string>;
|
|
161
148
|
/**
|
|
162
|
-
*
|
|
163
|
-
* of a specified locale (or union of locales).
|
|
149
|
+
* Leaf keys scoped under a given prefix key.
|
|
164
150
|
*
|
|
165
151
|
* @example
|
|
166
152
|
* ```ts
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* // 2. For a specified locale
|
|
176
|
-
* LocalizedLeafKeys<typeof messages, "en"> // → "greeting.morning"
|
|
177
|
-
* LocalizedLeafKeys<typeof messages, "zh"> // → "greeting.evening"
|
|
153
|
+
* ScopedKey<{ en: { a: { b: { c: string }; z: string } } }, "a">; // => "b.c" | "z"
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
type ScopedKey<M, PK extends string> = IfLocaleMessages<M, Key<IfMessageObject<AtPath<M[keyof M], PK>>>, string>;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Prefix keys that may resolve to intermediate or leaf paths.
|
|
178
160
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* PreKey<{ a: { b: { c: string }; z: string } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
181
164
|
* ```
|
|
182
165
|
*/
|
|
183
|
-
type
|
|
166
|
+
type PreKey<M> = GeneratePaths<M, true>;
|
|
184
167
|
/**
|
|
185
|
-
*
|
|
186
|
-
* from the messages of a specified locale (or union of locales).
|
|
168
|
+
* Prefix keys resolved from localized messages (union of all locales).
|
|
187
169
|
*
|
|
188
|
-
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* LocalizedPreKey<{ en: { a: { b: { c: string }; z: string } } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
173
|
+
* ```
|
|
189
174
|
*/
|
|
190
|
-
type
|
|
175
|
+
type LocalizedPreKey<M> = IfLocaleMessages<M, PreKey<IfMessageObject<M[keyof M]>>, string>;
|
|
191
176
|
|
|
192
177
|
/**
|
|
193
|
-
*
|
|
194
|
-
* of a specified locale (`L`) (or union of locales).
|
|
178
|
+
* Resolves the value type at a dot-separated path.
|
|
195
179
|
*
|
|
196
180
|
* @example
|
|
197
181
|
* ```ts
|
|
198
|
-
*
|
|
199
|
-
* en: { a: { b: { c: "hello" }, z: "world" } },
|
|
200
|
-
* zh: { a: { b: "hello" },
|
|
201
|
-
* };
|
|
202
|
-
*
|
|
203
|
-
* ScopedLeafKeys<typeof messages, "a">; // → "b.c" | "z"
|
|
204
|
-
* ScopedLeafKeys<typeof messages, "a.b">; // → "c"
|
|
205
|
-
* ScopedLeafKeys<typeof messages, "a", "zh">; // → "b"
|
|
182
|
+
* Value<{ a: { b: { c: string } } }, "a.b.c">; // => string
|
|
206
183
|
* ```
|
|
207
184
|
*/
|
|
208
|
-
type
|
|
185
|
+
type Value<M, K extends string> = K extends `${infer Head}.${infer Tail}` ? Head extends keyof M ? Value<M[Head], Tail> : never : K extends keyof M ? M[K] : never;
|
|
209
186
|
/**
|
|
210
|
-
*
|
|
211
|
-
* under a prefix path (`PK`) from localized messages.
|
|
187
|
+
* Value resolved from localized messages (union of all locales).
|
|
212
188
|
*
|
|
213
189
|
* @example
|
|
214
190
|
* ```ts
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
|
|
191
|
+
* LocalizedValue<{ en: { a: { b: { c: string }; z: string } } }, "a.b.c">; // => string
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
type LocalizedValue<M, K extends string> = IfLocaleMessages<M, Value<M[keyof M], K>, MessageValue>;
|
|
195
|
+
/**
|
|
196
|
+
* Value resolved under a scoped prefix key.
|
|
218
197
|
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* ScopedValue<{ en: { a: { b: { c: string }; z: string } } }, "a", "b.c">; // => string
|
|
221
201
|
* ```
|
|
222
202
|
*/
|
|
223
|
-
type
|
|
203
|
+
type ScopedValue<M, PK extends string, K extends string> = IfLocaleMessages<M, Value<AtPath<M[keyof M], PK>, K>, MessageValue>;
|
|
224
204
|
|
|
225
205
|
/**
|
|
226
|
-
*
|
|
227
|
-
* in message templates.
|
|
228
|
-
*
|
|
229
|
-
* Replacement values are treated as plain data and interpreted
|
|
230
|
-
* by the message formatter at runtime.
|
|
206
|
+
* Generic replacement object used when no schema is available.
|
|
231
207
|
*
|
|
232
|
-
*
|
|
233
|
-
* const replacements: Replacement = {
|
|
234
|
-
* name: "Alice",
|
|
235
|
-
* count: 5,
|
|
236
|
-
* nested: {
|
|
237
|
-
* score: 100,
|
|
238
|
-
* },
|
|
239
|
-
* };
|
|
208
|
+
* Acts as a safe fallback for dynamic or unknown replacement shapes.
|
|
240
209
|
*/
|
|
241
210
|
type Replacement = Record<string, unknown>;
|
|
242
211
|
/**
|
|
243
|
-
*
|
|
212
|
+
* Replacement object resolved from a localized replacement schema.
|
|
244
213
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
214
|
+
* - If the key exists in the schema, resolves to the declared object shape
|
|
215
|
+
* - Otherwise falls back to generic `Replacement`
|
|
247
216
|
*
|
|
248
217
|
* @example
|
|
249
218
|
* ```ts
|
|
250
|
-
* type
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* total: { count: MessageValue };
|
|
254
|
-
* };
|
|
255
|
-
* };
|
|
256
|
-
*
|
|
257
|
-
* type WelcomeReplacement = LocalizedReplacement<RMap, "welcome">;
|
|
258
|
-
* // => { name: MessageValue }
|
|
259
|
-
*
|
|
260
|
-
* type UnknownReplacement = LocalizedReplacement<RMap, "unknown">;
|
|
261
|
-
* // => Replacement
|
|
219
|
+
* type ReplacementSchema = { "{locale}": { greeting: { name: string } } };
|
|
220
|
+
* LocalizedReplacement<ReplacementSchema, "greeting">; // => { name: string }
|
|
221
|
+
* LocalizedReplacement<ReplacementSchema, "missing">; // => Replacement
|
|
262
222
|
* ```
|
|
263
223
|
*/
|
|
264
224
|
type LocalizedReplacement<ReplacementSchema, K extends string> = ReplacementSchema extends {
|
|
265
225
|
"{locale}": infer LM;
|
|
266
|
-
} ? AtPath<LM, K
|
|
226
|
+
} ? IsNever<AtPath<LM, K>> extends true ? Replacement : AtPath<LM, K> extends MessageObject ? AtPath<LM, K> : Replacement : Replacement;
|
|
227
|
+
/**
|
|
228
|
+
* Replacement object resolved under a scoped prefix key.
|
|
229
|
+
*
|
|
230
|
+
* Internally composes the full dot-path (`"${PK}.${K}"`)
|
|
231
|
+
* and delegates resolution to `LocalizedReplacement`.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* type ReplacementSchema = { "{locale}": { user: { info: { name: string } } } };
|
|
236
|
+
* ScopedReplacement<ReplacementSchema, "user", "info">; // => { name: string }
|
|
237
|
+
* ScopedReplacement<ReplacementSchema, "user", "missing">; // => Replacement
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
type ScopedReplacement<ReplacementSchema, PK extends string | undefined, K extends string> = LocalizedReplacement<ReplacementSchema, `${PK}.${K}`>;
|
|
267
241
|
|
|
268
242
|
/**
|
|
269
243
|
* Options for initializing a translator
|
|
@@ -427,23 +401,21 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, Repla
|
|
|
427
401
|
/** Outputs a debug overview of the active pipeline. */
|
|
428
402
|
debugHooks(): void;
|
|
429
403
|
/** Check if a key exists in the specified locale or current locale. */
|
|
430
|
-
hasKey: <K extends
|
|
404
|
+
hasKey: <K extends LocalizedKey<M>>(key: K, targetLocale?: Locale<M>) => boolean;
|
|
431
405
|
/** Get the translated message for a key, with optional replacements. */
|
|
432
|
-
t: <K extends
|
|
406
|
+
t: <K extends LocalizedKey<M> = LocalizedKey<M>>(key: K, replacements?: LocalizedReplacement<ReplacementSchema, K>) => LocalizedValue<M, K>;
|
|
433
407
|
}
|
|
434
408
|
|
|
435
409
|
type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
|
|
436
|
-
type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown, PK extends string | undefined = undefined, K extends string = PK extends string ?
|
|
410
|
+
type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown, PK extends string | undefined = undefined, K extends string = PK extends string ? ScopedKey<M, PK> : LocalizedKey<M>> = {
|
|
437
411
|
hasKey: (key?: K, targetLocale?: Locale<M>) => boolean;
|
|
438
|
-
t: <Key extends K>(key?: Key,
|
|
439
|
-
LocalizedReplacement<ReplacementSchema, PK extends string ? `${PK}.${Key & string}` : Key>?
|
|
440
|
-
]) => PK extends string ? ScopedLeafValue<M, PK, Key> : LocalizedLeafValue<M, Key>;
|
|
412
|
+
t: <Key extends K>(key?: Key, replacements?: ScopedReplacement<ReplacementSchema, PK, K>) => PK extends string ? ScopedValue<M, PK, Key> : LocalizedValue<M, Key>;
|
|
441
413
|
};
|
|
442
414
|
|
|
443
415
|
declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown> extends CoreTranslator<M, ReplacementSchema> {
|
|
444
416
|
constructor(options: ScopeTranslatorOptions<M>);
|
|
445
417
|
/** Create a scoped translator with a prefix key for resolving nested message paths. */
|
|
446
|
-
scoped<PK extends
|
|
418
|
+
scoped<PK extends LocalizedPreKey<M> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, ReplacementSchema, PK> : ScopeTranslatorMethods<M, ReplacementSchema>;
|
|
447
419
|
}
|
|
448
420
|
|
|
449
421
|
/** Semantic tag attributes map. */
|
|
@@ -518,4 +490,4 @@ interface Renderer<Output> {
|
|
|
518
490
|
*/
|
|
519
491
|
declare function renderRichMessage<Output>(message: MessageValue, renderer: Renderer<Output>): Output[];
|
|
520
492
|
|
|
521
|
-
export { type ASTNode, type AtPath, type Attributes, type
|
|
493
|
+
export { type ASTNode, type AtPath, type Attributes, type FallbackLocalesMap, type FormatHandler, type GeneratePaths, type HandlerContext, type IfLocaleMessages, type IfMessageObject, type Key, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedKey, type LocalizedPreKey, type LocalizedReplacement, type LocalizedValue, type MessageObject, type MessageValue, type MissingHandler, type PreKey, type Renderer, type Replacement, type ScopedKey, type ScopedReplacement, type ScopedValue, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, type Value, parseRichMessage, renderRichMessage };
|
package/dist/index.d.ts
CHANGED
|
@@ -88,182 +88,156 @@ type FallbackLocalesMap<L extends string = string> = Partial<Record<L, L[]>>;
|
|
|
88
88
|
*/
|
|
89
89
|
type DefaultDepth = 15;
|
|
90
90
|
/** Countdown tuple for limiting recursive depth (up to 15 levels). */
|
|
91
|
-
type
|
|
91
|
+
type PrevDepth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
92
|
+
/** Detects `any` to prevent infinite type recursion. */
|
|
93
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
94
|
+
/** Detects `never` for safe conditional branching in type pipelines. */
|
|
95
|
+
type IsNever<T> = [T] extends [never] ? true : false;
|
|
92
96
|
/**
|
|
93
|
-
*
|
|
97
|
+
* Expands a single object property into its dot-separated path form.
|
|
94
98
|
*
|
|
95
99
|
* @example
|
|
96
100
|
* ```ts
|
|
97
|
-
*
|
|
101
|
+
* ExpandPath<"user", { name: string }>; // => "user" | "user.name"
|
|
98
102
|
* ```
|
|
103
|
+
*
|
|
99
104
|
*/
|
|
100
|
-
type
|
|
101
|
-
[K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}` | `${K & string}.${NodeKeys<M[K], Prev[D]>}` : never;
|
|
102
|
-
}[keyof M] : never;
|
|
105
|
+
type ExpandPath<K extends PropertyKey, V, IncludeSelf extends boolean = true, D extends number = DefaultDepth> = V extends MessageLeaf ? `${K & string}` : V extends MessageObject ? IncludeSelf extends true ? `${K & string}` | `${K & string}.${GeneratePaths<V, IncludeSelf, PrevDepth[D]>}` : `${K & string}.${GeneratePaths<V, IncludeSelf, PrevDepth[D]>}` : never;
|
|
103
106
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
107
|
+
* Generates dot-separated path strings from a nested message object.
|
|
106
108
|
* @example
|
|
107
109
|
* ```ts
|
|
108
|
-
*
|
|
110
|
+
* GeneratePaths<{ user: { name: "Ivan" } }>; // => "user" | "user.name"
|
|
109
111
|
* ```
|
|
110
112
|
*/
|
|
111
|
-
type
|
|
112
|
-
[K in keyof M]:
|
|
113
|
+
type GeneratePaths<M, IncludeSelf extends boolean = true, D extends number = DefaultDepth> = IsAny<M> extends true ? never : [D] extends [never] ? never : M extends MessageObject ? {
|
|
114
|
+
[K in keyof M]: ExpandPath<K, M[K], IncludeSelf, D>;
|
|
113
115
|
}[keyof M] : never;
|
|
114
116
|
/**
|
|
115
|
-
* Resolves the
|
|
116
|
-
* within a nested message object.
|
|
117
|
+
* Resolves the type located at a dot-separated path.
|
|
117
118
|
*
|
|
118
119
|
* @example
|
|
119
120
|
* ```ts
|
|
120
|
-
*
|
|
121
|
+
* AtPath<{ a: { b: { c: string } } }, "a.b">; // => { c: string };
|
|
121
122
|
* ```
|
|
122
123
|
*/
|
|
123
|
-
type
|
|
124
|
+
type AtPath<MessageSchema, PK extends string> = PK extends `${infer Head}.${infer Tail}` ? Head extends keyof MessageSchema ? AtPath<MessageSchema[Head], Tail> : never : PK extends keyof MessageSchema ? MessageSchema[PK] : never;
|
|
125
|
+
/** Conditional helper for branching on `LocaleMessages`. */
|
|
126
|
+
type IfLocaleMessages<T, Then, Else> = T extends LocaleMessages ? Then : Else;
|
|
127
|
+
/** Narrows a type to `MessageObject`, otherwise resolves to never. */
|
|
128
|
+
type IfMessageObject<T> = T extends MessageObject ? T : never;
|
|
129
|
+
|
|
124
130
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* The resolved type may be a subtree or a leaf value.
|
|
131
|
+
* Dot-separated leaf keys derived from a single message object.
|
|
128
132
|
*
|
|
129
133
|
* @example
|
|
130
134
|
* ```ts
|
|
131
|
-
*
|
|
132
|
-
* AtPath<typeof messages, "a">; // → { b: { c: string }; z: string };
|
|
133
|
-
* AtPath<typeof messages, "a.b">; // → { c: string };
|
|
135
|
+
* Key<{ a: { b: { c: string }; z: string } }>; // => "a.z" | "a.b.c"
|
|
134
136
|
* ```
|
|
135
137
|
*/
|
|
136
|
-
type
|
|
137
|
-
|
|
138
|
+
type Key<M> = GeneratePaths<M, false>;
|
|
138
139
|
/**
|
|
139
|
-
*
|
|
140
|
-
* of a specified locale (or union of locales).
|
|
140
|
+
* Leaf keys resolved from localized messages (union of all locales).
|
|
141
141
|
*
|
|
142
142
|
* @example
|
|
143
143
|
* ```ts
|
|
144
|
-
*
|
|
145
|
-
* en: { greeting: { morning: "morning" } },
|
|
146
|
-
* zh: { greeting: { evening: "晚上好" } },
|
|
147
|
-
* };
|
|
148
|
-
*
|
|
149
|
-
* // 1. Union of all locales
|
|
150
|
-
* LocalizedNodeKeys<typeof messages> // → "greeting" | "greeting.morning" | "greeting.evening"
|
|
151
|
-
*
|
|
152
|
-
* // 2. For a specified locale
|
|
153
|
-
* LocalizedNodeKeys<typeof messages, "en"> // → "greeting" | "greeting.morning"
|
|
154
|
-
* LocalizedNodeKeys<typeof messages, "zh"> // → "greeting" | "greeting.evening"
|
|
155
|
-
*
|
|
156
|
-
* // 3. Fallback when M is not LocaleMessages
|
|
157
|
-
* LocalizedNodeKeys // → string
|
|
144
|
+
* LocalizedKey<{ en: { a: { b: { c: string }; z: string } } }>; // => "a.z" | "a.b.c"
|
|
158
145
|
* ```
|
|
159
146
|
*/
|
|
160
|
-
type
|
|
147
|
+
type LocalizedKey<M> = IfLocaleMessages<M, Key<IfMessageObject<M[keyof M]>>, string>;
|
|
161
148
|
/**
|
|
162
|
-
*
|
|
163
|
-
* of a specified locale (or union of locales).
|
|
149
|
+
* Leaf keys scoped under a given prefix key.
|
|
164
150
|
*
|
|
165
151
|
* @example
|
|
166
152
|
* ```ts
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* // 2. For a specified locale
|
|
176
|
-
* LocalizedLeafKeys<typeof messages, "en"> // → "greeting.morning"
|
|
177
|
-
* LocalizedLeafKeys<typeof messages, "zh"> // → "greeting.evening"
|
|
153
|
+
* ScopedKey<{ en: { a: { b: { c: string }; z: string } } }, "a">; // => "b.c" | "z"
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
type ScopedKey<M, PK extends string> = IfLocaleMessages<M, Key<IfMessageObject<AtPath<M[keyof M], PK>>>, string>;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Prefix keys that may resolve to intermediate or leaf paths.
|
|
178
160
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* PreKey<{ a: { b: { c: string }; z: string } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
181
164
|
* ```
|
|
182
165
|
*/
|
|
183
|
-
type
|
|
166
|
+
type PreKey<M> = GeneratePaths<M, true>;
|
|
184
167
|
/**
|
|
185
|
-
*
|
|
186
|
-
* from the messages of a specified locale (or union of locales).
|
|
168
|
+
* Prefix keys resolved from localized messages (union of all locales).
|
|
187
169
|
*
|
|
188
|
-
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* LocalizedPreKey<{ en: { a: { b: { c: string }; z: string } } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
173
|
+
* ```
|
|
189
174
|
*/
|
|
190
|
-
type
|
|
175
|
+
type LocalizedPreKey<M> = IfLocaleMessages<M, PreKey<IfMessageObject<M[keyof M]>>, string>;
|
|
191
176
|
|
|
192
177
|
/**
|
|
193
|
-
*
|
|
194
|
-
* of a specified locale (`L`) (or union of locales).
|
|
178
|
+
* Resolves the value type at a dot-separated path.
|
|
195
179
|
*
|
|
196
180
|
* @example
|
|
197
181
|
* ```ts
|
|
198
|
-
*
|
|
199
|
-
* en: { a: { b: { c: "hello" }, z: "world" } },
|
|
200
|
-
* zh: { a: { b: "hello" },
|
|
201
|
-
* };
|
|
202
|
-
*
|
|
203
|
-
* ScopedLeafKeys<typeof messages, "a">; // → "b.c" | "z"
|
|
204
|
-
* ScopedLeafKeys<typeof messages, "a.b">; // → "c"
|
|
205
|
-
* ScopedLeafKeys<typeof messages, "a", "zh">; // → "b"
|
|
182
|
+
* Value<{ a: { b: { c: string } } }, "a.b.c">; // => string
|
|
206
183
|
* ```
|
|
207
184
|
*/
|
|
208
|
-
type
|
|
185
|
+
type Value<M, K extends string> = K extends `${infer Head}.${infer Tail}` ? Head extends keyof M ? Value<M[Head], Tail> : never : K extends keyof M ? M[K] : never;
|
|
209
186
|
/**
|
|
210
|
-
*
|
|
211
|
-
* under a prefix path (`PK`) from localized messages.
|
|
187
|
+
* Value resolved from localized messages (union of all locales).
|
|
212
188
|
*
|
|
213
189
|
* @example
|
|
214
190
|
* ```ts
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
|
|
191
|
+
* LocalizedValue<{ en: { a: { b: { c: string }; z: string } } }, "a.b.c">; // => string
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
type LocalizedValue<M, K extends string> = IfLocaleMessages<M, Value<M[keyof M], K>, MessageValue>;
|
|
195
|
+
/**
|
|
196
|
+
* Value resolved under a scoped prefix key.
|
|
218
197
|
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* ScopedValue<{ en: { a: { b: { c: string }; z: string } } }, "a", "b.c">; // => string
|
|
221
201
|
* ```
|
|
222
202
|
*/
|
|
223
|
-
type
|
|
203
|
+
type ScopedValue<M, PK extends string, K extends string> = IfLocaleMessages<M, Value<AtPath<M[keyof M], PK>, K>, MessageValue>;
|
|
224
204
|
|
|
225
205
|
/**
|
|
226
|
-
*
|
|
227
|
-
* in message templates.
|
|
228
|
-
*
|
|
229
|
-
* Replacement values are treated as plain data and interpreted
|
|
230
|
-
* by the message formatter at runtime.
|
|
206
|
+
* Generic replacement object used when no schema is available.
|
|
231
207
|
*
|
|
232
|
-
*
|
|
233
|
-
* const replacements: Replacement = {
|
|
234
|
-
* name: "Alice",
|
|
235
|
-
* count: 5,
|
|
236
|
-
* nested: {
|
|
237
|
-
* score: 100,
|
|
238
|
-
* },
|
|
239
|
-
* };
|
|
208
|
+
* Acts as a safe fallback for dynamic or unknown replacement shapes.
|
|
240
209
|
*/
|
|
241
210
|
type Replacement = Record<string, unknown>;
|
|
242
211
|
/**
|
|
243
|
-
*
|
|
212
|
+
* Replacement object resolved from a localized replacement schema.
|
|
244
213
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
214
|
+
* - If the key exists in the schema, resolves to the declared object shape
|
|
215
|
+
* - Otherwise falls back to generic `Replacement`
|
|
247
216
|
*
|
|
248
217
|
* @example
|
|
249
218
|
* ```ts
|
|
250
|
-
* type
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* total: { count: MessageValue };
|
|
254
|
-
* };
|
|
255
|
-
* };
|
|
256
|
-
*
|
|
257
|
-
* type WelcomeReplacement = LocalizedReplacement<RMap, "welcome">;
|
|
258
|
-
* // => { name: MessageValue }
|
|
259
|
-
*
|
|
260
|
-
* type UnknownReplacement = LocalizedReplacement<RMap, "unknown">;
|
|
261
|
-
* // => Replacement
|
|
219
|
+
* type ReplacementSchema = { "{locale}": { greeting: { name: string } } };
|
|
220
|
+
* LocalizedReplacement<ReplacementSchema, "greeting">; // => { name: string }
|
|
221
|
+
* LocalizedReplacement<ReplacementSchema, "missing">; // => Replacement
|
|
262
222
|
* ```
|
|
263
223
|
*/
|
|
264
224
|
type LocalizedReplacement<ReplacementSchema, K extends string> = ReplacementSchema extends {
|
|
265
225
|
"{locale}": infer LM;
|
|
266
|
-
} ? AtPath<LM, K
|
|
226
|
+
} ? IsNever<AtPath<LM, K>> extends true ? Replacement : AtPath<LM, K> extends MessageObject ? AtPath<LM, K> : Replacement : Replacement;
|
|
227
|
+
/**
|
|
228
|
+
* Replacement object resolved under a scoped prefix key.
|
|
229
|
+
*
|
|
230
|
+
* Internally composes the full dot-path (`"${PK}.${K}"`)
|
|
231
|
+
* and delegates resolution to `LocalizedReplacement`.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* type ReplacementSchema = { "{locale}": { user: { info: { name: string } } } };
|
|
236
|
+
* ScopedReplacement<ReplacementSchema, "user", "info">; // => { name: string }
|
|
237
|
+
* ScopedReplacement<ReplacementSchema, "user", "missing">; // => Replacement
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
type ScopedReplacement<ReplacementSchema, PK extends string | undefined, K extends string> = LocalizedReplacement<ReplacementSchema, `${PK}.${K}`>;
|
|
267
241
|
|
|
268
242
|
/**
|
|
269
243
|
* Options for initializing a translator
|
|
@@ -427,23 +401,21 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, Repla
|
|
|
427
401
|
/** Outputs a debug overview of the active pipeline. */
|
|
428
402
|
debugHooks(): void;
|
|
429
403
|
/** Check if a key exists in the specified locale or current locale. */
|
|
430
|
-
hasKey: <K extends
|
|
404
|
+
hasKey: <K extends LocalizedKey<M>>(key: K, targetLocale?: Locale<M>) => boolean;
|
|
431
405
|
/** Get the translated message for a key, with optional replacements. */
|
|
432
|
-
t: <K extends
|
|
406
|
+
t: <K extends LocalizedKey<M> = LocalizedKey<M>>(key: K, replacements?: LocalizedReplacement<ReplacementSchema, K>) => LocalizedValue<M, K>;
|
|
433
407
|
}
|
|
434
408
|
|
|
435
409
|
type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
|
|
436
|
-
type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown, PK extends string | undefined = undefined, K extends string = PK extends string ?
|
|
410
|
+
type ScopeTranslatorMethods<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown, PK extends string | undefined = undefined, K extends string = PK extends string ? ScopedKey<M, PK> : LocalizedKey<M>> = {
|
|
437
411
|
hasKey: (key?: K, targetLocale?: Locale<M>) => boolean;
|
|
438
|
-
t: <Key extends K>(key?: Key,
|
|
439
|
-
LocalizedReplacement<ReplacementSchema, PK extends string ? `${PK}.${Key & string}` : Key>?
|
|
440
|
-
]) => PK extends string ? ScopedLeafValue<M, PK, Key> : LocalizedLeafValue<M, Key>;
|
|
412
|
+
t: <Key extends K>(key?: Key, replacements?: ScopedReplacement<ReplacementSchema, PK, K>) => PK extends string ? ScopedValue<M, PK, Key> : LocalizedValue<M, Key>;
|
|
441
413
|
};
|
|
442
414
|
|
|
443
415
|
declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown> extends CoreTranslator<M, ReplacementSchema> {
|
|
444
416
|
constructor(options: ScopeTranslatorOptions<M>);
|
|
445
417
|
/** Create a scoped translator with a prefix key for resolving nested message paths. */
|
|
446
|
-
scoped<PK extends
|
|
418
|
+
scoped<PK extends LocalizedPreKey<M> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, ReplacementSchema, PK> : ScopeTranslatorMethods<M, ReplacementSchema>;
|
|
447
419
|
}
|
|
448
420
|
|
|
449
421
|
/** Semantic tag attributes map. */
|
|
@@ -518,4 +490,4 @@ interface Renderer<Output> {
|
|
|
518
490
|
*/
|
|
519
491
|
declare function renderRichMessage<Output>(message: MessageValue, renderer: Renderer<Output>): Output[];
|
|
520
492
|
|
|
521
|
-
export { type ASTNode, type AtPath, type Attributes, type
|
|
493
|
+
export { type ASTNode, type AtPath, type Attributes, type FallbackLocalesMap, type FormatHandler, type GeneratePaths, type HandlerContext, type IfLocaleMessages, type IfMessageObject, type Key, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedKey, type LocalizedPreKey, type LocalizedReplacement, type LocalizedValue, type MessageObject, type MessageValue, type MissingHandler, type PreKey, type Renderer, type Replacement, type ScopedKey, type ScopedReplacement, type ScopedValue, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, type Value, parseRichMessage, renderRichMessage };
|
package/dist/index.js
CHANGED
|
@@ -293,7 +293,7 @@ var CoreTranslator = class extends BaseTranslator {
|
|
|
293
293
|
});
|
|
294
294
|
};
|
|
295
295
|
/** Get the translated message for a key, with optional replacements. */
|
|
296
|
-
t = (key,
|
|
296
|
+
t = (key, replacements) => {
|
|
297
297
|
return translate({
|
|
298
298
|
hooks: this.hooks,
|
|
299
299
|
messages: this._messages,
|
|
@@ -301,7 +301,7 @@ var CoreTranslator = class extends BaseTranslator {
|
|
|
301
301
|
isLoading: this._isLoading,
|
|
302
302
|
translateConfig: this.translateConfig,
|
|
303
303
|
key,
|
|
304
|
-
replacements
|
|
304
|
+
replacements
|
|
305
305
|
});
|
|
306
306
|
};
|
|
307
307
|
};
|
|
@@ -330,7 +330,7 @@ var ScopeTranslator = class extends CoreTranslator {
|
|
|
330
330
|
targetLocale
|
|
331
331
|
});
|
|
332
332
|
},
|
|
333
|
-
t: (key,
|
|
333
|
+
t: (key, replacements) => {
|
|
334
334
|
const fullKey = getFullKey(preKey, key);
|
|
335
335
|
return translate({
|
|
336
336
|
hooks: this.hooks,
|
|
@@ -339,7 +339,7 @@ var ScopeTranslator = class extends CoreTranslator {
|
|
|
339
339
|
isLoading: this._isLoading,
|
|
340
340
|
translateConfig: this.translateConfig,
|
|
341
341
|
key: fullKey,
|
|
342
|
-
replacements
|
|
342
|
+
replacements
|
|
343
343
|
});
|
|
344
344
|
}
|
|
345
345
|
};
|