@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.
@@ -1,21 +1,11 @@
1
1
  /*!
2
- * core-base v11.4.7
2
+ * core-base v11.4.9
3
3
  * (c) 2026 kazuya kawaguchi
4
4
  * Released under the MIT License.
5
5
  */
6
6
  var IntlifyCoreBase = (function (exports) {
7
7
  'use strict';
8
8
 
9
- function warn(msg, err) {
10
- if (typeof console !== 'undefined') {
11
- console.warn(`[intlify] ` + msg);
12
- /* istanbul ignore if */
13
- if (err) {
14
- console.warn(err.stack);
15
- }
16
- }
17
- }
18
-
19
9
  /**
20
10
  * Original Utilities
21
11
  * written by kazuya kawaguchi
@@ -66,6 +56,86 @@ var IntlifyCoreBase = (function (exports) {
66
56
  const assign = Object.assign;
67
57
  const _create = Object.create;
68
58
  const create = (obj = null) => _create(obj);
59
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
60
+ function hasOwn(obj, key) {
61
+ return hasOwnProperty.call(obj, key);
62
+ }
63
+ /* eslint-enable */
64
+ /**
65
+ * Useful Utilities By Evan you
66
+ * Modified by kazuya kawaguchi
67
+ * MIT License
68
+ * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
69
+ * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
70
+ */
71
+ const isArray = Array.isArray;
72
+ const isFunction = (val) => typeof val === 'function';
73
+ const isString = (val) => typeof val === 'string';
74
+ const isBoolean = (val) => typeof val === 'boolean';
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ const isObject = (val) => val !== null && typeof val === 'object';
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ const isPromise = (val) => {
79
+ return isObject(val) && isFunction(val.then) && isFunction(val.catch);
80
+ };
81
+ const objectToString = Object.prototype.toString;
82
+ const toTypeString = (value) => objectToString.call(value);
83
+ const isPlainObject = (val) => toTypeString(val) === '[object Object]';
84
+ // for converting list and named values to displayed strings.
85
+ const toDisplayString = (val) => {
86
+ return val == null
87
+ ? ''
88
+ : isArray(val) || (isPlainObject(val) && val.toString === objectToString)
89
+ ? JSON.stringify(val, null, 2)
90
+ : String(val);
91
+ };
92
+ function join(items, separator = '') {
93
+ return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
94
+ }
95
+ const RANGE = 2;
96
+ function generateCodeFrame(source, start = 0, end = source.length) {
97
+ const lines = source.split(/\r?\n/);
98
+ let count = 0;
99
+ const res = [];
100
+ for (let i = 0; i < lines.length; i++) {
101
+ count += lines[i].length + 1;
102
+ if (count >= start) {
103
+ for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
104
+ if (j < 0 || j >= lines.length)
105
+ continue;
106
+ const line = j + 1;
107
+ res.push(`${line}${' '.repeat(3 - String(line).length)}| ${lines[j]}`);
108
+ const lineLength = lines[j].length;
109
+ if (j === i) {
110
+ // push underline
111
+ const pad = start - (count - lineLength) + 1;
112
+ const length = Math.max(1, end > count ? lineLength - pad : end - start);
113
+ res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
114
+ }
115
+ else if (j > i) {
116
+ if (end > count) {
117
+ const length = Math.max(Math.min(end - count, lineLength), 1);
118
+ res.push(` | ` + '^'.repeat(length));
119
+ }
120
+ count += lineLength + 1;
121
+ }
122
+ }
123
+ break;
124
+ }
125
+ }
126
+ return res.join('\n');
127
+ }
128
+
129
+ function warn(msg, err) {
130
+ if (typeof console !== 'undefined') {
131
+ console.warn(`[intlify] ` + msg);
132
+ /* istanbul ignore if */
133
+ if (err) {
134
+ console.warn(err.stack);
135
+ }
136
+ }
137
+ }
138
+
69
139
  function escapeHtml(rawText) {
70
140
  return rawText
71
141
  .replace(/&/g, '&amp;') // escape `&` first to avoid double escaping
@@ -78,16 +148,37 @@ var IntlifyCoreBase = (function (exports) {
78
148
  }
79
149
  function escapeAttributeValue(value) {
80
150
  return value
81
- .replace(/&(?![a-zA-Z0-9#]{2,6};)/g, '&amp;') // escape unescaped `&`
151
+ .replace(/&(?![a-z0-9#]{2,6};)/gi, '&amp;') // escape unescaped `&`
82
152
  .replace(/"/g, '&quot;')
83
153
  .replace(/'/g, '&apos;')
84
154
  .replace(/</g, '&lt;')
85
155
  .replace(/>/g, '&gt;');
86
156
  }
87
- const javascriptSchemePattern = /^\s*javascript\s*(?::|&#0*58;?|&#x0*3a;?|&colon;?)/i;
157
+ const javascriptSchemePattern = /^javascript:/i;
88
158
  const urlAttributePattern = /^(?:href|src|action|formaction)$/i;
159
+ const numericCharacterReferencePattern = /&#(?:x([0-9a-f]+)|(\d+));?/gi;
160
+ const namedWhitespaceCharacterReferencePattern = /&(?:Tab|NewLine);/g;
161
+ const colonCharacterReferencePattern = /&colon;?/gi;
162
+ // eslint-disable-next-line no-control-regex -- URL scheme normalization requires the full control range
163
+ const controlOrWhitespacePattern = /[\u0000-\u0020\u007f-\u009f]/g;
164
+ const eventHandlerPattern = /(?:^|[\s"'<>/])on\w+\s*=\s*["']?[^"'>]+["']?/i;
165
+ const eventHandlerAttributePattern = /(^|[\s"'<>/])on(\w+\s*=)/gi;
166
+ const unquotedUrlAttributePattern = /(^|[\s"'<>/])((?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi;
167
+ function decodeNumericCharacterReference(match, hex, decimal) {
168
+ const digits = hex || decimal;
169
+ if (!digits) {
170
+ return match;
171
+ }
172
+ const codePoint = Number.parseInt(digits, hex ? 16 : 10);
173
+ return codePoint <= 0x7f ? String.fromCharCode(codePoint) : match;
174
+ }
89
175
  function hasJavascriptScheme(value) {
90
- return javascriptSchemePattern.test(value);
176
+ const normalized = value
177
+ .replace(numericCharacterReferencePattern, decodeNumericCharacterReference)
178
+ .replace(namedWhitespaceCharacterReferencePattern, '')
179
+ .replace(colonCharacterReferencePattern, ':')
180
+ .replace(controlOrWhitespacePattern, '');
181
+ return javascriptSchemePattern.test(normalized);
91
182
  }
92
183
  function sanitizeStyleValue(value) {
93
184
  const urlPattern = /url\s*\(/gi;
@@ -151,88 +242,18 @@ var IntlifyCoreBase = (function (exports) {
151
242
  // Process attributes with single quotes
152
243
  html = html.replace(/([\w:-]+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${sanitizeAttributeValue(attrName, attrValue)}'`);
153
244
  // Detect and neutralize event handler attributes
154
- const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi;
155
245
  if (eventHandlerPattern.test(html)) {
156
246
  {
157
247
  warn('Potentially dangerous event handlers detected in translation. ' +
158
248
  'Consider removing onclick, onerror, etc. from your translation messages.');
159
249
  }
160
250
  // Neutralize event handler attributes by escaping 'on'
161
- html = html.replace(/(\s+)(on)(\w+\s*=)/gi, '$1&#111;n$3');
251
+ html = html.replace(eventHandlerAttributePattern, '$1&#111;n$2');
162
252
  }
163
253
  // Disable javascript: URLs in unquoted attributes
164
- html = html.replace(/(\s+(?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi, (match, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${prefix}about:blank` : match);
254
+ html = html.replace(unquotedUrlAttributePattern, (match, boundary, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${boundary}${prefix}about:blank` : match);
165
255
  return html;
166
256
  }
167
- const hasOwnProperty = Object.prototype.hasOwnProperty;
168
- function hasOwn(obj, key) {
169
- return hasOwnProperty.call(obj, key);
170
- }
171
- /* eslint-enable */
172
- /**
173
- * Useful Utilities By Evan you
174
- * Modified by kazuya kawaguchi
175
- * MIT License
176
- * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
177
- * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
178
- */
179
- const isArray = Array.isArray;
180
- const isFunction = (val) => typeof val === 'function';
181
- const isString = (val) => typeof val === 'string';
182
- const isBoolean = (val) => typeof val === 'boolean';
183
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
184
- const isObject = (val) => val !== null && typeof val === 'object';
185
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
186
- const isPromise = (val) => {
187
- return isObject(val) && isFunction(val.then) && isFunction(val.catch);
188
- };
189
- const objectToString = Object.prototype.toString;
190
- const toTypeString = (value) => objectToString.call(value);
191
- const isPlainObject = (val) => toTypeString(val) === '[object Object]';
192
- // for converting list and named values to displayed strings.
193
- const toDisplayString = (val) => {
194
- return val == null
195
- ? ''
196
- : isArray(val) || (isPlainObject(val) && val.toString === objectToString)
197
- ? JSON.stringify(val, null, 2)
198
- : String(val);
199
- };
200
- function join(items, separator = '') {
201
- return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
202
- }
203
- const RANGE = 2;
204
- function generateCodeFrame(source, start = 0, end = source.length) {
205
- const lines = source.split(/\r?\n/);
206
- let count = 0;
207
- const res = [];
208
- for (let i = 0; i < lines.length; i++) {
209
- count += lines[i].length + 1;
210
- if (count >= start) {
211
- for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
212
- if (j < 0 || j >= lines.length)
213
- continue;
214
- const line = j + 1;
215
- res.push(`${line}${' '.repeat(3 - String(line).length)}| ${lines[j]}`);
216
- const lineLength = lines[j].length;
217
- if (j === i) {
218
- // push underline
219
- const pad = start - (count - lineLength) + 1;
220
- const length = Math.max(1, end > count ? lineLength - pad : end - start);
221
- res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
222
- }
223
- else if (j > i) {
224
- if (end > count) {
225
- const length = Math.max(Math.min(end - count, lineLength), 1);
226
- res.push(` | ` + '^'.repeat(length));
227
- }
228
- count += lineLength + 1;
229
- }
230
- }
231
- break;
232
- }
233
- }
234
- return res.join('\n');
235
- }
236
257
 
237
258
  function createPosition(line, column, offset) {
238
259
  return { line, column, offset };
@@ -2081,7 +2102,7 @@ var IntlifyCoreBase = (function (exports) {
2081
2102
  * @remarks
2082
2103
  * A fallback locale function implemented with a simple fallback algorithm.
2083
2104
  *
2084
- * Basically, it returns the value as specified in the `fallbackLocale` props, and is processed with the fallback inside intlify.
2105
+ * 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.
2085
2106
  *
2086
2107
  * @param ctx - A {@link CoreContext | context}
2087
2108
  * @param fallback - A {@link FallbackLocale | fallback locale}
@@ -2098,7 +2119,7 @@ var IntlifyCoreBase = (function (exports) {
2098
2119
  ...(isArray(fallback)
2099
2120
  ? fallback
2100
2121
  : isObject(fallback)
2101
- ? Object.keys(fallback)
2122
+ ? Object.keys(fallback).filter(locale => locale !== 'default')
2102
2123
  : isString(fallback)
2103
2124
  ? [fallback]
2104
2125
  : [start])
@@ -2126,29 +2147,36 @@ var IntlifyCoreBase = (function (exports) {
2126
2147
  if (!context.__localeChainCache) {
2127
2148
  context.__localeChainCache = new Map();
2128
2149
  }
2129
- let chain = context.__localeChainCache.get(startLocale);
2130
- if (!chain) {
2131
- chain = [];
2132
- // first block defined by start
2133
- let block = [start];
2134
- // while any intervening block found
2135
- while (isArray(block)) {
2136
- block = appendBlockToChain(chain, block, fallback);
2137
- }
2138
- // prettier-ignore
2139
- // last block defined by default
2140
- const defaults = isArray(fallback) || !isPlainObject(fallback)
2141
- ? fallback
2142
- : fallback['default']
2143
- ? fallback['default']
2144
- : null;
2145
- // convert defaults to array
2146
- block = isString(defaults) ? [defaults] : defaults;
2147
- if (isArray(block)) {
2148
- appendBlockToChain(chain, block, false);
2149
- }
2150
- context.__localeChainCache.set(startLocale, chain);
2150
+ const fallbackKey = friendlyJSONstringify(fallback);
2151
+ let chains = context.__localeChainCache.get(startLocale);
2152
+ if (!chains) {
2153
+ chains = new Map();
2154
+ context.__localeChainCache.set(startLocale, chains);
2155
+ }
2156
+ const cached = chains.get(fallbackKey);
2157
+ if (cached) {
2158
+ return cached;
2151
2159
  }
2160
+ const chain = [];
2161
+ // first block defined by start
2162
+ let block = [start];
2163
+ // while any intervening block found
2164
+ while (isArray(block)) {
2165
+ block = appendBlockToChain(chain, block, fallback);
2166
+ }
2167
+ // prettier-ignore
2168
+ // last block defined by default
2169
+ const defaults = isArray(fallback) || !isPlainObject(fallback)
2170
+ ? fallback
2171
+ : fallback['default']
2172
+ ? fallback['default']
2173
+ : null;
2174
+ // convert defaults to array
2175
+ block = isString(defaults) ? [defaults] : defaults;
2176
+ if (isArray(block)) {
2177
+ appendBlockToChain(chain, block, false);
2178
+ }
2179
+ chains.set(fallbackKey, chain);
2152
2180
  return chain;
2153
2181
  }
2154
2182
  function appendBlockToChain(chain, block, blocks) {
@@ -2507,7 +2535,7 @@ var IntlifyCoreBase = (function (exports) {
2507
2535
  * Intlify core-base version
2508
2536
  * @internal
2509
2537
  */
2510
- const VERSION = '11.4.7';
2538
+ const VERSION = '11.4.9';
2511
2539
  const NOT_REOSLVED = -1;
2512
2540
  const DEFAULT_LOCALE = 'en-US';
2513
2541
  const MISSING_RESOLVE_VALUE = '';
@@ -2754,6 +2782,88 @@ var IntlifyCoreBase = (function (exports) {
2754
2782
  }
2755
2783
  /* eslint-enable @typescript-eslint/no-explicit-any */
2756
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
+
2757
2867
  const intlDefined = typeof Intl !== 'undefined';
2758
2868
  const Availabilities = {
2759
2869
  dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
@@ -2762,7 +2872,7 @@ var IntlifyCoreBase = (function (exports) {
2762
2872
 
2763
2873
  // implementation of `datetime` function
2764
2874
  function datetime(context, ...args) {
2765
- const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
2875
+ const { datetimeFormats, unresolving, onWarn } = context;
2766
2876
  const { __datetimeFormatters } = context;
2767
2877
  if (!Availabilities.dateTimeFormat) {
2768
2878
  onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
@@ -2785,57 +2895,16 @@ var IntlifyCoreBase = (function (exports) {
2785
2895
  : context.fallbackWarn;
2786
2896
  const part = !!options.part;
2787
2897
  const locale = getLocale(context, options);
2788
- const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
2789
- fallbackLocale, locale);
2790
2898
  if (!isString(key) || key === '') {
2791
2899
  const formatter = new Intl.DateTimeFormat(locale.replace(/!/g, ''), overrides);
2792
2900
  return !part ? formatter.format(value) : formatter.formatToParts(value);
2793
2901
  }
2794
- // resolve format
2795
- let datetimeFormat = {};
2796
- let targetLocale;
2797
- let format = null;
2798
- let from = locale;
2799
- let to = null;
2800
- const type = 'datetime format';
2801
- for (let i = 0; i < locales.length; i++) {
2802
- targetLocale = to = locales[i];
2803
- if (locale !== targetLocale &&
2804
- isTranslateFallbackWarn(fallbackWarn, key)) {
2805
- onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_DATE_FORMAT, {
2806
- key,
2807
- target: targetLocale
2808
- }));
2809
- }
2810
- // for vue-devtools timeline event
2811
- if (locale !== targetLocale) {
2812
- const emitter = context.__v_emitter;
2813
- if (emitter) {
2814
- emitter.emit('fallback', {
2815
- type,
2816
- key,
2817
- from,
2818
- to,
2819
- groupId: `${type}:${key}`
2820
- });
2821
- }
2822
- }
2823
- datetimeFormat =
2824
- datetimeFormats[targetLocale] || {};
2825
- format = datetimeFormat[key];
2826
- if (isPlainObject(format))
2827
- break;
2828
- handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
2829
- from = to;
2830
- }
2831
- // checking format and target locale
2832
- if (!isPlainObject(format) || !isString(targetLocale)) {
2902
+ const targetLocale = resolveFormatLocale(context, key, locale, datetimeFormats, missingWarn, fallbackWarn, 'datetime format');
2903
+ if (!isString(targetLocale)) {
2833
2904
  return unresolving ? NOT_REOSLVED : key;
2834
2905
  }
2835
- let id = `${targetLocale}__${key}`;
2836
- if (!isEmptyObject(overrides)) {
2837
- id = `${id}__${JSON.stringify(overrides)}`;
2838
- }
2906
+ const format = datetimeFormats[targetLocale][key];
2907
+ const id = getFormatterCacheKey(targetLocale, key, overrides);
2839
2908
  let formatter = __datetimeFormatters.get(id);
2840
2909
  if (!formatter) {
2841
2910
  formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
@@ -2868,9 +2937,9 @@ var IntlifyCoreBase = (function (exports) {
2868
2937
  ];
2869
2938
  /** @internal */
2870
2939
  function parseDateTimeArgs(...args) {
2871
- const [arg1, arg2, arg3, arg4] = args;
2940
+ const [arg1] = args;
2872
2941
  const options = create();
2873
- let overrides = create();
2942
+ const initialOverrides = create();
2874
2943
  let value;
2875
2944
  if (isString(arg1)) {
2876
2945
  // Only allow ISO strings - other date formats are often supported,
@@ -2907,45 +2976,18 @@ var IntlifyCoreBase = (function (exports) {
2907
2976
  else {
2908
2977
  throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
2909
2978
  }
2910
- if (isString(arg2)) {
2911
- options.key = arg2;
2912
- }
2913
- else if (isPlainObject(arg2)) {
2914
- Object.keys(arg2).forEach(key => {
2915
- if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
2916
- overrides[key] = arg2[key];
2917
- }
2918
- else {
2919
- options[key] = arg2[key];
2920
- }
2921
- });
2922
- }
2923
- if (isString(arg3)) {
2924
- options.locale = arg3;
2925
- }
2926
- else if (isPlainObject(arg3)) {
2927
- overrides = arg3;
2928
- }
2929
- if (isPlainObject(arg4)) {
2930
- overrides = arg4;
2931
- }
2979
+ const overrides = parseFormatArgs(args, options, initialOverrides, DATETIME_FORMAT_OPTIONS_KEYS);
2932
2980
  return [options.key || '', value, options, overrides];
2933
2981
  }
2934
2982
  /** @internal */
2935
2983
  function clearDateTimeFormat(ctx, locale, format) {
2936
2984
  const context = ctx;
2937
- for (const key in format) {
2938
- const id = `${locale}__${key}`;
2939
- if (!context.__datetimeFormatters.has(id)) {
2940
- continue;
2941
- }
2942
- context.__datetimeFormatters.delete(id);
2943
- }
2985
+ clearFormatCache(context.__datetimeFormatters, locale, format);
2944
2986
  }
2945
2987
 
2946
2988
  // implementation of `number` function
2947
2989
  function number(context, ...args) {
2948
- const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
2990
+ const { numberFormats, unresolving, onWarn } = context;
2949
2991
  const { __numberFormatters } = context;
2950
2992
  if (!Availabilities.numberFormat) {
2951
2993
  onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
@@ -2968,57 +3010,16 @@ var IntlifyCoreBase = (function (exports) {
2968
3010
  : context.fallbackWarn;
2969
3011
  const part = !!options.part;
2970
3012
  const locale = getLocale(context, options);
2971
- const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
2972
- fallbackLocale, locale);
2973
3013
  if (!isString(key) || key === '') {
2974
3014
  const formatter = new Intl.NumberFormat(locale.replace(/!/g, ''), overrides);
2975
3015
  return !part ? formatter.format(value) : formatter.formatToParts(value);
2976
3016
  }
2977
- // resolve format
2978
- let numberFormat = {};
2979
- let targetLocale;
2980
- let format = null;
2981
- let from = locale;
2982
- let to = null;
2983
- const type = 'number format';
2984
- for (let i = 0; i < locales.length; i++) {
2985
- targetLocale = to = locales[i];
2986
- if (locale !== targetLocale &&
2987
- isTranslateFallbackWarn(fallbackWarn, key)) {
2988
- onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
2989
- key,
2990
- target: targetLocale
2991
- }));
2992
- }
2993
- // for vue-devtools timeline event
2994
- if (locale !== targetLocale) {
2995
- const emitter = context.__v_emitter;
2996
- if (emitter) {
2997
- emitter.emit('fallback', {
2998
- type,
2999
- key,
3000
- from,
3001
- to,
3002
- groupId: `${type}:${key}`
3003
- });
3004
- }
3005
- }
3006
- numberFormat =
3007
- numberFormats[targetLocale] || {};
3008
- format = numberFormat[key];
3009
- if (isPlainObject(format))
3010
- break;
3011
- handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
3012
- from = to;
3013
- }
3014
- // checking format and target locale
3015
- if (!isPlainObject(format) || !isString(targetLocale)) {
3017
+ const targetLocale = resolveFormatLocale(context, key, locale, numberFormats, missingWarn, fallbackWarn, 'number format');
3018
+ if (!isString(targetLocale)) {
3016
3019
  return unresolving ? NOT_REOSLVED : key;
3017
3020
  }
3018
- let id = `${targetLocale}__${key}`;
3019
- if (!isEmptyObject(overrides)) {
3020
- id = `${id}__${JSON.stringify(overrides)}`;
3021
- }
3021
+ const format = numberFormats[targetLocale][key];
3022
+ const id = getFormatterCacheKey(targetLocale, key, overrides);
3022
3023
  let formatter = __numberFormatters.get(id);
3023
3024
  if (!formatter) {
3024
3025
  formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
@@ -3051,47 +3052,20 @@ var IntlifyCoreBase = (function (exports) {
3051
3052
  ];
3052
3053
  /** @internal */
3053
3054
  function parseNumberArgs(...args) {
3054
- const [arg1, arg2, arg3, arg4] = args;
3055
+ const [arg1] = args;
3055
3056
  const options = create();
3056
- let overrides = create();
3057
+ const initialOverrides = create();
3057
3058
  if (!isNumber(arg1)) {
3058
3059
  throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
3059
3060
  }
3060
3061
  const value = arg1;
3061
- if (isString(arg2)) {
3062
- options.key = arg2;
3063
- }
3064
- else if (isPlainObject(arg2)) {
3065
- Object.keys(arg2).forEach(key => {
3066
- if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
3067
- overrides[key] = arg2[key];
3068
- }
3069
- else {
3070
- options[key] = arg2[key];
3071
- }
3072
- });
3073
- }
3074
- if (isString(arg3)) {
3075
- options.locale = arg3;
3076
- }
3077
- else if (isPlainObject(arg3)) {
3078
- overrides = arg3;
3079
- }
3080
- if (isPlainObject(arg4)) {
3081
- overrides = arg4;
3082
- }
3062
+ const overrides = parseFormatArgs(args, options, initialOverrides, NUMBER_FORMAT_OPTIONS_KEYS);
3083
3063
  return [options.key || '', value, options, overrides];
3084
3064
  }
3085
3065
  /** @internal */
3086
3066
  function clearNumberFormat(ctx, locale, format) {
3087
3067
  const context = ctx;
3088
- for (const key in format) {
3089
- const id = `${locale}__${key}`;
3090
- if (!context.__numberFormatters.has(id)) {
3091
- continue;
3092
- }
3093
- context.__numberFormatters.delete(id);
3094
- }
3068
+ clearFormatCache(context.__numberFormatters, locale, format);
3095
3069
  }
3096
3070
 
3097
3071
  const DEFAULT_MODIFIER = (str) => str;