@intlify/core-base 11.4.6 → 11.4.8
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 +102 -156
- package/dist/core-base.esm-browser.js +215 -248
- package/dist/core-base.esm-browser.prod.js +2 -2
- package/dist/core-base.global.js +208 -241
- package/dist/core-base.global.prod.js +2 -2
- package/dist/core-base.mjs +104 -159
- package/dist/core-base.prod.cjs +81 -112
- package/package.json +4 -4
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* core-base v11.4.
|
|
2
|
+
* core-base v11.4.8
|
|
3
3
|
* (c) 2026 kazuya kawaguchi
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
|
-
function warn(msg, err) {
|
|
7
|
-
if (typeof console !== 'undefined') {
|
|
8
|
-
console.warn(`[intlify] ` + msg);
|
|
9
|
-
/* istanbul ignore if */
|
|
10
|
-
if (err) {
|
|
11
|
-
console.warn(err.stack);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
const hasWarned = {};
|
|
16
|
-
function warnOnce(msg) {
|
|
17
|
-
if (!hasWarned[msg]) {
|
|
18
|
-
hasWarned[msg] = true;
|
|
19
|
-
warn(msg);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
6
|
/**
|
|
24
7
|
* Original Utilities
|
|
25
8
|
* written by kazuya kawaguchi
|
|
@@ -70,6 +53,93 @@ const isEmptyObject = (val) => isPlainObject(val) && Object.keys(val).length ===
|
|
|
70
53
|
const assign = Object.assign;
|
|
71
54
|
const _create = Object.create;
|
|
72
55
|
const create = (obj = null) => _create(obj);
|
|
56
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
57
|
+
function hasOwn(obj, key) {
|
|
58
|
+
return hasOwnProperty.call(obj, key);
|
|
59
|
+
}
|
|
60
|
+
/* eslint-enable */
|
|
61
|
+
/**
|
|
62
|
+
* Useful Utilities By Evan you
|
|
63
|
+
* Modified by kazuya kawaguchi
|
|
64
|
+
* MIT License
|
|
65
|
+
* https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
|
|
66
|
+
* https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
|
|
67
|
+
*/
|
|
68
|
+
const isArray = Array.isArray;
|
|
69
|
+
const isFunction = (val) => typeof val === 'function';
|
|
70
|
+
const isString = (val) => typeof val === 'string';
|
|
71
|
+
const isBoolean = (val) => typeof val === 'boolean';
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
const isObject = (val) => val !== null && typeof val === 'object';
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
+
const isPromise = (val) => {
|
|
76
|
+
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
|
|
77
|
+
};
|
|
78
|
+
const objectToString = Object.prototype.toString;
|
|
79
|
+
const toTypeString = (value) => objectToString.call(value);
|
|
80
|
+
const isPlainObject = (val) => toTypeString(val) === '[object Object]';
|
|
81
|
+
// for converting list and named values to displayed strings.
|
|
82
|
+
const toDisplayString = (val) => {
|
|
83
|
+
return val == null
|
|
84
|
+
? ''
|
|
85
|
+
: isArray(val) || (isPlainObject(val) && val.toString === objectToString)
|
|
86
|
+
? JSON.stringify(val, null, 2)
|
|
87
|
+
: String(val);
|
|
88
|
+
};
|
|
89
|
+
function join(items, separator = '') {
|
|
90
|
+
return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
|
|
91
|
+
}
|
|
92
|
+
const RANGE = 2;
|
|
93
|
+
function generateCodeFrame(source, start = 0, end = source.length) {
|
|
94
|
+
const lines = source.split(/\r?\n/);
|
|
95
|
+
let count = 0;
|
|
96
|
+
const res = [];
|
|
97
|
+
for (let i = 0; i < lines.length; i++) {
|
|
98
|
+
count += lines[i].length + 1;
|
|
99
|
+
if (count >= start) {
|
|
100
|
+
for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
|
|
101
|
+
if (j < 0 || j >= lines.length)
|
|
102
|
+
continue;
|
|
103
|
+
const line = j + 1;
|
|
104
|
+
res.push(`${line}${' '.repeat(3 - String(line).length)}| ${lines[j]}`);
|
|
105
|
+
const lineLength = lines[j].length;
|
|
106
|
+
if (j === i) {
|
|
107
|
+
// push underline
|
|
108
|
+
const pad = start - (count - lineLength) + 1;
|
|
109
|
+
const length = Math.max(1, end > count ? lineLength - pad : end - start);
|
|
110
|
+
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
|
|
111
|
+
}
|
|
112
|
+
else if (j > i) {
|
|
113
|
+
if (end > count) {
|
|
114
|
+
const length = Math.max(Math.min(end - count, lineLength), 1);
|
|
115
|
+
res.push(` | ` + '^'.repeat(length));
|
|
116
|
+
}
|
|
117
|
+
count += lineLength + 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return res.join('\n');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function warn(msg, err) {
|
|
127
|
+
if (typeof console !== 'undefined') {
|
|
128
|
+
console.warn(`[intlify] ` + msg);
|
|
129
|
+
/* istanbul ignore if */
|
|
130
|
+
if (err) {
|
|
131
|
+
console.warn(err.stack);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const hasWarned = {};
|
|
136
|
+
function warnOnce(msg) {
|
|
137
|
+
if (!hasWarned[msg]) {
|
|
138
|
+
hasWarned[msg] = true;
|
|
139
|
+
warn(msg);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
73
143
|
function escapeHtml(rawText) {
|
|
74
144
|
return rawText
|
|
75
145
|
.replace(/&/g, '&') // escape `&` first to avoid double escaping
|
|
@@ -82,16 +152,37 @@ function escapeHtml(rawText) {
|
|
|
82
152
|
}
|
|
83
153
|
function escapeAttributeValue(value) {
|
|
84
154
|
return value
|
|
85
|
-
.replace(/&(?![a-
|
|
155
|
+
.replace(/&(?![a-z0-9#]{2,6};)/gi, '&') // escape unescaped `&`
|
|
86
156
|
.replace(/"/g, '"')
|
|
87
157
|
.replace(/'/g, ''')
|
|
88
158
|
.replace(/</g, '<')
|
|
89
159
|
.replace(/>/g, '>');
|
|
90
160
|
}
|
|
91
|
-
const javascriptSchemePattern =
|
|
161
|
+
const javascriptSchemePattern = /^javascript:/i;
|
|
92
162
|
const urlAttributePattern = /^(?:href|src|action|formaction)$/i;
|
|
163
|
+
const numericCharacterReferencePattern = /&#(?:x([0-9a-f]+)|(\d+));?/gi;
|
|
164
|
+
const namedWhitespaceCharacterReferencePattern = /&(?:Tab|NewLine);/g;
|
|
165
|
+
const colonCharacterReferencePattern = /:?/gi;
|
|
166
|
+
// eslint-disable-next-line no-control-regex -- URL scheme normalization requires the full control range
|
|
167
|
+
const controlOrWhitespacePattern = /[\u0000-\u0020\u007f-\u009f]/g;
|
|
168
|
+
const eventHandlerPattern = /(?:^|[\s"'<>/])on\w+\s*=\s*["']?[^"'>]+["']?/i;
|
|
169
|
+
const eventHandlerAttributePattern = /(^|[\s"'<>/])on(\w+\s*=)/gi;
|
|
170
|
+
const unquotedUrlAttributePattern = /(^|[\s"'<>/])((?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi;
|
|
171
|
+
function decodeNumericCharacterReference(match, hex, decimal) {
|
|
172
|
+
const digits = hex || decimal;
|
|
173
|
+
if (!digits) {
|
|
174
|
+
return match;
|
|
175
|
+
}
|
|
176
|
+
const codePoint = Number.parseInt(digits, hex ? 16 : 10);
|
|
177
|
+
return codePoint <= 0x7f ? String.fromCharCode(codePoint) : match;
|
|
178
|
+
}
|
|
93
179
|
function hasJavascriptScheme(value) {
|
|
94
|
-
|
|
180
|
+
const normalized = value
|
|
181
|
+
.replace(numericCharacterReferencePattern, decodeNumericCharacterReference)
|
|
182
|
+
.replace(namedWhitespaceCharacterReferencePattern, '')
|
|
183
|
+
.replace(colonCharacterReferencePattern, ':')
|
|
184
|
+
.replace(controlOrWhitespacePattern, '');
|
|
185
|
+
return javascriptSchemePattern.test(normalized);
|
|
95
186
|
}
|
|
96
187
|
function sanitizeStyleValue(value) {
|
|
97
188
|
const urlPattern = /url\s*\(/gi;
|
|
@@ -155,88 +246,18 @@ function sanitizeTranslatedHtml(html) {
|
|
|
155
246
|
// Process attributes with single quotes
|
|
156
247
|
html = html.replace(/([\w:-]+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${sanitizeAttributeValue(attrName, attrValue)}'`);
|
|
157
248
|
// Detect and neutralize event handler attributes
|
|
158
|
-
const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi;
|
|
159
249
|
if (eventHandlerPattern.test(html)) {
|
|
160
250
|
{
|
|
161
251
|
warn('Potentially dangerous event handlers detected in translation. ' +
|
|
162
252
|
'Consider removing onclick, onerror, etc. from your translation messages.');
|
|
163
253
|
}
|
|
164
254
|
// Neutralize event handler attributes by escaping 'on'
|
|
165
|
-
html = html.replace(
|
|
255
|
+
html = html.replace(eventHandlerAttributePattern, '$1on$2');
|
|
166
256
|
}
|
|
167
257
|
// Disable javascript: URLs in unquoted attributes
|
|
168
|
-
html = html.replace(
|
|
258
|
+
html = html.replace(unquotedUrlAttributePattern, (match, boundary, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${boundary}${prefix}about:blank` : match);
|
|
169
259
|
return html;
|
|
170
260
|
}
|
|
171
|
-
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
172
|
-
function hasOwn(obj, key) {
|
|
173
|
-
return hasOwnProperty.call(obj, key);
|
|
174
|
-
}
|
|
175
|
-
/* eslint-enable */
|
|
176
|
-
/**
|
|
177
|
-
* Useful Utilities By Evan you
|
|
178
|
-
* Modified by kazuya kawaguchi
|
|
179
|
-
* MIT License
|
|
180
|
-
* https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
|
|
181
|
-
* https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
|
|
182
|
-
*/
|
|
183
|
-
const isArray = Array.isArray;
|
|
184
|
-
const isFunction = (val) => typeof val === 'function';
|
|
185
|
-
const isString = (val) => typeof val === 'string';
|
|
186
|
-
const isBoolean = (val) => typeof val === 'boolean';
|
|
187
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
188
|
-
const isObject = (val) => val !== null && typeof val === 'object';
|
|
189
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
190
|
-
const isPromise = (val) => {
|
|
191
|
-
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
|
|
192
|
-
};
|
|
193
|
-
const objectToString = Object.prototype.toString;
|
|
194
|
-
const toTypeString = (value) => objectToString.call(value);
|
|
195
|
-
const isPlainObject = (val) => toTypeString(val) === '[object Object]';
|
|
196
|
-
// for converting list and named values to displayed strings.
|
|
197
|
-
const toDisplayString = (val) => {
|
|
198
|
-
return val == null
|
|
199
|
-
? ''
|
|
200
|
-
: isArray(val) || (isPlainObject(val) && val.toString === objectToString)
|
|
201
|
-
? JSON.stringify(val, null, 2)
|
|
202
|
-
: String(val);
|
|
203
|
-
};
|
|
204
|
-
function join(items, separator = '') {
|
|
205
|
-
return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
|
|
206
|
-
}
|
|
207
|
-
const RANGE = 2;
|
|
208
|
-
function generateCodeFrame(source, start = 0, end = source.length) {
|
|
209
|
-
const lines = source.split(/\r?\n/);
|
|
210
|
-
let count = 0;
|
|
211
|
-
const res = [];
|
|
212
|
-
for (let i = 0; i < lines.length; i++) {
|
|
213
|
-
count += lines[i].length + 1;
|
|
214
|
-
if (count >= start) {
|
|
215
|
-
for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
|
|
216
|
-
if (j < 0 || j >= lines.length)
|
|
217
|
-
continue;
|
|
218
|
-
const line = j + 1;
|
|
219
|
-
res.push(`${line}${' '.repeat(3 - String(line).length)}| ${lines[j]}`);
|
|
220
|
-
const lineLength = lines[j].length;
|
|
221
|
-
if (j === i) {
|
|
222
|
-
// push underline
|
|
223
|
-
const pad = start - (count - lineLength) + 1;
|
|
224
|
-
const length = Math.max(1, end > count ? lineLength - pad : end - start);
|
|
225
|
-
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
|
|
226
|
-
}
|
|
227
|
-
else if (j > i) {
|
|
228
|
-
if (end > count) {
|
|
229
|
-
const length = Math.max(Math.min(end - count, lineLength), 1);
|
|
230
|
-
res.push(` | ` + '^'.repeat(length));
|
|
231
|
-
}
|
|
232
|
-
count += lineLength + 1;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return res.join('\n');
|
|
239
|
-
}
|
|
240
261
|
|
|
241
262
|
function createPosition(line, column, offset) {
|
|
242
263
|
return { line, column, offset };
|
|
@@ -2511,7 +2532,7 @@ function getWarnMessage(code, ...args) {
|
|
|
2511
2532
|
* Intlify core-base version
|
|
2512
2533
|
* @internal
|
|
2513
2534
|
*/
|
|
2514
|
-
const VERSION = '11.4.
|
|
2535
|
+
const VERSION = '11.4.8';
|
|
2515
2536
|
const NOT_REOSLVED = -1;
|
|
2516
2537
|
const DEFAULT_LOCALE = 'en-US';
|
|
2517
2538
|
const MISSING_RESOLVE_VALUE = '';
|
|
@@ -2761,6 +2782,88 @@ function isImplicitFallback(targetLocale, locales) {
|
|
|
2761
2782
|
}
|
|
2762
2783
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
2763
2784
|
|
|
2785
|
+
function resolveFormatLocale(context, key, locale, formats, missingWarn, fallbackWarn, type) {
|
|
2786
|
+
const { fallbackLocale, localeFallbacker, onWarn } = context;
|
|
2787
|
+
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2788
|
+
fallbackLocale, locale);
|
|
2789
|
+
let from = locale;
|
|
2790
|
+
for (let i = 0; i < locales.length; i++) {
|
|
2791
|
+
const targetLocale = locales[i];
|
|
2792
|
+
if (locale !== targetLocale &&
|
|
2793
|
+
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
2794
|
+
onWarn(getWarnMessage(type === 'datetime format'
|
|
2795
|
+
? CoreWarnCodes.FALLBACK_TO_DATE_FORMAT
|
|
2796
|
+
: CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
|
|
2797
|
+
key,
|
|
2798
|
+
target: targetLocale
|
|
2799
|
+
}));
|
|
2800
|
+
}
|
|
2801
|
+
if (locale !== targetLocale) {
|
|
2802
|
+
const emitter = context.__v_emitter;
|
|
2803
|
+
if (emitter) {
|
|
2804
|
+
emitter.emit('fallback', {
|
|
2805
|
+
type,
|
|
2806
|
+
key,
|
|
2807
|
+
from,
|
|
2808
|
+
to: targetLocale,
|
|
2809
|
+
groupId: `${type}:${key}`
|
|
2810
|
+
});
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
const format = (formats[targetLocale] || {})[key];
|
|
2814
|
+
if (isPlainObject(format) && isString(targetLocale)) {
|
|
2815
|
+
return targetLocale;
|
|
2816
|
+
}
|
|
2817
|
+
handleMissing(context, key, targetLocale, missingWarn, type);
|
|
2818
|
+
from = targetLocale;
|
|
2819
|
+
}
|
|
2820
|
+
return null;
|
|
2821
|
+
}
|
|
2822
|
+
function getFormatterCacheKey(locale, key, overrides) {
|
|
2823
|
+
let id = `${locale}__${key}`;
|
|
2824
|
+
if (isPlainObject(overrides) && !isEmptyObject(overrides)) {
|
|
2825
|
+
id = `${id}__${JSON.stringify(overrides)}`;
|
|
2826
|
+
}
|
|
2827
|
+
return id;
|
|
2828
|
+
}
|
|
2829
|
+
function clearFormatCache(formatters, locale, format) {
|
|
2830
|
+
for (const key in format) {
|
|
2831
|
+
const prefix = `${locale}__${key}`;
|
|
2832
|
+
for (const id of formatters.keys()) {
|
|
2833
|
+
if (id === prefix || id.startsWith(`${prefix}__`)) {
|
|
2834
|
+
formatters.delete(id);
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
function parseFormatArgs(args, options, initialOverrides, optionsKeys) {
|
|
2840
|
+
const [, arg2, arg3, arg4] = args;
|
|
2841
|
+
let overrides = initialOverrides;
|
|
2842
|
+
if (isString(arg2)) {
|
|
2843
|
+
options.key = arg2;
|
|
2844
|
+
}
|
|
2845
|
+
else if (isPlainObject(arg2)) {
|
|
2846
|
+
Object.keys(arg2).forEach(key => {
|
|
2847
|
+
if (optionsKeys.includes(key)) {
|
|
2848
|
+
overrides[key] = arg2[key];
|
|
2849
|
+
}
|
|
2850
|
+
else {
|
|
2851
|
+
options[key] = arg2[key];
|
|
2852
|
+
}
|
|
2853
|
+
});
|
|
2854
|
+
}
|
|
2855
|
+
if (isString(arg3)) {
|
|
2856
|
+
options.locale = arg3;
|
|
2857
|
+
}
|
|
2858
|
+
else if (isPlainObject(arg3)) {
|
|
2859
|
+
overrides = arg3;
|
|
2860
|
+
}
|
|
2861
|
+
if (isPlainObject(arg4)) {
|
|
2862
|
+
overrides = arg4;
|
|
2863
|
+
}
|
|
2864
|
+
return overrides;
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2764
2867
|
const intlDefined = typeof Intl !== 'undefined';
|
|
2765
2868
|
const Availabilities = {
|
|
2766
2869
|
dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
|
|
@@ -2769,7 +2872,7 @@ const Availabilities = {
|
|
|
2769
2872
|
|
|
2770
2873
|
// implementation of `datetime` function
|
|
2771
2874
|
function datetime(context, ...args) {
|
|
2772
|
-
const { datetimeFormats, unresolving,
|
|
2875
|
+
const { datetimeFormats, unresolving, onWarn } = context;
|
|
2773
2876
|
const { __datetimeFormatters } = context;
|
|
2774
2877
|
if (!Availabilities.dateTimeFormat) {
|
|
2775
2878
|
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
|
|
@@ -2792,57 +2895,16 @@ function datetime(context, ...args) {
|
|
|
2792
2895
|
: context.fallbackWarn;
|
|
2793
2896
|
const part = !!options.part;
|
|
2794
2897
|
const locale = getLocale(context, options);
|
|
2795
|
-
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2796
|
-
fallbackLocale, locale);
|
|
2797
2898
|
if (!isString(key) || key === '') {
|
|
2798
2899
|
const formatter = new Intl.DateTimeFormat(locale.replace(/!/g, ''), overrides);
|
|
2799
2900
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
2800
2901
|
}
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
let targetLocale;
|
|
2804
|
-
let format = null;
|
|
2805
|
-
let from = locale;
|
|
2806
|
-
let to = null;
|
|
2807
|
-
const type = 'datetime format';
|
|
2808
|
-
for (let i = 0; i < locales.length; i++) {
|
|
2809
|
-
targetLocale = to = locales[i];
|
|
2810
|
-
if (locale !== targetLocale &&
|
|
2811
|
-
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
2812
|
-
onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_DATE_FORMAT, {
|
|
2813
|
-
key,
|
|
2814
|
-
target: targetLocale
|
|
2815
|
-
}));
|
|
2816
|
-
}
|
|
2817
|
-
// for vue-devtools timeline event
|
|
2818
|
-
if (locale !== targetLocale) {
|
|
2819
|
-
const emitter = context.__v_emitter;
|
|
2820
|
-
if (emitter) {
|
|
2821
|
-
emitter.emit('fallback', {
|
|
2822
|
-
type,
|
|
2823
|
-
key,
|
|
2824
|
-
from,
|
|
2825
|
-
to,
|
|
2826
|
-
groupId: `${type}:${key}`
|
|
2827
|
-
});
|
|
2828
|
-
}
|
|
2829
|
-
}
|
|
2830
|
-
datetimeFormat =
|
|
2831
|
-
datetimeFormats[targetLocale] || {};
|
|
2832
|
-
format = datetimeFormat[key];
|
|
2833
|
-
if (isPlainObject(format))
|
|
2834
|
-
break;
|
|
2835
|
-
handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2836
|
-
from = to;
|
|
2837
|
-
}
|
|
2838
|
-
// checking format and target locale
|
|
2839
|
-
if (!isPlainObject(format) || !isString(targetLocale)) {
|
|
2902
|
+
const targetLocale = resolveFormatLocale(context, key, locale, datetimeFormats, missingWarn, fallbackWarn, 'datetime format');
|
|
2903
|
+
if (!isString(targetLocale)) {
|
|
2840
2904
|
return unresolving ? NOT_REOSLVED : key;
|
|
2841
2905
|
}
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
id = `${id}__${JSON.stringify(overrides)}`;
|
|
2845
|
-
}
|
|
2906
|
+
const format = datetimeFormats[targetLocale][key];
|
|
2907
|
+
const id = getFormatterCacheKey(targetLocale, key, overrides);
|
|
2846
2908
|
let formatter = __datetimeFormatters.get(id);
|
|
2847
2909
|
if (!formatter) {
|
|
2848
2910
|
formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
|
|
@@ -2875,9 +2937,9 @@ const DATETIME_FORMAT_OPTIONS_KEYS = [
|
|
|
2875
2937
|
];
|
|
2876
2938
|
/** @internal */
|
|
2877
2939
|
function parseDateTimeArgs(...args) {
|
|
2878
|
-
const [arg1
|
|
2940
|
+
const [arg1] = args;
|
|
2879
2941
|
const options = create();
|
|
2880
|
-
|
|
2942
|
+
const initialOverrides = create();
|
|
2881
2943
|
let value;
|
|
2882
2944
|
if (isString(arg1)) {
|
|
2883
2945
|
// Only allow ISO strings - other date formats are often supported,
|
|
@@ -2914,45 +2976,18 @@ function parseDateTimeArgs(...args) {
|
|
|
2914
2976
|
else {
|
|
2915
2977
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
2916
2978
|
}
|
|
2917
|
-
|
|
2918
|
-
options.key = arg2;
|
|
2919
|
-
}
|
|
2920
|
-
else if (isPlainObject(arg2)) {
|
|
2921
|
-
Object.keys(arg2).forEach(key => {
|
|
2922
|
-
if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
2923
|
-
overrides[key] = arg2[key];
|
|
2924
|
-
}
|
|
2925
|
-
else {
|
|
2926
|
-
options[key] = arg2[key];
|
|
2927
|
-
}
|
|
2928
|
-
});
|
|
2929
|
-
}
|
|
2930
|
-
if (isString(arg3)) {
|
|
2931
|
-
options.locale = arg3;
|
|
2932
|
-
}
|
|
2933
|
-
else if (isPlainObject(arg3)) {
|
|
2934
|
-
overrides = arg3;
|
|
2935
|
-
}
|
|
2936
|
-
if (isPlainObject(arg4)) {
|
|
2937
|
-
overrides = arg4;
|
|
2938
|
-
}
|
|
2979
|
+
const overrides = parseFormatArgs(args, options, initialOverrides, DATETIME_FORMAT_OPTIONS_KEYS);
|
|
2939
2980
|
return [options.key || '', value, options, overrides];
|
|
2940
2981
|
}
|
|
2941
2982
|
/** @internal */
|
|
2942
2983
|
function clearDateTimeFormat(ctx, locale, format) {
|
|
2943
2984
|
const context = ctx;
|
|
2944
|
-
|
|
2945
|
-
const id = `${locale}__${key}`;
|
|
2946
|
-
if (!context.__datetimeFormatters.has(id)) {
|
|
2947
|
-
continue;
|
|
2948
|
-
}
|
|
2949
|
-
context.__datetimeFormatters.delete(id);
|
|
2950
|
-
}
|
|
2985
|
+
clearFormatCache(context.__datetimeFormatters, locale, format);
|
|
2951
2986
|
}
|
|
2952
2987
|
|
|
2953
2988
|
// implementation of `number` function
|
|
2954
2989
|
function number(context, ...args) {
|
|
2955
|
-
const { numberFormats, unresolving,
|
|
2990
|
+
const { numberFormats, unresolving, onWarn } = context;
|
|
2956
2991
|
const { __numberFormatters } = context;
|
|
2957
2992
|
if (!Availabilities.numberFormat) {
|
|
2958
2993
|
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
|
|
@@ -2975,57 +3010,16 @@ function number(context, ...args) {
|
|
|
2975
3010
|
: context.fallbackWarn;
|
|
2976
3011
|
const part = !!options.part;
|
|
2977
3012
|
const locale = getLocale(context, options);
|
|
2978
|
-
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2979
|
-
fallbackLocale, locale);
|
|
2980
3013
|
if (!isString(key) || key === '') {
|
|
2981
3014
|
const formatter = new Intl.NumberFormat(locale.replace(/!/g, ''), overrides);
|
|
2982
3015
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
2983
3016
|
}
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
let targetLocale;
|
|
2987
|
-
let format = null;
|
|
2988
|
-
let from = locale;
|
|
2989
|
-
let to = null;
|
|
2990
|
-
const type = 'number format';
|
|
2991
|
-
for (let i = 0; i < locales.length; i++) {
|
|
2992
|
-
targetLocale = to = locales[i];
|
|
2993
|
-
if (locale !== targetLocale &&
|
|
2994
|
-
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
2995
|
-
onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
|
|
2996
|
-
key,
|
|
2997
|
-
target: targetLocale
|
|
2998
|
-
}));
|
|
2999
|
-
}
|
|
3000
|
-
// for vue-devtools timeline event
|
|
3001
|
-
if (locale !== targetLocale) {
|
|
3002
|
-
const emitter = context.__v_emitter;
|
|
3003
|
-
if (emitter) {
|
|
3004
|
-
emitter.emit('fallback', {
|
|
3005
|
-
type,
|
|
3006
|
-
key,
|
|
3007
|
-
from,
|
|
3008
|
-
to,
|
|
3009
|
-
groupId: `${type}:${key}`
|
|
3010
|
-
});
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
numberFormat =
|
|
3014
|
-
numberFormats[targetLocale] || {};
|
|
3015
|
-
format = numberFormat[key];
|
|
3016
|
-
if (isPlainObject(format))
|
|
3017
|
-
break;
|
|
3018
|
-
handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
3019
|
-
from = to;
|
|
3020
|
-
}
|
|
3021
|
-
// checking format and target locale
|
|
3022
|
-
if (!isPlainObject(format) || !isString(targetLocale)) {
|
|
3017
|
+
const targetLocale = resolveFormatLocale(context, key, locale, numberFormats, missingWarn, fallbackWarn, 'number format');
|
|
3018
|
+
if (!isString(targetLocale)) {
|
|
3023
3019
|
return unresolving ? NOT_REOSLVED : key;
|
|
3024
3020
|
}
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
id = `${id}__${JSON.stringify(overrides)}`;
|
|
3028
|
-
}
|
|
3021
|
+
const format = numberFormats[targetLocale][key];
|
|
3022
|
+
const id = getFormatterCacheKey(targetLocale, key, overrides);
|
|
3029
3023
|
let formatter = __numberFormatters.get(id);
|
|
3030
3024
|
if (!formatter) {
|
|
3031
3025
|
formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
|
|
@@ -3058,47 +3052,20 @@ const NUMBER_FORMAT_OPTIONS_KEYS = [
|
|
|
3058
3052
|
];
|
|
3059
3053
|
/** @internal */
|
|
3060
3054
|
function parseNumberArgs(...args) {
|
|
3061
|
-
const [arg1
|
|
3055
|
+
const [arg1] = args;
|
|
3062
3056
|
const options = create();
|
|
3063
|
-
|
|
3057
|
+
const initialOverrides = create();
|
|
3064
3058
|
if (!isNumber(arg1)) {
|
|
3065
3059
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
3066
3060
|
}
|
|
3067
3061
|
const value = arg1;
|
|
3068
|
-
|
|
3069
|
-
options.key = arg2;
|
|
3070
|
-
}
|
|
3071
|
-
else if (isPlainObject(arg2)) {
|
|
3072
|
-
Object.keys(arg2).forEach(key => {
|
|
3073
|
-
if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
|
|
3074
|
-
overrides[key] = arg2[key];
|
|
3075
|
-
}
|
|
3076
|
-
else {
|
|
3077
|
-
options[key] = arg2[key];
|
|
3078
|
-
}
|
|
3079
|
-
});
|
|
3080
|
-
}
|
|
3081
|
-
if (isString(arg3)) {
|
|
3082
|
-
options.locale = arg3;
|
|
3083
|
-
}
|
|
3084
|
-
else if (isPlainObject(arg3)) {
|
|
3085
|
-
overrides = arg3;
|
|
3086
|
-
}
|
|
3087
|
-
if (isPlainObject(arg4)) {
|
|
3088
|
-
overrides = arg4;
|
|
3089
|
-
}
|
|
3062
|
+
const overrides = parseFormatArgs(args, options, initialOverrides, NUMBER_FORMAT_OPTIONS_KEYS);
|
|
3090
3063
|
return [options.key || '', value, options, overrides];
|
|
3091
3064
|
}
|
|
3092
3065
|
/** @internal */
|
|
3093
3066
|
function clearNumberFormat(ctx, locale, format) {
|
|
3094
3067
|
const context = ctx;
|
|
3095
|
-
|
|
3096
|
-
const id = `${locale}__${key}`;
|
|
3097
|
-
if (!context.__numberFormatters.has(id)) {
|
|
3098
|
-
continue;
|
|
3099
|
-
}
|
|
3100
|
-
context.__numberFormatters.delete(id);
|
|
3101
|
-
}
|
|
3068
|
+
clearFormatCache(context.__numberFormatters, locale, format);
|
|
3102
3069
|
}
|
|
3103
3070
|
|
|
3104
3071
|
const DEFAULT_MODIFIER = (str) => str;
|