intor-translator 1.4.8 → 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 +2 -2
- package/dist/index.d.cts +101 -102
- package/dist/index.d.ts +101 -102
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -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
|
@@ -82,163 +82,162 @@ type Locale<M = unknown> = M extends LocaleMessages ? keyof M & string : string;
|
|
|
82
82
|
*/
|
|
83
83
|
type FallbackLocalesMap<L extends string = string> = Partial<Record<L, L[]>>;
|
|
84
84
|
|
|
85
|
-
/**
|
|
86
|
-
* Represents a replacement map used for interpolating values
|
|
87
|
-
* in message templates.
|
|
88
|
-
*
|
|
89
|
-
* Replacement values are treated as plain data and interpreted
|
|
90
|
-
* by the message formatter at runtime.
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* const replacements: Replacement = {
|
|
94
|
-
* name: "Alice",
|
|
95
|
-
* count: 5,
|
|
96
|
-
* nested: {
|
|
97
|
-
* score: 100,
|
|
98
|
-
* },
|
|
99
|
-
* };
|
|
100
|
-
*/
|
|
101
|
-
type Replacement = Record<string, MessageValue>;
|
|
102
|
-
|
|
103
85
|
/**
|
|
104
86
|
* Default maximum recursive depth for nested key type computations,
|
|
105
87
|
* balancing type safety and compiler performance.
|
|
106
88
|
*/
|
|
107
89
|
type DefaultDepth = 15;
|
|
108
90
|
/** Countdown tuple for limiting recursive depth (up to 15 levels). */
|
|
109
|
-
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;
|
|
110
96
|
/**
|
|
111
|
-
*
|
|
97
|
+
* Expands a single object property into its dot-separated path form.
|
|
112
98
|
*
|
|
113
99
|
* @example
|
|
114
100
|
* ```ts
|
|
115
|
-
*
|
|
101
|
+
* ExpandPath<"user", { name: string }>; // => "user" | "user.name"
|
|
116
102
|
* ```
|
|
103
|
+
*
|
|
117
104
|
*/
|
|
118
|
-
type
|
|
119
|
-
|
|
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;
|
|
106
|
+
/**
|
|
107
|
+
* Generates dot-separated path strings from a nested message object.
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* GeneratePaths<{ user: { name: "Ivan" } }>; // => "user" | "user.name"
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
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>;
|
|
120
115
|
}[keyof M] : never;
|
|
121
116
|
/**
|
|
122
|
-
*
|
|
117
|
+
* Resolves the type located at a dot-separated path.
|
|
123
118
|
*
|
|
124
119
|
* @example
|
|
125
120
|
* ```ts
|
|
126
|
-
*
|
|
121
|
+
* AtPath<{ a: { b: { c: string } } }, "a.b">; // => { c: string };
|
|
127
122
|
* ```
|
|
128
123
|
*/
|
|
129
|
-
type
|
|
130
|
-
|
|
131
|
-
|
|
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
|
+
|
|
132
130
|
/**
|
|
133
|
-
*
|
|
134
|
-
* within a nested message object.
|
|
131
|
+
* Dot-separated leaf keys derived from a single message object.
|
|
135
132
|
*
|
|
136
133
|
* @example
|
|
137
134
|
* ```ts
|
|
138
|
-
*
|
|
135
|
+
* Key<{ a: { b: { c: string }; z: string } }>; // => "a.z" | "a.b.c"
|
|
139
136
|
* ```
|
|
140
137
|
*/
|
|
141
|
-
type
|
|
138
|
+
type Key<M> = GeneratePaths<M, false>;
|
|
142
139
|
/**
|
|
143
|
-
*
|
|
140
|
+
* Leaf keys resolved from localized messages (union of all locales).
|
|
144
141
|
*
|
|
145
|
-
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* LocalizedKey<{ en: { a: { b: { c: string }; z: string } } }>; // => "a.z" | "a.b.c"
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
type LocalizedKey<M> = IfLocaleMessages<M, Key<IfMessageObject<M[keyof M]>>, string>;
|
|
148
|
+
/**
|
|
149
|
+
* Leaf keys scoped under a given prefix key.
|
|
146
150
|
*
|
|
147
151
|
* @example
|
|
148
152
|
* ```ts
|
|
149
|
-
*
|
|
150
|
-
* AtPath<typeof messages, "a">; // → { b: { c: string }; z: string };
|
|
151
|
-
* AtPath<typeof messages, "a.b">; // → { c: string };
|
|
153
|
+
* ScopedKey<{ en: { a: { b: { c: string }; z: string } } }, "a">; // => "b.c" | "z"
|
|
152
154
|
* ```
|
|
153
155
|
*/
|
|
154
|
-
type
|
|
156
|
+
type ScopedKey<M, PK extends string> = IfLocaleMessages<M, Key<IfMessageObject<AtPath<M[keyof M], PK>>>, string>;
|
|
155
157
|
|
|
156
158
|
/**
|
|
157
|
-
*
|
|
158
|
-
* of a specified locale (or union of locales).
|
|
159
|
+
* Prefix keys that may resolve to intermediate or leaf paths.
|
|
159
160
|
*
|
|
160
161
|
* @example
|
|
161
162
|
* ```ts
|
|
162
|
-
*
|
|
163
|
-
* en: { greeting: { morning: "morning" } },
|
|
164
|
-
* zh: { greeting: { evening: "晚上好" } },
|
|
165
|
-
* };
|
|
166
|
-
*
|
|
167
|
-
* // 1. Union of all locales
|
|
168
|
-
* LocalizedNodeKeys<typeof messages> // → "greeting" | "greeting.morning" | "greeting.evening"
|
|
169
|
-
*
|
|
170
|
-
* // 2. For a specified locale
|
|
171
|
-
* LocalizedNodeKeys<typeof messages, "en"> // → "greeting" | "greeting.morning"
|
|
172
|
-
* LocalizedNodeKeys<typeof messages, "zh"> // → "greeting" | "greeting.evening"
|
|
173
|
-
*
|
|
174
|
-
* // 3. Fallback when M is not LocaleMessages
|
|
175
|
-
* LocalizedNodeKeys // → string
|
|
163
|
+
* PreKey<{ a: { b: { c: string }; z: string } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
176
164
|
* ```
|
|
177
165
|
*/
|
|
178
|
-
type
|
|
166
|
+
type PreKey<M> = GeneratePaths<M, true>;
|
|
179
167
|
/**
|
|
180
|
-
*
|
|
181
|
-
* of a specified locale (or union of locales).
|
|
168
|
+
* Prefix keys resolved from localized messages (union of all locales).
|
|
182
169
|
*
|
|
183
170
|
* @example
|
|
184
171
|
* ```ts
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*
|
|
172
|
+
* LocalizedPreKey<{ en: { a: { b: { c: string }; z: string } } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
type LocalizedPreKey<M> = IfLocaleMessages<M, PreKey<IfMessageObject<M[keyof M]>>, string>;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Resolves the value type at a dot-separated path.
|
|
192
179
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* Value<{ a: { b: { c: string } } }, "a.b.c">; // => string
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
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;
|
|
186
|
+
/**
|
|
187
|
+
* Value resolved from localized messages (union of all locales).
|
|
196
188
|
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* LocalizedValue<{ en: { a: { b: { c: string }; z: string } } }, "a.b.c">; // => string
|
|
199
192
|
* ```
|
|
200
193
|
*/
|
|
201
|
-
type
|
|
194
|
+
type LocalizedValue<M, K extends string> = IfLocaleMessages<M, Value<M[keyof M], K>, MessageValue>;
|
|
202
195
|
/**
|
|
203
|
-
*
|
|
204
|
-
* from the messages of a specified locale (or union of locales).
|
|
196
|
+
* Value resolved under a scoped prefix key.
|
|
205
197
|
*
|
|
206
|
-
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* ScopedValue<{ en: { a: { b: { c: string }; z: string } } }, "a", "b.c">; // => string
|
|
201
|
+
* ```
|
|
207
202
|
*/
|
|
208
|
-
type
|
|
203
|
+
type ScopedValue<M, PK extends string, K extends string> = IfLocaleMessages<M, Value<AtPath<M[keyof M], PK>, K>, MessageValue>;
|
|
209
204
|
|
|
210
205
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
206
|
+
* Generic replacement object used when no schema is available.
|
|
207
|
+
*
|
|
208
|
+
* Acts as a safe fallback for dynamic or unknown replacement shapes.
|
|
209
|
+
*/
|
|
210
|
+
type Replacement = Record<string, unknown>;
|
|
211
|
+
/**
|
|
212
|
+
* Replacement object resolved from a localized replacement schema.
|
|
213
|
+
*
|
|
214
|
+
* - If the key exists in the schema, resolves to the declared object shape
|
|
215
|
+
* - Otherwise falls back to generic `Replacement`
|
|
213
216
|
*
|
|
214
217
|
* @example
|
|
215
218
|
* ```ts
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* };
|
|
220
|
-
*
|
|
221
|
-
* ScopedLeafKeys<typeof messages, "a">; // → "b.c" | "z"
|
|
222
|
-
* ScopedLeafKeys<typeof messages, "a.b">; // → "c"
|
|
223
|
-
* ScopedLeafKeys<typeof messages, "a", "zh">; // → "b"
|
|
219
|
+
* type ReplacementSchema = { "{locale}": { greeting: { name: string } } };
|
|
220
|
+
* LocalizedReplacement<ReplacementSchema, "greeting">; // => { name: string }
|
|
221
|
+
* LocalizedReplacement<ReplacementSchema, "missing">; // => Replacement
|
|
224
222
|
* ```
|
|
225
223
|
*/
|
|
226
|
-
type
|
|
224
|
+
type LocalizedReplacement<ReplacementSchema, K extends string> = ReplacementSchema extends {
|
|
225
|
+
"{locale}": infer LM;
|
|
226
|
+
} ? IsNever<AtPath<LM, K>> extends true ? Replacement : AtPath<LM, K> extends MessageObject ? AtPath<LM, K> : Replacement : Replacement;
|
|
227
227
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
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`.
|
|
230
232
|
*
|
|
231
233
|
* @example
|
|
232
234
|
* ```ts
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* ScopedLeafValue<typeof messages, "a", "z">; // number[]
|
|
238
|
-
* ScopedLeafValue<typeof messages, "a.b", "c">; // string
|
|
235
|
+
* type ReplacementSchema = { "{locale}": { user: { info: { name: string } } } };
|
|
236
|
+
* ScopedReplacement<ReplacementSchema, "user", "info">; // => { name: string }
|
|
237
|
+
* ScopedReplacement<ReplacementSchema, "user", "missing">; // => Replacement
|
|
239
238
|
* ```
|
|
240
239
|
*/
|
|
241
|
-
type
|
|
240
|
+
type ScopedReplacement<ReplacementSchema, PK extends string | undefined, K extends string> = LocalizedReplacement<ReplacementSchema, `${PK}.${K}`>;
|
|
242
241
|
|
|
243
242
|
/**
|
|
244
243
|
* Options for initializing a translator
|
|
@@ -389,7 +388,7 @@ interface TranslatorPlugin {
|
|
|
389
388
|
*
|
|
390
389
|
* @template M - Shape of the messages object.
|
|
391
390
|
*/
|
|
392
|
-
declare class CoreTranslator<M extends LocaleMessages | unknown = unknown> extends BaseTranslator<M> {
|
|
391
|
+
declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown> extends BaseTranslator<M> {
|
|
393
392
|
/** User-provided options including messages, locale, and config. */
|
|
394
393
|
protected translateConfig: TranslateConfig<M>;
|
|
395
394
|
/** Active pipeline hooks applied during translation. */
|
|
@@ -402,21 +401,21 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown> exten
|
|
|
402
401
|
/** Outputs a debug overview of the active pipeline. */
|
|
403
402
|
debugHooks(): void;
|
|
404
403
|
/** Check if a key exists in the specified locale or current locale. */
|
|
405
|
-
hasKey: <K extends
|
|
404
|
+
hasKey: <K extends LocalizedKey<M>>(key: K, targetLocale?: Locale<M>) => boolean;
|
|
406
405
|
/** Get the translated message for a key, with optional replacements. */
|
|
407
|
-
t: <K extends
|
|
406
|
+
t: <K extends LocalizedKey<M> = LocalizedKey<M>>(key: K, replacements?: LocalizedReplacement<ReplacementSchema, K>) => LocalizedValue<M, K>;
|
|
408
407
|
}
|
|
409
408
|
|
|
410
409
|
type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
|
|
411
|
-
type ScopeTranslatorMethods<M extends LocaleMessages | unknown = 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>> = {
|
|
412
411
|
hasKey: (key?: K, targetLocale?: Locale<M>) => boolean;
|
|
413
|
-
t: (key?:
|
|
412
|
+
t: <Key extends K>(key?: Key, replacements?: ScopedReplacement<ReplacementSchema, PK, K>) => PK extends string ? ScopedValue<M, PK, Key> : LocalizedValue<M, Key>;
|
|
414
413
|
};
|
|
415
414
|
|
|
416
|
-
declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown> extends CoreTranslator<M> {
|
|
415
|
+
declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown> extends CoreTranslator<M, ReplacementSchema> {
|
|
417
416
|
constructor(options: ScopeTranslatorOptions<M>);
|
|
418
417
|
/** Create a scoped translator with a prefix key for resolving nested message paths. */
|
|
419
|
-
scoped<PK extends
|
|
418
|
+
scoped<PK extends LocalizedPreKey<M> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, ReplacementSchema, PK> : ScopeTranslatorMethods<M, ReplacementSchema>;
|
|
420
419
|
}
|
|
421
420
|
|
|
422
421
|
/** Semantic tag attributes map. */
|
|
@@ -491,4 +490,4 @@ interface Renderer<Output> {
|
|
|
491
490
|
*/
|
|
492
491
|
declare function renderRichMessage<Output>(message: MessageValue, renderer: Renderer<Output>): Output[];
|
|
493
492
|
|
|
494
|
-
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
|
@@ -82,163 +82,162 @@ type Locale<M = unknown> = M extends LocaleMessages ? keyof M & string : string;
|
|
|
82
82
|
*/
|
|
83
83
|
type FallbackLocalesMap<L extends string = string> = Partial<Record<L, L[]>>;
|
|
84
84
|
|
|
85
|
-
/**
|
|
86
|
-
* Represents a replacement map used for interpolating values
|
|
87
|
-
* in message templates.
|
|
88
|
-
*
|
|
89
|
-
* Replacement values are treated as plain data and interpreted
|
|
90
|
-
* by the message formatter at runtime.
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* const replacements: Replacement = {
|
|
94
|
-
* name: "Alice",
|
|
95
|
-
* count: 5,
|
|
96
|
-
* nested: {
|
|
97
|
-
* score: 100,
|
|
98
|
-
* },
|
|
99
|
-
* };
|
|
100
|
-
*/
|
|
101
|
-
type Replacement = Record<string, MessageValue>;
|
|
102
|
-
|
|
103
85
|
/**
|
|
104
86
|
* Default maximum recursive depth for nested key type computations,
|
|
105
87
|
* balancing type safety and compiler performance.
|
|
106
88
|
*/
|
|
107
89
|
type DefaultDepth = 15;
|
|
108
90
|
/** Countdown tuple for limiting recursive depth (up to 15 levels). */
|
|
109
|
-
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;
|
|
110
96
|
/**
|
|
111
|
-
*
|
|
97
|
+
* Expands a single object property into its dot-separated path form.
|
|
112
98
|
*
|
|
113
99
|
* @example
|
|
114
100
|
* ```ts
|
|
115
|
-
*
|
|
101
|
+
* ExpandPath<"user", { name: string }>; // => "user" | "user.name"
|
|
116
102
|
* ```
|
|
103
|
+
*
|
|
117
104
|
*/
|
|
118
|
-
type
|
|
119
|
-
|
|
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;
|
|
106
|
+
/**
|
|
107
|
+
* Generates dot-separated path strings from a nested message object.
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* GeneratePaths<{ user: { name: "Ivan" } }>; // => "user" | "user.name"
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
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>;
|
|
120
115
|
}[keyof M] : never;
|
|
121
116
|
/**
|
|
122
|
-
*
|
|
117
|
+
* Resolves the type located at a dot-separated path.
|
|
123
118
|
*
|
|
124
119
|
* @example
|
|
125
120
|
* ```ts
|
|
126
|
-
*
|
|
121
|
+
* AtPath<{ a: { b: { c: string } } }, "a.b">; // => { c: string };
|
|
127
122
|
* ```
|
|
128
123
|
*/
|
|
129
|
-
type
|
|
130
|
-
|
|
131
|
-
|
|
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
|
+
|
|
132
130
|
/**
|
|
133
|
-
*
|
|
134
|
-
* within a nested message object.
|
|
131
|
+
* Dot-separated leaf keys derived from a single message object.
|
|
135
132
|
*
|
|
136
133
|
* @example
|
|
137
134
|
* ```ts
|
|
138
|
-
*
|
|
135
|
+
* Key<{ a: { b: { c: string }; z: string } }>; // => "a.z" | "a.b.c"
|
|
139
136
|
* ```
|
|
140
137
|
*/
|
|
141
|
-
type
|
|
138
|
+
type Key<M> = GeneratePaths<M, false>;
|
|
142
139
|
/**
|
|
143
|
-
*
|
|
140
|
+
* Leaf keys resolved from localized messages (union of all locales).
|
|
144
141
|
*
|
|
145
|
-
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* LocalizedKey<{ en: { a: { b: { c: string }; z: string } } }>; // => "a.z" | "a.b.c"
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
type LocalizedKey<M> = IfLocaleMessages<M, Key<IfMessageObject<M[keyof M]>>, string>;
|
|
148
|
+
/**
|
|
149
|
+
* Leaf keys scoped under a given prefix key.
|
|
146
150
|
*
|
|
147
151
|
* @example
|
|
148
152
|
* ```ts
|
|
149
|
-
*
|
|
150
|
-
* AtPath<typeof messages, "a">; // → { b: { c: string }; z: string };
|
|
151
|
-
* AtPath<typeof messages, "a.b">; // → { c: string };
|
|
153
|
+
* ScopedKey<{ en: { a: { b: { c: string }; z: string } } }, "a">; // => "b.c" | "z"
|
|
152
154
|
* ```
|
|
153
155
|
*/
|
|
154
|
-
type
|
|
156
|
+
type ScopedKey<M, PK extends string> = IfLocaleMessages<M, Key<IfMessageObject<AtPath<M[keyof M], PK>>>, string>;
|
|
155
157
|
|
|
156
158
|
/**
|
|
157
|
-
*
|
|
158
|
-
* of a specified locale (or union of locales).
|
|
159
|
+
* Prefix keys that may resolve to intermediate or leaf paths.
|
|
159
160
|
*
|
|
160
161
|
* @example
|
|
161
162
|
* ```ts
|
|
162
|
-
*
|
|
163
|
-
* en: { greeting: { morning: "morning" } },
|
|
164
|
-
* zh: { greeting: { evening: "晚上好" } },
|
|
165
|
-
* };
|
|
166
|
-
*
|
|
167
|
-
* // 1. Union of all locales
|
|
168
|
-
* LocalizedNodeKeys<typeof messages> // → "greeting" | "greeting.morning" | "greeting.evening"
|
|
169
|
-
*
|
|
170
|
-
* // 2. For a specified locale
|
|
171
|
-
* LocalizedNodeKeys<typeof messages, "en"> // → "greeting" | "greeting.morning"
|
|
172
|
-
* LocalizedNodeKeys<typeof messages, "zh"> // → "greeting" | "greeting.evening"
|
|
173
|
-
*
|
|
174
|
-
* // 3. Fallback when M is not LocaleMessages
|
|
175
|
-
* LocalizedNodeKeys // → string
|
|
163
|
+
* PreKey<{ a: { b: { c: string }; z: string } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
176
164
|
* ```
|
|
177
165
|
*/
|
|
178
|
-
type
|
|
166
|
+
type PreKey<M> = GeneratePaths<M, true>;
|
|
179
167
|
/**
|
|
180
|
-
*
|
|
181
|
-
* of a specified locale (or union of locales).
|
|
168
|
+
* Prefix keys resolved from localized messages (union of all locales).
|
|
182
169
|
*
|
|
183
170
|
* @example
|
|
184
171
|
* ```ts
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*
|
|
172
|
+
* LocalizedPreKey<{ en: { a: { b: { c: string }; z: string } } }>; // → "a" | "a.b" | "a.z" | "a.b.c"
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
type LocalizedPreKey<M> = IfLocaleMessages<M, PreKey<IfMessageObject<M[keyof M]>>, string>;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Resolves the value type at a dot-separated path.
|
|
192
179
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* Value<{ a: { b: { c: string } } }, "a.b.c">; // => string
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
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;
|
|
186
|
+
/**
|
|
187
|
+
* Value resolved from localized messages (union of all locales).
|
|
196
188
|
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* LocalizedValue<{ en: { a: { b: { c: string }; z: string } } }, "a.b.c">; // => string
|
|
199
192
|
* ```
|
|
200
193
|
*/
|
|
201
|
-
type
|
|
194
|
+
type LocalizedValue<M, K extends string> = IfLocaleMessages<M, Value<M[keyof M], K>, MessageValue>;
|
|
202
195
|
/**
|
|
203
|
-
*
|
|
204
|
-
* from the messages of a specified locale (or union of locales).
|
|
196
|
+
* Value resolved under a scoped prefix key.
|
|
205
197
|
*
|
|
206
|
-
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* ScopedValue<{ en: { a: { b: { c: string }; z: string } } }, "a", "b.c">; // => string
|
|
201
|
+
* ```
|
|
207
202
|
*/
|
|
208
|
-
type
|
|
203
|
+
type ScopedValue<M, PK extends string, K extends string> = IfLocaleMessages<M, Value<AtPath<M[keyof M], PK>, K>, MessageValue>;
|
|
209
204
|
|
|
210
205
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
206
|
+
* Generic replacement object used when no schema is available.
|
|
207
|
+
*
|
|
208
|
+
* Acts as a safe fallback for dynamic or unknown replacement shapes.
|
|
209
|
+
*/
|
|
210
|
+
type Replacement = Record<string, unknown>;
|
|
211
|
+
/**
|
|
212
|
+
* Replacement object resolved from a localized replacement schema.
|
|
213
|
+
*
|
|
214
|
+
* - If the key exists in the schema, resolves to the declared object shape
|
|
215
|
+
* - Otherwise falls back to generic `Replacement`
|
|
213
216
|
*
|
|
214
217
|
* @example
|
|
215
218
|
* ```ts
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* };
|
|
220
|
-
*
|
|
221
|
-
* ScopedLeafKeys<typeof messages, "a">; // → "b.c" | "z"
|
|
222
|
-
* ScopedLeafKeys<typeof messages, "a.b">; // → "c"
|
|
223
|
-
* ScopedLeafKeys<typeof messages, "a", "zh">; // → "b"
|
|
219
|
+
* type ReplacementSchema = { "{locale}": { greeting: { name: string } } };
|
|
220
|
+
* LocalizedReplacement<ReplacementSchema, "greeting">; // => { name: string }
|
|
221
|
+
* LocalizedReplacement<ReplacementSchema, "missing">; // => Replacement
|
|
224
222
|
* ```
|
|
225
223
|
*/
|
|
226
|
-
type
|
|
224
|
+
type LocalizedReplacement<ReplacementSchema, K extends string> = ReplacementSchema extends {
|
|
225
|
+
"{locale}": infer LM;
|
|
226
|
+
} ? IsNever<AtPath<LM, K>> extends true ? Replacement : AtPath<LM, K> extends MessageObject ? AtPath<LM, K> : Replacement : Replacement;
|
|
227
227
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
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`.
|
|
230
232
|
*
|
|
231
233
|
* @example
|
|
232
234
|
* ```ts
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* ScopedLeafValue<typeof messages, "a", "z">; // number[]
|
|
238
|
-
* ScopedLeafValue<typeof messages, "a.b", "c">; // string
|
|
235
|
+
* type ReplacementSchema = { "{locale}": { user: { info: { name: string } } } };
|
|
236
|
+
* ScopedReplacement<ReplacementSchema, "user", "info">; // => { name: string }
|
|
237
|
+
* ScopedReplacement<ReplacementSchema, "user", "missing">; // => Replacement
|
|
239
238
|
* ```
|
|
240
239
|
*/
|
|
241
|
-
type
|
|
240
|
+
type ScopedReplacement<ReplacementSchema, PK extends string | undefined, K extends string> = LocalizedReplacement<ReplacementSchema, `${PK}.${K}`>;
|
|
242
241
|
|
|
243
242
|
/**
|
|
244
243
|
* Options for initializing a translator
|
|
@@ -389,7 +388,7 @@ interface TranslatorPlugin {
|
|
|
389
388
|
*
|
|
390
389
|
* @template M - Shape of the messages object.
|
|
391
390
|
*/
|
|
392
|
-
declare class CoreTranslator<M extends LocaleMessages | unknown = unknown> extends BaseTranslator<M> {
|
|
391
|
+
declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown> extends BaseTranslator<M> {
|
|
393
392
|
/** User-provided options including messages, locale, and config. */
|
|
394
393
|
protected translateConfig: TranslateConfig<M>;
|
|
395
394
|
/** Active pipeline hooks applied during translation. */
|
|
@@ -402,21 +401,21 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown> exten
|
|
|
402
401
|
/** Outputs a debug overview of the active pipeline. */
|
|
403
402
|
debugHooks(): void;
|
|
404
403
|
/** Check if a key exists in the specified locale or current locale. */
|
|
405
|
-
hasKey: <K extends
|
|
404
|
+
hasKey: <K extends LocalizedKey<M>>(key: K, targetLocale?: Locale<M>) => boolean;
|
|
406
405
|
/** Get the translated message for a key, with optional replacements. */
|
|
407
|
-
t: <K extends
|
|
406
|
+
t: <K extends LocalizedKey<M> = LocalizedKey<M>>(key: K, replacements?: LocalizedReplacement<ReplacementSchema, K>) => LocalizedValue<M, K>;
|
|
408
407
|
}
|
|
409
408
|
|
|
410
409
|
type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
|
|
411
|
-
type ScopeTranslatorMethods<M extends LocaleMessages | unknown = 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>> = {
|
|
412
411
|
hasKey: (key?: K, targetLocale?: Locale<M>) => boolean;
|
|
413
|
-
t: (key?:
|
|
412
|
+
t: <Key extends K>(key?: Key, replacements?: ScopedReplacement<ReplacementSchema, PK, K>) => PK extends string ? ScopedValue<M, PK, Key> : LocalizedValue<M, Key>;
|
|
414
413
|
};
|
|
415
414
|
|
|
416
|
-
declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown> extends CoreTranslator<M> {
|
|
415
|
+
declare class ScopeTranslator<M extends LocaleMessages | unknown = unknown, ReplacementSchema = unknown> extends CoreTranslator<M, ReplacementSchema> {
|
|
417
416
|
constructor(options: ScopeTranslatorOptions<M>);
|
|
418
417
|
/** Create a scoped translator with a prefix key for resolving nested message paths. */
|
|
419
|
-
scoped<PK extends
|
|
418
|
+
scoped<PK extends LocalizedPreKey<M> | undefined = undefined>(preKey?: PK): PK extends string ? ScopeTranslatorMethods<M, ReplacementSchema, PK> : ScopeTranslatorMethods<M, ReplacementSchema>;
|
|
420
419
|
}
|
|
421
420
|
|
|
422
421
|
/** Semantic tag attributes map. */
|
|
@@ -491,4 +490,4 @@ interface Renderer<Output> {
|
|
|
491
490
|
*/
|
|
492
491
|
declare function renderRichMessage<Output>(message: MessageValue, renderer: Renderer<Output>): Output[];
|
|
493
492
|
|
|
494
|
-
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
|
@@ -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
|
};
|