@intlify/core-base 10.0.0-beta.5 → 10.0.0-rc.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/core-base.cjs +1253 -1252
- package/dist/core-base.d.ts +20 -5
- package/dist/core-base.esm-browser.js +1253 -1252
- package/dist/core-base.esm-browser.prod.js +2 -2
- package/dist/core-base.global.js +1253 -1252
- package/dist/core-base.global.prod.js +2 -2
- package/dist/core-base.mjs +1252 -1251
- package/dist/core-base.prod.cjs +1017 -1016
- package/package.json +4 -4
package/dist/core-base.prod.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* core-base v10.0.0-
|
|
2
|
+
* core-base v10.0.0-rc.1
|
|
3
3
|
* (c) 2024 kazuya kawaguchi
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -8,402 +8,135 @@
|
|
|
8
8
|
var messageCompiler = require('@intlify/message-compiler');
|
|
9
9
|
var shared = require('@intlify/shared');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
15
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
16
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
17
|
-
};
|
|
18
|
-
pathStateMachine[1 /* States.IN_PATH */] = {
|
|
19
|
-
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */],
|
|
20
|
-
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */],
|
|
21
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
22
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
23
|
-
};
|
|
24
|
-
pathStateMachine[2 /* States.BEFORE_IDENT */] = {
|
|
25
|
-
["w" /* PathCharTypes.WORKSPACE */]: [2 /* States.BEFORE_IDENT */],
|
|
26
|
-
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
27
|
-
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */]
|
|
28
|
-
};
|
|
29
|
-
pathStateMachine[3 /* States.IN_IDENT */] = {
|
|
30
|
-
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
31
|
-
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
32
|
-
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */, 1 /* Actions.PUSH */],
|
|
33
|
-
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */, 1 /* Actions.PUSH */],
|
|
34
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */, 1 /* Actions.PUSH */],
|
|
35
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */, 1 /* Actions.PUSH */]
|
|
36
|
-
};
|
|
37
|
-
pathStateMachine[4 /* States.IN_SUB_PATH */] = {
|
|
38
|
-
["'" /* PathCharTypes.SINGLE_QUOTE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
39
|
-
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
40
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [
|
|
41
|
-
4 /* States.IN_SUB_PATH */,
|
|
42
|
-
2 /* Actions.INC_SUB_PATH_DEPTH */
|
|
43
|
-
],
|
|
44
|
-
["]" /* PathCharTypes.RIGHT_BRACKET */]: [1 /* States.IN_PATH */, 3 /* Actions.PUSH_SUB_PATH */],
|
|
45
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
46
|
-
["l" /* PathCharTypes.ELSE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */]
|
|
47
|
-
};
|
|
48
|
-
pathStateMachine[5 /* States.IN_SINGLE_QUOTE */] = {
|
|
49
|
-
["'" /* PathCharTypes.SINGLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
50
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
51
|
-
["l" /* PathCharTypes.ELSE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
52
|
-
};
|
|
53
|
-
pathStateMachine[6 /* States.IN_DOUBLE_QUOTE */] = {
|
|
54
|
-
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
55
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
56
|
-
["l" /* PathCharTypes.ELSE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Check if an expression is a literal value.
|
|
60
|
-
*/
|
|
61
|
-
const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
|
|
62
|
-
function isLiteral(exp) {
|
|
63
|
-
return literalValueRE.test(exp);
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Strip quotes from a string
|
|
67
|
-
*/
|
|
68
|
-
function stripQuotes(str) {
|
|
69
|
-
const a = str.charCodeAt(0);
|
|
70
|
-
const b = str.charCodeAt(str.length - 1);
|
|
71
|
-
return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
|
|
11
|
+
function format(ast) {
|
|
12
|
+
const msg = (ctx) => formatParts(ctx, ast);
|
|
13
|
+
return msg;
|
|
72
14
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return
|
|
15
|
+
function formatParts(ctx, ast) {
|
|
16
|
+
const body = ast.b || ast.body;
|
|
17
|
+
if ((body.t || body.type) === 1 /* NodeTypes.Plural */) {
|
|
18
|
+
const plural = body;
|
|
19
|
+
const cases = plural.c || plural.cases;
|
|
20
|
+
return ctx.plural(cases.reduce((messages, c) => [
|
|
21
|
+
...messages,
|
|
22
|
+
formatMessageParts(ctx, c)
|
|
23
|
+
], []));
|
|
79
24
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
case 0x5b: // [
|
|
83
|
-
case 0x5d: // ]
|
|
84
|
-
case 0x2e: // .
|
|
85
|
-
case 0x22: // "
|
|
86
|
-
case 0x27: // '
|
|
87
|
-
return ch;
|
|
88
|
-
case 0x5f: // _
|
|
89
|
-
case 0x24: // $
|
|
90
|
-
case 0x2d: // -
|
|
91
|
-
return "i" /* PathCharTypes.IDENT */;
|
|
92
|
-
case 0x09: // Tab (HT)
|
|
93
|
-
case 0x0a: // Newline (LF)
|
|
94
|
-
case 0x0d: // Return (CR)
|
|
95
|
-
case 0xa0: // No-break space (NBSP)
|
|
96
|
-
case 0xfeff: // Byte Order Mark (BOM)
|
|
97
|
-
case 0x2028: // Line Separator (LS)
|
|
98
|
-
case 0x2029: // Paragraph Separator (PS)
|
|
99
|
-
return "w" /* PathCharTypes.WORKSPACE */;
|
|
25
|
+
else {
|
|
26
|
+
return formatMessageParts(ctx, body);
|
|
100
27
|
}
|
|
101
|
-
return "i" /* PathCharTypes.IDENT */;
|
|
102
28
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const trimmed = path.trim();
|
|
110
|
-
// invalid leading 0
|
|
111
|
-
if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
|
|
112
|
-
return false;
|
|
29
|
+
function formatMessageParts(ctx, node) {
|
|
30
|
+
const _static = node.s || node.static;
|
|
31
|
+
if (_static) {
|
|
32
|
+
return ctx.type === 'text'
|
|
33
|
+
? _static
|
|
34
|
+
: ctx.normalize([_static]);
|
|
113
35
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Parse a string path into an array of segments
|
|
120
|
-
*/
|
|
121
|
-
function parse(path) {
|
|
122
|
-
const keys = [];
|
|
123
|
-
let index = -1;
|
|
124
|
-
let mode = 0 /* States.BEFORE_PATH */;
|
|
125
|
-
let subPathDepth = 0;
|
|
126
|
-
let c;
|
|
127
|
-
let key; // eslint-disable-line
|
|
128
|
-
let newChar;
|
|
129
|
-
let type;
|
|
130
|
-
let transition;
|
|
131
|
-
let action;
|
|
132
|
-
let typeMap;
|
|
133
|
-
const actions = [];
|
|
134
|
-
actions[0 /* Actions.APPEND */] = () => {
|
|
135
|
-
if (key === undefined) {
|
|
136
|
-
key = newChar;
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
key += newChar;
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
actions[1 /* Actions.PUSH */] = () => {
|
|
143
|
-
if (key !== undefined) {
|
|
144
|
-
keys.push(key);
|
|
145
|
-
key = undefined;
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
actions[2 /* Actions.INC_SUB_PATH_DEPTH */] = () => {
|
|
149
|
-
actions[0 /* Actions.APPEND */]();
|
|
150
|
-
subPathDepth++;
|
|
151
|
-
};
|
|
152
|
-
actions[3 /* Actions.PUSH_SUB_PATH */] = () => {
|
|
153
|
-
if (subPathDepth > 0) {
|
|
154
|
-
subPathDepth--;
|
|
155
|
-
mode = 4 /* States.IN_SUB_PATH */;
|
|
156
|
-
actions[0 /* Actions.APPEND */]();
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
subPathDepth = 0;
|
|
160
|
-
if (key === undefined) {
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
key = formatSubPath(key);
|
|
164
|
-
if (key === false) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
actions[1 /* Actions.PUSH */]();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
function maybeUnescapeQuote() {
|
|
173
|
-
const nextChar = path[index + 1];
|
|
174
|
-
if ((mode === 5 /* States.IN_SINGLE_QUOTE */ &&
|
|
175
|
-
nextChar === "'" /* PathCharTypes.SINGLE_QUOTE */) ||
|
|
176
|
-
(mode === 6 /* States.IN_DOUBLE_QUOTE */ &&
|
|
177
|
-
nextChar === "\"" /* PathCharTypes.DOUBLE_QUOTE */)) {
|
|
178
|
-
index++;
|
|
179
|
-
newChar = '\\' + nextChar;
|
|
180
|
-
actions[0 /* Actions.APPEND */]();
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
36
|
+
else {
|
|
37
|
+
const messages = (node.i || node.items).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
|
|
38
|
+
return ctx.normalize(messages);
|
|
183
39
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
40
|
+
}
|
|
41
|
+
function formatMessagePart(ctx, node) {
|
|
42
|
+
const type = node.t || node.type;
|
|
43
|
+
switch (type) {
|
|
44
|
+
case 3 /* NodeTypes.Text */: {
|
|
45
|
+
const text = node;
|
|
46
|
+
return (text.v || text.value);
|
|
189
47
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// check parse error
|
|
194
|
-
if (transition === 8 /* States.ERROR */) {
|
|
195
|
-
return;
|
|
48
|
+
case 9 /* NodeTypes.Literal */: {
|
|
49
|
+
const literal = node;
|
|
50
|
+
return (literal.v || literal.value);
|
|
196
51
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (action) {
|
|
201
|
-
newChar = c;
|
|
202
|
-
if (action() === false) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
52
|
+
case 4 /* NodeTypes.Named */: {
|
|
53
|
+
const named = node;
|
|
54
|
+
return ctx.interpolate(ctx.named(named.k || named.key));
|
|
206
55
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return
|
|
56
|
+
case 5 /* NodeTypes.List */: {
|
|
57
|
+
const list = node;
|
|
58
|
+
return ctx.interpolate(ctx.list(list.i != null ? list.i : list.index));
|
|
210
59
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* key-value message resolver
|
|
217
|
-
*
|
|
218
|
-
* @remarks
|
|
219
|
-
* Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
|
|
220
|
-
*
|
|
221
|
-
* @param obj - A target object to be resolved with path
|
|
222
|
-
* @param path - A {@link Path | path} to resolve the value of message
|
|
223
|
-
*
|
|
224
|
-
* @returns A resolved {@link PathValue | path value}
|
|
225
|
-
*
|
|
226
|
-
* @VueI18nGeneral
|
|
227
|
-
*/
|
|
228
|
-
function resolveWithKeyValue(obj, path) {
|
|
229
|
-
return shared.isObject(obj) ? obj[path] : null;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* message resolver
|
|
233
|
-
*
|
|
234
|
-
* @remarks
|
|
235
|
-
* Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
|
|
236
|
-
*
|
|
237
|
-
* @param obj - A target object to be resolved with path
|
|
238
|
-
* @param path - A {@link Path | path} to resolve the value of message
|
|
239
|
-
*
|
|
240
|
-
* @returns A resolved {@link PathValue | path value}
|
|
241
|
-
*
|
|
242
|
-
* @VueI18nGeneral
|
|
243
|
-
*/
|
|
244
|
-
function resolveValue(obj, path) {
|
|
245
|
-
// check object
|
|
246
|
-
if (!shared.isObject(obj)) {
|
|
247
|
-
return null;
|
|
248
|
-
}
|
|
249
|
-
// parse path
|
|
250
|
-
let hit = cache.get(path);
|
|
251
|
-
if (!hit) {
|
|
252
|
-
hit = parse(path);
|
|
253
|
-
if (hit) {
|
|
254
|
-
cache.set(path, hit);
|
|
60
|
+
case 6 /* NodeTypes.Linked */: {
|
|
61
|
+
const linked = node;
|
|
62
|
+
const modifier = linked.m || linked.modifier;
|
|
63
|
+
return ctx.linked(formatMessagePart(ctx, linked.k || linked.key), modifier ? formatMessagePart(ctx, modifier) : undefined, ctx.type);
|
|
255
64
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return null;
|
|
260
|
-
}
|
|
261
|
-
// resolve path value
|
|
262
|
-
const len = hit.length;
|
|
263
|
-
let last = obj;
|
|
264
|
-
let i = 0;
|
|
265
|
-
while (i < len) {
|
|
266
|
-
const val = last[hit[i]];
|
|
267
|
-
if (val === undefined) {
|
|
268
|
-
return null;
|
|
65
|
+
case 7 /* NodeTypes.LinkedKey */: {
|
|
66
|
+
const linkedKey = node;
|
|
67
|
+
return (linkedKey.v || linkedKey.value);
|
|
269
68
|
}
|
|
270
|
-
|
|
271
|
-
|
|
69
|
+
case 8 /* NodeTypes.LinkedModifier */: {
|
|
70
|
+
const linkedModifier = node;
|
|
71
|
+
return (linkedModifier.v || linkedModifier.value);
|
|
272
72
|
}
|
|
273
|
-
|
|
274
|
-
|
|
73
|
+
default:
|
|
74
|
+
throw new Error(`unhandled node type on format message part: ${type}`);
|
|
275
75
|
}
|
|
276
|
-
return last;
|
|
277
76
|
}
|
|
278
77
|
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const DEFAULT_INTERPOLATE = shared.toDisplayString;
|
|
284
|
-
function pluralDefault(choice, choicesLength) {
|
|
285
|
-
choice = Math.abs(choice);
|
|
286
|
-
if (choicesLength === 2) {
|
|
287
|
-
// prettier-ignore
|
|
288
|
-
return choice
|
|
289
|
-
? choice > 1
|
|
290
|
-
? 1
|
|
291
|
-
: 0
|
|
292
|
-
: 1;
|
|
293
|
-
}
|
|
294
|
-
return choice ? Math.min(choice, 2) : 0;
|
|
295
|
-
}
|
|
296
|
-
function getPluralIndex(options) {
|
|
297
|
-
// prettier-ignore
|
|
298
|
-
const index = shared.isNumber(options.pluralIndex)
|
|
299
|
-
? options.pluralIndex
|
|
300
|
-
: -1;
|
|
301
|
-
// prettier-ignore
|
|
302
|
-
return options.named && (shared.isNumber(options.named.count) || shared.isNumber(options.named.n))
|
|
303
|
-
? shared.isNumber(options.named.count)
|
|
304
|
-
? options.named.count
|
|
305
|
-
: shared.isNumber(options.named.n)
|
|
306
|
-
? options.named.n
|
|
307
|
-
: index
|
|
308
|
-
: index;
|
|
309
|
-
}
|
|
310
|
-
function normalizeNamed(pluralIndex, props) {
|
|
311
|
-
if (!props.count) {
|
|
312
|
-
props.count = pluralIndex;
|
|
313
|
-
}
|
|
314
|
-
if (!props.n) {
|
|
315
|
-
props.n = pluralIndex;
|
|
316
|
-
}
|
|
78
|
+
const defaultOnCacheKey = (message) => message;
|
|
79
|
+
let compileCache = Object.create(null);
|
|
80
|
+
function clearCompileCache() {
|
|
81
|
+
compileCache = Object.create(null);
|
|
317
82
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
shared.isFunction(options.pluralRules[locale])
|
|
329
|
-
? pluralDefault
|
|
330
|
-
: undefined;
|
|
331
|
-
const plural = (messages) => {
|
|
332
|
-
return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
|
|
83
|
+
const isMessageAST = (val) => shared.isObject(val) &&
|
|
84
|
+
(val.t === 0 || val.type === 0) &&
|
|
85
|
+
('b' in val || 'body' in val);
|
|
86
|
+
function baseCompile(message, options = {}) {
|
|
87
|
+
// error detecting on compile
|
|
88
|
+
let detectError = false;
|
|
89
|
+
const onError = options.onError || messageCompiler.defaultOnError;
|
|
90
|
+
options.onError = (err) => {
|
|
91
|
+
detectError = true;
|
|
92
|
+
onError(err);
|
|
333
93
|
};
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
94
|
+
// compile with mesasge-compiler
|
|
95
|
+
return { ...messageCompiler.baseCompile(message, options), detectError };
|
|
96
|
+
}
|
|
97
|
+
/* #__NO_SIDE_EFFECTS__ */
|
|
98
|
+
function compile(message, context) {
|
|
99
|
+
if (shared.isString(message)) {
|
|
100
|
+
// check HTML message
|
|
101
|
+
shared.isBoolean(context.warnHtmlMessage)
|
|
102
|
+
? context.warnHtmlMessage
|
|
103
|
+
: true;
|
|
104
|
+
// check caches
|
|
105
|
+
const onCacheKey = context.onCacheKey || defaultOnCacheKey;
|
|
106
|
+
const cacheKey = onCacheKey(message);
|
|
107
|
+
const cached = compileCache[cacheKey];
|
|
108
|
+
if (cached) {
|
|
109
|
+
return cached;
|
|
110
|
+
}
|
|
111
|
+
// compile with JIT mode
|
|
112
|
+
const { ast, detectError } = baseCompile(message, {
|
|
113
|
+
...context,
|
|
114
|
+
location: false,
|
|
115
|
+
jit: true
|
|
116
|
+
});
|
|
117
|
+
// compose message function from AST
|
|
118
|
+
const msg = format(ast);
|
|
119
|
+
// if occurred compile error, don't cache
|
|
120
|
+
return !detectError
|
|
121
|
+
? (compileCache[cacheKey] = msg)
|
|
351
122
|
: msg;
|
|
352
123
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
shared.isFunction(options.processor.interpolate)
|
|
361
|
-
? options.processor.interpolate
|
|
362
|
-
: DEFAULT_INTERPOLATE;
|
|
363
|
-
const type = shared.isPlainObject(options.processor) && shared.isString(options.processor.type)
|
|
364
|
-
? options.processor.type
|
|
365
|
-
: DEFAULT_MESSAGE_DATA_TYPE;
|
|
366
|
-
const linked = (key, ...args) => {
|
|
367
|
-
const [arg1, arg2] = args;
|
|
368
|
-
let type = 'text';
|
|
369
|
-
let modifier = '';
|
|
370
|
-
if (args.length === 1) {
|
|
371
|
-
if (shared.isObject(arg1)) {
|
|
372
|
-
modifier = arg1.modifier || modifier;
|
|
373
|
-
type = arg1.type || type;
|
|
374
|
-
}
|
|
375
|
-
else if (shared.isString(arg1)) {
|
|
376
|
-
modifier = arg1 || modifier;
|
|
124
|
+
else {
|
|
125
|
+
// AST case (passed from bundler)
|
|
126
|
+
const cacheKey = message.cacheKey;
|
|
127
|
+
if (cacheKey) {
|
|
128
|
+
const cached = compileCache[cacheKey];
|
|
129
|
+
if (cached) {
|
|
130
|
+
return cached;
|
|
377
131
|
}
|
|
132
|
+
// compose message function from message (AST)
|
|
133
|
+
return (compileCache[cacheKey] =
|
|
134
|
+
format(message));
|
|
378
135
|
}
|
|
379
|
-
else
|
|
380
|
-
|
|
381
|
-
modifier = arg1 || modifier;
|
|
382
|
-
}
|
|
383
|
-
if (shared.isString(arg2)) {
|
|
384
|
-
type = arg2 || type;
|
|
385
|
-
}
|
|
136
|
+
else {
|
|
137
|
+
return format(message);
|
|
386
138
|
}
|
|
387
|
-
|
|
388
|
-
const msg =
|
|
389
|
-
// The message in vnode resolved with linked are returned as an array by processor.nomalize
|
|
390
|
-
type === 'vnode' && shared.isArray(ret) && modifier
|
|
391
|
-
? ret[0]
|
|
392
|
-
: ret;
|
|
393
|
-
return modifier ? _modifier(modifier)(msg, type) : msg;
|
|
394
|
-
};
|
|
395
|
-
const ctx = {
|
|
396
|
-
["list" /* HelperNameMap.LIST */]: list,
|
|
397
|
-
["named" /* HelperNameMap.NAMED */]: named,
|
|
398
|
-
["plural" /* HelperNameMap.PLURAL */]: plural,
|
|
399
|
-
["linked" /* HelperNameMap.LINKED */]: linked,
|
|
400
|
-
["message" /* HelperNameMap.MESSAGE */]: message,
|
|
401
|
-
["type" /* HelperNameMap.TYPE */]: type,
|
|
402
|
-
["interpolate" /* HelperNameMap.INTERPOLATE */]: interpolate,
|
|
403
|
-
["normalize" /* HelperNameMap.NORMALIZE */]: normalize,
|
|
404
|
-
["values" /* HelperNameMap.VALUES */]: shared.assign({}, _list, _named)
|
|
405
|
-
};
|
|
406
|
-
return ctx;
|
|
139
|
+
}
|
|
407
140
|
}
|
|
408
141
|
|
|
409
142
|
let devtools = null;
|
|
@@ -429,30 +162,6 @@ function createDevToolsHook(hook) {
|
|
|
429
162
|
return (payloads) => devtools && devtools.emit(hook, payloads);
|
|
430
163
|
}
|
|
431
164
|
|
|
432
|
-
const CoreWarnCodes = {
|
|
433
|
-
NOT_FOUND_KEY: 1,
|
|
434
|
-
FALLBACK_TO_TRANSLATE: 2,
|
|
435
|
-
CANNOT_FORMAT_NUMBER: 3,
|
|
436
|
-
FALLBACK_TO_NUMBER_FORMAT: 4,
|
|
437
|
-
CANNOT_FORMAT_DATE: 5,
|
|
438
|
-
FALLBACK_TO_DATE_FORMAT: 6,
|
|
439
|
-
EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7
|
|
440
|
-
};
|
|
441
|
-
const CORE_WARN_CODES_EXTEND_POINT = 8;
|
|
442
|
-
/** @internal */
|
|
443
|
-
const warnMessages = {
|
|
444
|
-
[CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
|
|
445
|
-
[CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
|
|
446
|
-
[CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
|
|
447
|
-
[CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
|
|
448
|
-
[CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
|
|
449
|
-
[CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
|
|
450
|
-
[CoreWarnCodes.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER]: `This project is using Custom Message Compiler, which is an experimental feature. It may receive breaking changes or be removed in the future.`
|
|
451
|
-
};
|
|
452
|
-
function getWarnMessage(code, ...args) {
|
|
453
|
-
return shared.format(warnMessages[code], ...args);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
165
|
const CoreErrorCodes = {
|
|
457
166
|
INVALID_ARGUMENT: messageCompiler.COMPILE_ERROR_CODES_EXTEND_POINT, // 17
|
|
458
167
|
INVALID_DATE_ARGUMENT: 18,
|
|
@@ -595,35 +304,327 @@ function appendBlockToChain(chain, block, blocks) {
|
|
|
595
304
|
follow = appendLocaleToChain(chain, block[i], blocks);
|
|
596
305
|
}
|
|
597
306
|
}
|
|
598
|
-
return follow;
|
|
307
|
+
return follow;
|
|
308
|
+
}
|
|
309
|
+
function appendLocaleToChain(chain, locale, blocks) {
|
|
310
|
+
let follow;
|
|
311
|
+
const tokens = locale.split('-');
|
|
312
|
+
do {
|
|
313
|
+
const target = tokens.join('-');
|
|
314
|
+
follow = appendItemToChain(chain, target, blocks);
|
|
315
|
+
tokens.splice(-1, 1);
|
|
316
|
+
} while (tokens.length && follow === true);
|
|
317
|
+
return follow;
|
|
318
|
+
}
|
|
319
|
+
function appendItemToChain(chain, target, blocks) {
|
|
320
|
+
let follow = false;
|
|
321
|
+
if (!chain.includes(target)) {
|
|
322
|
+
follow = true;
|
|
323
|
+
if (target) {
|
|
324
|
+
follow = target[target.length - 1] !== '!';
|
|
325
|
+
const locale = target.replace(/!/g, '');
|
|
326
|
+
chain.push(locale);
|
|
327
|
+
if ((shared.isArray(blocks) || shared.isPlainObject(blocks)) &&
|
|
328
|
+
blocks[locale] // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
329
|
+
) {
|
|
330
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
331
|
+
follow = blocks[locale];
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return follow;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const pathStateMachine = [];
|
|
339
|
+
pathStateMachine[0 /* States.BEFORE_PATH */] = {
|
|
340
|
+
["w" /* PathCharTypes.WORKSPACE */]: [0 /* States.BEFORE_PATH */],
|
|
341
|
+
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
342
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
343
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
344
|
+
};
|
|
345
|
+
pathStateMachine[1 /* States.IN_PATH */] = {
|
|
346
|
+
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */],
|
|
347
|
+
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */],
|
|
348
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
349
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
350
|
+
};
|
|
351
|
+
pathStateMachine[2 /* States.BEFORE_IDENT */] = {
|
|
352
|
+
["w" /* PathCharTypes.WORKSPACE */]: [2 /* States.BEFORE_IDENT */],
|
|
353
|
+
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
354
|
+
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */]
|
|
355
|
+
};
|
|
356
|
+
pathStateMachine[3 /* States.IN_IDENT */] = {
|
|
357
|
+
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
358
|
+
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
359
|
+
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */, 1 /* Actions.PUSH */],
|
|
360
|
+
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */, 1 /* Actions.PUSH */],
|
|
361
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */, 1 /* Actions.PUSH */],
|
|
362
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */, 1 /* Actions.PUSH */]
|
|
363
|
+
};
|
|
364
|
+
pathStateMachine[4 /* States.IN_SUB_PATH */] = {
|
|
365
|
+
["'" /* PathCharTypes.SINGLE_QUOTE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
366
|
+
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
367
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [
|
|
368
|
+
4 /* States.IN_SUB_PATH */,
|
|
369
|
+
2 /* Actions.INC_SUB_PATH_DEPTH */
|
|
370
|
+
],
|
|
371
|
+
["]" /* PathCharTypes.RIGHT_BRACKET */]: [1 /* States.IN_PATH */, 3 /* Actions.PUSH_SUB_PATH */],
|
|
372
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
373
|
+
["l" /* PathCharTypes.ELSE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */]
|
|
374
|
+
};
|
|
375
|
+
pathStateMachine[5 /* States.IN_SINGLE_QUOTE */] = {
|
|
376
|
+
["'" /* PathCharTypes.SINGLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
377
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
378
|
+
["l" /* PathCharTypes.ELSE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
379
|
+
};
|
|
380
|
+
pathStateMachine[6 /* States.IN_DOUBLE_QUOTE */] = {
|
|
381
|
+
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
382
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
383
|
+
["l" /* PathCharTypes.ELSE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* Check if an expression is a literal value.
|
|
387
|
+
*/
|
|
388
|
+
const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
|
|
389
|
+
function isLiteral(exp) {
|
|
390
|
+
return literalValueRE.test(exp);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Strip quotes from a string
|
|
394
|
+
*/
|
|
395
|
+
function stripQuotes(str) {
|
|
396
|
+
const a = str.charCodeAt(0);
|
|
397
|
+
const b = str.charCodeAt(str.length - 1);
|
|
398
|
+
return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Determine the type of a character in a keypath.
|
|
402
|
+
*/
|
|
403
|
+
function getPathCharType(ch) {
|
|
404
|
+
if (ch === undefined || ch === null) {
|
|
405
|
+
return "o" /* PathCharTypes.END_OF_FAIL */;
|
|
406
|
+
}
|
|
407
|
+
const code = ch.charCodeAt(0);
|
|
408
|
+
switch (code) {
|
|
409
|
+
case 0x5b: // [
|
|
410
|
+
case 0x5d: // ]
|
|
411
|
+
case 0x2e: // .
|
|
412
|
+
case 0x22: // "
|
|
413
|
+
case 0x27: // '
|
|
414
|
+
return ch;
|
|
415
|
+
case 0x5f: // _
|
|
416
|
+
case 0x24: // $
|
|
417
|
+
case 0x2d: // -
|
|
418
|
+
return "i" /* PathCharTypes.IDENT */;
|
|
419
|
+
case 0x09: // Tab (HT)
|
|
420
|
+
case 0x0a: // Newline (LF)
|
|
421
|
+
case 0x0d: // Return (CR)
|
|
422
|
+
case 0xa0: // No-break space (NBSP)
|
|
423
|
+
case 0xfeff: // Byte Order Mark (BOM)
|
|
424
|
+
case 0x2028: // Line Separator (LS)
|
|
425
|
+
case 0x2029: // Paragraph Separator (PS)
|
|
426
|
+
return "w" /* PathCharTypes.WORKSPACE */;
|
|
427
|
+
}
|
|
428
|
+
return "i" /* PathCharTypes.IDENT */;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Format a subPath, return its plain form if it is
|
|
432
|
+
* a literal string or number. Otherwise prepend the
|
|
433
|
+
* dynamic indicator (*).
|
|
434
|
+
*/
|
|
435
|
+
function formatSubPath(path) {
|
|
436
|
+
const trimmed = path.trim();
|
|
437
|
+
// invalid leading 0
|
|
438
|
+
if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
return isLiteral(trimmed)
|
|
442
|
+
? stripQuotes(trimmed)
|
|
443
|
+
: "*" /* PathCharTypes.ASTARISK */ + trimmed;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Parse a string path into an array of segments
|
|
447
|
+
*/
|
|
448
|
+
function parse(path) {
|
|
449
|
+
const keys = [];
|
|
450
|
+
let index = -1;
|
|
451
|
+
let mode = 0 /* States.BEFORE_PATH */;
|
|
452
|
+
let subPathDepth = 0;
|
|
453
|
+
let c;
|
|
454
|
+
let key; // eslint-disable-line
|
|
455
|
+
let newChar;
|
|
456
|
+
let type;
|
|
457
|
+
let transition;
|
|
458
|
+
let action;
|
|
459
|
+
let typeMap;
|
|
460
|
+
const actions = [];
|
|
461
|
+
actions[0 /* Actions.APPEND */] = () => {
|
|
462
|
+
if (key === undefined) {
|
|
463
|
+
key = newChar;
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
key += newChar;
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
actions[1 /* Actions.PUSH */] = () => {
|
|
470
|
+
if (key !== undefined) {
|
|
471
|
+
keys.push(key);
|
|
472
|
+
key = undefined;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
actions[2 /* Actions.INC_SUB_PATH_DEPTH */] = () => {
|
|
476
|
+
actions[0 /* Actions.APPEND */]();
|
|
477
|
+
subPathDepth++;
|
|
478
|
+
};
|
|
479
|
+
actions[3 /* Actions.PUSH_SUB_PATH */] = () => {
|
|
480
|
+
if (subPathDepth > 0) {
|
|
481
|
+
subPathDepth--;
|
|
482
|
+
mode = 4 /* States.IN_SUB_PATH */;
|
|
483
|
+
actions[0 /* Actions.APPEND */]();
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
subPathDepth = 0;
|
|
487
|
+
if (key === undefined) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
key = formatSubPath(key);
|
|
491
|
+
if (key === false) {
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
actions[1 /* Actions.PUSH */]();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
function maybeUnescapeQuote() {
|
|
500
|
+
const nextChar = path[index + 1];
|
|
501
|
+
if ((mode === 5 /* States.IN_SINGLE_QUOTE */ &&
|
|
502
|
+
nextChar === "'" /* PathCharTypes.SINGLE_QUOTE */) ||
|
|
503
|
+
(mode === 6 /* States.IN_DOUBLE_QUOTE */ &&
|
|
504
|
+
nextChar === "\"" /* PathCharTypes.DOUBLE_QUOTE */)) {
|
|
505
|
+
index++;
|
|
506
|
+
newChar = '\\' + nextChar;
|
|
507
|
+
actions[0 /* Actions.APPEND */]();
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
while (mode !== null) {
|
|
512
|
+
index++;
|
|
513
|
+
c = path[index];
|
|
514
|
+
if (c === '\\' && maybeUnescapeQuote()) {
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
type = getPathCharType(c);
|
|
518
|
+
typeMap = pathStateMachine[mode];
|
|
519
|
+
transition = typeMap[type] || typeMap["l" /* PathCharTypes.ELSE */] || 8 /* States.ERROR */;
|
|
520
|
+
// check parse error
|
|
521
|
+
if (transition === 8 /* States.ERROR */) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
mode = transition[0];
|
|
525
|
+
if (transition[1] !== undefined) {
|
|
526
|
+
action = actions[transition[1]];
|
|
527
|
+
if (action) {
|
|
528
|
+
newChar = c;
|
|
529
|
+
if (action() === false) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// check parse finish
|
|
535
|
+
if (mode === 7 /* States.AFTER_PATH */) {
|
|
536
|
+
return keys;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
599
539
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
540
|
+
// path token cache
|
|
541
|
+
const cache = new Map();
|
|
542
|
+
/**
|
|
543
|
+
* key-value message resolver
|
|
544
|
+
*
|
|
545
|
+
* @remarks
|
|
546
|
+
* Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
|
|
547
|
+
*
|
|
548
|
+
* @param obj - A target object to be resolved with path
|
|
549
|
+
* @param path - A {@link Path | path} to resolve the value of message
|
|
550
|
+
*
|
|
551
|
+
* @returns A resolved {@link PathValue | path value}
|
|
552
|
+
*
|
|
553
|
+
* @VueI18nGeneral
|
|
554
|
+
*/
|
|
555
|
+
function resolveWithKeyValue(obj, path) {
|
|
556
|
+
return shared.isObject(obj) ? obj[path] : null;
|
|
609
557
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
558
|
+
/**
|
|
559
|
+
* message resolver
|
|
560
|
+
*
|
|
561
|
+
* @remarks
|
|
562
|
+
* Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
|
|
563
|
+
*
|
|
564
|
+
* @param obj - A target object to be resolved with path
|
|
565
|
+
* @param path - A {@link Path | path} to resolve the value of message
|
|
566
|
+
*
|
|
567
|
+
* @returns A resolved {@link PathValue | path value}
|
|
568
|
+
*
|
|
569
|
+
* @VueI18nGeneral
|
|
570
|
+
*/
|
|
571
|
+
function resolveValue(obj, path) {
|
|
572
|
+
// check object
|
|
573
|
+
if (!shared.isObject(obj)) {
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
// parse path
|
|
577
|
+
let hit = cache.get(path);
|
|
578
|
+
if (!hit) {
|
|
579
|
+
hit = parse(path);
|
|
580
|
+
if (hit) {
|
|
581
|
+
cache.set(path, hit);
|
|
624
582
|
}
|
|
625
583
|
}
|
|
626
|
-
|
|
584
|
+
// check hit
|
|
585
|
+
if (!hit) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
// resolve path value
|
|
589
|
+
const len = hit.length;
|
|
590
|
+
let last = obj;
|
|
591
|
+
let i = 0;
|
|
592
|
+
while (i < len) {
|
|
593
|
+
const val = last[hit[i]];
|
|
594
|
+
if (val === undefined) {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
if (shared.isFunction(last)) {
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
last = val;
|
|
601
|
+
i++;
|
|
602
|
+
}
|
|
603
|
+
return last;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const CoreWarnCodes = {
|
|
607
|
+
NOT_FOUND_KEY: 1,
|
|
608
|
+
FALLBACK_TO_TRANSLATE: 2,
|
|
609
|
+
CANNOT_FORMAT_NUMBER: 3,
|
|
610
|
+
FALLBACK_TO_NUMBER_FORMAT: 4,
|
|
611
|
+
CANNOT_FORMAT_DATE: 5,
|
|
612
|
+
FALLBACK_TO_DATE_FORMAT: 6,
|
|
613
|
+
EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7
|
|
614
|
+
};
|
|
615
|
+
const CORE_WARN_CODES_EXTEND_POINT = 8;
|
|
616
|
+
/** @internal */
|
|
617
|
+
const warnMessages = {
|
|
618
|
+
[CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
|
|
619
|
+
[CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
|
|
620
|
+
[CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
|
|
621
|
+
[CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
|
|
622
|
+
[CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
|
|
623
|
+
[CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
|
|
624
|
+
[CoreWarnCodes.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER]: `This project is using Custom Message Compiler, which is an experimental feature. It may receive breaking changes or be removed in the future.`
|
|
625
|
+
};
|
|
626
|
+
function getWarnMessage(code, ...args) {
|
|
627
|
+
return shared.format(warnMessages[code], ...args);
|
|
627
628
|
}
|
|
628
629
|
|
|
629
630
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
@@ -631,7 +632,7 @@ function appendItemToChain(chain, target, blocks) {
|
|
|
631
632
|
* Intlify core-base version
|
|
632
633
|
* @internal
|
|
633
634
|
*/
|
|
634
|
-
const VERSION = '10.0.0-
|
|
635
|
+
const VERSION = '10.0.0-rc.1';
|
|
635
636
|
const NOT_REOSLVED = -1;
|
|
636
637
|
const DEFAULT_LOCALE = 'en-US';
|
|
637
638
|
const MISSING_RESOLVE_VALUE = '';
|
|
@@ -817,683 +818,683 @@ function isTranslateMissingWarn(missing, key) {
|
|
|
817
818
|
function handleMissing(context, key, locale, missingWarn, type) {
|
|
818
819
|
const { missing, onWarn } = context;
|
|
819
820
|
if (missing !== null) {
|
|
820
|
-
const ret = missing(context, locale, key, type);
|
|
821
|
-
return shared.isString(ret) ? ret : key;
|
|
822
|
-
}
|
|
823
|
-
else {
|
|
824
|
-
return key;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
/** @internal */
|
|
828
|
-
function updateFallbackLocale(ctx, locale, fallback) {
|
|
829
|
-
const context = ctx;
|
|
830
|
-
context.__localeChainCache = new Map();
|
|
831
|
-
ctx.localeFallbacker(ctx, fallback, locale);
|
|
832
|
-
}
|
|
833
|
-
/** @internal */
|
|
834
|
-
function isAlmostSameLocale(locale, compareLocale) {
|
|
835
|
-
if (locale === compareLocale)
|
|
836
|
-
return false;
|
|
837
|
-
return locale.split('-')[0] === compareLocale.split('-')[0];
|
|
838
|
-
}
|
|
839
|
-
/** @internal */
|
|
840
|
-
function isImplicitFallback(targetLocale, locales) {
|
|
841
|
-
const index = locales.indexOf(targetLocale);
|
|
842
|
-
if (index === -1) {
|
|
843
|
-
return false;
|
|
844
|
-
}
|
|
845
|
-
for (let i = index + 1; i < locales.length; i++) {
|
|
846
|
-
if (isAlmostSameLocale(targetLocale, locales[i])) {
|
|
847
|
-
return true;
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
return false;
|
|
851
|
-
}
|
|
852
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
853
|
-
|
|
854
|
-
function format(ast) {
|
|
855
|
-
const msg = (ctx) => formatParts(ctx, ast);
|
|
856
|
-
return msg;
|
|
857
|
-
}
|
|
858
|
-
function formatParts(ctx, ast) {
|
|
859
|
-
const body = ast.b || ast.body;
|
|
860
|
-
if ((body.t || body.type) === 1 /* NodeTypes.Plural */) {
|
|
861
|
-
const plural = body;
|
|
862
|
-
const cases = plural.c || plural.cases;
|
|
863
|
-
return ctx.plural(cases.reduce((messages, c) => [
|
|
864
|
-
...messages,
|
|
865
|
-
formatMessageParts(ctx, c)
|
|
866
|
-
], []));
|
|
867
|
-
}
|
|
868
|
-
else {
|
|
869
|
-
return formatMessageParts(ctx, body);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
function formatMessageParts(ctx, node) {
|
|
873
|
-
const _static = node.s || node.static;
|
|
874
|
-
if (_static) {
|
|
875
|
-
return ctx.type === 'text'
|
|
876
|
-
? _static
|
|
877
|
-
: ctx.normalize([_static]);
|
|
878
|
-
}
|
|
879
|
-
else {
|
|
880
|
-
const messages = (node.i || node.items).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
|
|
881
|
-
return ctx.normalize(messages);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
function formatMessagePart(ctx, node) {
|
|
885
|
-
const type = node.t || node.type;
|
|
886
|
-
switch (type) {
|
|
887
|
-
case 3 /* NodeTypes.Text */: {
|
|
888
|
-
const text = node;
|
|
889
|
-
return (text.v || text.value);
|
|
890
|
-
}
|
|
891
|
-
case 9 /* NodeTypes.Literal */: {
|
|
892
|
-
const literal = node;
|
|
893
|
-
return (literal.v || literal.value);
|
|
894
|
-
}
|
|
895
|
-
case 4 /* NodeTypes.Named */: {
|
|
896
|
-
const named = node;
|
|
897
|
-
return ctx.interpolate(ctx.named(named.k || named.key));
|
|
898
|
-
}
|
|
899
|
-
case 5 /* NodeTypes.List */: {
|
|
900
|
-
const list = node;
|
|
901
|
-
return ctx.interpolate(ctx.list(list.i != null ? list.i : list.index));
|
|
902
|
-
}
|
|
903
|
-
case 6 /* NodeTypes.Linked */: {
|
|
904
|
-
const linked = node;
|
|
905
|
-
const modifier = linked.m || linked.modifier;
|
|
906
|
-
return ctx.linked(formatMessagePart(ctx, linked.k || linked.key), modifier ? formatMessagePart(ctx, modifier) : undefined, ctx.type);
|
|
907
|
-
}
|
|
908
|
-
case 7 /* NodeTypes.LinkedKey */: {
|
|
909
|
-
const linkedKey = node;
|
|
910
|
-
return (linkedKey.v || linkedKey.value);
|
|
911
|
-
}
|
|
912
|
-
case 8 /* NodeTypes.LinkedModifier */: {
|
|
913
|
-
const linkedModifier = node;
|
|
914
|
-
return (linkedModifier.v || linkedModifier.value);
|
|
915
|
-
}
|
|
916
|
-
default:
|
|
917
|
-
throw new Error(`unhandled node type on format message part: ${type}`);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
const defaultOnCacheKey = (message) => message;
|
|
922
|
-
let compileCache = Object.create(null);
|
|
923
|
-
function clearCompileCache() {
|
|
924
|
-
compileCache = Object.create(null);
|
|
925
|
-
}
|
|
926
|
-
const isMessageAST = (val) => shared.isObject(val) &&
|
|
927
|
-
(val.t === 0 || val.type === 0) &&
|
|
928
|
-
('b' in val || 'body' in val);
|
|
929
|
-
function baseCompile(message, options = {}) {
|
|
930
|
-
// error detecting on compile
|
|
931
|
-
let detectError = false;
|
|
932
|
-
const onError = options.onError || messageCompiler.defaultOnError;
|
|
933
|
-
options.onError = (err) => {
|
|
934
|
-
detectError = true;
|
|
935
|
-
onError(err);
|
|
936
|
-
};
|
|
937
|
-
// compile with mesasge-compiler
|
|
938
|
-
return { ...messageCompiler.baseCompile(message, options), detectError };
|
|
939
|
-
}
|
|
940
|
-
/* #__NO_SIDE_EFFECTS__ */
|
|
941
|
-
function compile(message, context) {
|
|
942
|
-
if (shared.isString(message)) {
|
|
943
|
-
// check HTML message
|
|
944
|
-
shared.isBoolean(context.warnHtmlMessage)
|
|
945
|
-
? context.warnHtmlMessage
|
|
946
|
-
: true;
|
|
947
|
-
// check caches
|
|
948
|
-
const onCacheKey = context.onCacheKey || defaultOnCacheKey;
|
|
949
|
-
const cacheKey = onCacheKey(message);
|
|
950
|
-
const cached = compileCache[cacheKey];
|
|
951
|
-
if (cached) {
|
|
952
|
-
return cached;
|
|
953
|
-
}
|
|
954
|
-
// compile with JIT mode
|
|
955
|
-
const { ast, detectError } = baseCompile(message, {
|
|
956
|
-
...context,
|
|
957
|
-
location: false,
|
|
958
|
-
jit: true
|
|
959
|
-
});
|
|
960
|
-
// compose message function from AST
|
|
961
|
-
const msg = format(ast);
|
|
962
|
-
// if occurred compile error, don't cache
|
|
963
|
-
return !detectError
|
|
964
|
-
? (compileCache[cacheKey] = msg)
|
|
965
|
-
: msg;
|
|
821
|
+
const ret = missing(context, locale, key, type);
|
|
822
|
+
return shared.isString(ret) ? ret : key;
|
|
966
823
|
}
|
|
967
824
|
else {
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
825
|
+
return key;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
/** @internal */
|
|
829
|
+
function updateFallbackLocale(ctx, locale, fallback) {
|
|
830
|
+
const context = ctx;
|
|
831
|
+
context.__localeChainCache = new Map();
|
|
832
|
+
ctx.localeFallbacker(ctx, fallback, locale);
|
|
833
|
+
}
|
|
834
|
+
/** @internal */
|
|
835
|
+
function isAlmostSameLocale(locale, compareLocale) {
|
|
836
|
+
if (locale === compareLocale)
|
|
837
|
+
return false;
|
|
838
|
+
return locale.split('-')[0] === compareLocale.split('-')[0];
|
|
839
|
+
}
|
|
840
|
+
/** @internal */
|
|
841
|
+
function isImplicitFallback(targetLocale, locales) {
|
|
842
|
+
const index = locales.indexOf(targetLocale);
|
|
843
|
+
if (index === -1) {
|
|
844
|
+
return false;
|
|
845
|
+
}
|
|
846
|
+
for (let i = index + 1; i < locales.length; i++) {
|
|
847
|
+
if (isAlmostSameLocale(targetLocale, locales[i])) {
|
|
848
|
+
return true;
|
|
981
849
|
}
|
|
982
850
|
}
|
|
851
|
+
return false;
|
|
983
852
|
}
|
|
853
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
984
854
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
const
|
|
990
|
-
const [key, options] = parseTranslateArgs(...args);
|
|
855
|
+
// implementation of `datetime` function
|
|
856
|
+
function datetime(context, ...args) {
|
|
857
|
+
const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
|
|
858
|
+
const { __datetimeFormatters } = context;
|
|
859
|
+
const [key, value, options, overrides] = parseDateTimeArgs(...args);
|
|
991
860
|
const missingWarn = shared.isBoolean(options.missingWarn)
|
|
992
861
|
? options.missingWarn
|
|
993
862
|
: context.missingWarn;
|
|
994
|
-
|
|
863
|
+
shared.isBoolean(options.fallbackWarn)
|
|
995
864
|
? options.fallbackWarn
|
|
996
865
|
: context.fallbackWarn;
|
|
997
|
-
const
|
|
998
|
-
? options.escapeParameter
|
|
999
|
-
: context.escapeParameter;
|
|
1000
|
-
const resolvedMessage = !!options.resolvedMessage;
|
|
1001
|
-
// prettier-ignore
|
|
1002
|
-
const defaultMsgOrKey = shared.isString(options.default) || shared.isBoolean(options.default) // default by function option
|
|
1003
|
-
? !shared.isBoolean(options.default)
|
|
1004
|
-
? options.default
|
|
1005
|
-
: (!messageCompiler ? () => key : key)
|
|
1006
|
-
: fallbackFormat // default by `fallbackFormat` option
|
|
1007
|
-
? (!messageCompiler ? () => key : key)
|
|
1008
|
-
: null;
|
|
1009
|
-
const enableDefaultMsg = fallbackFormat ||
|
|
1010
|
-
(defaultMsgOrKey != null &&
|
|
1011
|
-
(shared.isString(defaultMsgOrKey) || shared.isFunction(defaultMsgOrKey)));
|
|
866
|
+
const part = !!options.part;
|
|
1012
867
|
const locale = getLocale(context, options);
|
|
1013
|
-
//
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
let [formatScope, targetLocale, message] = !resolvedMessage
|
|
1018
|
-
? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
|
|
1019
|
-
: [
|
|
1020
|
-
key,
|
|
1021
|
-
locale,
|
|
1022
|
-
messages[locale] || {}
|
|
1023
|
-
];
|
|
1024
|
-
// NOTE:
|
|
1025
|
-
// Fix to work around `ssrTransfrom` bug in Vite.
|
|
1026
|
-
// https://github.com/vitejs/vite/issues/4306
|
|
1027
|
-
// To get around this, use temporary variables.
|
|
1028
|
-
// https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
|
|
1029
|
-
let format = formatScope;
|
|
1030
|
-
// if you use default message, set it as message format!
|
|
1031
|
-
let cacheBaseKey = key;
|
|
1032
|
-
if (!resolvedMessage &&
|
|
1033
|
-
!(shared.isString(format) ||
|
|
1034
|
-
isMessageAST(format) ||
|
|
1035
|
-
isMessageFunction(format))) {
|
|
1036
|
-
if (enableDefaultMsg) {
|
|
1037
|
-
format = defaultMsgOrKey;
|
|
1038
|
-
cacheBaseKey = format;
|
|
1039
|
-
}
|
|
868
|
+
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
869
|
+
fallbackLocale, locale);
|
|
870
|
+
if (!shared.isString(key) || key === '') {
|
|
871
|
+
return new Intl.DateTimeFormat(locale, overrides).format(value);
|
|
1040
872
|
}
|
|
1041
|
-
//
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
873
|
+
// resolve format
|
|
874
|
+
let datetimeFormat = {};
|
|
875
|
+
let targetLocale;
|
|
876
|
+
let format = null;
|
|
877
|
+
const type = 'datetime format';
|
|
878
|
+
for (let i = 0; i < locales.length; i++) {
|
|
879
|
+
targetLocale = locales[i];
|
|
880
|
+
datetimeFormat =
|
|
881
|
+
datetimeFormats[targetLocale] || {};
|
|
882
|
+
format = datetimeFormat[key];
|
|
883
|
+
if (shared.isPlainObject(format))
|
|
884
|
+
break;
|
|
885
|
+
handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
886
|
+
}
|
|
887
|
+
// checking format and target locale
|
|
888
|
+
if (!shared.isPlainObject(format) || !shared.isString(targetLocale)) {
|
|
1047
889
|
return unresolving ? NOT_REOSLVED : key;
|
|
1048
890
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
occurred = true;
|
|
1053
|
-
};
|
|
1054
|
-
// compile message format
|
|
1055
|
-
const msg = !isMessageFunction(format)
|
|
1056
|
-
? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError)
|
|
1057
|
-
: format;
|
|
1058
|
-
// if occurred compile error, return the message format
|
|
1059
|
-
if (occurred) {
|
|
1060
|
-
return format;
|
|
891
|
+
let id = `${targetLocale}__${key}`;
|
|
892
|
+
if (!shared.isEmptyObject(overrides)) {
|
|
893
|
+
id = `${id}__${JSON.stringify(overrides)}`;
|
|
1061
894
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
? postTranslation(messaged, key)
|
|
1069
|
-
: messaged;
|
|
1070
|
-
return ret;
|
|
895
|
+
let formatter = __datetimeFormatters.get(id);
|
|
896
|
+
if (!formatter) {
|
|
897
|
+
formatter = new Intl.DateTimeFormat(targetLocale, shared.assign({}, format, overrides));
|
|
898
|
+
__datetimeFormatters.set(id, formatter);
|
|
899
|
+
}
|
|
900
|
+
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
1071
901
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
902
|
+
/** @internal */
|
|
903
|
+
const DATETIME_FORMAT_OPTIONS_KEYS = [
|
|
904
|
+
'localeMatcher',
|
|
905
|
+
'weekday',
|
|
906
|
+
'era',
|
|
907
|
+
'year',
|
|
908
|
+
'month',
|
|
909
|
+
'day',
|
|
910
|
+
'hour',
|
|
911
|
+
'minute',
|
|
912
|
+
'second',
|
|
913
|
+
'timeZoneName',
|
|
914
|
+
'formatMatcher',
|
|
915
|
+
'hour12',
|
|
916
|
+
'timeZone',
|
|
917
|
+
'dateStyle',
|
|
918
|
+
'timeStyle',
|
|
919
|
+
'calendar',
|
|
920
|
+
'dayPeriod',
|
|
921
|
+
'numberingSystem',
|
|
922
|
+
'hourCycle',
|
|
923
|
+
'fractionalSecondDigits'
|
|
924
|
+
];
|
|
925
|
+
/** @internal */
|
|
926
|
+
function parseDateTimeArgs(...args) {
|
|
927
|
+
const [arg1, arg2, arg3, arg4] = args;
|
|
928
|
+
const options = {};
|
|
929
|
+
let overrides = {};
|
|
930
|
+
let value;
|
|
931
|
+
if (shared.isString(arg1)) {
|
|
932
|
+
// Only allow ISO strings - other date formats are often supported,
|
|
933
|
+
// but may cause different results in different browsers.
|
|
934
|
+
const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
|
|
935
|
+
if (!matches) {
|
|
936
|
+
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
937
|
+
}
|
|
938
|
+
// Some browsers can not parse the iso datetime separated by space,
|
|
939
|
+
// this is a compromise solution by replace the 'T'/' ' with 'T'
|
|
940
|
+
const dateTime = matches[3]
|
|
941
|
+
? matches[3].trim().startsWith('T')
|
|
942
|
+
? `${matches[1].trim()}${matches[3].trim()}`
|
|
943
|
+
: `${matches[1].trim()}T${matches[3].trim()}`
|
|
944
|
+
: matches[1].trim();
|
|
945
|
+
value = new Date(dateTime);
|
|
946
|
+
try {
|
|
947
|
+
// This will fail if the date is not valid
|
|
948
|
+
value.toISOString();
|
|
949
|
+
}
|
|
950
|
+
catch {
|
|
951
|
+
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
952
|
+
}
|
|
1075
953
|
}
|
|
1076
|
-
else if (shared.
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
954
|
+
else if (shared.isDate(arg1)) {
|
|
955
|
+
if (isNaN(arg1.getTime())) {
|
|
956
|
+
throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
|
|
957
|
+
}
|
|
958
|
+
value = arg1;
|
|
959
|
+
}
|
|
960
|
+
else if (shared.isNumber(arg1)) {
|
|
961
|
+
value = arg1;
|
|
962
|
+
}
|
|
963
|
+
else {
|
|
964
|
+
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
965
|
+
}
|
|
966
|
+
if (shared.isString(arg2)) {
|
|
967
|
+
options.key = arg2;
|
|
968
|
+
}
|
|
969
|
+
else if (shared.isPlainObject(arg2)) {
|
|
970
|
+
Object.keys(arg2).forEach(key => {
|
|
971
|
+
if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
972
|
+
overrides[key] = arg2[key];
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
options[key] = arg2[key];
|
|
1080
976
|
}
|
|
1081
977
|
});
|
|
1082
978
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
979
|
+
if (shared.isString(arg3)) {
|
|
980
|
+
options.locale = arg3;
|
|
981
|
+
}
|
|
982
|
+
else if (shared.isPlainObject(arg3)) {
|
|
983
|
+
overrides = arg3;
|
|
984
|
+
}
|
|
985
|
+
if (shared.isPlainObject(arg4)) {
|
|
986
|
+
overrides = arg4;
|
|
987
|
+
}
|
|
988
|
+
return [options.key || '', value, options, overrides];
|
|
989
|
+
}
|
|
990
|
+
/** @internal */
|
|
991
|
+
function clearDateTimeFormat(ctx, locale, format) {
|
|
992
|
+
const context = ctx;
|
|
993
|
+
for (const key in format) {
|
|
994
|
+
const id = `${locale}__${key}`;
|
|
995
|
+
if (!context.__datetimeFormatters.has(id)) {
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
context.__datetimeFormatters.delete(id);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
// implementation of `number` function
|
|
1003
|
+
function number(context, ...args) {
|
|
1004
|
+
const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
|
|
1005
|
+
const { __numberFormatters } = context;
|
|
1006
|
+
const [key, value, options, overrides] = parseNumberArgs(...args);
|
|
1007
|
+
const missingWarn = shared.isBoolean(options.missingWarn)
|
|
1008
|
+
? options.missingWarn
|
|
1009
|
+
: context.missingWarn;
|
|
1010
|
+
shared.isBoolean(options.fallbackWarn)
|
|
1011
|
+
? options.fallbackWarn
|
|
1012
|
+
: context.fallbackWarn;
|
|
1013
|
+
const part = !!options.part;
|
|
1014
|
+
const locale = getLocale(context, options);
|
|
1015
|
+
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1016
|
+
fallbackLocale, locale);
|
|
1017
|
+
if (!shared.isString(key) || key === '') {
|
|
1018
|
+
return new Intl.NumberFormat(locale, overrides).format(value);
|
|
1019
|
+
}
|
|
1020
|
+
// resolve format
|
|
1021
|
+
let numberFormat = {};
|
|
1088
1022
|
let targetLocale;
|
|
1089
1023
|
let format = null;
|
|
1090
|
-
const type = '
|
|
1024
|
+
const type = 'number format';
|
|
1091
1025
|
for (let i = 0; i < locales.length; i++) {
|
|
1092
1026
|
targetLocale = locales[i];
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1098
|
-
}
|
|
1099
|
-
if (shared.isString(format) || isMessageAST(format) || isMessageFunction(format)) {
|
|
1027
|
+
numberFormat =
|
|
1028
|
+
numberFormats[targetLocale] || {};
|
|
1029
|
+
format = numberFormat[key];
|
|
1030
|
+
if (shared.isPlainObject(format))
|
|
1100
1031
|
break;
|
|
1101
|
-
|
|
1102
|
-
if (!isImplicitFallback(targetLocale, locales)) {
|
|
1103
|
-
const missingRet = handleMissing(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1104
|
-
key, targetLocale, missingWarn, type);
|
|
1105
|
-
if (missingRet !== key) {
|
|
1106
|
-
format = missingRet;
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1032
|
+
handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1109
1033
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
const { messageCompiler, warnHtmlMessage } = context;
|
|
1114
|
-
if (isMessageFunction(format)) {
|
|
1115
|
-
const msg = format;
|
|
1116
|
-
msg.locale = msg.locale || targetLocale;
|
|
1117
|
-
msg.key = msg.key || key;
|
|
1118
|
-
return msg;
|
|
1034
|
+
// checking format and target locale
|
|
1035
|
+
if (!shared.isPlainObject(format) || !shared.isString(targetLocale)) {
|
|
1036
|
+
return unresolving ? NOT_REOSLVED : key;
|
|
1119
1037
|
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
msg.key = key;
|
|
1124
|
-
return msg;
|
|
1038
|
+
let id = `${targetLocale}__${key}`;
|
|
1039
|
+
if (!shared.isEmptyObject(overrides)) {
|
|
1040
|
+
id = `${id}__${JSON.stringify(overrides)}`;
|
|
1125
1041
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
function evaluateMessage(context, msg, msgCtx) {
|
|
1133
|
-
const messaged = msg(msgCtx);
|
|
1134
|
-
return messaged;
|
|
1042
|
+
let formatter = __numberFormatters.get(id);
|
|
1043
|
+
if (!formatter) {
|
|
1044
|
+
formatter = new Intl.NumberFormat(targetLocale, shared.assign({}, format, overrides));
|
|
1045
|
+
__numberFormatters.set(id, formatter);
|
|
1046
|
+
}
|
|
1047
|
+
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
1135
1048
|
}
|
|
1136
1049
|
/** @internal */
|
|
1137
|
-
|
|
1138
|
-
|
|
1050
|
+
const NUMBER_FORMAT_OPTIONS_KEYS = [
|
|
1051
|
+
'localeMatcher',
|
|
1052
|
+
'style',
|
|
1053
|
+
'currency',
|
|
1054
|
+
'currencyDisplay',
|
|
1055
|
+
'currencySign',
|
|
1056
|
+
'useGrouping',
|
|
1057
|
+
'minimumIntegerDigits',
|
|
1058
|
+
'minimumFractionDigits',
|
|
1059
|
+
'maximumFractionDigits',
|
|
1060
|
+
'minimumSignificantDigits',
|
|
1061
|
+
'maximumSignificantDigits',
|
|
1062
|
+
'compactDisplay',
|
|
1063
|
+
'notation',
|
|
1064
|
+
'signDisplay',
|
|
1065
|
+
'unit',
|
|
1066
|
+
'unitDisplay',
|
|
1067
|
+
'roundingMode',
|
|
1068
|
+
'roundingPriority',
|
|
1069
|
+
'roundingIncrement',
|
|
1070
|
+
'trailingZeroDisplay'
|
|
1071
|
+
];
|
|
1072
|
+
/** @internal */
|
|
1073
|
+
function parseNumberArgs(...args) {
|
|
1074
|
+
const [arg1, arg2, arg3, arg4] = args;
|
|
1139
1075
|
const options = {};
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
!isMessageFunction(arg1) &&
|
|
1143
|
-
!isMessageAST(arg1)) {
|
|
1076
|
+
let overrides = {};
|
|
1077
|
+
if (!shared.isNumber(arg1)) {
|
|
1144
1078
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
1145
1079
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
: isMessageFunction(arg1)
|
|
1150
|
-
? arg1
|
|
1151
|
-
: arg1;
|
|
1152
|
-
if (shared.isNumber(arg2)) {
|
|
1153
|
-
options.plural = arg2;
|
|
1080
|
+
const value = arg1;
|
|
1081
|
+
if (shared.isString(arg2)) {
|
|
1082
|
+
options.key = arg2;
|
|
1154
1083
|
}
|
|
1155
|
-
else if (shared.
|
|
1156
|
-
|
|
1084
|
+
else if (shared.isPlainObject(arg2)) {
|
|
1085
|
+
Object.keys(arg2).forEach(key => {
|
|
1086
|
+
if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
1087
|
+
overrides[key] = arg2[key];
|
|
1088
|
+
}
|
|
1089
|
+
else {
|
|
1090
|
+
options[key] = arg2[key];
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1157
1093
|
}
|
|
1158
|
-
|
|
1159
|
-
options.
|
|
1094
|
+
if (shared.isString(arg3)) {
|
|
1095
|
+
options.locale = arg3;
|
|
1160
1096
|
}
|
|
1161
|
-
else if (shared.
|
|
1162
|
-
|
|
1097
|
+
else if (shared.isPlainObject(arg3)) {
|
|
1098
|
+
overrides = arg3;
|
|
1163
1099
|
}
|
|
1164
|
-
if (shared.
|
|
1165
|
-
|
|
1100
|
+
if (shared.isPlainObject(arg4)) {
|
|
1101
|
+
overrides = arg4;
|
|
1166
1102
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1103
|
+
return [options.key || '', value, options, overrides];
|
|
1104
|
+
}
|
|
1105
|
+
/** @internal */
|
|
1106
|
+
function clearNumberFormat(ctx, locale, format) {
|
|
1107
|
+
const context = ctx;
|
|
1108
|
+
for (const key in format) {
|
|
1109
|
+
const id = `${locale}__${key}`;
|
|
1110
|
+
if (!context.__numberFormatters.has(id)) {
|
|
1111
|
+
continue;
|
|
1112
|
+
}
|
|
1113
|
+
context.__numberFormatters.delete(id);
|
|
1169
1114
|
}
|
|
1170
|
-
|
|
1171
|
-
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
const DEFAULT_MODIFIER = (str) => str;
|
|
1118
|
+
const DEFAULT_MESSAGE = (ctx) => ''; // eslint-disable-line
|
|
1119
|
+
const DEFAULT_MESSAGE_DATA_TYPE = 'text';
|
|
1120
|
+
const DEFAULT_NORMALIZE = (values) => values.length === 0 ? '' : shared.join(values);
|
|
1121
|
+
const DEFAULT_INTERPOLATE = shared.toDisplayString;
|
|
1122
|
+
function pluralDefault(choice, choicesLength) {
|
|
1123
|
+
choice = Math.abs(choice);
|
|
1124
|
+
if (choicesLength === 2) {
|
|
1125
|
+
// prettier-ignore
|
|
1126
|
+
return choice
|
|
1127
|
+
? choice > 1
|
|
1128
|
+
? 1
|
|
1129
|
+
: 0
|
|
1130
|
+
: 1;
|
|
1172
1131
|
}
|
|
1173
|
-
return
|
|
1132
|
+
return choice ? Math.min(choice, 2) : 0;
|
|
1174
1133
|
}
|
|
1175
|
-
function
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1134
|
+
function getPluralIndex(options) {
|
|
1135
|
+
// prettier-ignore
|
|
1136
|
+
const index = shared.isNumber(options.pluralIndex)
|
|
1137
|
+
? options.pluralIndex
|
|
1138
|
+
: -1;
|
|
1139
|
+
// prettier-ignore
|
|
1140
|
+
return options.named && (shared.isNumber(options.named.count) || shared.isNumber(options.named.n))
|
|
1141
|
+
? shared.isNumber(options.named.count)
|
|
1142
|
+
? options.named.count
|
|
1143
|
+
: shared.isNumber(options.named.n)
|
|
1144
|
+
? options.named.n
|
|
1145
|
+
: index
|
|
1146
|
+
: index;
|
|
1147
|
+
}
|
|
1148
|
+
function normalizeNamed(pluralIndex, props) {
|
|
1149
|
+
if (!props.count) {
|
|
1150
|
+
props.count = pluralIndex;
|
|
1151
|
+
}
|
|
1152
|
+
if (!props.n) {
|
|
1153
|
+
props.n = pluralIndex;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
function createMessageContext(options = {}) {
|
|
1157
|
+
const locale = options.locale;
|
|
1158
|
+
const pluralIndex = getPluralIndex(options);
|
|
1159
|
+
const pluralRule = shared.isObject(options.pluralRules) &&
|
|
1160
|
+
shared.isString(locale) &&
|
|
1161
|
+
shared.isFunction(options.pluralRules[locale])
|
|
1162
|
+
? options.pluralRules[locale]
|
|
1163
|
+
: pluralDefault;
|
|
1164
|
+
const orgPluralRule = shared.isObject(options.pluralRules) &&
|
|
1165
|
+
shared.isString(locale) &&
|
|
1166
|
+
shared.isFunction(options.pluralRules[locale])
|
|
1167
|
+
? pluralDefault
|
|
1168
|
+
: undefined;
|
|
1169
|
+
const plural = (messages) => {
|
|
1170
|
+
return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
|
|
1171
|
+
};
|
|
1172
|
+
const _list = options.list || [];
|
|
1173
|
+
const list = (index) => _list[index];
|
|
1174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1175
|
+
const _named = options.named || {};
|
|
1176
|
+
shared.isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
|
|
1177
|
+
const named = (key) => _named[key];
|
|
1178
|
+
function message(key, useLinked) {
|
|
1179
|
+
// prettier-ignore
|
|
1180
|
+
const msg = shared.isFunction(options.messages)
|
|
1181
|
+
? options.messages(key, !!useLinked)
|
|
1182
|
+
: shared.isObject(options.messages)
|
|
1183
|
+
? options.messages[key]
|
|
1184
|
+
: false;
|
|
1185
|
+
return !msg
|
|
1186
|
+
? options.parent
|
|
1187
|
+
? options.parent.message(key) // resolve from parent messages
|
|
1188
|
+
: DEFAULT_MESSAGE
|
|
1189
|
+
: msg;
|
|
1190
|
+
}
|
|
1191
|
+
const _modifier = (name) => options.modifiers
|
|
1192
|
+
? options.modifiers[name]
|
|
1193
|
+
: DEFAULT_MODIFIER;
|
|
1194
|
+
const normalize = shared.isPlainObject(options.processor) && shared.isFunction(options.processor.normalize)
|
|
1195
|
+
? options.processor.normalize
|
|
1196
|
+
: DEFAULT_NORMALIZE;
|
|
1197
|
+
const interpolate = shared.isPlainObject(options.processor) &&
|
|
1198
|
+
shared.isFunction(options.processor.interpolate)
|
|
1199
|
+
? options.processor.interpolate
|
|
1200
|
+
: DEFAULT_INTERPOLATE;
|
|
1201
|
+
const type = shared.isPlainObject(options.processor) && shared.isString(options.processor.type)
|
|
1202
|
+
? options.processor.type
|
|
1203
|
+
: DEFAULT_MESSAGE_DATA_TYPE;
|
|
1204
|
+
const linked = (key, ...args) => {
|
|
1205
|
+
const [arg1, arg2] = args;
|
|
1206
|
+
let type = 'text';
|
|
1207
|
+
let modifier = '';
|
|
1208
|
+
if (args.length === 1) {
|
|
1209
|
+
if (shared.isObject(arg1)) {
|
|
1210
|
+
modifier = arg1.modifier || modifier;
|
|
1211
|
+
type = arg1.type || type;
|
|
1212
|
+
}
|
|
1213
|
+
else if (shared.isString(arg1)) {
|
|
1214
|
+
modifier = arg1 || modifier;
|
|
1184
1215
|
}
|
|
1185
|
-
},
|
|
1186
|
-
onCacheKey: (source) => shared.generateFormatCacheKey(locale, key, source)
|
|
1187
|
-
};
|
|
1188
|
-
}
|
|
1189
|
-
function getMessageContextOptions(context, locale, message, options) {
|
|
1190
|
-
const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
|
|
1191
|
-
const resolveMessage = (key) => {
|
|
1192
|
-
let val = resolveValue(message, key);
|
|
1193
|
-
// fallback to root context
|
|
1194
|
-
if (val == null && fallbackContext) {
|
|
1195
|
-
const [, , message] = resolveMessageFormat(fallbackContext, key, locale, fallbackLocale, fallbackWarn, missingWarn);
|
|
1196
|
-
val = resolveValue(message, key);
|
|
1197
|
-
}
|
|
1198
|
-
if (shared.isString(val) || isMessageAST(val)) {
|
|
1199
|
-
let occurred = false;
|
|
1200
|
-
const onError = () => {
|
|
1201
|
-
occurred = true;
|
|
1202
|
-
};
|
|
1203
|
-
const msg = compileMessageFormat(context, key, locale, val, key, onError);
|
|
1204
|
-
return !occurred
|
|
1205
|
-
? msg
|
|
1206
|
-
: NOOP_MESSAGE_FUNCTION;
|
|
1207
|
-
}
|
|
1208
|
-
else if (isMessageFunction(val)) {
|
|
1209
|
-
return val;
|
|
1210
1216
|
}
|
|
1211
|
-
else {
|
|
1212
|
-
|
|
1213
|
-
|
|
1217
|
+
else if (args.length === 2) {
|
|
1218
|
+
if (shared.isString(arg1)) {
|
|
1219
|
+
modifier = arg1 || modifier;
|
|
1220
|
+
}
|
|
1221
|
+
if (shared.isString(arg2)) {
|
|
1222
|
+
type = arg2 || type;
|
|
1223
|
+
}
|
|
1214
1224
|
}
|
|
1225
|
+
const ret = message(key, true)(ctx);
|
|
1226
|
+
const msg =
|
|
1227
|
+
// The message in vnode resolved with linked are returned as an array by processor.nomalize
|
|
1228
|
+
type === 'vnode' && shared.isArray(ret) && modifier
|
|
1229
|
+
? ret[0]
|
|
1230
|
+
: ret;
|
|
1231
|
+
return modifier ? _modifier(modifier)(msg, type) : msg;
|
|
1215
1232
|
};
|
|
1216
|
-
const
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1233
|
+
const ctx = {
|
|
1234
|
+
["list" /* HelperNameMap.LIST */]: list,
|
|
1235
|
+
["named" /* HelperNameMap.NAMED */]: named,
|
|
1236
|
+
["plural" /* HelperNameMap.PLURAL */]: plural,
|
|
1237
|
+
["linked" /* HelperNameMap.LINKED */]: linked,
|
|
1238
|
+
["message" /* HelperNameMap.MESSAGE */]: message,
|
|
1239
|
+
["type" /* HelperNameMap.TYPE */]: type,
|
|
1240
|
+
["interpolate" /* HelperNameMap.INTERPOLATE */]: interpolate,
|
|
1241
|
+
["normalize" /* HelperNameMap.NORMALIZE */]: normalize,
|
|
1242
|
+
["values" /* HelperNameMap.VALUES */]: shared.assign({}, _list, _named)
|
|
1221
1243
|
};
|
|
1222
|
-
|
|
1223
|
-
ctxOptions.processor = context.processor;
|
|
1224
|
-
}
|
|
1225
|
-
if (options.list) {
|
|
1226
|
-
ctxOptions.list = options.list;
|
|
1227
|
-
}
|
|
1228
|
-
if (options.named) {
|
|
1229
|
-
ctxOptions.named = options.named;
|
|
1230
|
-
}
|
|
1231
|
-
if (shared.isNumber(options.plural)) {
|
|
1232
|
-
ctxOptions.pluralIndex = options.plural;
|
|
1233
|
-
}
|
|
1234
|
-
return ctxOptions;
|
|
1244
|
+
return ctx;
|
|
1235
1245
|
}
|
|
1236
1246
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
const
|
|
1247
|
+
const NOOP_MESSAGE_FUNCTION = () => '';
|
|
1248
|
+
const isMessageFunction = (val) => shared.isFunction(val);
|
|
1249
|
+
// implementation of `translate` function
|
|
1250
|
+
function translate(context, ...args) {
|
|
1251
|
+
const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
|
|
1252
|
+
const [key, options] = parseTranslateArgs(...args);
|
|
1242
1253
|
const missingWarn = shared.isBoolean(options.missingWarn)
|
|
1243
1254
|
? options.missingWarn
|
|
1244
1255
|
: context.missingWarn;
|
|
1245
|
-
shared.isBoolean(options.fallbackWarn)
|
|
1256
|
+
const fallbackWarn = shared.isBoolean(options.fallbackWarn)
|
|
1246
1257
|
? options.fallbackWarn
|
|
1247
1258
|
: context.fallbackWarn;
|
|
1248
|
-
const
|
|
1259
|
+
const escapeParameter = shared.isBoolean(options.escapeParameter)
|
|
1260
|
+
? options.escapeParameter
|
|
1261
|
+
: context.escapeParameter;
|
|
1262
|
+
const resolvedMessage = !!options.resolvedMessage;
|
|
1263
|
+
// prettier-ignore
|
|
1264
|
+
const defaultMsgOrKey = shared.isString(options.default) || shared.isBoolean(options.default) // default by function option
|
|
1265
|
+
? !shared.isBoolean(options.default)
|
|
1266
|
+
? options.default
|
|
1267
|
+
: (!messageCompiler ? () => key : key)
|
|
1268
|
+
: fallbackFormat // default by `fallbackFormat` option
|
|
1269
|
+
? (!messageCompiler ? () => key : key)
|
|
1270
|
+
: null;
|
|
1271
|
+
const enableDefaultMsg = fallbackFormat ||
|
|
1272
|
+
(defaultMsgOrKey != null &&
|
|
1273
|
+
(shared.isString(defaultMsgOrKey) || shared.isFunction(defaultMsgOrKey)));
|
|
1249
1274
|
const locale = getLocale(context, options);
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
let formatter = __datetimeFormatters.get(id);
|
|
1278
|
-
if (!formatter) {
|
|
1279
|
-
formatter = new Intl.DateTimeFormat(targetLocale, shared.assign({}, format, overrides));
|
|
1280
|
-
__datetimeFormatters.set(id, formatter);
|
|
1281
|
-
}
|
|
1282
|
-
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
1283
|
-
}
|
|
1284
|
-
/** @internal */
|
|
1285
|
-
const DATETIME_FORMAT_OPTIONS_KEYS = [
|
|
1286
|
-
'localeMatcher',
|
|
1287
|
-
'weekday',
|
|
1288
|
-
'era',
|
|
1289
|
-
'year',
|
|
1290
|
-
'month',
|
|
1291
|
-
'day',
|
|
1292
|
-
'hour',
|
|
1293
|
-
'minute',
|
|
1294
|
-
'second',
|
|
1295
|
-
'timeZoneName',
|
|
1296
|
-
'formatMatcher',
|
|
1297
|
-
'hour12',
|
|
1298
|
-
'timeZone',
|
|
1299
|
-
'dateStyle',
|
|
1300
|
-
'timeStyle',
|
|
1301
|
-
'calendar',
|
|
1302
|
-
'dayPeriod',
|
|
1303
|
-
'numberingSystem',
|
|
1304
|
-
'hourCycle',
|
|
1305
|
-
'fractionalSecondDigits'
|
|
1306
|
-
];
|
|
1307
|
-
/** @internal */
|
|
1308
|
-
function parseDateTimeArgs(...args) {
|
|
1309
|
-
const [arg1, arg2, arg3, arg4] = args;
|
|
1310
|
-
const options = {};
|
|
1311
|
-
let overrides = {};
|
|
1312
|
-
let value;
|
|
1313
|
-
if (shared.isString(arg1)) {
|
|
1314
|
-
// Only allow ISO strings - other date formats are often supported,
|
|
1315
|
-
// but may cause different results in different browsers.
|
|
1316
|
-
const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
|
|
1317
|
-
if (!matches) {
|
|
1318
|
-
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
1319
|
-
}
|
|
1320
|
-
// Some browsers can not parse the iso datetime separated by space,
|
|
1321
|
-
// this is a compromise solution by replace the 'T'/' ' with 'T'
|
|
1322
|
-
const dateTime = matches[3]
|
|
1323
|
-
? matches[3].trim().startsWith('T')
|
|
1324
|
-
? `${matches[1].trim()}${matches[3].trim()}`
|
|
1325
|
-
: `${matches[1].trim()}T${matches[3].trim()}`
|
|
1326
|
-
: matches[1].trim();
|
|
1327
|
-
value = new Date(dateTime);
|
|
1328
|
-
try {
|
|
1329
|
-
// This will fail if the date is not valid
|
|
1330
|
-
value.toISOString();
|
|
1331
|
-
}
|
|
1332
|
-
catch (e) {
|
|
1333
|
-
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
else if (shared.isDate(arg1)) {
|
|
1337
|
-
if (isNaN(arg1.getTime())) {
|
|
1338
|
-
throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
|
|
1275
|
+
// escape params
|
|
1276
|
+
escapeParameter && escapeParams(options);
|
|
1277
|
+
// resolve message format
|
|
1278
|
+
// eslint-disable-next-line prefer-const
|
|
1279
|
+
let [formatScope, targetLocale, message] = !resolvedMessage
|
|
1280
|
+
? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
|
|
1281
|
+
: [
|
|
1282
|
+
key,
|
|
1283
|
+
locale,
|
|
1284
|
+
messages[locale] || {}
|
|
1285
|
+
];
|
|
1286
|
+
// NOTE:
|
|
1287
|
+
// Fix to work around `ssrTransfrom` bug in Vite.
|
|
1288
|
+
// https://github.com/vitejs/vite/issues/4306
|
|
1289
|
+
// To get around this, use temporary variables.
|
|
1290
|
+
// https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
|
|
1291
|
+
let format = formatScope;
|
|
1292
|
+
// if you use default message, set it as message format!
|
|
1293
|
+
let cacheBaseKey = key;
|
|
1294
|
+
if (!resolvedMessage &&
|
|
1295
|
+
!(shared.isString(format) ||
|
|
1296
|
+
isMessageAST(format) ||
|
|
1297
|
+
isMessageFunction(format))) {
|
|
1298
|
+
if (enableDefaultMsg) {
|
|
1299
|
+
format = defaultMsgOrKey;
|
|
1300
|
+
cacheBaseKey = format;
|
|
1339
1301
|
}
|
|
1340
|
-
value = arg1;
|
|
1341
1302
|
}
|
|
1342
|
-
|
|
1343
|
-
|
|
1303
|
+
// checking message format and target locale
|
|
1304
|
+
if (!resolvedMessage &&
|
|
1305
|
+
(!(shared.isString(format) ||
|
|
1306
|
+
isMessageAST(format) ||
|
|
1307
|
+
isMessageFunction(format)) ||
|
|
1308
|
+
!shared.isString(targetLocale))) {
|
|
1309
|
+
return unresolving ? NOT_REOSLVED : key;
|
|
1344
1310
|
}
|
|
1345
|
-
|
|
1346
|
-
|
|
1311
|
+
// setup compile error detecting
|
|
1312
|
+
let occurred = false;
|
|
1313
|
+
const onError = () => {
|
|
1314
|
+
occurred = true;
|
|
1315
|
+
};
|
|
1316
|
+
// compile message format
|
|
1317
|
+
const msg = !isMessageFunction(format)
|
|
1318
|
+
? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError)
|
|
1319
|
+
: format;
|
|
1320
|
+
// if occurred compile error, return the message format
|
|
1321
|
+
if (occurred) {
|
|
1322
|
+
return format;
|
|
1347
1323
|
}
|
|
1348
|
-
|
|
1349
|
-
|
|
1324
|
+
// evaluate message with context
|
|
1325
|
+
const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
|
|
1326
|
+
const msgContext = createMessageContext(ctxOptions);
|
|
1327
|
+
const messaged = evaluateMessage(context, msg, msgContext);
|
|
1328
|
+
// if use post translation option, proceed it with handler
|
|
1329
|
+
const ret = postTranslation
|
|
1330
|
+
? postTranslation(messaged, key)
|
|
1331
|
+
: messaged;
|
|
1332
|
+
return ret;
|
|
1333
|
+
}
|
|
1334
|
+
function escapeParams(options) {
|
|
1335
|
+
if (shared.isArray(options.list)) {
|
|
1336
|
+
options.list = options.list.map(item => shared.isString(item) ? shared.escapeHtml(item) : item);
|
|
1350
1337
|
}
|
|
1351
|
-
else if (shared.
|
|
1352
|
-
Object.keys(
|
|
1353
|
-
if (
|
|
1354
|
-
|
|
1355
|
-
}
|
|
1356
|
-
else {
|
|
1357
|
-
options[key] = arg2[key];
|
|
1338
|
+
else if (shared.isObject(options.named)) {
|
|
1339
|
+
Object.keys(options.named).forEach(key => {
|
|
1340
|
+
if (shared.isString(options.named[key])) {
|
|
1341
|
+
options.named[key] = shared.escapeHtml(options.named[key]);
|
|
1358
1342
|
}
|
|
1359
1343
|
});
|
|
1360
1344
|
}
|
|
1361
|
-
if (shared.isString(arg3)) {
|
|
1362
|
-
options.locale = arg3;
|
|
1363
|
-
}
|
|
1364
|
-
else if (shared.isPlainObject(arg3)) {
|
|
1365
|
-
overrides = arg3;
|
|
1366
|
-
}
|
|
1367
|
-
if (shared.isPlainObject(arg4)) {
|
|
1368
|
-
overrides = arg4;
|
|
1369
|
-
}
|
|
1370
|
-
return [options.key || '', value, options, overrides];
|
|
1371
|
-
}
|
|
1372
|
-
/** @internal */
|
|
1373
|
-
function clearDateTimeFormat(ctx, locale, format) {
|
|
1374
|
-
const context = ctx;
|
|
1375
|
-
for (const key in format) {
|
|
1376
|
-
const id = `${locale}__${key}`;
|
|
1377
|
-
if (!context.__datetimeFormatters.has(id)) {
|
|
1378
|
-
continue;
|
|
1379
|
-
}
|
|
1380
|
-
context.__datetimeFormatters.delete(id);
|
|
1381
|
-
}
|
|
1382
1345
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
const { __numberFormatters } = context;
|
|
1388
|
-
const [key, value, options, overrides] = parseNumberArgs(...args);
|
|
1389
|
-
const missingWarn = shared.isBoolean(options.missingWarn)
|
|
1390
|
-
? options.missingWarn
|
|
1391
|
-
: context.missingWarn;
|
|
1392
|
-
shared.isBoolean(options.fallbackWarn)
|
|
1393
|
-
? options.fallbackWarn
|
|
1394
|
-
: context.fallbackWarn;
|
|
1395
|
-
const part = !!options.part;
|
|
1396
|
-
const locale = getLocale(context, options);
|
|
1397
|
-
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1398
|
-
fallbackLocale, locale);
|
|
1399
|
-
if (!shared.isString(key) || key === '') {
|
|
1400
|
-
return new Intl.NumberFormat(locale, overrides).format(value);
|
|
1401
|
-
}
|
|
1402
|
-
// resolve format
|
|
1403
|
-
let numberFormat = {};
|
|
1346
|
+
function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
|
|
1347
|
+
const { messages, onWarn, messageResolver: resolveValue, localeFallbacker } = context;
|
|
1348
|
+
const locales = localeFallbacker(context, fallbackLocale, locale); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1349
|
+
let message = {};
|
|
1404
1350
|
let targetLocale;
|
|
1405
1351
|
let format = null;
|
|
1406
|
-
const type = '
|
|
1352
|
+
const type = 'translate';
|
|
1407
1353
|
for (let i = 0; i < locales.length; i++) {
|
|
1408
1354
|
targetLocale = locales[i];
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
format =
|
|
1412
|
-
|
|
1355
|
+
message =
|
|
1356
|
+
messages[targetLocale] || {};
|
|
1357
|
+
if ((format = resolveValue(message, key)) === null) {
|
|
1358
|
+
// if null, resolve with object key path
|
|
1359
|
+
format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1360
|
+
}
|
|
1361
|
+
if (shared.isString(format) || isMessageAST(format) || isMessageFunction(format)) {
|
|
1413
1362
|
break;
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1363
|
+
}
|
|
1364
|
+
if (!isImplicitFallback(targetLocale, locales)) {
|
|
1365
|
+
const missingRet = handleMissing(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1366
|
+
key, targetLocale, missingWarn, type);
|
|
1367
|
+
if (missingRet !== key) {
|
|
1368
|
+
format = missingRet;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1419
1371
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1372
|
+
return [format, targetLocale, message];
|
|
1373
|
+
}
|
|
1374
|
+
function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError) {
|
|
1375
|
+
const { messageCompiler, warnHtmlMessage } = context;
|
|
1376
|
+
if (isMessageFunction(format)) {
|
|
1377
|
+
const msg = format;
|
|
1378
|
+
msg.locale = msg.locale || targetLocale;
|
|
1379
|
+
msg.key = msg.key || key;
|
|
1380
|
+
return msg;
|
|
1423
1381
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1382
|
+
if (messageCompiler == null) {
|
|
1383
|
+
const msg = (() => format);
|
|
1384
|
+
msg.locale = targetLocale;
|
|
1385
|
+
msg.key = key;
|
|
1386
|
+
return msg;
|
|
1428
1387
|
}
|
|
1429
|
-
|
|
1388
|
+
const msg = messageCompiler(format, getCompileContext(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, onError));
|
|
1389
|
+
msg.locale = targetLocale;
|
|
1390
|
+
msg.key = key;
|
|
1391
|
+
msg.source = format;
|
|
1392
|
+
return msg;
|
|
1393
|
+
}
|
|
1394
|
+
function evaluateMessage(context, msg, msgCtx) {
|
|
1395
|
+
const messaged = msg(msgCtx);
|
|
1396
|
+
return messaged;
|
|
1430
1397
|
}
|
|
1431
1398
|
/** @internal */
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
'style',
|
|
1435
|
-
'currency',
|
|
1436
|
-
'currencyDisplay',
|
|
1437
|
-
'currencySign',
|
|
1438
|
-
'useGrouping',
|
|
1439
|
-
'minimumIntegerDigits',
|
|
1440
|
-
'minimumFractionDigits',
|
|
1441
|
-
'maximumFractionDigits',
|
|
1442
|
-
'minimumSignificantDigits',
|
|
1443
|
-
'maximumSignificantDigits',
|
|
1444
|
-
'compactDisplay',
|
|
1445
|
-
'notation',
|
|
1446
|
-
'signDisplay',
|
|
1447
|
-
'unit',
|
|
1448
|
-
'unitDisplay',
|
|
1449
|
-
'roundingMode',
|
|
1450
|
-
'roundingPriority',
|
|
1451
|
-
'roundingIncrement',
|
|
1452
|
-
'trailingZeroDisplay'
|
|
1453
|
-
];
|
|
1454
|
-
/** @internal */
|
|
1455
|
-
function parseNumberArgs(...args) {
|
|
1456
|
-
const [arg1, arg2, arg3, arg4] = args;
|
|
1399
|
+
function parseTranslateArgs(...args) {
|
|
1400
|
+
const [arg1, arg2, arg3] = args;
|
|
1457
1401
|
const options = {};
|
|
1458
|
-
|
|
1459
|
-
|
|
1402
|
+
if (!shared.isString(arg1) &&
|
|
1403
|
+
!shared.isNumber(arg1) &&
|
|
1404
|
+
!isMessageFunction(arg1) &&
|
|
1405
|
+
!isMessageAST(arg1)) {
|
|
1460
1406
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
1461
1407
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1408
|
+
// prettier-ignore
|
|
1409
|
+
const key = shared.isNumber(arg1)
|
|
1410
|
+
? String(arg1)
|
|
1411
|
+
: isMessageFunction(arg1)
|
|
1412
|
+
? arg1
|
|
1413
|
+
: arg1;
|
|
1414
|
+
if (shared.isNumber(arg2)) {
|
|
1415
|
+
options.plural = arg2;
|
|
1465
1416
|
}
|
|
1466
|
-
else if (shared.
|
|
1467
|
-
|
|
1468
|
-
if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
1469
|
-
overrides[key] = arg2[key];
|
|
1470
|
-
}
|
|
1471
|
-
else {
|
|
1472
|
-
options[key] = arg2[key];
|
|
1473
|
-
}
|
|
1474
|
-
});
|
|
1417
|
+
else if (shared.isString(arg2)) {
|
|
1418
|
+
options.default = arg2;
|
|
1475
1419
|
}
|
|
1476
|
-
if (shared.
|
|
1477
|
-
options.
|
|
1420
|
+
else if (shared.isPlainObject(arg2) && !shared.isEmptyObject(arg2)) {
|
|
1421
|
+
options.named = arg2;
|
|
1478
1422
|
}
|
|
1479
|
-
else if (shared.
|
|
1480
|
-
|
|
1423
|
+
else if (shared.isArray(arg2)) {
|
|
1424
|
+
options.list = arg2;
|
|
1481
1425
|
}
|
|
1482
|
-
if (shared.
|
|
1483
|
-
|
|
1426
|
+
if (shared.isNumber(arg3)) {
|
|
1427
|
+
options.plural = arg3;
|
|
1484
1428
|
}
|
|
1485
|
-
|
|
1429
|
+
else if (shared.isString(arg3)) {
|
|
1430
|
+
options.default = arg3;
|
|
1431
|
+
}
|
|
1432
|
+
else if (shared.isPlainObject(arg3)) {
|
|
1433
|
+
shared.assign(options, arg3);
|
|
1434
|
+
}
|
|
1435
|
+
return [key, options];
|
|
1486
1436
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1437
|
+
function getCompileContext(context, locale, key, source, warnHtmlMessage, onError) {
|
|
1438
|
+
return {
|
|
1439
|
+
locale,
|
|
1440
|
+
key,
|
|
1441
|
+
warnHtmlMessage,
|
|
1442
|
+
onError: (err) => {
|
|
1443
|
+
onError && onError(err);
|
|
1444
|
+
{
|
|
1445
|
+
throw err;
|
|
1446
|
+
}
|
|
1447
|
+
},
|
|
1448
|
+
onCacheKey: (source) => shared.generateFormatCacheKey(locale, key, source)
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function getMessageContextOptions(context, locale, message, options) {
|
|
1452
|
+
const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
|
|
1453
|
+
const resolveMessage = (key, useLinked) => {
|
|
1454
|
+
let val = resolveValue(message, key);
|
|
1455
|
+
// fallback
|
|
1456
|
+
if (val == null && (fallbackContext || useLinked)) {
|
|
1457
|
+
const [, , message] = resolveMessageFormat(fallbackContext || context, // NOTE: if has fallbackContext, fallback to root, else if use linked, fallback to local context
|
|
1458
|
+
key, locale, fallbackLocale, fallbackWarn, missingWarn);
|
|
1459
|
+
val = resolveValue(message, key);
|
|
1494
1460
|
}
|
|
1495
|
-
|
|
1461
|
+
if (shared.isString(val) || isMessageAST(val)) {
|
|
1462
|
+
let occurred = false;
|
|
1463
|
+
const onError = () => {
|
|
1464
|
+
occurred = true;
|
|
1465
|
+
};
|
|
1466
|
+
const msg = compileMessageFormat(context, key, locale, val, key, onError);
|
|
1467
|
+
return !occurred
|
|
1468
|
+
? msg
|
|
1469
|
+
: NOOP_MESSAGE_FUNCTION;
|
|
1470
|
+
}
|
|
1471
|
+
else if (isMessageFunction(val)) {
|
|
1472
|
+
return val;
|
|
1473
|
+
}
|
|
1474
|
+
else {
|
|
1475
|
+
// TODO: should be implemented warning message
|
|
1476
|
+
return NOOP_MESSAGE_FUNCTION;
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
const ctxOptions = {
|
|
1480
|
+
locale,
|
|
1481
|
+
modifiers,
|
|
1482
|
+
pluralRules,
|
|
1483
|
+
messages: resolveMessage
|
|
1484
|
+
};
|
|
1485
|
+
if (context.processor) {
|
|
1486
|
+
ctxOptions.processor = context.processor;
|
|
1487
|
+
}
|
|
1488
|
+
if (options.list) {
|
|
1489
|
+
ctxOptions.list = options.list;
|
|
1490
|
+
}
|
|
1491
|
+
if (options.named) {
|
|
1492
|
+
ctxOptions.named = options.named;
|
|
1496
1493
|
}
|
|
1494
|
+
if (shared.isNumber(options.plural)) {
|
|
1495
|
+
ctxOptions.pluralIndex = options.plural;
|
|
1496
|
+
}
|
|
1497
|
+
return ctxOptions;
|
|
1497
1498
|
}
|
|
1498
1499
|
|
|
1499
1500
|
exports.CompileErrorCodes = messageCompiler.CompileErrorCodes;
|