@intlify/core-base 10.0.0-beta.6 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core-base.cjs +1233 -1233
- package/dist/core-base.d.ts +19 -4
- package/dist/core-base.esm-browser.js +1233 -1233
- package/dist/core-base.esm-browser.prod.js +2 -2
- package/dist/core-base.global.js +1233 -1233
- package/dist/core-base.global.prod.js +2 -2
- package/dist/core-base.mjs +1243 -1243
- package/dist/core-base.prod.cjs +1116 -1116
- package/package.json +4 -4
package/dist/core-base.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* core-base v10.0.0
|
|
2
|
+
* core-base v10.0.0
|
|
3
3
|
* (c) 2024 kazuya kawaguchi
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
|
-
import { getGlobalThis, isObject,
|
|
7
|
-
import {
|
|
6
|
+
import { getGlobalThis, isObject, isString, isBoolean, warn, format as format$1, isFunction, isPromise, isArray, isPlainObject, assign, isRegExp, warnOnce, isEmptyObject, isDate, isNumber, join, toDisplayString, escapeHtml, inBrowser, mark, measure, generateCodeFrame, generateFormatCacheKey } from '@intlify/shared';
|
|
7
|
+
import { detectHtmlTag, defaultOnError, baseCompile as baseCompile$1, COMPILE_ERROR_CODES_EXTEND_POINT, createCompileError } from '@intlify/message-compiler';
|
|
8
8
|
export { CompileErrorCodes, createCompileError } from '@intlify/message-compiler';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -20,402 +20,147 @@ function initFeatureFlags() {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
27
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
28
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
29
|
-
};
|
|
30
|
-
pathStateMachine[1 /* States.IN_PATH */] = {
|
|
31
|
-
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */],
|
|
32
|
-
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */],
|
|
33
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
34
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
35
|
-
};
|
|
36
|
-
pathStateMachine[2 /* States.BEFORE_IDENT */] = {
|
|
37
|
-
["w" /* PathCharTypes.WORKSPACE */]: [2 /* States.BEFORE_IDENT */],
|
|
38
|
-
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
39
|
-
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */]
|
|
40
|
-
};
|
|
41
|
-
pathStateMachine[3 /* States.IN_IDENT */] = {
|
|
42
|
-
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
43
|
-
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
44
|
-
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */, 1 /* Actions.PUSH */],
|
|
45
|
-
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */, 1 /* Actions.PUSH */],
|
|
46
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */, 1 /* Actions.PUSH */],
|
|
47
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */, 1 /* Actions.PUSH */]
|
|
48
|
-
};
|
|
49
|
-
pathStateMachine[4 /* States.IN_SUB_PATH */] = {
|
|
50
|
-
["'" /* PathCharTypes.SINGLE_QUOTE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
51
|
-
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
52
|
-
["[" /* PathCharTypes.LEFT_BRACKET */]: [
|
|
53
|
-
4 /* States.IN_SUB_PATH */,
|
|
54
|
-
2 /* Actions.INC_SUB_PATH_DEPTH */
|
|
55
|
-
],
|
|
56
|
-
["]" /* PathCharTypes.RIGHT_BRACKET */]: [1 /* States.IN_PATH */, 3 /* Actions.PUSH_SUB_PATH */],
|
|
57
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
58
|
-
["l" /* PathCharTypes.ELSE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */]
|
|
59
|
-
};
|
|
60
|
-
pathStateMachine[5 /* States.IN_SINGLE_QUOTE */] = {
|
|
61
|
-
["'" /* PathCharTypes.SINGLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
62
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
63
|
-
["l" /* PathCharTypes.ELSE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
64
|
-
};
|
|
65
|
-
pathStateMachine[6 /* States.IN_DOUBLE_QUOTE */] = {
|
|
66
|
-
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
67
|
-
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
68
|
-
["l" /* PathCharTypes.ELSE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Check if an expression is a literal value.
|
|
72
|
-
*/
|
|
73
|
-
const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
|
|
74
|
-
function isLiteral(exp) {
|
|
75
|
-
return literalValueRE.test(exp);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Strip quotes from a string
|
|
79
|
-
*/
|
|
80
|
-
function stripQuotes(str) {
|
|
81
|
-
const a = str.charCodeAt(0);
|
|
82
|
-
const b = str.charCodeAt(str.length - 1);
|
|
83
|
-
return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
|
|
23
|
+
function format(ast) {
|
|
24
|
+
const msg = (ctx) => formatParts(ctx, ast);
|
|
25
|
+
return msg;
|
|
84
26
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
*/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return
|
|
27
|
+
function formatParts(ctx, ast) {
|
|
28
|
+
const body = ast.b || ast.body;
|
|
29
|
+
if ((body.t || body.type) === 1 /* NodeTypes.Plural */) {
|
|
30
|
+
const plural = body;
|
|
31
|
+
const cases = plural.c || plural.cases;
|
|
32
|
+
return ctx.plural(cases.reduce((messages, c) => [
|
|
33
|
+
...messages,
|
|
34
|
+
formatMessageParts(ctx, c)
|
|
35
|
+
], []));
|
|
91
36
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
case 0x5b: // [
|
|
95
|
-
case 0x5d: // ]
|
|
96
|
-
case 0x2e: // .
|
|
97
|
-
case 0x22: // "
|
|
98
|
-
case 0x27: // '
|
|
99
|
-
return ch;
|
|
100
|
-
case 0x5f: // _
|
|
101
|
-
case 0x24: // $
|
|
102
|
-
case 0x2d: // -
|
|
103
|
-
return "i" /* PathCharTypes.IDENT */;
|
|
104
|
-
case 0x09: // Tab (HT)
|
|
105
|
-
case 0x0a: // Newline (LF)
|
|
106
|
-
case 0x0d: // Return (CR)
|
|
107
|
-
case 0xa0: // No-break space (NBSP)
|
|
108
|
-
case 0xfeff: // Byte Order Mark (BOM)
|
|
109
|
-
case 0x2028: // Line Separator (LS)
|
|
110
|
-
case 0x2029: // Paragraph Separator (PS)
|
|
111
|
-
return "w" /* PathCharTypes.WORKSPACE */;
|
|
37
|
+
else {
|
|
38
|
+
return formatMessageParts(ctx, body);
|
|
112
39
|
}
|
|
113
|
-
return "i" /* PathCharTypes.IDENT */;
|
|
114
40
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return
|
|
41
|
+
function formatMessageParts(ctx, node) {
|
|
42
|
+
const _static = node.s || node.static;
|
|
43
|
+
if (_static) {
|
|
44
|
+
return ctx.type === 'text'
|
|
45
|
+
? _static
|
|
46
|
+
: ctx.normalize([_static]);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const messages = (node.i || node.items).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
|
|
50
|
+
return ctx.normalize(messages);
|
|
125
51
|
}
|
|
126
|
-
return isLiteral(trimmed)
|
|
127
|
-
? stripQuotes(trimmed)
|
|
128
|
-
: "*" /* PathCharTypes.ASTARISK */ + trimmed;
|
|
129
52
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
let mode = 0 /* States.BEFORE_PATH */;
|
|
137
|
-
let subPathDepth = 0;
|
|
138
|
-
let c;
|
|
139
|
-
let key; // eslint-disable-line
|
|
140
|
-
let newChar;
|
|
141
|
-
let type;
|
|
142
|
-
let transition;
|
|
143
|
-
let action;
|
|
144
|
-
let typeMap;
|
|
145
|
-
const actions = [];
|
|
146
|
-
actions[0 /* Actions.APPEND */] = () => {
|
|
147
|
-
if (key === undefined) {
|
|
148
|
-
key = newChar;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
key += newChar;
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
actions[1 /* Actions.PUSH */] = () => {
|
|
155
|
-
if (key !== undefined) {
|
|
156
|
-
keys.push(key);
|
|
157
|
-
key = undefined;
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
actions[2 /* Actions.INC_SUB_PATH_DEPTH */] = () => {
|
|
161
|
-
actions[0 /* Actions.APPEND */]();
|
|
162
|
-
subPathDepth++;
|
|
163
|
-
};
|
|
164
|
-
actions[3 /* Actions.PUSH_SUB_PATH */] = () => {
|
|
165
|
-
if (subPathDepth > 0) {
|
|
166
|
-
subPathDepth--;
|
|
167
|
-
mode = 4 /* States.IN_SUB_PATH */;
|
|
168
|
-
actions[0 /* Actions.APPEND */]();
|
|
53
|
+
function formatMessagePart(ctx, node) {
|
|
54
|
+
const type = node.t || node.type;
|
|
55
|
+
switch (type) {
|
|
56
|
+
case 3 /* NodeTypes.Text */: {
|
|
57
|
+
const text = node;
|
|
58
|
+
return (text.v || text.value);
|
|
169
59
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
key = formatSubPath(key);
|
|
176
|
-
if (key === false) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
actions[1 /* Actions.PUSH */]();
|
|
181
|
-
}
|
|
60
|
+
case 9 /* NodeTypes.Literal */: {
|
|
61
|
+
const literal = node;
|
|
62
|
+
return (literal.v || literal.value);
|
|
182
63
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if ((mode === 5 /* States.IN_SINGLE_QUOTE */ &&
|
|
187
|
-
nextChar === "'" /* PathCharTypes.SINGLE_QUOTE */) ||
|
|
188
|
-
(mode === 6 /* States.IN_DOUBLE_QUOTE */ &&
|
|
189
|
-
nextChar === "\"" /* PathCharTypes.DOUBLE_QUOTE */)) {
|
|
190
|
-
index++;
|
|
191
|
-
newChar = '\\' + nextChar;
|
|
192
|
-
actions[0 /* Actions.APPEND */]();
|
|
193
|
-
return true;
|
|
64
|
+
case 4 /* NodeTypes.Named */: {
|
|
65
|
+
const named = node;
|
|
66
|
+
return ctx.interpolate(ctx.named(named.k || named.key));
|
|
194
67
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
c = path[index];
|
|
199
|
-
if (c === '\\' && maybeUnescapeQuote()) {
|
|
200
|
-
continue;
|
|
68
|
+
case 5 /* NodeTypes.List */: {
|
|
69
|
+
const list = node;
|
|
70
|
+
return ctx.interpolate(ctx.list(list.i != null ? list.i : list.index));
|
|
201
71
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (transition === 8 /* States.ERROR */) {
|
|
207
|
-
return;
|
|
72
|
+
case 6 /* NodeTypes.Linked */: {
|
|
73
|
+
const linked = node;
|
|
74
|
+
const modifier = linked.m || linked.modifier;
|
|
75
|
+
return ctx.linked(formatMessagePart(ctx, linked.k || linked.key), modifier ? formatMessagePart(ctx, modifier) : undefined, ctx.type);
|
|
208
76
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (action) {
|
|
213
|
-
newChar = c;
|
|
214
|
-
if (action() === false) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
77
|
+
case 7 /* NodeTypes.LinkedKey */: {
|
|
78
|
+
const linkedKey = node;
|
|
79
|
+
return (linkedKey.v || linkedKey.value);
|
|
218
80
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return
|
|
81
|
+
case 8 /* NodeTypes.LinkedModifier */: {
|
|
82
|
+
const linkedModifier = node;
|
|
83
|
+
return (linkedModifier.v || linkedModifier.value);
|
|
222
84
|
}
|
|
85
|
+
default:
|
|
86
|
+
throw new Error(`unhandled node type on format message part: ${type}`);
|
|
223
87
|
}
|
|
224
88
|
}
|
|
225
|
-
// path token cache
|
|
226
|
-
const cache = new Map();
|
|
227
|
-
/**
|
|
228
|
-
* key-value message resolver
|
|
229
|
-
*
|
|
230
|
-
* @remarks
|
|
231
|
-
* Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
|
|
232
|
-
*
|
|
233
|
-
* @param obj - A target object to be resolved with path
|
|
234
|
-
* @param path - A {@link Path | path} to resolve the value of message
|
|
235
|
-
*
|
|
236
|
-
* @returns A resolved {@link PathValue | path value}
|
|
237
|
-
*
|
|
238
|
-
* @VueI18nGeneral
|
|
239
|
-
*/
|
|
240
|
-
function resolveWithKeyValue(obj, path) {
|
|
241
|
-
return isObject(obj) ? obj[path] : null;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* message resolver
|
|
245
|
-
*
|
|
246
|
-
* @remarks
|
|
247
|
-
* Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
|
|
248
|
-
*
|
|
249
|
-
* @param obj - A target object to be resolved with path
|
|
250
|
-
* @param path - A {@link Path | path} to resolve the value of message
|
|
251
|
-
*
|
|
252
|
-
* @returns A resolved {@link PathValue | path value}
|
|
253
|
-
*
|
|
254
|
-
* @VueI18nGeneral
|
|
255
|
-
*/
|
|
256
|
-
function resolveValue(obj, path) {
|
|
257
|
-
// check object
|
|
258
|
-
if (!isObject(obj)) {
|
|
259
|
-
return null;
|
|
260
|
-
}
|
|
261
|
-
// parse path
|
|
262
|
-
let hit = cache.get(path);
|
|
263
|
-
if (!hit) {
|
|
264
|
-
hit = parse(path);
|
|
265
|
-
if (hit) {
|
|
266
|
-
cache.set(path, hit);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
// check hit
|
|
270
|
-
if (!hit) {
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
// resolve path value
|
|
274
|
-
const len = hit.length;
|
|
275
|
-
let last = obj;
|
|
276
|
-
let i = 0;
|
|
277
|
-
while (i < len) {
|
|
278
|
-
const val = last[hit[i]];
|
|
279
|
-
if (val === undefined) {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
if (isFunction(last)) {
|
|
283
|
-
return null;
|
|
284
|
-
}
|
|
285
|
-
last = val;
|
|
286
|
-
i++;
|
|
287
|
-
}
|
|
288
|
-
return last;
|
|
289
|
-
}
|
|
290
89
|
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const DEFAULT_INTERPOLATE = toDisplayString;
|
|
296
|
-
function pluralDefault(choice, choicesLength) {
|
|
297
|
-
choice = Math.abs(choice);
|
|
298
|
-
if (choicesLength === 2) {
|
|
299
|
-
// prettier-ignore
|
|
300
|
-
return choice
|
|
301
|
-
? choice > 1
|
|
302
|
-
? 1
|
|
303
|
-
: 0
|
|
304
|
-
: 1;
|
|
90
|
+
const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
|
|
91
|
+
function checkHtmlMessage(source, warnHtmlMessage) {
|
|
92
|
+
if (warnHtmlMessage && detectHtmlTag(source)) {
|
|
93
|
+
warn(format$1(WARN_MESSAGE, { source }));
|
|
305
94
|
}
|
|
306
|
-
return choice ? Math.min(choice, 2) : 0;
|
|
307
|
-
}
|
|
308
|
-
function getPluralIndex(options) {
|
|
309
|
-
// prettier-ignore
|
|
310
|
-
const index = isNumber(options.pluralIndex)
|
|
311
|
-
? options.pluralIndex
|
|
312
|
-
: -1;
|
|
313
|
-
// prettier-ignore
|
|
314
|
-
return options.named && (isNumber(options.named.count) || isNumber(options.named.n))
|
|
315
|
-
? isNumber(options.named.count)
|
|
316
|
-
? options.named.count
|
|
317
|
-
: isNumber(options.named.n)
|
|
318
|
-
? options.named.n
|
|
319
|
-
: index
|
|
320
|
-
: index;
|
|
321
95
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (!props.n) {
|
|
327
|
-
props.n = pluralIndex;
|
|
328
|
-
}
|
|
96
|
+
const defaultOnCacheKey = (message) => message;
|
|
97
|
+
let compileCache = Object.create(null);
|
|
98
|
+
function clearCompileCache() {
|
|
99
|
+
compileCache = Object.create(null);
|
|
329
100
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
isFunction(options.pluralRules[locale])
|
|
341
|
-
? pluralDefault
|
|
342
|
-
: undefined;
|
|
343
|
-
const plural = (messages) => {
|
|
344
|
-
return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
|
|
101
|
+
const isMessageAST = (val) => isObject(val) &&
|
|
102
|
+
(val.t === 0 || val.type === 0) &&
|
|
103
|
+
('b' in val || 'body' in val);
|
|
104
|
+
function baseCompile(message, options = {}) {
|
|
105
|
+
// error detecting on compile
|
|
106
|
+
let detectError = false;
|
|
107
|
+
const onError = options.onError || defaultOnError;
|
|
108
|
+
options.onError = (err) => {
|
|
109
|
+
detectError = true;
|
|
110
|
+
onError(err);
|
|
345
111
|
};
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
//
|
|
354
|
-
const
|
|
355
|
-
?
|
|
356
|
-
:
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
112
|
+
// compile with mesasge-compiler
|
|
113
|
+
return { ...baseCompile$1(message, options), detectError };
|
|
114
|
+
}
|
|
115
|
+
/* #__NO_SIDE_EFFECTS__ */
|
|
116
|
+
function compile(message, context) {
|
|
117
|
+
if ((!__INTLIFY_DROP_MESSAGE_COMPILER__) &&
|
|
118
|
+
isString(message)) {
|
|
119
|
+
// check HTML message
|
|
120
|
+
const warnHtmlMessage = isBoolean(context.warnHtmlMessage)
|
|
121
|
+
? context.warnHtmlMessage
|
|
122
|
+
: true;
|
|
123
|
+
(process.env.NODE_ENV !== 'production') && checkHtmlMessage(message, warnHtmlMessage);
|
|
124
|
+
// check caches
|
|
125
|
+
const onCacheKey = context.onCacheKey || defaultOnCacheKey;
|
|
126
|
+
const cacheKey = onCacheKey(message);
|
|
127
|
+
const cached = compileCache[cacheKey];
|
|
128
|
+
if (cached) {
|
|
129
|
+
return cached;
|
|
130
|
+
}
|
|
131
|
+
// compile with JIT mode
|
|
132
|
+
const { ast, detectError } = baseCompile(message, {
|
|
133
|
+
...context,
|
|
134
|
+
location: (process.env.NODE_ENV !== 'production'),
|
|
135
|
+
jit: true
|
|
136
|
+
});
|
|
137
|
+
// compose message function from AST
|
|
138
|
+
const msg = format(ast);
|
|
139
|
+
// if occurred compile error, don't cache
|
|
140
|
+
return !detectError
|
|
141
|
+
? (compileCache[cacheKey] = msg)
|
|
363
142
|
: msg;
|
|
364
143
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
? options.processor.normalize
|
|
370
|
-
: DEFAULT_NORMALIZE;
|
|
371
|
-
const interpolate = isPlainObject(options.processor) &&
|
|
372
|
-
isFunction(options.processor.interpolate)
|
|
373
|
-
? options.processor.interpolate
|
|
374
|
-
: DEFAULT_INTERPOLATE;
|
|
375
|
-
const type = isPlainObject(options.processor) && isString(options.processor.type)
|
|
376
|
-
? options.processor.type
|
|
377
|
-
: DEFAULT_MESSAGE_DATA_TYPE;
|
|
378
|
-
const linked = (key, ...args) => {
|
|
379
|
-
const [arg1, arg2] = args;
|
|
380
|
-
let type = 'text';
|
|
381
|
-
let modifier = '';
|
|
382
|
-
if (args.length === 1) {
|
|
383
|
-
if (isObject(arg1)) {
|
|
384
|
-
modifier = arg1.modifier || modifier;
|
|
385
|
-
type = arg1.type || type;
|
|
386
|
-
}
|
|
387
|
-
else if (isString(arg1)) {
|
|
388
|
-
modifier = arg1 || modifier;
|
|
389
|
-
}
|
|
144
|
+
else {
|
|
145
|
+
if ((process.env.NODE_ENV !== 'production') && !isMessageAST(message)) {
|
|
146
|
+
warn(`the message that is resolve with key '${context.key}' is not supported for jit compilation`);
|
|
147
|
+
return (() => message);
|
|
390
148
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
if (
|
|
396
|
-
|
|
149
|
+
// AST case (passed from bundler)
|
|
150
|
+
const cacheKey = message.cacheKey;
|
|
151
|
+
if (cacheKey) {
|
|
152
|
+
const cached = compileCache[cacheKey];
|
|
153
|
+
if (cached) {
|
|
154
|
+
return cached;
|
|
397
155
|
}
|
|
156
|
+
// compose message function from message (AST)
|
|
157
|
+
return (compileCache[cacheKey] =
|
|
158
|
+
format(message));
|
|
398
159
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
? ret[0]
|
|
404
|
-
: ret;
|
|
405
|
-
return modifier ? _modifier(modifier)(msg, type) : msg;
|
|
406
|
-
};
|
|
407
|
-
const ctx = {
|
|
408
|
-
["list" /* HelperNameMap.LIST */]: list,
|
|
409
|
-
["named" /* HelperNameMap.NAMED */]: named,
|
|
410
|
-
["plural" /* HelperNameMap.PLURAL */]: plural,
|
|
411
|
-
["linked" /* HelperNameMap.LINKED */]: linked,
|
|
412
|
-
["message" /* HelperNameMap.MESSAGE */]: message,
|
|
413
|
-
["type" /* HelperNameMap.TYPE */]: type,
|
|
414
|
-
["interpolate" /* HelperNameMap.INTERPOLATE */]: interpolate,
|
|
415
|
-
["normalize" /* HelperNameMap.NORMALIZE */]: normalize,
|
|
416
|
-
["values" /* HelperNameMap.VALUES */]: assign({}, _list, _named)
|
|
417
|
-
};
|
|
418
|
-
return ctx;
|
|
160
|
+
else {
|
|
161
|
+
return format(message);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
419
164
|
}
|
|
420
165
|
|
|
421
166
|
let devtools = null;
|
|
@@ -441,30 +186,6 @@ function createDevToolsHook(hook) {
|
|
|
441
186
|
return (payloads) => devtools && devtools.emit(hook, payloads);
|
|
442
187
|
}
|
|
443
188
|
|
|
444
|
-
const CoreWarnCodes = {
|
|
445
|
-
NOT_FOUND_KEY: 1,
|
|
446
|
-
FALLBACK_TO_TRANSLATE: 2,
|
|
447
|
-
CANNOT_FORMAT_NUMBER: 3,
|
|
448
|
-
FALLBACK_TO_NUMBER_FORMAT: 4,
|
|
449
|
-
CANNOT_FORMAT_DATE: 5,
|
|
450
|
-
FALLBACK_TO_DATE_FORMAT: 6,
|
|
451
|
-
EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7
|
|
452
|
-
};
|
|
453
|
-
const CORE_WARN_CODES_EXTEND_POINT = 8;
|
|
454
|
-
/** @internal */
|
|
455
|
-
const warnMessages = {
|
|
456
|
-
[CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
|
|
457
|
-
[CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
|
|
458
|
-
[CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
|
|
459
|
-
[CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
|
|
460
|
-
[CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
|
|
461
|
-
[CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
|
|
462
|
-
[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.`
|
|
463
|
-
};
|
|
464
|
-
function getWarnMessage(code, ...args) {
|
|
465
|
-
return format$1(warnMessages[code], ...args);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
189
|
const CoreErrorCodes = {
|
|
469
190
|
INVALID_ARGUMENT: COMPILE_ERROR_CODES_EXTEND_POINT, // 17
|
|
470
191
|
INVALID_DATE_ARGUMENT: 18,
|
|
@@ -638,66 +359,358 @@ function appendItemToChain(chain, target, blocks) {
|
|
|
638
359
|
return follow;
|
|
639
360
|
}
|
|
640
361
|
|
|
641
|
-
|
|
362
|
+
const pathStateMachine = [];
|
|
363
|
+
pathStateMachine[0 /* States.BEFORE_PATH */] = {
|
|
364
|
+
["w" /* PathCharTypes.WORKSPACE */]: [0 /* States.BEFORE_PATH */],
|
|
365
|
+
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
366
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
367
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
368
|
+
};
|
|
369
|
+
pathStateMachine[1 /* States.IN_PATH */] = {
|
|
370
|
+
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */],
|
|
371
|
+
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */],
|
|
372
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
|
|
373
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
|
|
374
|
+
};
|
|
375
|
+
pathStateMachine[2 /* States.BEFORE_IDENT */] = {
|
|
376
|
+
["w" /* PathCharTypes.WORKSPACE */]: [2 /* States.BEFORE_IDENT */],
|
|
377
|
+
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
378
|
+
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */]
|
|
379
|
+
};
|
|
380
|
+
pathStateMachine[3 /* States.IN_IDENT */] = {
|
|
381
|
+
["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
382
|
+
["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
|
|
383
|
+
["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */, 1 /* Actions.PUSH */],
|
|
384
|
+
["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */, 1 /* Actions.PUSH */],
|
|
385
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */, 1 /* Actions.PUSH */],
|
|
386
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */, 1 /* Actions.PUSH */]
|
|
387
|
+
};
|
|
388
|
+
pathStateMachine[4 /* States.IN_SUB_PATH */] = {
|
|
389
|
+
["'" /* PathCharTypes.SINGLE_QUOTE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
390
|
+
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */],
|
|
391
|
+
["[" /* PathCharTypes.LEFT_BRACKET */]: [
|
|
392
|
+
4 /* States.IN_SUB_PATH */,
|
|
393
|
+
2 /* Actions.INC_SUB_PATH_DEPTH */
|
|
394
|
+
],
|
|
395
|
+
["]" /* PathCharTypes.RIGHT_BRACKET */]: [1 /* States.IN_PATH */, 3 /* Actions.PUSH_SUB_PATH */],
|
|
396
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
397
|
+
["l" /* PathCharTypes.ELSE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */]
|
|
398
|
+
};
|
|
399
|
+
pathStateMachine[5 /* States.IN_SINGLE_QUOTE */] = {
|
|
400
|
+
["'" /* PathCharTypes.SINGLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
401
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
402
|
+
["l" /* PathCharTypes.ELSE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
403
|
+
};
|
|
404
|
+
pathStateMachine[6 /* States.IN_DOUBLE_QUOTE */] = {
|
|
405
|
+
["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
|
|
406
|
+
["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
|
|
407
|
+
["l" /* PathCharTypes.ELSE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */]
|
|
408
|
+
};
|
|
642
409
|
/**
|
|
643
|
-
*
|
|
644
|
-
* @internal
|
|
410
|
+
* Check if an expression is a literal value.
|
|
645
411
|
*/
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
412
|
+
const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
|
|
413
|
+
function isLiteral(exp) {
|
|
414
|
+
return literalValueRE.test(exp);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Strip quotes from a string
|
|
418
|
+
*/
|
|
419
|
+
function stripQuotes(str) {
|
|
420
|
+
const a = str.charCodeAt(0);
|
|
421
|
+
const b = str.charCodeAt(str.length - 1);
|
|
422
|
+
return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Determine the type of a character in a keypath.
|
|
426
|
+
*/
|
|
427
|
+
function getPathCharType(ch) {
|
|
428
|
+
if (ch === undefined || ch === null) {
|
|
429
|
+
return "o" /* PathCharTypes.END_OF_FAIL */;
|
|
430
|
+
}
|
|
431
|
+
const code = ch.charCodeAt(0);
|
|
432
|
+
switch (code) {
|
|
433
|
+
case 0x5b: // [
|
|
434
|
+
case 0x5d: // ]
|
|
435
|
+
case 0x2e: // .
|
|
436
|
+
case 0x22: // "
|
|
437
|
+
case 0x27: // '
|
|
438
|
+
return ch;
|
|
439
|
+
case 0x5f: // _
|
|
440
|
+
case 0x24: // $
|
|
441
|
+
case 0x2d: // -
|
|
442
|
+
return "i" /* PathCharTypes.IDENT */;
|
|
443
|
+
case 0x09: // Tab (HT)
|
|
444
|
+
case 0x0a: // Newline (LF)
|
|
445
|
+
case 0x0d: // Return (CR)
|
|
446
|
+
case 0xa0: // No-break space (NBSP)
|
|
447
|
+
case 0xfeff: // Byte Order Mark (BOM)
|
|
448
|
+
case 0x2028: // Line Separator (LS)
|
|
449
|
+
case 0x2029: // Paragraph Separator (PS)
|
|
450
|
+
return "w" /* PathCharTypes.WORKSPACE */;
|
|
451
|
+
}
|
|
452
|
+
return "i" /* PathCharTypes.IDENT */;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Format a subPath, return its plain form if it is
|
|
456
|
+
* a literal string or number. Otherwise prepend the
|
|
457
|
+
* dynamic indicator (*).
|
|
458
|
+
*/
|
|
459
|
+
function formatSubPath(path) {
|
|
460
|
+
const trimmed = path.trim();
|
|
461
|
+
// invalid leading 0
|
|
462
|
+
if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
return isLiteral(trimmed)
|
|
466
|
+
? stripQuotes(trimmed)
|
|
467
|
+
: "*" /* PathCharTypes.ASTARISK */ + trimmed;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Parse a string path into an array of segments
|
|
471
|
+
*/
|
|
472
|
+
function parse(path) {
|
|
473
|
+
const keys = [];
|
|
474
|
+
let index = -1;
|
|
475
|
+
let mode = 0 /* States.BEFORE_PATH */;
|
|
476
|
+
let subPathDepth = 0;
|
|
477
|
+
let c;
|
|
478
|
+
let key; // eslint-disable-line
|
|
479
|
+
let newChar;
|
|
480
|
+
let type;
|
|
481
|
+
let transition;
|
|
482
|
+
let action;
|
|
483
|
+
let typeMap;
|
|
484
|
+
const actions = [];
|
|
485
|
+
actions[0 /* Actions.APPEND */] = () => {
|
|
486
|
+
if (key === undefined) {
|
|
487
|
+
key = newChar;
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
key += newChar;
|
|
676
491
|
}
|
|
677
492
|
};
|
|
493
|
+
actions[1 /* Actions.PUSH */] = () => {
|
|
494
|
+
if (key !== undefined) {
|
|
495
|
+
keys.push(key);
|
|
496
|
+
key = undefined;
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
actions[2 /* Actions.INC_SUB_PATH_DEPTH */] = () => {
|
|
500
|
+
actions[0 /* Actions.APPEND */]();
|
|
501
|
+
subPathDepth++;
|
|
502
|
+
};
|
|
503
|
+
actions[3 /* Actions.PUSH_SUB_PATH */] = () => {
|
|
504
|
+
if (subPathDepth > 0) {
|
|
505
|
+
subPathDepth--;
|
|
506
|
+
mode = 4 /* States.IN_SUB_PATH */;
|
|
507
|
+
actions[0 /* Actions.APPEND */]();
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
subPathDepth = 0;
|
|
511
|
+
if (key === undefined) {
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
key = formatSubPath(key);
|
|
515
|
+
if (key === false) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
actions[1 /* Actions.PUSH */]();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
function maybeUnescapeQuote() {
|
|
524
|
+
const nextChar = path[index + 1];
|
|
525
|
+
if ((mode === 5 /* States.IN_SINGLE_QUOTE */ &&
|
|
526
|
+
nextChar === "'" /* PathCharTypes.SINGLE_QUOTE */) ||
|
|
527
|
+
(mode === 6 /* States.IN_DOUBLE_QUOTE */ &&
|
|
528
|
+
nextChar === "\"" /* PathCharTypes.DOUBLE_QUOTE */)) {
|
|
529
|
+
index++;
|
|
530
|
+
newChar = '\\' + nextChar;
|
|
531
|
+
actions[0 /* Actions.APPEND */]();
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
while (mode !== null) {
|
|
536
|
+
index++;
|
|
537
|
+
c = path[index];
|
|
538
|
+
if (c === '\\' && maybeUnescapeQuote()) {
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
type = getPathCharType(c);
|
|
542
|
+
typeMap = pathStateMachine[mode];
|
|
543
|
+
transition = typeMap[type] || typeMap["l" /* PathCharTypes.ELSE */] || 8 /* States.ERROR */;
|
|
544
|
+
// check parse error
|
|
545
|
+
if (transition === 8 /* States.ERROR */) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
mode = transition[0];
|
|
549
|
+
if (transition[1] !== undefined) {
|
|
550
|
+
action = actions[transition[1]];
|
|
551
|
+
if (action) {
|
|
552
|
+
newChar = c;
|
|
553
|
+
if (action() === false) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
// check parse finish
|
|
559
|
+
if (mode === 7 /* States.AFTER_PATH */) {
|
|
560
|
+
return keys;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
678
563
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
_compiler = compiler;
|
|
682
|
-
}
|
|
683
|
-
let _resolver;
|
|
564
|
+
// path token cache
|
|
565
|
+
const cache = new Map();
|
|
684
566
|
/**
|
|
685
|
-
*
|
|
567
|
+
* key-value message resolver
|
|
686
568
|
*
|
|
687
|
-
* @
|
|
569
|
+
* @remarks
|
|
570
|
+
* Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
|
|
571
|
+
*
|
|
572
|
+
* @param obj - A target object to be resolved with path
|
|
573
|
+
* @param path - A {@link Path | path} to resolve the value of message
|
|
574
|
+
*
|
|
575
|
+
* @returns A resolved {@link PathValue | path value}
|
|
688
576
|
*
|
|
689
577
|
* @VueI18nGeneral
|
|
690
578
|
*/
|
|
691
|
-
function
|
|
692
|
-
|
|
579
|
+
function resolveWithKeyValue(obj, path) {
|
|
580
|
+
return isObject(obj) ? obj[path] : null;
|
|
693
581
|
}
|
|
694
|
-
let _fallbacker;
|
|
695
582
|
/**
|
|
696
|
-
*
|
|
583
|
+
* message resolver
|
|
697
584
|
*
|
|
698
|
-
* @
|
|
585
|
+
* @remarks
|
|
586
|
+
* Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
|
|
699
587
|
*
|
|
700
|
-
* @
|
|
588
|
+
* @param obj - A target object to be resolved with path
|
|
589
|
+
* @param path - A {@link Path | path} to resolve the value of message
|
|
590
|
+
*
|
|
591
|
+
* @returns A resolved {@link PathValue | path value}
|
|
592
|
+
*
|
|
593
|
+
* @VueI18nGeneral
|
|
594
|
+
*/
|
|
595
|
+
function resolveValue(obj, path) {
|
|
596
|
+
// check object
|
|
597
|
+
if (!isObject(obj)) {
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
// parse path
|
|
601
|
+
let hit = cache.get(path);
|
|
602
|
+
if (!hit) {
|
|
603
|
+
hit = parse(path);
|
|
604
|
+
if (hit) {
|
|
605
|
+
cache.set(path, hit);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
// check hit
|
|
609
|
+
if (!hit) {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
// resolve path value
|
|
613
|
+
const len = hit.length;
|
|
614
|
+
let last = obj;
|
|
615
|
+
let i = 0;
|
|
616
|
+
while (i < len) {
|
|
617
|
+
const val = last[hit[i]];
|
|
618
|
+
if (val === undefined) {
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
if (isFunction(last)) {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
last = val;
|
|
625
|
+
i++;
|
|
626
|
+
}
|
|
627
|
+
return last;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const CoreWarnCodes = {
|
|
631
|
+
NOT_FOUND_KEY: 1,
|
|
632
|
+
FALLBACK_TO_TRANSLATE: 2,
|
|
633
|
+
CANNOT_FORMAT_NUMBER: 3,
|
|
634
|
+
FALLBACK_TO_NUMBER_FORMAT: 4,
|
|
635
|
+
CANNOT_FORMAT_DATE: 5,
|
|
636
|
+
FALLBACK_TO_DATE_FORMAT: 6,
|
|
637
|
+
EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7
|
|
638
|
+
};
|
|
639
|
+
const CORE_WARN_CODES_EXTEND_POINT = 8;
|
|
640
|
+
/** @internal */
|
|
641
|
+
const warnMessages = {
|
|
642
|
+
[CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
|
|
643
|
+
[CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
|
|
644
|
+
[CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
|
|
645
|
+
[CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
|
|
646
|
+
[CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
|
|
647
|
+
[CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
|
|
648
|
+
[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.`
|
|
649
|
+
};
|
|
650
|
+
function getWarnMessage(code, ...args) {
|
|
651
|
+
return format$1(warnMessages[code], ...args);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
655
|
+
/**
|
|
656
|
+
* Intlify core-base version
|
|
657
|
+
* @internal
|
|
658
|
+
*/
|
|
659
|
+
const VERSION = '10.0.0';
|
|
660
|
+
const NOT_REOSLVED = -1;
|
|
661
|
+
const DEFAULT_LOCALE = 'en-US';
|
|
662
|
+
const MISSING_RESOLVE_VALUE = '';
|
|
663
|
+
const capitalize = (str) => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`;
|
|
664
|
+
function getDefaultLinkedModifiers() {
|
|
665
|
+
return {
|
|
666
|
+
upper: (val, type) => {
|
|
667
|
+
// prettier-ignore
|
|
668
|
+
return type === 'text' && isString(val)
|
|
669
|
+
? val.toUpperCase()
|
|
670
|
+
: type === 'vnode' && isObject(val) && '__v_isVNode' in val
|
|
671
|
+
? val.children.toUpperCase()
|
|
672
|
+
: val;
|
|
673
|
+
},
|
|
674
|
+
lower: (val, type) => {
|
|
675
|
+
// prettier-ignore
|
|
676
|
+
return type === 'text' && isString(val)
|
|
677
|
+
? val.toLowerCase()
|
|
678
|
+
: type === 'vnode' && isObject(val) && '__v_isVNode' in val
|
|
679
|
+
? val.children.toLowerCase()
|
|
680
|
+
: val;
|
|
681
|
+
},
|
|
682
|
+
capitalize: (val, type) => {
|
|
683
|
+
// prettier-ignore
|
|
684
|
+
return (type === 'text' && isString(val)
|
|
685
|
+
? capitalize(val)
|
|
686
|
+
: type === 'vnode' && isObject(val) && '__v_isVNode' in val
|
|
687
|
+
? capitalize(val.children)
|
|
688
|
+
: val);
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
let _compiler;
|
|
693
|
+
function registerMessageCompiler(compiler) {
|
|
694
|
+
_compiler = compiler;
|
|
695
|
+
}
|
|
696
|
+
let _resolver;
|
|
697
|
+
/**
|
|
698
|
+
* Register the message resolver
|
|
699
|
+
*
|
|
700
|
+
* @param resolver - A {@link MessageResolver} function
|
|
701
|
+
*
|
|
702
|
+
* @VueI18nGeneral
|
|
703
|
+
*/
|
|
704
|
+
function registerMessageResolver(resolver) {
|
|
705
|
+
_resolver = resolver;
|
|
706
|
+
}
|
|
707
|
+
let _fallbacker;
|
|
708
|
+
/**
|
|
709
|
+
* Register the locale fallbacker
|
|
710
|
+
*
|
|
711
|
+
* @param fallbacker - A {@link LocaleFallbacker} function
|
|
712
|
+
*
|
|
713
|
+
* @VueI18nGeneral
|
|
701
714
|
*/
|
|
702
715
|
function registerLocaleFallbacker(fallbacker) {
|
|
703
716
|
_fallbacker = fallbacker;
|
|
@@ -811,667 +824,280 @@ function createCoreContext(options = {}) {
|
|
|
811
824
|
messageCompiler,
|
|
812
825
|
messageResolver,
|
|
813
826
|
localeFallbacker,
|
|
814
|
-
fallbackContext,
|
|
815
|
-
onWarn,
|
|
816
|
-
__meta
|
|
817
|
-
};
|
|
818
|
-
{
|
|
819
|
-
context.datetimeFormats = datetimeFormats;
|
|
820
|
-
context.numberFormats = numberFormats;
|
|
821
|
-
context.__datetimeFormatters = __datetimeFormatters;
|
|
822
|
-
context.__numberFormatters = __numberFormatters;
|
|
823
|
-
}
|
|
824
|
-
// for vue-devtools timeline event
|
|
825
|
-
if ((process.env.NODE_ENV !== 'production')) {
|
|
826
|
-
context.__v_emitter =
|
|
827
|
-
internalOptions.__v_emitter != null
|
|
828
|
-
? internalOptions.__v_emitter
|
|
829
|
-
: undefined;
|
|
830
|
-
}
|
|
831
|
-
// NOTE: experimental !!
|
|
832
|
-
if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
|
|
833
|
-
initI18nDevTools(context, version, __meta);
|
|
834
|
-
}
|
|
835
|
-
return context;
|
|
836
|
-
}
|
|
837
|
-
/** @internal */
|
|
838
|
-
function isTranslateFallbackWarn(fallback, key) {
|
|
839
|
-
return fallback instanceof RegExp ? fallback.test(key) : fallback;
|
|
840
|
-
}
|
|
841
|
-
/** @internal */
|
|
842
|
-
function isTranslateMissingWarn(missing, key) {
|
|
843
|
-
return missing instanceof RegExp ? missing.test(key) : missing;
|
|
844
|
-
}
|
|
845
|
-
/** @internal */
|
|
846
|
-
function handleMissing(context, key, locale, missingWarn, type) {
|
|
847
|
-
const { missing, onWarn } = context;
|
|
848
|
-
// for vue-devtools timeline event
|
|
849
|
-
if ((process.env.NODE_ENV !== 'production')) {
|
|
850
|
-
const emitter = context.__v_emitter;
|
|
851
|
-
if (emitter) {
|
|
852
|
-
emitter.emit('missing', {
|
|
853
|
-
locale,
|
|
854
|
-
key,
|
|
855
|
-
type,
|
|
856
|
-
groupId: `${type}:${key}`
|
|
857
|
-
});
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
if (missing !== null) {
|
|
861
|
-
const ret = missing(context, locale, key, type);
|
|
862
|
-
return isString(ret) ? ret : key;
|
|
863
|
-
}
|
|
864
|
-
else {
|
|
865
|
-
if ((process.env.NODE_ENV !== 'production') && isTranslateMissingWarn(missingWarn, key)) {
|
|
866
|
-
onWarn(getWarnMessage(CoreWarnCodes.NOT_FOUND_KEY, { key, locale }));
|
|
867
|
-
}
|
|
868
|
-
return key;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
/** @internal */
|
|
872
|
-
function updateFallbackLocale(ctx, locale, fallback) {
|
|
873
|
-
const context = ctx;
|
|
874
|
-
context.__localeChainCache = new Map();
|
|
875
|
-
ctx.localeFallbacker(ctx, fallback, locale);
|
|
876
|
-
}
|
|
877
|
-
/** @internal */
|
|
878
|
-
function isAlmostSameLocale(locale, compareLocale) {
|
|
879
|
-
if (locale === compareLocale)
|
|
880
|
-
return false;
|
|
881
|
-
return locale.split('-')[0] === compareLocale.split('-')[0];
|
|
882
|
-
}
|
|
883
|
-
/** @internal */
|
|
884
|
-
function isImplicitFallback(targetLocale, locales) {
|
|
885
|
-
const index = locales.indexOf(targetLocale);
|
|
886
|
-
if (index === -1) {
|
|
887
|
-
return false;
|
|
888
|
-
}
|
|
889
|
-
for (let i = index + 1; i < locales.length; i++) {
|
|
890
|
-
if (isAlmostSameLocale(targetLocale, locales[i])) {
|
|
891
|
-
return true;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
return false;
|
|
895
|
-
}
|
|
896
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
897
|
-
|
|
898
|
-
function format(ast) {
|
|
899
|
-
const msg = (ctx) => formatParts(ctx, ast);
|
|
900
|
-
return msg;
|
|
901
|
-
}
|
|
902
|
-
function formatParts(ctx, ast) {
|
|
903
|
-
const body = ast.b || ast.body;
|
|
904
|
-
if ((body.t || body.type) === 1 /* NodeTypes.Plural */) {
|
|
905
|
-
const plural = body;
|
|
906
|
-
const cases = plural.c || plural.cases;
|
|
907
|
-
return ctx.plural(cases.reduce((messages, c) => [
|
|
908
|
-
...messages,
|
|
909
|
-
formatMessageParts(ctx, c)
|
|
910
|
-
], []));
|
|
911
|
-
}
|
|
912
|
-
else {
|
|
913
|
-
return formatMessageParts(ctx, body);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
function formatMessageParts(ctx, node) {
|
|
917
|
-
const _static = node.s || node.static;
|
|
918
|
-
if (_static) {
|
|
919
|
-
return ctx.type === 'text'
|
|
920
|
-
? _static
|
|
921
|
-
: ctx.normalize([_static]);
|
|
922
|
-
}
|
|
923
|
-
else {
|
|
924
|
-
const messages = (node.i || node.items).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
|
|
925
|
-
return ctx.normalize(messages);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
function formatMessagePart(ctx, node) {
|
|
929
|
-
const type = node.t || node.type;
|
|
930
|
-
switch (type) {
|
|
931
|
-
case 3 /* NodeTypes.Text */: {
|
|
932
|
-
const text = node;
|
|
933
|
-
return (text.v || text.value);
|
|
934
|
-
}
|
|
935
|
-
case 9 /* NodeTypes.Literal */: {
|
|
936
|
-
const literal = node;
|
|
937
|
-
return (literal.v || literal.value);
|
|
938
|
-
}
|
|
939
|
-
case 4 /* NodeTypes.Named */: {
|
|
940
|
-
const named = node;
|
|
941
|
-
return ctx.interpolate(ctx.named(named.k || named.key));
|
|
942
|
-
}
|
|
943
|
-
case 5 /* NodeTypes.List */: {
|
|
944
|
-
const list = node;
|
|
945
|
-
return ctx.interpolate(ctx.list(list.i != null ? list.i : list.index));
|
|
946
|
-
}
|
|
947
|
-
case 6 /* NodeTypes.Linked */: {
|
|
948
|
-
const linked = node;
|
|
949
|
-
const modifier = linked.m || linked.modifier;
|
|
950
|
-
return ctx.linked(formatMessagePart(ctx, linked.k || linked.key), modifier ? formatMessagePart(ctx, modifier) : undefined, ctx.type);
|
|
951
|
-
}
|
|
952
|
-
case 7 /* NodeTypes.LinkedKey */: {
|
|
953
|
-
const linkedKey = node;
|
|
954
|
-
return (linkedKey.v || linkedKey.value);
|
|
955
|
-
}
|
|
956
|
-
case 8 /* NodeTypes.LinkedModifier */: {
|
|
957
|
-
const linkedModifier = node;
|
|
958
|
-
return (linkedModifier.v || linkedModifier.value);
|
|
959
|
-
}
|
|
960
|
-
default:
|
|
961
|
-
throw new Error(`unhandled node type on format message part: ${type}`);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
|
|
966
|
-
function checkHtmlMessage(source, warnHtmlMessage) {
|
|
967
|
-
if (warnHtmlMessage && detectHtmlTag(source)) {
|
|
968
|
-
warn(format$1(WARN_MESSAGE, { source }));
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
const defaultOnCacheKey = (message) => message;
|
|
972
|
-
let compileCache = Object.create(null);
|
|
973
|
-
function clearCompileCache() {
|
|
974
|
-
compileCache = Object.create(null);
|
|
975
|
-
}
|
|
976
|
-
const isMessageAST = (val) => isObject(val) &&
|
|
977
|
-
(val.t === 0 || val.type === 0) &&
|
|
978
|
-
('b' in val || 'body' in val);
|
|
979
|
-
function baseCompile(message, options = {}) {
|
|
980
|
-
// error detecting on compile
|
|
981
|
-
let detectError = false;
|
|
982
|
-
const onError = options.onError || defaultOnError;
|
|
983
|
-
options.onError = (err) => {
|
|
984
|
-
detectError = true;
|
|
985
|
-
onError(err);
|
|
986
|
-
};
|
|
987
|
-
// compile with mesasge-compiler
|
|
988
|
-
return { ...baseCompile$1(message, options), detectError };
|
|
989
|
-
}
|
|
990
|
-
/* #__NO_SIDE_EFFECTS__ */
|
|
991
|
-
function compile(message, context) {
|
|
992
|
-
if ((!__INTLIFY_DROP_MESSAGE_COMPILER__) &&
|
|
993
|
-
isString(message)) {
|
|
994
|
-
// check HTML message
|
|
995
|
-
const warnHtmlMessage = isBoolean(context.warnHtmlMessage)
|
|
996
|
-
? context.warnHtmlMessage
|
|
997
|
-
: true;
|
|
998
|
-
(process.env.NODE_ENV !== 'production') && checkHtmlMessage(message, warnHtmlMessage);
|
|
999
|
-
// check caches
|
|
1000
|
-
const onCacheKey = context.onCacheKey || defaultOnCacheKey;
|
|
1001
|
-
const cacheKey = onCacheKey(message);
|
|
1002
|
-
const cached = compileCache[cacheKey];
|
|
1003
|
-
if (cached) {
|
|
1004
|
-
return cached;
|
|
1005
|
-
}
|
|
1006
|
-
// compile with JIT mode
|
|
1007
|
-
const { ast, detectError } = baseCompile(message, {
|
|
1008
|
-
...context,
|
|
1009
|
-
location: (process.env.NODE_ENV !== 'production'),
|
|
1010
|
-
jit: true
|
|
1011
|
-
});
|
|
1012
|
-
// compose message function from AST
|
|
1013
|
-
const msg = format(ast);
|
|
1014
|
-
// if occurred compile error, don't cache
|
|
1015
|
-
return !detectError
|
|
1016
|
-
? (compileCache[cacheKey] = msg)
|
|
1017
|
-
: msg;
|
|
1018
|
-
}
|
|
1019
|
-
else {
|
|
1020
|
-
if ((process.env.NODE_ENV !== 'production') && !isMessageAST(message)) {
|
|
1021
|
-
warn(`the message that is resolve with key '${context.key}' is not supported for jit compilation`);
|
|
1022
|
-
return (() => message);
|
|
1023
|
-
}
|
|
1024
|
-
// AST case (passed from bundler)
|
|
1025
|
-
const cacheKey = message.cacheKey;
|
|
1026
|
-
if (cacheKey) {
|
|
1027
|
-
const cached = compileCache[cacheKey];
|
|
1028
|
-
if (cached) {
|
|
1029
|
-
return cached;
|
|
1030
|
-
}
|
|
1031
|
-
// compose message function from message (AST)
|
|
1032
|
-
return (compileCache[cacheKey] =
|
|
1033
|
-
format(message));
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
return format(message);
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
const NOOP_MESSAGE_FUNCTION = () => '';
|
|
1042
|
-
const isMessageFunction = (val) => isFunction(val);
|
|
1043
|
-
// implementation of `translate` function
|
|
1044
|
-
function translate(context, ...args) {
|
|
1045
|
-
const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
|
|
1046
|
-
const [key, options] = parseTranslateArgs(...args);
|
|
1047
|
-
const missingWarn = isBoolean(options.missingWarn)
|
|
1048
|
-
? options.missingWarn
|
|
1049
|
-
: context.missingWarn;
|
|
1050
|
-
const fallbackWarn = isBoolean(options.fallbackWarn)
|
|
1051
|
-
? options.fallbackWarn
|
|
1052
|
-
: context.fallbackWarn;
|
|
1053
|
-
const escapeParameter = isBoolean(options.escapeParameter)
|
|
1054
|
-
? options.escapeParameter
|
|
1055
|
-
: context.escapeParameter;
|
|
1056
|
-
const resolvedMessage = !!options.resolvedMessage;
|
|
1057
|
-
// prettier-ignore
|
|
1058
|
-
const defaultMsgOrKey = isString(options.default) || isBoolean(options.default) // default by function option
|
|
1059
|
-
? !isBoolean(options.default)
|
|
1060
|
-
? options.default
|
|
1061
|
-
: (!messageCompiler ? () => key : key)
|
|
1062
|
-
: fallbackFormat // default by `fallbackFormat` option
|
|
1063
|
-
? (!messageCompiler ? () => key : key)
|
|
1064
|
-
: null;
|
|
1065
|
-
const enableDefaultMsg = fallbackFormat ||
|
|
1066
|
-
(defaultMsgOrKey != null &&
|
|
1067
|
-
(isString(defaultMsgOrKey) || isFunction(defaultMsgOrKey)));
|
|
1068
|
-
const locale = getLocale(context, options);
|
|
1069
|
-
// escape params
|
|
1070
|
-
escapeParameter && escapeParams(options);
|
|
1071
|
-
// resolve message format
|
|
1072
|
-
// eslint-disable-next-line prefer-const
|
|
1073
|
-
let [formatScope, targetLocale, message] = !resolvedMessage
|
|
1074
|
-
? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
|
|
1075
|
-
: [
|
|
1076
|
-
key,
|
|
1077
|
-
locale,
|
|
1078
|
-
messages[locale] || {}
|
|
1079
|
-
];
|
|
1080
|
-
// NOTE:
|
|
1081
|
-
// Fix to work around `ssrTransfrom` bug in Vite.
|
|
1082
|
-
// https://github.com/vitejs/vite/issues/4306
|
|
1083
|
-
// To get around this, use temporary variables.
|
|
1084
|
-
// https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
|
|
1085
|
-
let format = formatScope;
|
|
1086
|
-
// if you use default message, set it as message format!
|
|
1087
|
-
let cacheBaseKey = key;
|
|
1088
|
-
if (!resolvedMessage &&
|
|
1089
|
-
!(isString(format) ||
|
|
1090
|
-
isMessageAST(format) ||
|
|
1091
|
-
isMessageFunction(format))) {
|
|
1092
|
-
if (enableDefaultMsg) {
|
|
1093
|
-
format = defaultMsgOrKey;
|
|
1094
|
-
cacheBaseKey = format;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
// checking message format and target locale
|
|
1098
|
-
if (!resolvedMessage &&
|
|
1099
|
-
(!(isString(format) ||
|
|
1100
|
-
isMessageAST(format) ||
|
|
1101
|
-
isMessageFunction(format)) ||
|
|
1102
|
-
!isString(targetLocale))) {
|
|
1103
|
-
return unresolving ? NOT_REOSLVED : key;
|
|
1104
|
-
}
|
|
1105
|
-
// TODO: refactor
|
|
1106
|
-
if ((process.env.NODE_ENV !== 'production') && isString(format) && context.messageCompiler == null) {
|
|
1107
|
-
warn(`The message format compilation is not supported in this build. ` +
|
|
1108
|
-
`Because message compiler isn't included. ` +
|
|
1109
|
-
`You need to pre-compilation all message format. ` +
|
|
1110
|
-
`So translate function return '${key}'.`);
|
|
1111
|
-
return key;
|
|
1112
|
-
}
|
|
1113
|
-
// setup compile error detecting
|
|
1114
|
-
let occurred = false;
|
|
1115
|
-
const onError = () => {
|
|
1116
|
-
occurred = true;
|
|
827
|
+
fallbackContext,
|
|
828
|
+
onWarn,
|
|
829
|
+
__meta
|
|
1117
830
|
};
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
831
|
+
{
|
|
832
|
+
context.datetimeFormats = datetimeFormats;
|
|
833
|
+
context.numberFormats = numberFormats;
|
|
834
|
+
context.__datetimeFormatters = __datetimeFormatters;
|
|
835
|
+
context.__numberFormatters = __numberFormatters;
|
|
836
|
+
}
|
|
837
|
+
// for vue-devtools timeline event
|
|
838
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
839
|
+
context.__v_emitter =
|
|
840
|
+
internalOptions.__v_emitter != null
|
|
841
|
+
? internalOptions.__v_emitter
|
|
842
|
+
: undefined;
|
|
1125
843
|
}
|
|
1126
|
-
// evaluate message with context
|
|
1127
|
-
const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
|
|
1128
|
-
const msgContext = createMessageContext(ctxOptions);
|
|
1129
|
-
const messaged = evaluateMessage(context, msg, msgContext);
|
|
1130
|
-
// if use post translation option, proceed it with handler
|
|
1131
|
-
const ret = postTranslation
|
|
1132
|
-
? postTranslation(messaged, key)
|
|
1133
|
-
: messaged;
|
|
1134
844
|
// NOTE: experimental !!
|
|
1135
845
|
if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
|
|
1136
|
-
|
|
1137
|
-
const payloads = {
|
|
1138
|
-
timestamp: Date.now(),
|
|
1139
|
-
key: isString(key)
|
|
1140
|
-
? key
|
|
1141
|
-
: isMessageFunction(format)
|
|
1142
|
-
? format.key
|
|
1143
|
-
: '',
|
|
1144
|
-
locale: targetLocale || (isMessageFunction(format)
|
|
1145
|
-
? format.locale
|
|
1146
|
-
: ''),
|
|
1147
|
-
format: isString(format)
|
|
1148
|
-
? format
|
|
1149
|
-
: isMessageFunction(format)
|
|
1150
|
-
? format.source
|
|
1151
|
-
: '',
|
|
1152
|
-
message: ret
|
|
1153
|
-
};
|
|
1154
|
-
payloads.meta = assign({}, context.__meta, getAdditionalMeta() || {});
|
|
1155
|
-
translateDevTools(payloads);
|
|
846
|
+
initI18nDevTools(context, version, __meta);
|
|
1156
847
|
}
|
|
1157
|
-
return
|
|
848
|
+
return context;
|
|
1158
849
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
}
|
|
1163
|
-
else if (isObject(options.named)) {
|
|
1164
|
-
Object.keys(options.named).forEach(key => {
|
|
1165
|
-
if (isString(options.named[key])) {
|
|
1166
|
-
options.named[key] = escapeHtml(options.named[key]);
|
|
1167
|
-
}
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
850
|
+
/** @internal */
|
|
851
|
+
function isTranslateFallbackWarn(fallback, key) {
|
|
852
|
+
return fallback instanceof RegExp ? fallback.test(key) : fallback;
|
|
1170
853
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
!isAlmostSameLocale(locale, targetLocale) &&
|
|
1185
|
-
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
1186
|
-
onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_TRANSLATE, {
|
|
854
|
+
/** @internal */
|
|
855
|
+
function isTranslateMissingWarn(missing, key) {
|
|
856
|
+
return missing instanceof RegExp ? missing.test(key) : missing;
|
|
857
|
+
}
|
|
858
|
+
/** @internal */
|
|
859
|
+
function handleMissing(context, key, locale, missingWarn, type) {
|
|
860
|
+
const { missing, onWarn } = context;
|
|
861
|
+
// for vue-devtools timeline event
|
|
862
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
863
|
+
const emitter = context.__v_emitter;
|
|
864
|
+
if (emitter) {
|
|
865
|
+
emitter.emit('missing', {
|
|
866
|
+
locale,
|
|
1187
867
|
key,
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
// for vue-devtools timeline event
|
|
1192
|
-
if ((process.env.NODE_ENV !== 'production') && locale !== targetLocale) {
|
|
1193
|
-
const emitter = context.__v_emitter;
|
|
1194
|
-
if (emitter) {
|
|
1195
|
-
emitter.emit('fallback', {
|
|
1196
|
-
type,
|
|
1197
|
-
key,
|
|
1198
|
-
from,
|
|
1199
|
-
to,
|
|
1200
|
-
groupId: `${type}:${key}`
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
message =
|
|
1205
|
-
messages[targetLocale] || {};
|
|
1206
|
-
// for vue-devtools timeline event
|
|
1207
|
-
let start = null;
|
|
1208
|
-
let startTag;
|
|
1209
|
-
let endTag;
|
|
1210
|
-
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1211
|
-
start = window.performance.now();
|
|
1212
|
-
startTag = 'intlify-message-resolve-start';
|
|
1213
|
-
endTag = 'intlify-message-resolve-end';
|
|
1214
|
-
mark && mark(startTag);
|
|
1215
|
-
}
|
|
1216
|
-
if ((format = resolveValue(message, key)) === null) {
|
|
1217
|
-
// if null, resolve with object key path
|
|
1218
|
-
format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1219
|
-
}
|
|
1220
|
-
// for vue-devtools timeline event
|
|
1221
|
-
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1222
|
-
const end = window.performance.now();
|
|
1223
|
-
const emitter = context.__v_emitter;
|
|
1224
|
-
if (emitter && start && format) {
|
|
1225
|
-
emitter.emit('message-resolve', {
|
|
1226
|
-
type: 'message-resolve',
|
|
1227
|
-
key,
|
|
1228
|
-
message: format,
|
|
1229
|
-
time: end - start,
|
|
1230
|
-
groupId: `${type}:${key}`
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
if (startTag && endTag && mark && measure) {
|
|
1234
|
-
mark(endTag);
|
|
1235
|
-
measure('intlify message resolve', startTag, endTag);
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
if (isString(format) || isMessageAST(format) || isMessageFunction(format)) {
|
|
1239
|
-
break;
|
|
868
|
+
type,
|
|
869
|
+
groupId: `${type}:${key}`
|
|
870
|
+
});
|
|
1240
871
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
872
|
+
}
|
|
873
|
+
if (missing !== null) {
|
|
874
|
+
const ret = missing(context, locale, key, type);
|
|
875
|
+
return isString(ret) ? ret : key;
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
if ((process.env.NODE_ENV !== 'production') && isTranslateMissingWarn(missingWarn, key)) {
|
|
879
|
+
onWarn(getWarnMessage(CoreWarnCodes.NOT_FOUND_KEY, { key, locale }));
|
|
1247
880
|
}
|
|
1248
|
-
|
|
881
|
+
return key;
|
|
1249
882
|
}
|
|
1250
|
-
return [format, targetLocale, message];
|
|
1251
883
|
}
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
884
|
+
/** @internal */
|
|
885
|
+
function updateFallbackLocale(ctx, locale, fallback) {
|
|
886
|
+
const context = ctx;
|
|
887
|
+
context.__localeChainCache = new Map();
|
|
888
|
+
ctx.localeFallbacker(ctx, fallback, locale);
|
|
889
|
+
}
|
|
890
|
+
/** @internal */
|
|
891
|
+
function isAlmostSameLocale(locale, compareLocale) {
|
|
892
|
+
if (locale === compareLocale)
|
|
893
|
+
return false;
|
|
894
|
+
return locale.split('-')[0] === compareLocale.split('-')[0];
|
|
895
|
+
}
|
|
896
|
+
/** @internal */
|
|
897
|
+
function isImplicitFallback(targetLocale, locales) {
|
|
898
|
+
const index = locales.indexOf(targetLocale);
|
|
899
|
+
if (index === -1) {
|
|
900
|
+
return false;
|
|
1259
901
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
return msg;
|
|
902
|
+
for (let i = index + 1; i < locales.length; i++) {
|
|
903
|
+
if (isAlmostSameLocale(targetLocale, locales[i])) {
|
|
904
|
+
return true;
|
|
905
|
+
}
|
|
1265
906
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
910
|
+
|
|
911
|
+
const intlDefined = typeof Intl !== 'undefined';
|
|
912
|
+
const Availabilities = {
|
|
913
|
+
dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
|
|
914
|
+
numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
// implementation of `datetime` function
|
|
918
|
+
function datetime(context, ...args) {
|
|
919
|
+
const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
|
|
920
|
+
const { __datetimeFormatters } = context;
|
|
921
|
+
if ((process.env.NODE_ENV !== 'production') && !Availabilities.dateTimeFormat) {
|
|
922
|
+
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
|
|
923
|
+
return MISSING_RESOLVE_VALUE;
|
|
1275
924
|
}
|
|
1276
|
-
const
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
925
|
+
const [key, value, options, overrides] = parseDateTimeArgs(...args);
|
|
926
|
+
const missingWarn = isBoolean(options.missingWarn)
|
|
927
|
+
? options.missingWarn
|
|
928
|
+
: context.missingWarn;
|
|
929
|
+
const fallbackWarn = isBoolean(options.fallbackWarn)
|
|
930
|
+
? options.fallbackWarn
|
|
931
|
+
: context.fallbackWarn;
|
|
932
|
+
const part = !!options.part;
|
|
933
|
+
const locale = getLocale(context, options);
|
|
934
|
+
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
935
|
+
fallbackLocale, locale);
|
|
936
|
+
if (!isString(key) || key === '') {
|
|
937
|
+
return new Intl.DateTimeFormat(locale, overrides).format(value);
|
|
938
|
+
}
|
|
939
|
+
// resolve format
|
|
940
|
+
let datetimeFormat = {};
|
|
941
|
+
let targetLocale;
|
|
942
|
+
let format = null;
|
|
943
|
+
let from = locale;
|
|
944
|
+
let to = null;
|
|
945
|
+
const type = 'datetime format';
|
|
946
|
+
for (let i = 0; i < locales.length; i++) {
|
|
947
|
+
targetLocale = to = locales[i];
|
|
948
|
+
if ((process.env.NODE_ENV !== 'production') &&
|
|
949
|
+
locale !== targetLocale &&
|
|
950
|
+
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
951
|
+
onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_DATE_FORMAT, {
|
|
952
|
+
key,
|
|
953
|
+
target: targetLocale
|
|
954
|
+
}));
|
|
1288
955
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
956
|
+
// for vue-devtools timeline event
|
|
957
|
+
if ((process.env.NODE_ENV !== 'production') && locale !== targetLocale) {
|
|
958
|
+
const emitter = context.__v_emitter;
|
|
959
|
+
if (emitter) {
|
|
960
|
+
emitter.emit('fallback', {
|
|
961
|
+
type,
|
|
962
|
+
key,
|
|
963
|
+
from,
|
|
964
|
+
to,
|
|
965
|
+
groupId: `${type}:${key}`
|
|
966
|
+
});
|
|
967
|
+
}
|
|
1292
968
|
}
|
|
969
|
+
datetimeFormat =
|
|
970
|
+
datetimeFormats[targetLocale] || {};
|
|
971
|
+
format = datetimeFormat[key];
|
|
972
|
+
if (isPlainObject(format))
|
|
973
|
+
break;
|
|
974
|
+
handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
975
|
+
from = to;
|
|
1293
976
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
return msg;
|
|
1298
|
-
}
|
|
1299
|
-
function evaluateMessage(context, msg, msgCtx) {
|
|
1300
|
-
// for vue-devtools timeline event
|
|
1301
|
-
let start = null;
|
|
1302
|
-
let startTag;
|
|
1303
|
-
let endTag;
|
|
1304
|
-
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1305
|
-
start = window.performance.now();
|
|
1306
|
-
startTag = 'intlify-message-evaluation-start';
|
|
1307
|
-
endTag = 'intlify-message-evaluation-end';
|
|
1308
|
-
mark && mark(startTag);
|
|
977
|
+
// checking format and target locale
|
|
978
|
+
if (!isPlainObject(format) || !isString(targetLocale)) {
|
|
979
|
+
return unresolving ? NOT_REOSLVED : key;
|
|
1309
980
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
const end = window.performance.now();
|
|
1314
|
-
const emitter = context.__v_emitter;
|
|
1315
|
-
if (emitter && start) {
|
|
1316
|
-
emitter.emit('message-evaluation', {
|
|
1317
|
-
type: 'message-evaluation',
|
|
1318
|
-
value: messaged,
|
|
1319
|
-
time: end - start,
|
|
1320
|
-
groupId: `${'translate'}:${msg.key}`
|
|
1321
|
-
});
|
|
1322
|
-
}
|
|
1323
|
-
if (startTag && endTag && mark && measure) {
|
|
1324
|
-
mark(endTag);
|
|
1325
|
-
measure('intlify message evaluation', startTag, endTag);
|
|
1326
|
-
}
|
|
981
|
+
let id = `${targetLocale}__${key}`;
|
|
982
|
+
if (!isEmptyObject(overrides)) {
|
|
983
|
+
id = `${id}__${JSON.stringify(overrides)}`;
|
|
1327
984
|
}
|
|
1328
|
-
|
|
985
|
+
let formatter = __datetimeFormatters.get(id);
|
|
986
|
+
if (!formatter) {
|
|
987
|
+
formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
|
|
988
|
+
__datetimeFormatters.set(id, formatter);
|
|
989
|
+
}
|
|
990
|
+
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
1329
991
|
}
|
|
1330
992
|
/** @internal */
|
|
1331
|
-
|
|
1332
|
-
|
|
993
|
+
const DATETIME_FORMAT_OPTIONS_KEYS = [
|
|
994
|
+
'localeMatcher',
|
|
995
|
+
'weekday',
|
|
996
|
+
'era',
|
|
997
|
+
'year',
|
|
998
|
+
'month',
|
|
999
|
+
'day',
|
|
1000
|
+
'hour',
|
|
1001
|
+
'minute',
|
|
1002
|
+
'second',
|
|
1003
|
+
'timeZoneName',
|
|
1004
|
+
'formatMatcher',
|
|
1005
|
+
'hour12',
|
|
1006
|
+
'timeZone',
|
|
1007
|
+
'dateStyle',
|
|
1008
|
+
'timeStyle',
|
|
1009
|
+
'calendar',
|
|
1010
|
+
'dayPeriod',
|
|
1011
|
+
'numberingSystem',
|
|
1012
|
+
'hourCycle',
|
|
1013
|
+
'fractionalSecondDigits'
|
|
1014
|
+
];
|
|
1015
|
+
/** @internal */
|
|
1016
|
+
function parseDateTimeArgs(...args) {
|
|
1017
|
+
const [arg1, arg2, arg3, arg4] = args;
|
|
1333
1018
|
const options = {};
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1019
|
+
let overrides = {};
|
|
1020
|
+
let value;
|
|
1021
|
+
if (isString(arg1)) {
|
|
1022
|
+
// Only allow ISO strings - other date formats are often supported,
|
|
1023
|
+
// but may cause different results in different browsers.
|
|
1024
|
+
const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
|
|
1025
|
+
if (!matches) {
|
|
1026
|
+
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
1027
|
+
}
|
|
1028
|
+
// Some browsers can not parse the iso datetime separated by space,
|
|
1029
|
+
// this is a compromise solution by replace the 'T'/' ' with 'T'
|
|
1030
|
+
const dateTime = matches[3]
|
|
1031
|
+
? matches[3].trim().startsWith('T')
|
|
1032
|
+
? `${matches[1].trim()}${matches[3].trim()}`
|
|
1033
|
+
: `${matches[1].trim()}T${matches[3].trim()}`
|
|
1034
|
+
: matches[1].trim();
|
|
1035
|
+
value = new Date(dateTime);
|
|
1036
|
+
try {
|
|
1037
|
+
// This will fail if the date is not valid
|
|
1038
|
+
value.toISOString();
|
|
1039
|
+
}
|
|
1040
|
+
catch {
|
|
1041
|
+
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
1042
|
+
}
|
|
1354
1043
|
}
|
|
1355
|
-
else if (
|
|
1356
|
-
|
|
1044
|
+
else if (isDate(arg1)) {
|
|
1045
|
+
if (isNaN(arg1.getTime())) {
|
|
1046
|
+
throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
|
|
1047
|
+
}
|
|
1048
|
+
value = arg1;
|
|
1357
1049
|
}
|
|
1358
|
-
if (isNumber(
|
|
1359
|
-
|
|
1050
|
+
else if (isNumber(arg1)) {
|
|
1051
|
+
value = arg1;
|
|
1360
1052
|
}
|
|
1361
|
-
else
|
|
1362
|
-
|
|
1053
|
+
else {
|
|
1054
|
+
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
1363
1055
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1056
|
+
if (isString(arg2)) {
|
|
1057
|
+
options.key = arg2;
|
|
1366
1058
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
locale,
|
|
1372
|
-
key,
|
|
1373
|
-
warnHtmlMessage,
|
|
1374
|
-
onError: (err) => {
|
|
1375
|
-
onError && onError(err);
|
|
1376
|
-
if ((process.env.NODE_ENV !== 'production')) {
|
|
1377
|
-
const _source = getSourceForCodeFrame(source);
|
|
1378
|
-
const message = `Message compilation error: ${err.message}`;
|
|
1379
|
-
const codeFrame = err.location &&
|
|
1380
|
-
_source &&
|
|
1381
|
-
generateCodeFrame(_source, err.location.start.offset, err.location.end.offset);
|
|
1382
|
-
const emitter = context.__v_emitter;
|
|
1383
|
-
if (emitter && _source) {
|
|
1384
|
-
emitter.emit('compile-error', {
|
|
1385
|
-
message: _source,
|
|
1386
|
-
error: err.message,
|
|
1387
|
-
start: err.location && err.location.start.offset,
|
|
1388
|
-
end: err.location && err.location.end.offset,
|
|
1389
|
-
groupId: `${'translate'}:${key}`
|
|
1390
|
-
});
|
|
1391
|
-
}
|
|
1392
|
-
console.error(codeFrame ? `${message}\n${codeFrame}` : message);
|
|
1059
|
+
else if (isPlainObject(arg2)) {
|
|
1060
|
+
Object.keys(arg2).forEach(key => {
|
|
1061
|
+
if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
1062
|
+
overrides[key] = arg2[key];
|
|
1393
1063
|
}
|
|
1394
1064
|
else {
|
|
1395
|
-
|
|
1065
|
+
options[key] = arg2[key];
|
|
1396
1066
|
}
|
|
1397
|
-
}
|
|
1398
|
-
onCacheKey: (source) => generateFormatCacheKey(locale, key, source)
|
|
1399
|
-
};
|
|
1400
|
-
}
|
|
1401
|
-
function getSourceForCodeFrame(source) {
|
|
1402
|
-
if (isString(source)) {
|
|
1403
|
-
return source;
|
|
1404
|
-
}
|
|
1405
|
-
else {
|
|
1406
|
-
if (source.loc && source.loc.source) {
|
|
1407
|
-
return source.loc.source;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
function getMessageContextOptions(context, locale, message, options) {
|
|
1412
|
-
const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
|
|
1413
|
-
const resolveMessage = (key, useLinked) => {
|
|
1414
|
-
let val = resolveValue(message, key);
|
|
1415
|
-
// fallback
|
|
1416
|
-
if (val == null && (fallbackContext || useLinked)) {
|
|
1417
|
-
const [, , message] = resolveMessageFormat(fallbackContext || context, // NOTE: if has fallbackContext, fallback to root, else if use linked, fallback to local context
|
|
1418
|
-
key, locale, fallbackLocale, fallbackWarn, missingWarn);
|
|
1419
|
-
val = resolveValue(message, key);
|
|
1420
|
-
}
|
|
1421
|
-
if (isString(val) || isMessageAST(val)) {
|
|
1422
|
-
let occurred = false;
|
|
1423
|
-
const onError = () => {
|
|
1424
|
-
occurred = true;
|
|
1425
|
-
};
|
|
1426
|
-
const msg = compileMessageFormat(context, key, locale, val, key, onError);
|
|
1427
|
-
return !occurred
|
|
1428
|
-
? msg
|
|
1429
|
-
: NOOP_MESSAGE_FUNCTION;
|
|
1430
|
-
}
|
|
1431
|
-
else if (isMessageFunction(val)) {
|
|
1432
|
-
return val;
|
|
1433
|
-
}
|
|
1434
|
-
else {
|
|
1435
|
-
// TODO: should be implemented warning message
|
|
1436
|
-
return NOOP_MESSAGE_FUNCTION;
|
|
1437
|
-
}
|
|
1438
|
-
};
|
|
1439
|
-
const ctxOptions = {
|
|
1440
|
-
locale,
|
|
1441
|
-
modifiers,
|
|
1442
|
-
pluralRules,
|
|
1443
|
-
messages: resolveMessage
|
|
1444
|
-
};
|
|
1445
|
-
if (context.processor) {
|
|
1446
|
-
ctxOptions.processor = context.processor;
|
|
1067
|
+
});
|
|
1447
1068
|
}
|
|
1448
|
-
if (
|
|
1449
|
-
|
|
1069
|
+
if (isString(arg3)) {
|
|
1070
|
+
options.locale = arg3;
|
|
1450
1071
|
}
|
|
1451
|
-
if (
|
|
1452
|
-
|
|
1072
|
+
else if (isPlainObject(arg3)) {
|
|
1073
|
+
overrides = arg3;
|
|
1453
1074
|
}
|
|
1454
|
-
if (
|
|
1455
|
-
|
|
1075
|
+
if (isPlainObject(arg4)) {
|
|
1076
|
+
overrides = arg4;
|
|
1077
|
+
}
|
|
1078
|
+
return [options.key || '', value, options, overrides];
|
|
1079
|
+
}
|
|
1080
|
+
/** @internal */
|
|
1081
|
+
function clearDateTimeFormat(ctx, locale, format) {
|
|
1082
|
+
const context = ctx;
|
|
1083
|
+
for (const key in format) {
|
|
1084
|
+
const id = `${locale}__${key}`;
|
|
1085
|
+
if (!context.__datetimeFormatters.has(id)) {
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
context.__datetimeFormatters.delete(id);
|
|
1456
1089
|
}
|
|
1457
|
-
return ctxOptions;
|
|
1458
1090
|
}
|
|
1459
1091
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
// implementation of `datetime` function
|
|
1467
|
-
function datetime(context, ...args) {
|
|
1468
|
-
const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
|
|
1469
|
-
const { __datetimeFormatters } = context;
|
|
1470
|
-
if ((process.env.NODE_ENV !== 'production') && !Availabilities.dateTimeFormat) {
|
|
1471
|
-
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
|
|
1092
|
+
// implementation of `number` function
|
|
1093
|
+
function number(context, ...args) {
|
|
1094
|
+
const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
|
|
1095
|
+
const { __numberFormatters } = context;
|
|
1096
|
+
if ((process.env.NODE_ENV !== 'production') && !Availabilities.numberFormat) {
|
|
1097
|
+
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
|
|
1472
1098
|
return MISSING_RESOLVE_VALUE;
|
|
1473
1099
|
}
|
|
1474
|
-
const [key, value, options, overrides] =
|
|
1100
|
+
const [key, value, options, overrides] = parseNumberArgs(...args);
|
|
1475
1101
|
const missingWarn = isBoolean(options.missingWarn)
|
|
1476
1102
|
? options.missingWarn
|
|
1477
1103
|
: context.missingWarn;
|
|
@@ -1483,21 +1109,21 @@ function datetime(context, ...args) {
|
|
|
1483
1109
|
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1484
1110
|
fallbackLocale, locale);
|
|
1485
1111
|
if (!isString(key) || key === '') {
|
|
1486
|
-
return new Intl.
|
|
1112
|
+
return new Intl.NumberFormat(locale, overrides).format(value);
|
|
1487
1113
|
}
|
|
1488
1114
|
// resolve format
|
|
1489
|
-
let
|
|
1115
|
+
let numberFormat = {};
|
|
1490
1116
|
let targetLocale;
|
|
1491
1117
|
let format = null;
|
|
1492
1118
|
let from = locale;
|
|
1493
1119
|
let to = null;
|
|
1494
|
-
const type = '
|
|
1120
|
+
const type = 'number format';
|
|
1495
1121
|
for (let i = 0; i < locales.length; i++) {
|
|
1496
1122
|
targetLocale = to = locales[i];
|
|
1497
1123
|
if ((process.env.NODE_ENV !== 'production') &&
|
|
1498
1124
|
locale !== targetLocale &&
|
|
1499
1125
|
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
1500
|
-
onWarn(getWarnMessage(CoreWarnCodes.
|
|
1126
|
+
onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
|
|
1501
1127
|
key,
|
|
1502
1128
|
target: targetLocale
|
|
1503
1129
|
}));
|
|
@@ -1515,9 +1141,9 @@ function datetime(context, ...args) {
|
|
|
1515
1141
|
});
|
|
1516
1142
|
}
|
|
1517
1143
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
format =
|
|
1144
|
+
numberFormat =
|
|
1145
|
+
numberFormats[targetLocale] || {};
|
|
1146
|
+
format = numberFormat[key];
|
|
1521
1147
|
if (isPlainObject(format))
|
|
1522
1148
|
break;
|
|
1523
1149
|
handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
@@ -1531,148 +1157,357 @@ function datetime(context, ...args) {
|
|
|
1531
1157
|
if (!isEmptyObject(overrides)) {
|
|
1532
1158
|
id = `${id}__${JSON.stringify(overrides)}`;
|
|
1533
1159
|
}
|
|
1534
|
-
let formatter =
|
|
1160
|
+
let formatter = __numberFormatters.get(id);
|
|
1535
1161
|
if (!formatter) {
|
|
1536
|
-
formatter = new Intl.
|
|
1537
|
-
|
|
1162
|
+
formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
|
|
1163
|
+
__numberFormatters.set(id, formatter);
|
|
1538
1164
|
}
|
|
1539
1165
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
1540
1166
|
}
|
|
1541
1167
|
/** @internal */
|
|
1542
|
-
const
|
|
1168
|
+
const NUMBER_FORMAT_OPTIONS_KEYS = [
|
|
1543
1169
|
'localeMatcher',
|
|
1544
|
-
'
|
|
1545
|
-
'
|
|
1546
|
-
'
|
|
1547
|
-
'
|
|
1548
|
-
'
|
|
1549
|
-
'
|
|
1550
|
-
'
|
|
1551
|
-
'
|
|
1552
|
-
'
|
|
1553
|
-
'
|
|
1554
|
-
'
|
|
1555
|
-
'
|
|
1556
|
-
'
|
|
1557
|
-
'
|
|
1558
|
-
'
|
|
1559
|
-
'
|
|
1560
|
-
'
|
|
1561
|
-
'
|
|
1562
|
-
'
|
|
1170
|
+
'style',
|
|
1171
|
+
'currency',
|
|
1172
|
+
'currencyDisplay',
|
|
1173
|
+
'currencySign',
|
|
1174
|
+
'useGrouping',
|
|
1175
|
+
'minimumIntegerDigits',
|
|
1176
|
+
'minimumFractionDigits',
|
|
1177
|
+
'maximumFractionDigits',
|
|
1178
|
+
'minimumSignificantDigits',
|
|
1179
|
+
'maximumSignificantDigits',
|
|
1180
|
+
'compactDisplay',
|
|
1181
|
+
'notation',
|
|
1182
|
+
'signDisplay',
|
|
1183
|
+
'unit',
|
|
1184
|
+
'unitDisplay',
|
|
1185
|
+
'roundingMode',
|
|
1186
|
+
'roundingPriority',
|
|
1187
|
+
'roundingIncrement',
|
|
1188
|
+
'trailingZeroDisplay'
|
|
1563
1189
|
];
|
|
1564
1190
|
/** @internal */
|
|
1565
|
-
function
|
|
1191
|
+
function parseNumberArgs(...args) {
|
|
1566
1192
|
const [arg1, arg2, arg3, arg4] = args;
|
|
1567
1193
|
const options = {};
|
|
1568
1194
|
let overrides = {};
|
|
1569
|
-
|
|
1570
|
-
if (isString(arg1)) {
|
|
1571
|
-
// Only allow ISO strings - other date formats are often supported,
|
|
1572
|
-
// but may cause different results in different browsers.
|
|
1573
|
-
const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
|
|
1574
|
-
if (!matches) {
|
|
1575
|
-
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
1576
|
-
}
|
|
1577
|
-
// Some browsers can not parse the iso datetime separated by space,
|
|
1578
|
-
// this is a compromise solution by replace the 'T'/' ' with 'T'
|
|
1579
|
-
const dateTime = matches[3]
|
|
1580
|
-
? matches[3].trim().startsWith('T')
|
|
1581
|
-
? `${matches[1].trim()}${matches[3].trim()}`
|
|
1582
|
-
: `${matches[1].trim()}T${matches[3].trim()}`
|
|
1583
|
-
: matches[1].trim();
|
|
1584
|
-
value = new Date(dateTime);
|
|
1585
|
-
try {
|
|
1586
|
-
// This will fail if the date is not valid
|
|
1587
|
-
value.toISOString();
|
|
1588
|
-
}
|
|
1589
|
-
catch (e) {
|
|
1590
|
-
throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
else if (isDate(arg1)) {
|
|
1594
|
-
if (isNaN(arg1.getTime())) {
|
|
1595
|
-
throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
|
|
1596
|
-
}
|
|
1597
|
-
value = arg1;
|
|
1598
|
-
}
|
|
1599
|
-
else if (isNumber(arg1)) {
|
|
1600
|
-
value = arg1;
|
|
1601
|
-
}
|
|
1602
|
-
else {
|
|
1195
|
+
if (!isNumber(arg1)) {
|
|
1603
1196
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
1604
1197
|
}
|
|
1198
|
+
const value = arg1;
|
|
1605
1199
|
if (isString(arg2)) {
|
|
1606
1200
|
options.key = arg2;
|
|
1607
1201
|
}
|
|
1608
1202
|
else if (isPlainObject(arg2)) {
|
|
1609
1203
|
Object.keys(arg2).forEach(key => {
|
|
1610
|
-
if (
|
|
1204
|
+
if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
1611
1205
|
overrides[key] = arg2[key];
|
|
1612
1206
|
}
|
|
1613
|
-
else {
|
|
1614
|
-
options[key] = arg2[key];
|
|
1207
|
+
else {
|
|
1208
|
+
options[key] = arg2[key];
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
if (isString(arg3)) {
|
|
1213
|
+
options.locale = arg3;
|
|
1214
|
+
}
|
|
1215
|
+
else if (isPlainObject(arg3)) {
|
|
1216
|
+
overrides = arg3;
|
|
1217
|
+
}
|
|
1218
|
+
if (isPlainObject(arg4)) {
|
|
1219
|
+
overrides = arg4;
|
|
1220
|
+
}
|
|
1221
|
+
return [options.key || '', value, options, overrides];
|
|
1222
|
+
}
|
|
1223
|
+
/** @internal */
|
|
1224
|
+
function clearNumberFormat(ctx, locale, format) {
|
|
1225
|
+
const context = ctx;
|
|
1226
|
+
for (const key in format) {
|
|
1227
|
+
const id = `${locale}__${key}`;
|
|
1228
|
+
if (!context.__numberFormatters.has(id)) {
|
|
1229
|
+
continue;
|
|
1230
|
+
}
|
|
1231
|
+
context.__numberFormatters.delete(id);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
const DEFAULT_MODIFIER = (str) => str;
|
|
1236
|
+
const DEFAULT_MESSAGE = (ctx) => ''; // eslint-disable-line
|
|
1237
|
+
const DEFAULT_MESSAGE_DATA_TYPE = 'text';
|
|
1238
|
+
const DEFAULT_NORMALIZE = (values) => values.length === 0 ? '' : join(values);
|
|
1239
|
+
const DEFAULT_INTERPOLATE = toDisplayString;
|
|
1240
|
+
function pluralDefault(choice, choicesLength) {
|
|
1241
|
+
choice = Math.abs(choice);
|
|
1242
|
+
if (choicesLength === 2) {
|
|
1243
|
+
// prettier-ignore
|
|
1244
|
+
return choice
|
|
1245
|
+
? choice > 1
|
|
1246
|
+
? 1
|
|
1247
|
+
: 0
|
|
1248
|
+
: 1;
|
|
1249
|
+
}
|
|
1250
|
+
return choice ? Math.min(choice, 2) : 0;
|
|
1251
|
+
}
|
|
1252
|
+
function getPluralIndex(options) {
|
|
1253
|
+
// prettier-ignore
|
|
1254
|
+
const index = isNumber(options.pluralIndex)
|
|
1255
|
+
? options.pluralIndex
|
|
1256
|
+
: -1;
|
|
1257
|
+
// prettier-ignore
|
|
1258
|
+
return options.named && (isNumber(options.named.count) || isNumber(options.named.n))
|
|
1259
|
+
? isNumber(options.named.count)
|
|
1260
|
+
? options.named.count
|
|
1261
|
+
: isNumber(options.named.n)
|
|
1262
|
+
? options.named.n
|
|
1263
|
+
: index
|
|
1264
|
+
: index;
|
|
1265
|
+
}
|
|
1266
|
+
function normalizeNamed(pluralIndex, props) {
|
|
1267
|
+
if (!props.count) {
|
|
1268
|
+
props.count = pluralIndex;
|
|
1269
|
+
}
|
|
1270
|
+
if (!props.n) {
|
|
1271
|
+
props.n = pluralIndex;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
function createMessageContext(options = {}) {
|
|
1275
|
+
const locale = options.locale;
|
|
1276
|
+
const pluralIndex = getPluralIndex(options);
|
|
1277
|
+
const pluralRule = isObject(options.pluralRules) &&
|
|
1278
|
+
isString(locale) &&
|
|
1279
|
+
isFunction(options.pluralRules[locale])
|
|
1280
|
+
? options.pluralRules[locale]
|
|
1281
|
+
: pluralDefault;
|
|
1282
|
+
const orgPluralRule = isObject(options.pluralRules) &&
|
|
1283
|
+
isString(locale) &&
|
|
1284
|
+
isFunction(options.pluralRules[locale])
|
|
1285
|
+
? pluralDefault
|
|
1286
|
+
: undefined;
|
|
1287
|
+
const plural = (messages) => {
|
|
1288
|
+
return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
|
|
1289
|
+
};
|
|
1290
|
+
const _list = options.list || [];
|
|
1291
|
+
const list = (index) => _list[index];
|
|
1292
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1293
|
+
const _named = options.named || {};
|
|
1294
|
+
isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
|
|
1295
|
+
const named = (key) => _named[key];
|
|
1296
|
+
function message(key, useLinked) {
|
|
1297
|
+
// prettier-ignore
|
|
1298
|
+
const msg = isFunction(options.messages)
|
|
1299
|
+
? options.messages(key, !!useLinked)
|
|
1300
|
+
: isObject(options.messages)
|
|
1301
|
+
? options.messages[key]
|
|
1302
|
+
: false;
|
|
1303
|
+
return !msg
|
|
1304
|
+
? options.parent
|
|
1305
|
+
? options.parent.message(key) // resolve from parent messages
|
|
1306
|
+
: DEFAULT_MESSAGE
|
|
1307
|
+
: msg;
|
|
1308
|
+
}
|
|
1309
|
+
const _modifier = (name) => options.modifiers
|
|
1310
|
+
? options.modifiers[name]
|
|
1311
|
+
: DEFAULT_MODIFIER;
|
|
1312
|
+
const normalize = isPlainObject(options.processor) && isFunction(options.processor.normalize)
|
|
1313
|
+
? options.processor.normalize
|
|
1314
|
+
: DEFAULT_NORMALIZE;
|
|
1315
|
+
const interpolate = isPlainObject(options.processor) &&
|
|
1316
|
+
isFunction(options.processor.interpolate)
|
|
1317
|
+
? options.processor.interpolate
|
|
1318
|
+
: DEFAULT_INTERPOLATE;
|
|
1319
|
+
const type = isPlainObject(options.processor) && isString(options.processor.type)
|
|
1320
|
+
? options.processor.type
|
|
1321
|
+
: DEFAULT_MESSAGE_DATA_TYPE;
|
|
1322
|
+
const linked = (key, ...args) => {
|
|
1323
|
+
const [arg1, arg2] = args;
|
|
1324
|
+
let type = 'text';
|
|
1325
|
+
let modifier = '';
|
|
1326
|
+
if (args.length === 1) {
|
|
1327
|
+
if (isObject(arg1)) {
|
|
1328
|
+
modifier = arg1.modifier || modifier;
|
|
1329
|
+
type = arg1.type || type;
|
|
1330
|
+
}
|
|
1331
|
+
else if (isString(arg1)) {
|
|
1332
|
+
modifier = arg1 || modifier;
|
|
1615
1333
|
}
|
|
1616
|
-
});
|
|
1617
|
-
}
|
|
1618
|
-
if (isString(arg3)) {
|
|
1619
|
-
options.locale = arg3;
|
|
1620
|
-
}
|
|
1621
|
-
else if (isPlainObject(arg3)) {
|
|
1622
|
-
overrides = arg3;
|
|
1623
|
-
}
|
|
1624
|
-
if (isPlainObject(arg4)) {
|
|
1625
|
-
overrides = arg4;
|
|
1626
|
-
}
|
|
1627
|
-
return [options.key || '', value, options, overrides];
|
|
1628
|
-
}
|
|
1629
|
-
/** @internal */
|
|
1630
|
-
function clearDateTimeFormat(ctx, locale, format) {
|
|
1631
|
-
const context = ctx;
|
|
1632
|
-
for (const key in format) {
|
|
1633
|
-
const id = `${locale}__${key}`;
|
|
1634
|
-
if (!context.__datetimeFormatters.has(id)) {
|
|
1635
|
-
continue;
|
|
1636
1334
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1335
|
+
else if (args.length === 2) {
|
|
1336
|
+
if (isString(arg1)) {
|
|
1337
|
+
modifier = arg1 || modifier;
|
|
1338
|
+
}
|
|
1339
|
+
if (isString(arg2)) {
|
|
1340
|
+
type = arg2 || type;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
const ret = message(key, true)(ctx);
|
|
1344
|
+
const msg =
|
|
1345
|
+
// The message in vnode resolved with linked are returned as an array by processor.nomalize
|
|
1346
|
+
type === 'vnode' && isArray(ret) && modifier
|
|
1347
|
+
? ret[0]
|
|
1348
|
+
: ret;
|
|
1349
|
+
return modifier ? _modifier(modifier)(msg, type) : msg;
|
|
1350
|
+
};
|
|
1351
|
+
const ctx = {
|
|
1352
|
+
["list" /* HelperNameMap.LIST */]: list,
|
|
1353
|
+
["named" /* HelperNameMap.NAMED */]: named,
|
|
1354
|
+
["plural" /* HelperNameMap.PLURAL */]: plural,
|
|
1355
|
+
["linked" /* HelperNameMap.LINKED */]: linked,
|
|
1356
|
+
["message" /* HelperNameMap.MESSAGE */]: message,
|
|
1357
|
+
["type" /* HelperNameMap.TYPE */]: type,
|
|
1358
|
+
["interpolate" /* HelperNameMap.INTERPOLATE */]: interpolate,
|
|
1359
|
+
["normalize" /* HelperNameMap.NORMALIZE */]: normalize,
|
|
1360
|
+
["values" /* HelperNameMap.VALUES */]: assign({}, _list, _named)
|
|
1361
|
+
};
|
|
1362
|
+
return ctx;
|
|
1639
1363
|
}
|
|
1640
1364
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
return MISSING_RESOLVE_VALUE;
|
|
1648
|
-
}
|
|
1649
|
-
const [key, value, options, overrides] = parseNumberArgs(...args);
|
|
1365
|
+
const NOOP_MESSAGE_FUNCTION = () => '';
|
|
1366
|
+
const isMessageFunction = (val) => isFunction(val);
|
|
1367
|
+
// implementation of `translate` function
|
|
1368
|
+
function translate(context, ...args) {
|
|
1369
|
+
const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
|
|
1370
|
+
const [key, options] = parseTranslateArgs(...args);
|
|
1650
1371
|
const missingWarn = isBoolean(options.missingWarn)
|
|
1651
1372
|
? options.missingWarn
|
|
1652
1373
|
: context.missingWarn;
|
|
1653
1374
|
const fallbackWarn = isBoolean(options.fallbackWarn)
|
|
1654
1375
|
? options.fallbackWarn
|
|
1655
1376
|
: context.fallbackWarn;
|
|
1656
|
-
const
|
|
1377
|
+
const escapeParameter = isBoolean(options.escapeParameter)
|
|
1378
|
+
? options.escapeParameter
|
|
1379
|
+
: context.escapeParameter;
|
|
1380
|
+
const resolvedMessage = !!options.resolvedMessage;
|
|
1381
|
+
// prettier-ignore
|
|
1382
|
+
const defaultMsgOrKey = isString(options.default) || isBoolean(options.default) // default by function option
|
|
1383
|
+
? !isBoolean(options.default)
|
|
1384
|
+
? options.default
|
|
1385
|
+
: (!messageCompiler ? () => key : key)
|
|
1386
|
+
: fallbackFormat // default by `fallbackFormat` option
|
|
1387
|
+
? (!messageCompiler ? () => key : key)
|
|
1388
|
+
: null;
|
|
1389
|
+
const enableDefaultMsg = fallbackFormat ||
|
|
1390
|
+
(defaultMsgOrKey != null &&
|
|
1391
|
+
(isString(defaultMsgOrKey) || isFunction(defaultMsgOrKey)));
|
|
1657
1392
|
const locale = getLocale(context, options);
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1393
|
+
// escape params
|
|
1394
|
+
escapeParameter && escapeParams(options);
|
|
1395
|
+
// resolve message format
|
|
1396
|
+
// eslint-disable-next-line prefer-const
|
|
1397
|
+
let [formatScope, targetLocale, message] = !resolvedMessage
|
|
1398
|
+
? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
|
|
1399
|
+
: [
|
|
1400
|
+
key,
|
|
1401
|
+
locale,
|
|
1402
|
+
messages[locale] || {}
|
|
1403
|
+
];
|
|
1404
|
+
// NOTE:
|
|
1405
|
+
// Fix to work around `ssrTransfrom` bug in Vite.
|
|
1406
|
+
// https://github.com/vitejs/vite/issues/4306
|
|
1407
|
+
// To get around this, use temporary variables.
|
|
1408
|
+
// https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
|
|
1409
|
+
let format = formatScope;
|
|
1410
|
+
// if you use default message, set it as message format!
|
|
1411
|
+
let cacheBaseKey = key;
|
|
1412
|
+
if (!resolvedMessage &&
|
|
1413
|
+
!(isString(format) ||
|
|
1414
|
+
isMessageAST(format) ||
|
|
1415
|
+
isMessageFunction(format))) {
|
|
1416
|
+
if (enableDefaultMsg) {
|
|
1417
|
+
format = defaultMsgOrKey;
|
|
1418
|
+
cacheBaseKey = format;
|
|
1419
|
+
}
|
|
1662
1420
|
}
|
|
1663
|
-
//
|
|
1664
|
-
|
|
1421
|
+
// checking message format and target locale
|
|
1422
|
+
if (!resolvedMessage &&
|
|
1423
|
+
(!(isString(format) ||
|
|
1424
|
+
isMessageAST(format) ||
|
|
1425
|
+
isMessageFunction(format)) ||
|
|
1426
|
+
!isString(targetLocale))) {
|
|
1427
|
+
return unresolving ? NOT_REOSLVED : key;
|
|
1428
|
+
}
|
|
1429
|
+
// TODO: refactor
|
|
1430
|
+
if ((process.env.NODE_ENV !== 'production') && isString(format) && context.messageCompiler == null) {
|
|
1431
|
+
warn(`The message format compilation is not supported in this build. ` +
|
|
1432
|
+
`Because message compiler isn't included. ` +
|
|
1433
|
+
`You need to pre-compilation all message format. ` +
|
|
1434
|
+
`So translate function return '${key}'.`);
|
|
1435
|
+
return key;
|
|
1436
|
+
}
|
|
1437
|
+
// setup compile error detecting
|
|
1438
|
+
let occurred = false;
|
|
1439
|
+
const onError = () => {
|
|
1440
|
+
occurred = true;
|
|
1441
|
+
};
|
|
1442
|
+
// compile message format
|
|
1443
|
+
const msg = !isMessageFunction(format)
|
|
1444
|
+
? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError)
|
|
1445
|
+
: format;
|
|
1446
|
+
// if occurred compile error, return the message format
|
|
1447
|
+
if (occurred) {
|
|
1448
|
+
return format;
|
|
1449
|
+
}
|
|
1450
|
+
// evaluate message with context
|
|
1451
|
+
const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
|
|
1452
|
+
const msgContext = createMessageContext(ctxOptions);
|
|
1453
|
+
const messaged = evaluateMessage(context, msg, msgContext);
|
|
1454
|
+
// if use post translation option, proceed it with handler
|
|
1455
|
+
const ret = postTranslation
|
|
1456
|
+
? postTranslation(messaged, key)
|
|
1457
|
+
: messaged;
|
|
1458
|
+
// NOTE: experimental !!
|
|
1459
|
+
if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
|
|
1460
|
+
// prettier-ignore
|
|
1461
|
+
const payloads = {
|
|
1462
|
+
timestamp: Date.now(),
|
|
1463
|
+
key: isString(key)
|
|
1464
|
+
? key
|
|
1465
|
+
: isMessageFunction(format)
|
|
1466
|
+
? format.key
|
|
1467
|
+
: '',
|
|
1468
|
+
locale: targetLocale || (isMessageFunction(format)
|
|
1469
|
+
? format.locale
|
|
1470
|
+
: ''),
|
|
1471
|
+
format: isString(format)
|
|
1472
|
+
? format
|
|
1473
|
+
: isMessageFunction(format)
|
|
1474
|
+
? format.source
|
|
1475
|
+
: '',
|
|
1476
|
+
message: ret
|
|
1477
|
+
};
|
|
1478
|
+
payloads.meta = assign({}, context.__meta, getAdditionalMeta() || {});
|
|
1479
|
+
translateDevTools(payloads);
|
|
1480
|
+
}
|
|
1481
|
+
return ret;
|
|
1482
|
+
}
|
|
1483
|
+
function escapeParams(options) {
|
|
1484
|
+
if (isArray(options.list)) {
|
|
1485
|
+
options.list = options.list.map(item => isString(item) ? escapeHtml(item) : item);
|
|
1486
|
+
}
|
|
1487
|
+
else if (isObject(options.named)) {
|
|
1488
|
+
Object.keys(options.named).forEach(key => {
|
|
1489
|
+
if (isString(options.named[key])) {
|
|
1490
|
+
options.named[key] = escapeHtml(options.named[key]);
|
|
1491
|
+
}
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
|
|
1496
|
+
const { messages, onWarn, messageResolver: resolveValue, localeFallbacker } = context;
|
|
1497
|
+
const locales = localeFallbacker(context, fallbackLocale, locale); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1498
|
+
let message = {};
|
|
1665
1499
|
let targetLocale;
|
|
1666
1500
|
let format = null;
|
|
1667
1501
|
let from = locale;
|
|
1668
1502
|
let to = null;
|
|
1669
|
-
const type = '
|
|
1503
|
+
const type = 'translate';
|
|
1670
1504
|
for (let i = 0; i < locales.length; i++) {
|
|
1671
1505
|
targetLocale = to = locales[i];
|
|
1672
1506
|
if ((process.env.NODE_ENV !== 'production') &&
|
|
1673
1507
|
locale !== targetLocale &&
|
|
1508
|
+
!isAlmostSameLocale(locale, targetLocale) &&
|
|
1674
1509
|
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
1675
|
-
onWarn(getWarnMessage(CoreWarnCodes.
|
|
1510
|
+
onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_TRANSLATE, {
|
|
1676
1511
|
key,
|
|
1677
1512
|
target: targetLocale
|
|
1678
1513
|
}));
|
|
@@ -1690,95 +1525,260 @@ function number(context, ...args) {
|
|
|
1690
1525
|
});
|
|
1691
1526
|
}
|
|
1692
1527
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1528
|
+
message =
|
|
1529
|
+
messages[targetLocale] || {};
|
|
1530
|
+
// for vue-devtools timeline event
|
|
1531
|
+
let start = null;
|
|
1532
|
+
let startTag;
|
|
1533
|
+
let endTag;
|
|
1534
|
+
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1535
|
+
start = window.performance.now();
|
|
1536
|
+
startTag = 'intlify-message-resolve-start';
|
|
1537
|
+
endTag = 'intlify-message-resolve-end';
|
|
1538
|
+
mark && mark(startTag);
|
|
1539
|
+
}
|
|
1540
|
+
if ((format = resolveValue(message, key)) === null) {
|
|
1541
|
+
// if null, resolve with object key path
|
|
1542
|
+
format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1543
|
+
}
|
|
1544
|
+
// for vue-devtools timeline event
|
|
1545
|
+
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1546
|
+
const end = window.performance.now();
|
|
1547
|
+
const emitter = context.__v_emitter;
|
|
1548
|
+
if (emitter && start && format) {
|
|
1549
|
+
emitter.emit('message-resolve', {
|
|
1550
|
+
type: 'message-resolve',
|
|
1551
|
+
key,
|
|
1552
|
+
message: format,
|
|
1553
|
+
time: end - start,
|
|
1554
|
+
groupId: `${type}:${key}`
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
if (startTag && endTag && mark && measure) {
|
|
1558
|
+
mark(endTag);
|
|
1559
|
+
measure('intlify message resolve', startTag, endTag);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
if (isString(format) || isMessageAST(format) || isMessageFunction(format)) {
|
|
1697
1563
|
break;
|
|
1698
|
-
|
|
1564
|
+
}
|
|
1565
|
+
if (!isImplicitFallback(targetLocale, locales)) {
|
|
1566
|
+
const missingRet = handleMissing(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
1567
|
+
key, targetLocale, missingWarn, type);
|
|
1568
|
+
if (missingRet !== key) {
|
|
1569
|
+
format = missingRet;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1699
1572
|
from = to;
|
|
1700
1573
|
}
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1574
|
+
return [format, targetLocale, message];
|
|
1575
|
+
}
|
|
1576
|
+
function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError) {
|
|
1577
|
+
const { messageCompiler, warnHtmlMessage } = context;
|
|
1578
|
+
if (isMessageFunction(format)) {
|
|
1579
|
+
const msg = format;
|
|
1580
|
+
msg.locale = msg.locale || targetLocale;
|
|
1581
|
+
msg.key = msg.key || key;
|
|
1582
|
+
return msg;
|
|
1704
1583
|
}
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1584
|
+
if (messageCompiler == null) {
|
|
1585
|
+
const msg = (() => format);
|
|
1586
|
+
msg.locale = targetLocale;
|
|
1587
|
+
msg.key = key;
|
|
1588
|
+
return msg;
|
|
1708
1589
|
}
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1590
|
+
// for vue-devtools timeline event
|
|
1591
|
+
let start = null;
|
|
1592
|
+
let startTag;
|
|
1593
|
+
let endTag;
|
|
1594
|
+
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1595
|
+
start = window.performance.now();
|
|
1596
|
+
startTag = 'intlify-message-compilation-start';
|
|
1597
|
+
endTag = 'intlify-message-compilation-end';
|
|
1598
|
+
mark && mark(startTag);
|
|
1713
1599
|
}
|
|
1714
|
-
|
|
1600
|
+
const msg = messageCompiler(format, getCompileContext(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, onError));
|
|
1601
|
+
// for vue-devtools timeline event
|
|
1602
|
+
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1603
|
+
const end = window.performance.now();
|
|
1604
|
+
const emitter = context.__v_emitter;
|
|
1605
|
+
if (emitter && start) {
|
|
1606
|
+
emitter.emit('message-compilation', {
|
|
1607
|
+
type: 'message-compilation',
|
|
1608
|
+
message: format,
|
|
1609
|
+
time: end - start,
|
|
1610
|
+
groupId: `${'translate'}:${key}`
|
|
1611
|
+
});
|
|
1612
|
+
}
|
|
1613
|
+
if (startTag && endTag && mark && measure) {
|
|
1614
|
+
mark(endTag);
|
|
1615
|
+
measure('intlify message compilation', startTag, endTag);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
msg.locale = targetLocale;
|
|
1619
|
+
msg.key = key;
|
|
1620
|
+
msg.source = format;
|
|
1621
|
+
return msg;
|
|
1622
|
+
}
|
|
1623
|
+
function evaluateMessage(context, msg, msgCtx) {
|
|
1624
|
+
// for vue-devtools timeline event
|
|
1625
|
+
let start = null;
|
|
1626
|
+
let startTag;
|
|
1627
|
+
let endTag;
|
|
1628
|
+
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1629
|
+
start = window.performance.now();
|
|
1630
|
+
startTag = 'intlify-message-evaluation-start';
|
|
1631
|
+
endTag = 'intlify-message-evaluation-end';
|
|
1632
|
+
mark && mark(startTag);
|
|
1633
|
+
}
|
|
1634
|
+
const messaged = msg(msgCtx);
|
|
1635
|
+
// for vue-devtools timeline event
|
|
1636
|
+
if ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
|
1637
|
+
const end = window.performance.now();
|
|
1638
|
+
const emitter = context.__v_emitter;
|
|
1639
|
+
if (emitter && start) {
|
|
1640
|
+
emitter.emit('message-evaluation', {
|
|
1641
|
+
type: 'message-evaluation',
|
|
1642
|
+
value: messaged,
|
|
1643
|
+
time: end - start,
|
|
1644
|
+
groupId: `${'translate'}:${msg.key}`
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
1647
|
+
if (startTag && endTag && mark && measure) {
|
|
1648
|
+
mark(endTag);
|
|
1649
|
+
measure('intlify message evaluation', startTag, endTag);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
return messaged;
|
|
1715
1653
|
}
|
|
1716
1654
|
/** @internal */
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
'style',
|
|
1720
|
-
'currency',
|
|
1721
|
-
'currencyDisplay',
|
|
1722
|
-
'currencySign',
|
|
1723
|
-
'useGrouping',
|
|
1724
|
-
'minimumIntegerDigits',
|
|
1725
|
-
'minimumFractionDigits',
|
|
1726
|
-
'maximumFractionDigits',
|
|
1727
|
-
'minimumSignificantDigits',
|
|
1728
|
-
'maximumSignificantDigits',
|
|
1729
|
-
'compactDisplay',
|
|
1730
|
-
'notation',
|
|
1731
|
-
'signDisplay',
|
|
1732
|
-
'unit',
|
|
1733
|
-
'unitDisplay',
|
|
1734
|
-
'roundingMode',
|
|
1735
|
-
'roundingPriority',
|
|
1736
|
-
'roundingIncrement',
|
|
1737
|
-
'trailingZeroDisplay'
|
|
1738
|
-
];
|
|
1739
|
-
/** @internal */
|
|
1740
|
-
function parseNumberArgs(...args) {
|
|
1741
|
-
const [arg1, arg2, arg3, arg4] = args;
|
|
1655
|
+
function parseTranslateArgs(...args) {
|
|
1656
|
+
const [arg1, arg2, arg3] = args;
|
|
1742
1657
|
const options = {};
|
|
1743
|
-
|
|
1744
|
-
|
|
1658
|
+
if (!isString(arg1) &&
|
|
1659
|
+
!isNumber(arg1) &&
|
|
1660
|
+
!isMessageFunction(arg1) &&
|
|
1661
|
+
!isMessageAST(arg1)) {
|
|
1745
1662
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
1746
1663
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1664
|
+
// prettier-ignore
|
|
1665
|
+
const key = isNumber(arg1)
|
|
1666
|
+
? String(arg1)
|
|
1667
|
+
: isMessageFunction(arg1)
|
|
1668
|
+
? arg1
|
|
1669
|
+
: arg1;
|
|
1670
|
+
if (isNumber(arg2)) {
|
|
1671
|
+
options.plural = arg2;
|
|
1750
1672
|
}
|
|
1751
|
-
else if (
|
|
1752
|
-
|
|
1753
|
-
if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
1754
|
-
overrides[key] = arg2[key];
|
|
1755
|
-
}
|
|
1756
|
-
else {
|
|
1757
|
-
options[key] = arg2[key];
|
|
1758
|
-
}
|
|
1759
|
-
});
|
|
1673
|
+
else if (isString(arg2)) {
|
|
1674
|
+
options.default = arg2;
|
|
1760
1675
|
}
|
|
1761
|
-
if (
|
|
1762
|
-
options.
|
|
1676
|
+
else if (isPlainObject(arg2) && !isEmptyObject(arg2)) {
|
|
1677
|
+
options.named = arg2;
|
|
1678
|
+
}
|
|
1679
|
+
else if (isArray(arg2)) {
|
|
1680
|
+
options.list = arg2;
|
|
1681
|
+
}
|
|
1682
|
+
if (isNumber(arg3)) {
|
|
1683
|
+
options.plural = arg3;
|
|
1684
|
+
}
|
|
1685
|
+
else if (isString(arg3)) {
|
|
1686
|
+
options.default = arg3;
|
|
1763
1687
|
}
|
|
1764
1688
|
else if (isPlainObject(arg3)) {
|
|
1765
|
-
|
|
1689
|
+
assign(options, arg3);
|
|
1766
1690
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1691
|
+
return [key, options];
|
|
1692
|
+
}
|
|
1693
|
+
function getCompileContext(context, locale, key, source, warnHtmlMessage, onError) {
|
|
1694
|
+
return {
|
|
1695
|
+
locale,
|
|
1696
|
+
key,
|
|
1697
|
+
warnHtmlMessage,
|
|
1698
|
+
onError: (err) => {
|
|
1699
|
+
onError && onError(err);
|
|
1700
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
1701
|
+
const _source = getSourceForCodeFrame(source);
|
|
1702
|
+
const message = `Message compilation error: ${err.message}`;
|
|
1703
|
+
const codeFrame = err.location &&
|
|
1704
|
+
_source &&
|
|
1705
|
+
generateCodeFrame(_source, err.location.start.offset, err.location.end.offset);
|
|
1706
|
+
const emitter = context.__v_emitter;
|
|
1707
|
+
if (emitter && _source) {
|
|
1708
|
+
emitter.emit('compile-error', {
|
|
1709
|
+
message: _source,
|
|
1710
|
+
error: err.message,
|
|
1711
|
+
start: err.location && err.location.start.offset,
|
|
1712
|
+
end: err.location && err.location.end.offset,
|
|
1713
|
+
groupId: `${'translate'}:${key}`
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
console.error(codeFrame ? `${message}\n${codeFrame}` : message);
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
throw err;
|
|
1720
|
+
}
|
|
1721
|
+
},
|
|
1722
|
+
onCacheKey: (source) => generateFormatCacheKey(locale, key, source)
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
function getSourceForCodeFrame(source) {
|
|
1726
|
+
if (isString(source)) {
|
|
1727
|
+
return source;
|
|
1728
|
+
}
|
|
1729
|
+
else {
|
|
1730
|
+
if (source.loc && source.loc.source) {
|
|
1731
|
+
return source.loc.source;
|
|
1732
|
+
}
|
|
1769
1733
|
}
|
|
1770
|
-
return [options.key || '', value, options, overrides];
|
|
1771
1734
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
const
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
if (
|
|
1778
|
-
|
|
1735
|
+
function getMessageContextOptions(context, locale, message, options) {
|
|
1736
|
+
const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
|
|
1737
|
+
const resolveMessage = (key, useLinked) => {
|
|
1738
|
+
let val = resolveValue(message, key);
|
|
1739
|
+
// fallback
|
|
1740
|
+
if (val == null && (fallbackContext || useLinked)) {
|
|
1741
|
+
const [, , message] = resolveMessageFormat(fallbackContext || context, // NOTE: if has fallbackContext, fallback to root, else if use linked, fallback to local context
|
|
1742
|
+
key, locale, fallbackLocale, fallbackWarn, missingWarn);
|
|
1743
|
+
val = resolveValue(message, key);
|
|
1779
1744
|
}
|
|
1780
|
-
|
|
1745
|
+
if (isString(val) || isMessageAST(val)) {
|
|
1746
|
+
let occurred = false;
|
|
1747
|
+
const onError = () => {
|
|
1748
|
+
occurred = true;
|
|
1749
|
+
};
|
|
1750
|
+
const msg = compileMessageFormat(context, key, locale, val, key, onError);
|
|
1751
|
+
return !occurred
|
|
1752
|
+
? msg
|
|
1753
|
+
: NOOP_MESSAGE_FUNCTION;
|
|
1754
|
+
}
|
|
1755
|
+
else if (isMessageFunction(val)) {
|
|
1756
|
+
return val;
|
|
1757
|
+
}
|
|
1758
|
+
else {
|
|
1759
|
+
// TODO: should be implemented warning message
|
|
1760
|
+
return NOOP_MESSAGE_FUNCTION;
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
const ctxOptions = {
|
|
1764
|
+
locale,
|
|
1765
|
+
modifiers,
|
|
1766
|
+
pluralRules,
|
|
1767
|
+
messages: resolveMessage
|
|
1768
|
+
};
|
|
1769
|
+
if (context.processor) {
|
|
1770
|
+
ctxOptions.processor = context.processor;
|
|
1771
|
+
}
|
|
1772
|
+
if (options.list) {
|
|
1773
|
+
ctxOptions.list = options.list;
|
|
1774
|
+
}
|
|
1775
|
+
if (options.named) {
|
|
1776
|
+
ctxOptions.named = options.named;
|
|
1781
1777
|
}
|
|
1778
|
+
if (isNumber(options.plural)) {
|
|
1779
|
+
ctxOptions.pluralIndex = options.plural;
|
|
1780
|
+
}
|
|
1781
|
+
return ctxOptions;
|
|
1782
1782
|
}
|
|
1783
1783
|
|
|
1784
1784
|
{
|