intor-translator 1.3.2 → 1.4.1
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 +46 -18
- package/dist/index.d.cts +30 -37
- package/dist/index.d.ts +30 -37
- package/dist/index.js +46 -18
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -11,19 +11,19 @@ var findMessageInLocales = ({
|
|
|
11
11
|
key
|
|
12
12
|
}) => {
|
|
13
13
|
for (const locale of candidateLocales) {
|
|
14
|
-
const
|
|
15
|
-
if (!
|
|
16
|
-
let candidate =
|
|
14
|
+
const messagesForLocale = messages[locale];
|
|
15
|
+
if (!messagesForLocale) continue;
|
|
16
|
+
let candidate = messagesForLocale;
|
|
17
17
|
const keys = key.split(".");
|
|
18
|
-
for (const
|
|
19
|
-
if (candidate && typeof candidate === "object" &&
|
|
20
|
-
candidate = candidate[
|
|
18
|
+
for (const key2 of keys) {
|
|
19
|
+
if (candidate !== null && typeof candidate === "object" && key2 in candidate) {
|
|
20
|
+
candidate = candidate[key2];
|
|
21
21
|
} else {
|
|
22
22
|
candidate = void 0;
|
|
23
23
|
break;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
if (
|
|
26
|
+
if (candidate !== void 0) return candidate;
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
|
|
@@ -31,11 +31,15 @@ var findMessageInLocales = ({
|
|
|
31
31
|
var findMessage = rura.rura.createHook(
|
|
32
32
|
"findMessage",
|
|
33
33
|
(ctx) => {
|
|
34
|
-
ctx.
|
|
34
|
+
ctx.rawValue = void 0;
|
|
35
|
+
ctx.rawString = void 0;
|
|
36
|
+
const message = findMessageInLocales({
|
|
35
37
|
messages: ctx.messages,
|
|
36
38
|
candidateLocales: ctx.candidateLocales,
|
|
37
39
|
key: ctx.key
|
|
38
40
|
});
|
|
41
|
+
ctx.rawValue = message;
|
|
42
|
+
if (typeof message === "string") ctx.rawString = message;
|
|
39
43
|
},
|
|
40
44
|
200
|
|
41
45
|
);
|
|
@@ -50,7 +54,8 @@ function makeHandlerContext(ctx) {
|
|
|
50
54
|
key: ctx.key,
|
|
51
55
|
replacements: ctx.replacements,
|
|
52
56
|
candidateLocales: ctx.candidateLocales,
|
|
53
|
-
|
|
57
|
+
rawValue: ctx.rawValue,
|
|
58
|
+
rawString: ctx.rawString,
|
|
54
59
|
formattedMessage: ctx.formattedMessage,
|
|
55
60
|
meta: ctx.meta
|
|
56
61
|
});
|
|
@@ -60,9 +65,9 @@ function makeHandlerContext(ctx) {
|
|
|
60
65
|
var format = rura.rura.createHook(
|
|
61
66
|
"format",
|
|
62
67
|
(ctx) => {
|
|
63
|
-
const { config,
|
|
68
|
+
const { config, rawString } = ctx;
|
|
64
69
|
const { formatHandler } = config.handlers || {};
|
|
65
|
-
if (!formatHandler ||
|
|
70
|
+
if (!formatHandler || rawString === void 0) return;
|
|
66
71
|
ctx.formattedMessage = formatHandler(
|
|
67
72
|
makeHandlerContext(ctx)
|
|
68
73
|
);
|
|
@@ -93,8 +98,8 @@ var replaceValues = (message, params) => {
|
|
|
93
98
|
var interpolate = rura.rura.createHook(
|
|
94
99
|
"interpolate",
|
|
95
100
|
(ctx) => {
|
|
96
|
-
const {
|
|
97
|
-
const message = formattedMessage ??
|
|
101
|
+
const { rawString, formattedMessage, replacements } = ctx;
|
|
102
|
+
const message = formattedMessage ?? rawString;
|
|
98
103
|
if (typeof message !== "string" || !replacements) {
|
|
99
104
|
ctx.finalMessage = message;
|
|
100
105
|
return;
|
|
@@ -125,8 +130,8 @@ var loading = rura.rura.createHook(
|
|
|
125
130
|
var missing = rura.rura.createHook(
|
|
126
131
|
"missing",
|
|
127
132
|
(ctx) => {
|
|
128
|
-
const { config, key,
|
|
129
|
-
if (
|
|
133
|
+
const { config, key, rawString } = ctx;
|
|
134
|
+
if (rawString !== void 0) return;
|
|
130
135
|
const { missingHandler } = config.handlers || {};
|
|
131
136
|
if (missingHandler) {
|
|
132
137
|
return {
|
|
@@ -229,20 +234,31 @@ var hasKey = ({
|
|
|
229
234
|
}) => {
|
|
230
235
|
const candidateLocales = resolveCandidateLocales(targetLocale || locale);
|
|
231
236
|
const message = findMessageInLocales({ messages, candidateLocales, key });
|
|
232
|
-
return
|
|
237
|
+
return message !== void 0;
|
|
233
238
|
};
|
|
234
|
-
function
|
|
239
|
+
function runTranslate(options) {
|
|
235
240
|
const context = {
|
|
236
241
|
...options,
|
|
237
242
|
config: options.translateConfig,
|
|
238
243
|
candidateLocales: [],
|
|
239
244
|
meta: {}
|
|
240
245
|
};
|
|
241
|
-
|
|
246
|
+
return rura.rura.run(context, options.hooks);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/translators/methods/translate.ts
|
|
250
|
+
function translate(options) {
|
|
251
|
+
const { early, ctx, output } = runTranslate(options);
|
|
242
252
|
if (early === true) return output;
|
|
243
253
|
return ctx.finalMessage;
|
|
244
254
|
}
|
|
245
255
|
|
|
256
|
+
// src/translators/methods/translate-raw.ts
|
|
257
|
+
function translateRaw(options) {
|
|
258
|
+
const { ctx } = runTranslate(options);
|
|
259
|
+
return ctx.rawValue;
|
|
260
|
+
}
|
|
261
|
+
|
|
246
262
|
// src/translators/core-translator/core-translator.ts
|
|
247
263
|
var CoreTranslator = class extends BaseTranslator {
|
|
248
264
|
/** User-provided options including messages, locale, and config. */
|
|
@@ -298,6 +314,18 @@ var CoreTranslator = class extends BaseTranslator {
|
|
|
298
314
|
replacements
|
|
299
315
|
});
|
|
300
316
|
};
|
|
317
|
+
/** Get the raw message value for a key without formatting or interpolation. */
|
|
318
|
+
tRaw = (key, replacements) => {
|
|
319
|
+
return translateRaw({
|
|
320
|
+
hooks: this.hooks,
|
|
321
|
+
messages: this._messages,
|
|
322
|
+
locale: this._locale,
|
|
323
|
+
isLoading: this._isLoading,
|
|
324
|
+
translateConfig: this.translateConfig,
|
|
325
|
+
key,
|
|
326
|
+
replacements
|
|
327
|
+
});
|
|
328
|
+
};
|
|
301
329
|
};
|
|
302
330
|
|
|
303
331
|
// src/translators/scope-translator/utils/get-full-key.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { RuraHook } from 'rura';
|
|
2
2
|
|
|
3
|
+
type MessagePrimitive = string | number | boolean | null;
|
|
4
|
+
type MessageArray = readonly MessageValue[];
|
|
3
5
|
/**
|
|
4
|
-
* A
|
|
6
|
+
* A recursive message tree object.
|
|
5
7
|
*
|
|
6
|
-
*
|
|
8
|
+
* Represents the root message structure for a single locale
|
|
9
|
+
* (i.e. the value of `LocaleMessages[locale]`).
|
|
10
|
+
*/
|
|
11
|
+
interface MessageObject {
|
|
12
|
+
[key: string]: MessageValue;
|
|
13
|
+
}
|
|
14
|
+
/** A message value in the locale message tree. */
|
|
15
|
+
type MessageValue = MessagePrimitive | MessageObject | MessageArray;
|
|
16
|
+
/**
|
|
17
|
+
* A non-traversable message value.
|
|
7
18
|
*
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* const greeting: NestedMessage = "Hello";
|
|
11
|
-
* const userMessages: NestedMessage = {
|
|
12
|
-
* profile: {
|
|
13
|
-
* greeting: "Hello, user!",
|
|
14
|
-
* farewell: "Goodbye!"
|
|
15
|
-
* }
|
|
16
|
-
* };
|
|
17
|
-
* ```
|
|
19
|
+
* Leaf values represent the end of a message path.
|
|
18
20
|
*/
|
|
19
|
-
type
|
|
20
|
-
[key: string]: NestedMessage;
|
|
21
|
-
};
|
|
21
|
+
type MessageLeaf = MessagePrimitive | MessageArray;
|
|
22
22
|
/**
|
|
23
23
|
* Messages grouped by locale.
|
|
24
24
|
* Used to structure all available messages for multiple locales.
|
|
25
25
|
*
|
|
26
26
|
* - The root-level keys are locale identifiers, e.g., "en" or "zh-TW".
|
|
27
|
-
* - Each value is a `
|
|
27
|
+
* - Each value is a `MessageObject`, allowing for deeply nested message objects.
|
|
28
28
|
*
|
|
29
29
|
* @example
|
|
30
30
|
* ```ts
|
|
@@ -37,22 +37,11 @@ type NestedMessage = string | {
|
|
|
37
37
|
* failure: "Login failed"
|
|
38
38
|
* }
|
|
39
39
|
* }
|
|
40
|
-
* },
|
|
41
|
-
* "zh-TW": {
|
|
42
|
-
* welcome: "歡迎",
|
|
43
|
-
* auth: {
|
|
44
|
-
* login: {
|
|
45
|
-
* success: "登入成功",
|
|
46
|
-
* failure: "登入失敗"
|
|
47
|
-
* }
|
|
48
|
-
* }
|
|
49
40
|
* }
|
|
50
41
|
* };
|
|
51
42
|
* ```
|
|
52
43
|
*/
|
|
53
|
-
type LocaleMessages = Record<string,
|
|
54
|
-
[x: string]: NestedMessage;
|
|
55
|
-
}>;
|
|
44
|
+
type LocaleMessages = Record<string, MessageObject>;
|
|
56
45
|
/**
|
|
57
46
|
* Merges messages from all locales into a single unified structure,
|
|
58
47
|
* or extracts messages for a specific locale if `L` is provided.
|
|
@@ -144,7 +133,7 @@ type DefaultDepth = 15;
|
|
|
144
133
|
/** Countdown tuple for limiting recursive depth (up to 15 levels). */
|
|
145
134
|
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
146
135
|
/**
|
|
147
|
-
* Gets all dot-separated keys
|
|
136
|
+
* Gets all dot-separated keys of a nested object, stopping at message leaf values.
|
|
148
137
|
*
|
|
149
138
|
* @example
|
|
150
139
|
* ```ts
|
|
@@ -152,10 +141,10 @@ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
|
152
141
|
* ```
|
|
153
142
|
*/
|
|
154
143
|
type NodeKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never : M extends object ? {
|
|
155
|
-
[K in keyof M]: K extends string ? `${K}` | `${K}.${NodeKeys<M[K], Prev[D]>}` : never;
|
|
144
|
+
[K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}` | `${K & string}.${NodeKeys<M[K], Prev[D]>}` : never;
|
|
156
145
|
}[keyof M] : never;
|
|
157
146
|
/**
|
|
158
|
-
* Gets dot-separated keys to
|
|
147
|
+
* Gets dot-separated keys that resolve to message leaf values in a nested object.
|
|
159
148
|
*
|
|
160
149
|
* @example
|
|
161
150
|
* ```ts
|
|
@@ -163,7 +152,7 @@ type NodeKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never
|
|
|
163
152
|
* ```
|
|
164
153
|
*/
|
|
165
154
|
type LeafKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never : M extends object ? {
|
|
166
|
-
[K in keyof M]: M[K] extends
|
|
155
|
+
[K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}.${LeafKeys<M[K], Prev[D]>}` : never;
|
|
167
156
|
}[keyof M] : never;
|
|
168
157
|
|
|
169
158
|
/**
|
|
@@ -246,7 +235,7 @@ type MessagesAtPreKey<T, PK extends string> = PK extends `${infer Head}.${infer
|
|
|
246
235
|
* ScopedLeafKeys<typeof messages, "a", "zh">; // → "b"
|
|
247
236
|
* ```
|
|
248
237
|
*/
|
|
249
|
-
type ScopedLeafKeys<M, PK extends string, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer
|
|
238
|
+
type ScopedLeafKeys<M, PK extends string, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer Messages ? Messages extends MessageValue ? MessagesAtPreKey<Messages, PK> extends infer Scoped ? Scoped extends MessageObject ? LeafKeys<Scoped, D> : never : never : never : never : string;
|
|
250
239
|
|
|
251
240
|
/**
|
|
252
241
|
* Configuration options for translation behavior.
|
|
@@ -278,7 +267,7 @@ type LoadingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
|
|
|
278
267
|
type MissingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
|
|
279
268
|
/** Function to format a resolved message. */
|
|
280
269
|
type FormatHandler<Result = unknown> = (ctx: HandlerContext & {
|
|
281
|
-
|
|
270
|
+
rawString: string;
|
|
282
271
|
}) => Result;
|
|
283
272
|
/**
|
|
284
273
|
* Snapshot of the translate pipeline context exposed to handlers.
|
|
@@ -310,8 +299,10 @@ interface TranslateContext<Result = unknown> {
|
|
|
310
299
|
replacements?: Replacement;
|
|
311
300
|
/** Ordered list of locales to try, including fallbacks */
|
|
312
301
|
candidateLocales: string[];
|
|
313
|
-
/** Raw message
|
|
314
|
-
|
|
302
|
+
/** Raw message value resolved from the message tree. */
|
|
303
|
+
rawValue?: MessageValue;
|
|
304
|
+
/** Raw string message before formatting. */
|
|
305
|
+
rawString?: string;
|
|
315
306
|
/** Message after formatting (e.g. ICU, custom formatters) */
|
|
316
307
|
formattedMessage?: unknown;
|
|
317
308
|
/** Final value produced by the pipeline */
|
|
@@ -416,6 +407,8 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, L ext
|
|
|
416
407
|
hasKey: <K extends LocalizedLeafKeys<M, L>>(key: K, targetLocale?: Locale<M>) => boolean;
|
|
417
408
|
/** Get the translated message for a key, with optional replacements. */
|
|
418
409
|
t: <Result = string, K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => Result;
|
|
410
|
+
/** Get the raw message value for a key without formatting or interpolation. */
|
|
411
|
+
tRaw: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => MessageValue | undefined;
|
|
419
412
|
}
|
|
420
413
|
|
|
421
414
|
type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
|
|
@@ -496,4 +489,4 @@ interface Renderer<Output> {
|
|
|
496
489
|
*/
|
|
497
490
|
declare function renderRichMessage<Output>(message: string, renderer: Renderer<Output>): Output[];
|
|
498
491
|
|
|
499
|
-
export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedMessagesUnion, type LocalizedNodeKeys, type
|
|
492
|
+
export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedMessagesUnion, type LocalizedNodeKeys, type MessageObject, type MessageValue, type MissingHandler, type NodeKeys, type Renderer, type Replacement, type ScopedLeafKeys, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, parseRichMessage, renderRichMessage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { RuraHook } from 'rura';
|
|
2
2
|
|
|
3
|
+
type MessagePrimitive = string | number | boolean | null;
|
|
4
|
+
type MessageArray = readonly MessageValue[];
|
|
3
5
|
/**
|
|
4
|
-
* A
|
|
6
|
+
* A recursive message tree object.
|
|
5
7
|
*
|
|
6
|
-
*
|
|
8
|
+
* Represents the root message structure for a single locale
|
|
9
|
+
* (i.e. the value of `LocaleMessages[locale]`).
|
|
10
|
+
*/
|
|
11
|
+
interface MessageObject {
|
|
12
|
+
[key: string]: MessageValue;
|
|
13
|
+
}
|
|
14
|
+
/** A message value in the locale message tree. */
|
|
15
|
+
type MessageValue = MessagePrimitive | MessageObject | MessageArray;
|
|
16
|
+
/**
|
|
17
|
+
* A non-traversable message value.
|
|
7
18
|
*
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* const greeting: NestedMessage = "Hello";
|
|
11
|
-
* const userMessages: NestedMessage = {
|
|
12
|
-
* profile: {
|
|
13
|
-
* greeting: "Hello, user!",
|
|
14
|
-
* farewell: "Goodbye!"
|
|
15
|
-
* }
|
|
16
|
-
* };
|
|
17
|
-
* ```
|
|
19
|
+
* Leaf values represent the end of a message path.
|
|
18
20
|
*/
|
|
19
|
-
type
|
|
20
|
-
[key: string]: NestedMessage;
|
|
21
|
-
};
|
|
21
|
+
type MessageLeaf = MessagePrimitive | MessageArray;
|
|
22
22
|
/**
|
|
23
23
|
* Messages grouped by locale.
|
|
24
24
|
* Used to structure all available messages for multiple locales.
|
|
25
25
|
*
|
|
26
26
|
* - The root-level keys are locale identifiers, e.g., "en" or "zh-TW".
|
|
27
|
-
* - Each value is a `
|
|
27
|
+
* - Each value is a `MessageObject`, allowing for deeply nested message objects.
|
|
28
28
|
*
|
|
29
29
|
* @example
|
|
30
30
|
* ```ts
|
|
@@ -37,22 +37,11 @@ type NestedMessage = string | {
|
|
|
37
37
|
* failure: "Login failed"
|
|
38
38
|
* }
|
|
39
39
|
* }
|
|
40
|
-
* },
|
|
41
|
-
* "zh-TW": {
|
|
42
|
-
* welcome: "歡迎",
|
|
43
|
-
* auth: {
|
|
44
|
-
* login: {
|
|
45
|
-
* success: "登入成功",
|
|
46
|
-
* failure: "登入失敗"
|
|
47
|
-
* }
|
|
48
|
-
* }
|
|
49
40
|
* }
|
|
50
41
|
* };
|
|
51
42
|
* ```
|
|
52
43
|
*/
|
|
53
|
-
type LocaleMessages = Record<string,
|
|
54
|
-
[x: string]: NestedMessage;
|
|
55
|
-
}>;
|
|
44
|
+
type LocaleMessages = Record<string, MessageObject>;
|
|
56
45
|
/**
|
|
57
46
|
* Merges messages from all locales into a single unified structure,
|
|
58
47
|
* or extracts messages for a specific locale if `L` is provided.
|
|
@@ -144,7 +133,7 @@ type DefaultDepth = 15;
|
|
|
144
133
|
/** Countdown tuple for limiting recursive depth (up to 15 levels). */
|
|
145
134
|
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
146
135
|
/**
|
|
147
|
-
* Gets all dot-separated keys
|
|
136
|
+
* Gets all dot-separated keys of a nested object, stopping at message leaf values.
|
|
148
137
|
*
|
|
149
138
|
* @example
|
|
150
139
|
* ```ts
|
|
@@ -152,10 +141,10 @@ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
|
|
152
141
|
* ```
|
|
153
142
|
*/
|
|
154
143
|
type NodeKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never : M extends object ? {
|
|
155
|
-
[K in keyof M]: K extends string ? `${K}` | `${K}.${NodeKeys<M[K], Prev[D]>}` : never;
|
|
144
|
+
[K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}` | `${K & string}.${NodeKeys<M[K], Prev[D]>}` : never;
|
|
156
145
|
}[keyof M] : never;
|
|
157
146
|
/**
|
|
158
|
-
* Gets dot-separated keys to
|
|
147
|
+
* Gets dot-separated keys that resolve to message leaf values in a nested object.
|
|
159
148
|
*
|
|
160
149
|
* @example
|
|
161
150
|
* ```ts
|
|
@@ -163,7 +152,7 @@ type NodeKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never
|
|
|
163
152
|
* ```
|
|
164
153
|
*/
|
|
165
154
|
type LeafKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never : M extends object ? {
|
|
166
|
-
[K in keyof M]: M[K] extends
|
|
155
|
+
[K in keyof M]: M[K] extends MessageLeaf ? `${K & string}` : M[K] extends object ? `${K & string}.${LeafKeys<M[K], Prev[D]>}` : never;
|
|
167
156
|
}[keyof M] : never;
|
|
168
157
|
|
|
169
158
|
/**
|
|
@@ -246,7 +235,7 @@ type MessagesAtPreKey<T, PK extends string> = PK extends `${infer Head}.${infer
|
|
|
246
235
|
* ScopedLeafKeys<typeof messages, "a", "zh">; // → "b"
|
|
247
236
|
* ```
|
|
248
237
|
*/
|
|
249
|
-
type ScopedLeafKeys<M, PK extends string, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer
|
|
238
|
+
type ScopedLeafKeys<M, PK extends string, L extends keyof M | "union" = "union", D extends number = DefaultDepth> = M extends LocaleMessages ? LocalizedMessagesUnion<M, L> extends infer Messages ? Messages extends MessageValue ? MessagesAtPreKey<Messages, PK> extends infer Scoped ? Scoped extends MessageObject ? LeafKeys<Scoped, D> : never : never : never : never : string;
|
|
250
239
|
|
|
251
240
|
/**
|
|
252
241
|
* Configuration options for translation behavior.
|
|
@@ -278,7 +267,7 @@ type LoadingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
|
|
|
278
267
|
type MissingHandler<Result = unknown> = (ctx: HandlerContext) => Result;
|
|
279
268
|
/** Function to format a resolved message. */
|
|
280
269
|
type FormatHandler<Result = unknown> = (ctx: HandlerContext & {
|
|
281
|
-
|
|
270
|
+
rawString: string;
|
|
282
271
|
}) => Result;
|
|
283
272
|
/**
|
|
284
273
|
* Snapshot of the translate pipeline context exposed to handlers.
|
|
@@ -310,8 +299,10 @@ interface TranslateContext<Result = unknown> {
|
|
|
310
299
|
replacements?: Replacement;
|
|
311
300
|
/** Ordered list of locales to try, including fallbacks */
|
|
312
301
|
candidateLocales: string[];
|
|
313
|
-
/** Raw message
|
|
314
|
-
|
|
302
|
+
/** Raw message value resolved from the message tree. */
|
|
303
|
+
rawValue?: MessageValue;
|
|
304
|
+
/** Raw string message before formatting. */
|
|
305
|
+
rawString?: string;
|
|
315
306
|
/** Message after formatting (e.g. ICU, custom formatters) */
|
|
316
307
|
formattedMessage?: unknown;
|
|
317
308
|
/** Final value produced by the pipeline */
|
|
@@ -416,6 +407,8 @@ declare class CoreTranslator<M extends LocaleMessages | unknown = unknown, L ext
|
|
|
416
407
|
hasKey: <K extends LocalizedLeafKeys<M, L>>(key: K, targetLocale?: Locale<M>) => boolean;
|
|
417
408
|
/** Get the translated message for a key, with optional replacements. */
|
|
418
409
|
t: <Result = string, K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => Result;
|
|
410
|
+
/** Get the raw message value for a key without formatting or interpolation. */
|
|
411
|
+
tRaw: <K extends LocalizedLeafKeys<M, L> = LocalizedLeafKeys<M, L>>(key: K, replacements?: Replacement) => MessageValue | undefined;
|
|
419
412
|
}
|
|
420
413
|
|
|
421
414
|
type ScopeTranslatorOptions<M> = CoreTranslatorOptions<M>;
|
|
@@ -496,4 +489,4 @@ interface Renderer<Output> {
|
|
|
496
489
|
*/
|
|
497
490
|
declare function renderRichMessage<Output>(message: string, renderer: Renderer<Output>): Output[];
|
|
498
491
|
|
|
499
|
-
export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedMessagesUnion, type LocalizedNodeKeys, type
|
|
492
|
+
export { type ASTNode, type Attributes, type DefaultDepth, type FallbackLocalesMap, type FormatHandler, type HandlerContext, type LeafKeys, type LoadingHandler, type Locale, type LocaleMessages, type LocalizedLeafKeys, type LocalizedMessagesUnion, type LocalizedNodeKeys, type MessageObject, type MessageValue, type MissingHandler, type NodeKeys, type Renderer, type Replacement, type ScopedLeafKeys, type TranslateConfig, type TranslateContext, type TranslateHandlers, type TranslateHook, ScopeTranslator as Translator, type ScopeTranslatorMethods as TranslatorMethods, type ScopeTranslatorOptions as TranslatorOptions, type TranslatorPlugin, parseRichMessage, renderRichMessage };
|
package/dist/index.js
CHANGED
|
@@ -9,19 +9,19 @@ var findMessageInLocales = ({
|
|
|
9
9
|
key
|
|
10
10
|
}) => {
|
|
11
11
|
for (const locale of candidateLocales) {
|
|
12
|
-
const
|
|
13
|
-
if (!
|
|
14
|
-
let candidate =
|
|
12
|
+
const messagesForLocale = messages[locale];
|
|
13
|
+
if (!messagesForLocale) continue;
|
|
14
|
+
let candidate = messagesForLocale;
|
|
15
15
|
const keys = key.split(".");
|
|
16
|
-
for (const
|
|
17
|
-
if (candidate && typeof candidate === "object" &&
|
|
18
|
-
candidate = candidate[
|
|
16
|
+
for (const key2 of keys) {
|
|
17
|
+
if (candidate !== null && typeof candidate === "object" && key2 in candidate) {
|
|
18
|
+
candidate = candidate[key2];
|
|
19
19
|
} else {
|
|
20
20
|
candidate = void 0;
|
|
21
21
|
break;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
if (
|
|
24
|
+
if (candidate !== void 0) return candidate;
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -29,11 +29,15 @@ var findMessageInLocales = ({
|
|
|
29
29
|
var findMessage = rura.createHook(
|
|
30
30
|
"findMessage",
|
|
31
31
|
(ctx) => {
|
|
32
|
-
ctx.
|
|
32
|
+
ctx.rawValue = void 0;
|
|
33
|
+
ctx.rawString = void 0;
|
|
34
|
+
const message = findMessageInLocales({
|
|
33
35
|
messages: ctx.messages,
|
|
34
36
|
candidateLocales: ctx.candidateLocales,
|
|
35
37
|
key: ctx.key
|
|
36
38
|
});
|
|
39
|
+
ctx.rawValue = message;
|
|
40
|
+
if (typeof message === "string") ctx.rawString = message;
|
|
37
41
|
},
|
|
38
42
|
200
|
|
39
43
|
);
|
|
@@ -48,7 +52,8 @@ function makeHandlerContext(ctx) {
|
|
|
48
52
|
key: ctx.key,
|
|
49
53
|
replacements: ctx.replacements,
|
|
50
54
|
candidateLocales: ctx.candidateLocales,
|
|
51
|
-
|
|
55
|
+
rawValue: ctx.rawValue,
|
|
56
|
+
rawString: ctx.rawString,
|
|
52
57
|
formattedMessage: ctx.formattedMessage,
|
|
53
58
|
meta: ctx.meta
|
|
54
59
|
});
|
|
@@ -58,9 +63,9 @@ function makeHandlerContext(ctx) {
|
|
|
58
63
|
var format = rura.createHook(
|
|
59
64
|
"format",
|
|
60
65
|
(ctx) => {
|
|
61
|
-
const { config,
|
|
66
|
+
const { config, rawString } = ctx;
|
|
62
67
|
const { formatHandler } = config.handlers || {};
|
|
63
|
-
if (!formatHandler ||
|
|
68
|
+
if (!formatHandler || rawString === void 0) return;
|
|
64
69
|
ctx.formattedMessage = formatHandler(
|
|
65
70
|
makeHandlerContext(ctx)
|
|
66
71
|
);
|
|
@@ -91,8 +96,8 @@ var replaceValues = (message, params) => {
|
|
|
91
96
|
var interpolate = rura.createHook(
|
|
92
97
|
"interpolate",
|
|
93
98
|
(ctx) => {
|
|
94
|
-
const {
|
|
95
|
-
const message = formattedMessage ??
|
|
99
|
+
const { rawString, formattedMessage, replacements } = ctx;
|
|
100
|
+
const message = formattedMessage ?? rawString;
|
|
96
101
|
if (typeof message !== "string" || !replacements) {
|
|
97
102
|
ctx.finalMessage = message;
|
|
98
103
|
return;
|
|
@@ -123,8 +128,8 @@ var loading = rura.createHook(
|
|
|
123
128
|
var missing = rura.createHook(
|
|
124
129
|
"missing",
|
|
125
130
|
(ctx) => {
|
|
126
|
-
const { config, key,
|
|
127
|
-
if (
|
|
131
|
+
const { config, key, rawString } = ctx;
|
|
132
|
+
if (rawString !== void 0) return;
|
|
128
133
|
const { missingHandler } = config.handlers || {};
|
|
129
134
|
if (missingHandler) {
|
|
130
135
|
return {
|
|
@@ -227,20 +232,31 @@ var hasKey = ({
|
|
|
227
232
|
}) => {
|
|
228
233
|
const candidateLocales = resolveCandidateLocales(targetLocale || locale);
|
|
229
234
|
const message = findMessageInLocales({ messages, candidateLocales, key });
|
|
230
|
-
return
|
|
235
|
+
return message !== void 0;
|
|
231
236
|
};
|
|
232
|
-
function
|
|
237
|
+
function runTranslate(options) {
|
|
233
238
|
const context = {
|
|
234
239
|
...options,
|
|
235
240
|
config: options.translateConfig,
|
|
236
241
|
candidateLocales: [],
|
|
237
242
|
meta: {}
|
|
238
243
|
};
|
|
239
|
-
|
|
244
|
+
return rura.run(context, options.hooks);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/translators/methods/translate.ts
|
|
248
|
+
function translate(options) {
|
|
249
|
+
const { early, ctx, output } = runTranslate(options);
|
|
240
250
|
if (early === true) return output;
|
|
241
251
|
return ctx.finalMessage;
|
|
242
252
|
}
|
|
243
253
|
|
|
254
|
+
// src/translators/methods/translate-raw.ts
|
|
255
|
+
function translateRaw(options) {
|
|
256
|
+
const { ctx } = runTranslate(options);
|
|
257
|
+
return ctx.rawValue;
|
|
258
|
+
}
|
|
259
|
+
|
|
244
260
|
// src/translators/core-translator/core-translator.ts
|
|
245
261
|
var CoreTranslator = class extends BaseTranslator {
|
|
246
262
|
/** User-provided options including messages, locale, and config. */
|
|
@@ -296,6 +312,18 @@ var CoreTranslator = class extends BaseTranslator {
|
|
|
296
312
|
replacements
|
|
297
313
|
});
|
|
298
314
|
};
|
|
315
|
+
/** Get the raw message value for a key without formatting or interpolation. */
|
|
316
|
+
tRaw = (key, replacements) => {
|
|
317
|
+
return translateRaw({
|
|
318
|
+
hooks: this.hooks,
|
|
319
|
+
messages: this._messages,
|
|
320
|
+
locale: this._locale,
|
|
321
|
+
isLoading: this._isLoading,
|
|
322
|
+
translateConfig: this.translateConfig,
|
|
323
|
+
key,
|
|
324
|
+
replacements
|
|
325
|
+
});
|
|
326
|
+
};
|
|
299
327
|
};
|
|
300
328
|
|
|
301
329
|
// src/translators/scope-translator/utils/get-full-key.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intor-translator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "🤖 A modern, type-safe i18n engine.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Yiming Liao",
|
|
@@ -50,13 +50,14 @@
|
|
|
50
50
|
"node": ">=16.0.0"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
|
-
"build": "tsup",
|
|
54
|
-
"prepublishOnly": "yarn build",
|
|
55
|
-
"test": "vitest",
|
|
56
53
|
"type": "tsc --noEmit",
|
|
57
54
|
"lint": "eslint",
|
|
58
55
|
"lint:debug": "eslint --debug",
|
|
56
|
+
"test": "vitest",
|
|
57
|
+
"test:types": "tsx scripts/test-types.ts",
|
|
59
58
|
"knip": "knip --config .config/knip.config.ts",
|
|
59
|
+
"build": "tsup",
|
|
60
|
+
"prepublishOnly": "yarn build",
|
|
60
61
|
"examples:html": "vite --config examples/html/basic/vite.config.ts",
|
|
61
62
|
"examples:html:rich-message": "vite --config examples/html/rich-message/vite.config.ts"
|
|
62
63
|
},
|