@intlify/core-base 11.4.7 → 11.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core-base.cjs +133 -180
- package/dist/core-base.d.ts +2 -2
- package/dist/core-base.esm-browser.js +246 -272
- package/dist/core-base.esm-browser.prod.js +2 -2
- package/dist/core-base.global.js +239 -265
- package/dist/core-base.global.prod.js +2 -2
- package/dist/core-base.mjs +135 -183
- package/dist/core-base.prod.cjs +112 -136
- package/package.json +4 -4
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* core-base v11.4.
|
|
2
|
+
* core-base v11.4.9
|
|
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 };
|
|
@@ -2085,7 +2106,7 @@ function resolveLocale(locale) {
|
|
|
2085
2106
|
* @remarks
|
|
2086
2107
|
* A fallback locale function implemented with a simple fallback algorithm.
|
|
2087
2108
|
*
|
|
2088
|
-
* Basically,
|
|
2109
|
+
* Basically, the chain consists of `start` plus the specified fallback: for a string or array `fallbackLocale`, the value as specified in the props is used; for a map `fallbackLocale`, the map's **keys** are used and the `default` key is skipped since it is not a locale name.
|
|
2089
2110
|
*
|
|
2090
2111
|
* @param ctx - A {@link CoreContext | context}
|
|
2091
2112
|
* @param fallback - A {@link FallbackLocale | fallback locale}
|
|
@@ -2102,7 +2123,7 @@ function fallbackWithSimple(ctx, fallback, start) {
|
|
|
2102
2123
|
...(isArray(fallback)
|
|
2103
2124
|
? fallback
|
|
2104
2125
|
: isObject(fallback)
|
|
2105
|
-
? Object.keys(fallback)
|
|
2126
|
+
? Object.keys(fallback).filter(locale => locale !== 'default')
|
|
2106
2127
|
: isString(fallback)
|
|
2107
2128
|
? [fallback]
|
|
2108
2129
|
: [start])
|
|
@@ -2130,29 +2151,36 @@ function fallbackWithLocaleChain(ctx, fallback, start) {
|
|
|
2130
2151
|
if (!context.__localeChainCache) {
|
|
2131
2152
|
context.__localeChainCache = new Map();
|
|
2132
2153
|
}
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2154
|
+
const fallbackKey = friendlyJSONstringify(fallback);
|
|
2155
|
+
let chains = context.__localeChainCache.get(startLocale);
|
|
2156
|
+
if (!chains) {
|
|
2157
|
+
chains = new Map();
|
|
2158
|
+
context.__localeChainCache.set(startLocale, chains);
|
|
2159
|
+
}
|
|
2160
|
+
const cached = chains.get(fallbackKey);
|
|
2161
|
+
if (cached) {
|
|
2162
|
+
return cached;
|
|
2163
|
+
}
|
|
2164
|
+
const chain = [];
|
|
2165
|
+
// first block defined by start
|
|
2166
|
+
let block = [start];
|
|
2167
|
+
// while any intervening block found
|
|
2168
|
+
while (isArray(block)) {
|
|
2169
|
+
block = appendBlockToChain(chain, block, fallback);
|
|
2170
|
+
}
|
|
2171
|
+
// prettier-ignore
|
|
2172
|
+
// last block defined by default
|
|
2173
|
+
const defaults = isArray(fallback) || !isPlainObject(fallback)
|
|
2174
|
+
? fallback
|
|
2175
|
+
: fallback['default']
|
|
2176
|
+
? fallback['default']
|
|
2177
|
+
: null;
|
|
2178
|
+
// convert defaults to array
|
|
2179
|
+
block = isString(defaults) ? [defaults] : defaults;
|
|
2180
|
+
if (isArray(block)) {
|
|
2181
|
+
appendBlockToChain(chain, block, false);
|
|
2155
2182
|
}
|
|
2183
|
+
chains.set(fallbackKey, chain);
|
|
2156
2184
|
return chain;
|
|
2157
2185
|
}
|
|
2158
2186
|
function appendBlockToChain(chain, block, blocks) {
|
|
@@ -2511,7 +2539,7 @@ function getWarnMessage(code, ...args) {
|
|
|
2511
2539
|
* Intlify core-base version
|
|
2512
2540
|
* @internal
|
|
2513
2541
|
*/
|
|
2514
|
-
const VERSION = '11.4.
|
|
2542
|
+
const VERSION = '11.4.9';
|
|
2515
2543
|
const NOT_REOSLVED = -1;
|
|
2516
2544
|
const DEFAULT_LOCALE = 'en-US';
|
|
2517
2545
|
const MISSING_RESOLVE_VALUE = '';
|
|
@@ -2761,6 +2789,88 @@ function isImplicitFallback(targetLocale, locales) {
|
|
|
2761
2789
|
}
|
|
2762
2790
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
2763
2791
|
|
|
2792
|
+
function resolveFormatLocale(context, key, locale, formats, missingWarn, fallbackWarn, type) {
|
|
2793
|
+
const { fallbackLocale, localeFallbacker, onWarn } = context;
|
|
2794
|
+
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2795
|
+
fallbackLocale, locale);
|
|
2796
|
+
let from = locale;
|
|
2797
|
+
for (let i = 0; i < locales.length; i++) {
|
|
2798
|
+
const targetLocale = locales[i];
|
|
2799
|
+
if (locale !== targetLocale &&
|
|
2800
|
+
isTranslateFallbackWarn(fallbackWarn, key)) {
|
|
2801
|
+
onWarn(getWarnMessage(type === 'datetime format'
|
|
2802
|
+
? CoreWarnCodes.FALLBACK_TO_DATE_FORMAT
|
|
2803
|
+
: CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
|
|
2804
|
+
key,
|
|
2805
|
+
target: targetLocale
|
|
2806
|
+
}));
|
|
2807
|
+
}
|
|
2808
|
+
if (locale !== targetLocale) {
|
|
2809
|
+
const emitter = context.__v_emitter;
|
|
2810
|
+
if (emitter) {
|
|
2811
|
+
emitter.emit('fallback', {
|
|
2812
|
+
type,
|
|
2813
|
+
key,
|
|
2814
|
+
from,
|
|
2815
|
+
to: targetLocale,
|
|
2816
|
+
groupId: `${type}:${key}`
|
|
2817
|
+
});
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
const format = (formats[targetLocale] || {})[key];
|
|
2821
|
+
if (isPlainObject(format) && isString(targetLocale)) {
|
|
2822
|
+
return targetLocale;
|
|
2823
|
+
}
|
|
2824
|
+
handleMissing(context, key, targetLocale, missingWarn, type);
|
|
2825
|
+
from = targetLocale;
|
|
2826
|
+
}
|
|
2827
|
+
return null;
|
|
2828
|
+
}
|
|
2829
|
+
function getFormatterCacheKey(locale, key, overrides) {
|
|
2830
|
+
let id = `${locale}__${key}`;
|
|
2831
|
+
if (isPlainObject(overrides) && !isEmptyObject(overrides)) {
|
|
2832
|
+
id = `${id}__${JSON.stringify(overrides)}`;
|
|
2833
|
+
}
|
|
2834
|
+
return id;
|
|
2835
|
+
}
|
|
2836
|
+
function clearFormatCache(formatters, locale, format) {
|
|
2837
|
+
for (const key in format) {
|
|
2838
|
+
const prefix = `${locale}__${key}`;
|
|
2839
|
+
for (const id of formatters.keys()) {
|
|
2840
|
+
if (id === prefix || id.startsWith(`${prefix}__`)) {
|
|
2841
|
+
formatters.delete(id);
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
function parseFormatArgs(args, options, initialOverrides, optionsKeys) {
|
|
2847
|
+
const [, arg2, arg3, arg4] = args;
|
|
2848
|
+
let overrides = initialOverrides;
|
|
2849
|
+
if (isString(arg2)) {
|
|
2850
|
+
options.key = arg2;
|
|
2851
|
+
}
|
|
2852
|
+
else if (isPlainObject(arg2)) {
|
|
2853
|
+
Object.keys(arg2).forEach(key => {
|
|
2854
|
+
if (optionsKeys.includes(key)) {
|
|
2855
|
+
overrides[key] = arg2[key];
|
|
2856
|
+
}
|
|
2857
|
+
else {
|
|
2858
|
+
options[key] = arg2[key];
|
|
2859
|
+
}
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2862
|
+
if (isString(arg3)) {
|
|
2863
|
+
options.locale = arg3;
|
|
2864
|
+
}
|
|
2865
|
+
else if (isPlainObject(arg3)) {
|
|
2866
|
+
overrides = arg3;
|
|
2867
|
+
}
|
|
2868
|
+
if (isPlainObject(arg4)) {
|
|
2869
|
+
overrides = arg4;
|
|
2870
|
+
}
|
|
2871
|
+
return overrides;
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2764
2874
|
const intlDefined = typeof Intl !== 'undefined';
|
|
2765
2875
|
const Availabilities = {
|
|
2766
2876
|
dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
|
|
@@ -2769,7 +2879,7 @@ const Availabilities = {
|
|
|
2769
2879
|
|
|
2770
2880
|
// implementation of `datetime` function
|
|
2771
2881
|
function datetime(context, ...args) {
|
|
2772
|
-
const { datetimeFormats, unresolving,
|
|
2882
|
+
const { datetimeFormats, unresolving, onWarn } = context;
|
|
2773
2883
|
const { __datetimeFormatters } = context;
|
|
2774
2884
|
if (!Availabilities.dateTimeFormat) {
|
|
2775
2885
|
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
|
|
@@ -2792,57 +2902,16 @@ function datetime(context, ...args) {
|
|
|
2792
2902
|
: context.fallbackWarn;
|
|
2793
2903
|
const part = !!options.part;
|
|
2794
2904
|
const locale = getLocale(context, options);
|
|
2795
|
-
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2796
|
-
fallbackLocale, locale);
|
|
2797
2905
|
if (!isString(key) || key === '') {
|
|
2798
2906
|
const formatter = new Intl.DateTimeFormat(locale.replace(/!/g, ''), overrides);
|
|
2799
2907
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
2800
2908
|
}
|
|
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)) {
|
|
2909
|
+
const targetLocale = resolveFormatLocale(context, key, locale, datetimeFormats, missingWarn, fallbackWarn, 'datetime format');
|
|
2910
|
+
if (!isString(targetLocale)) {
|
|
2840
2911
|
return unresolving ? NOT_REOSLVED : key;
|
|
2841
2912
|
}
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
id = `${id}__${JSON.stringify(overrides)}`;
|
|
2845
|
-
}
|
|
2913
|
+
const format = datetimeFormats[targetLocale][key];
|
|
2914
|
+
const id = getFormatterCacheKey(targetLocale, key, overrides);
|
|
2846
2915
|
let formatter = __datetimeFormatters.get(id);
|
|
2847
2916
|
if (!formatter) {
|
|
2848
2917
|
formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
|
|
@@ -2875,9 +2944,9 @@ const DATETIME_FORMAT_OPTIONS_KEYS = [
|
|
|
2875
2944
|
];
|
|
2876
2945
|
/** @internal */
|
|
2877
2946
|
function parseDateTimeArgs(...args) {
|
|
2878
|
-
const [arg1
|
|
2947
|
+
const [arg1] = args;
|
|
2879
2948
|
const options = create();
|
|
2880
|
-
|
|
2949
|
+
const initialOverrides = create();
|
|
2881
2950
|
let value;
|
|
2882
2951
|
if (isString(arg1)) {
|
|
2883
2952
|
// Only allow ISO strings - other date formats are often supported,
|
|
@@ -2914,45 +2983,18 @@ function parseDateTimeArgs(...args) {
|
|
|
2914
2983
|
else {
|
|
2915
2984
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
2916
2985
|
}
|
|
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
|
-
}
|
|
2986
|
+
const overrides = parseFormatArgs(args, options, initialOverrides, DATETIME_FORMAT_OPTIONS_KEYS);
|
|
2939
2987
|
return [options.key || '', value, options, overrides];
|
|
2940
2988
|
}
|
|
2941
2989
|
/** @internal */
|
|
2942
2990
|
function clearDateTimeFormat(ctx, locale, format) {
|
|
2943
2991
|
const context = ctx;
|
|
2944
|
-
|
|
2945
|
-
const id = `${locale}__${key}`;
|
|
2946
|
-
if (!context.__datetimeFormatters.has(id)) {
|
|
2947
|
-
continue;
|
|
2948
|
-
}
|
|
2949
|
-
context.__datetimeFormatters.delete(id);
|
|
2950
|
-
}
|
|
2992
|
+
clearFormatCache(context.__datetimeFormatters, locale, format);
|
|
2951
2993
|
}
|
|
2952
2994
|
|
|
2953
2995
|
// implementation of `number` function
|
|
2954
2996
|
function number(context, ...args) {
|
|
2955
|
-
const { numberFormats, unresolving,
|
|
2997
|
+
const { numberFormats, unresolving, onWarn } = context;
|
|
2956
2998
|
const { __numberFormatters } = context;
|
|
2957
2999
|
if (!Availabilities.numberFormat) {
|
|
2958
3000
|
onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
|
|
@@ -2975,57 +3017,16 @@ function number(context, ...args) {
|
|
|
2975
3017
|
: context.fallbackWarn;
|
|
2976
3018
|
const part = !!options.part;
|
|
2977
3019
|
const locale = getLocale(context, options);
|
|
2978
|
-
const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
2979
|
-
fallbackLocale, locale);
|
|
2980
3020
|
if (!isString(key) || key === '') {
|
|
2981
3021
|
const formatter = new Intl.NumberFormat(locale.replace(/!/g, ''), overrides);
|
|
2982
3022
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
|
2983
3023
|
}
|
|
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)) {
|
|
3024
|
+
const targetLocale = resolveFormatLocale(context, key, locale, numberFormats, missingWarn, fallbackWarn, 'number format');
|
|
3025
|
+
if (!isString(targetLocale)) {
|
|
3023
3026
|
return unresolving ? NOT_REOSLVED : key;
|
|
3024
3027
|
}
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
id = `${id}__${JSON.stringify(overrides)}`;
|
|
3028
|
-
}
|
|
3028
|
+
const format = numberFormats[targetLocale][key];
|
|
3029
|
+
const id = getFormatterCacheKey(targetLocale, key, overrides);
|
|
3029
3030
|
let formatter = __numberFormatters.get(id);
|
|
3030
3031
|
if (!formatter) {
|
|
3031
3032
|
formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
|
|
@@ -3058,47 +3059,20 @@ const NUMBER_FORMAT_OPTIONS_KEYS = [
|
|
|
3058
3059
|
];
|
|
3059
3060
|
/** @internal */
|
|
3060
3061
|
function parseNumberArgs(...args) {
|
|
3061
|
-
const [arg1
|
|
3062
|
+
const [arg1] = args;
|
|
3062
3063
|
const options = create();
|
|
3063
|
-
|
|
3064
|
+
const initialOverrides = create();
|
|
3064
3065
|
if (!isNumber(arg1)) {
|
|
3065
3066
|
throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
|
|
3066
3067
|
}
|
|
3067
3068
|
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
|
-
}
|
|
3069
|
+
const overrides = parseFormatArgs(args, options, initialOverrides, NUMBER_FORMAT_OPTIONS_KEYS);
|
|
3090
3070
|
return [options.key || '', value, options, overrides];
|
|
3091
3071
|
}
|
|
3092
3072
|
/** @internal */
|
|
3093
3073
|
function clearNumberFormat(ctx, locale, format) {
|
|
3094
3074
|
const context = ctx;
|
|
3095
|
-
|
|
3096
|
-
const id = `${locale}__${key}`;
|
|
3097
|
-
if (!context.__numberFormatters.has(id)) {
|
|
3098
|
-
continue;
|
|
3099
|
-
}
|
|
3100
|
-
context.__numberFormatters.delete(id);
|
|
3101
|
-
}
|
|
3075
|
+
clearFormatCache(context.__numberFormatters, locale, format);
|
|
3102
3076
|
}
|
|
3103
3077
|
|
|
3104
3078
|
const DEFAULT_MODIFIER = (str) => str;
|