UNPKG

47.4 kBJavaScriptView Raw
1/*!
2 * vue-i18n-bridge v9.2.0-beta.6
3 * (c) 2021 kazuya kawaguchi
4 * Released under the MIT License.
5 */
6import { getGlobalThis, format, makeSymbol, isPlainObject, isArray, hasOwn, isObject, isBoolean, isString, isRegExp, isFunction, assign, isNumber, warn, isEmptyObject } from '@intlify/shared';
7import { CoreWarnCodes, createCompileError, CompileErrorCodes, DEFAULT_LOCALE, createCoreContext, updateFallbackLocale, clearDateTimeFormat, clearNumberFormat, setAdditionalMeta, NOT_REOSLVED, isTranslateFallbackWarn, isTranslateMissingWarn, parseTranslateArgs, translate, MISSING_RESOLVE_VALUE, parseDateTimeArgs, datetime, parseNumberArgs, number, fallbackWithLocaleChain, registerMessageCompiler, compileToFunction, registerMessageResolver, resolveValue, registerLocaleFallbacker, setDevToolsHook } from '@intlify/core-base';
8import { ref, getCurrentInstance, computed, watch, onBeforeMount, onUnmounted } from '@vue/composition-api';
9
10/**
11 * Vue I18n Version
12 *
13 * @remarks
14 * Semver format. Same format as the package.json `version` field.
15 *
16 * @VueI18nGeneral
17 */
18const VERSION = '9.2.0-beta.6';
19/**
20 * This is only called in esm-bundler builds.
21 * istanbul-ignore-next
22 */
23function initFeatureFlags() {
24 let needWarn = false;
25 if (typeof __VUE_I18N_FULL_INSTALL__ !== 'boolean') {
26 needWarn = true;
27 getGlobalThis().__VUE_I18N_FULL_INSTALL__ = true;
28 }
29 if (typeof __VUE_I18N_LEGACY_API__ !== 'boolean') {
30 needWarn = true;
31 getGlobalThis().__VUE_I18N_LEGACY_API__ = true;
32 }
33 if (typeof __INTLIFY_PROD_DEVTOOLS__ !== 'boolean') {
34 getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false;
35 }
36 if ((process.env.NODE_ENV !== 'production') && needWarn) {
37 console.warn(`You are running the esm-bundler build of vue-i18n. It is recommended to ` +
38 `configure your bundler to explicitly replace feature flag globals ` +
39 `with boolean literals to get proper tree-shaking in the final bundle.`);
40 }
41}
42
43let code$1 = CoreWarnCodes.__EXTEND_POINT__;
44const inc$1 = () => code$1++;
45const I18nWarnCodes = {
46 FALLBACK_TO_ROOT: code$1,
47 NOT_SUPPORTED_PRESERVE: inc$1(),
48 NOT_SUPPORTED_FORMATTER: inc$1(),
49 NOT_SUPPORTED_PRESERVE_DIRECTIVE: inc$1(),
50 NOT_SUPPORTED_GET_CHOICE_INDEX: inc$1(),
51 COMPONENT_NAME_LEGACY_COMPATIBLE: inc$1(),
52 NOT_FOUND_PARENT_SCOPE: inc$1(),
53 NOT_SUPPORT_MULTI_I18N_INSTANCE: inc$1() // 14
54};
55const warnMessages = {
56 [I18nWarnCodes.FALLBACK_TO_ROOT]: `Fall back to {type} '{key}' with root locale.`,
57 [I18nWarnCodes.NOT_SUPPORTED_PRESERVE]: `Not supported 'preserve'.`,
58 [I18nWarnCodes.NOT_SUPPORTED_FORMATTER]: `Not supported 'formatter'.`,
59 [I18nWarnCodes.NOT_SUPPORTED_PRESERVE_DIRECTIVE]: `Not supported 'preserveDirectiveContent'.`,
60 [I18nWarnCodes.NOT_SUPPORTED_GET_CHOICE_INDEX]: `Not supported 'getChoiceIndex'.`,
61 [I18nWarnCodes.COMPONENT_NAME_LEGACY_COMPATIBLE]: `Component name legacy compatible: '{name}' -> 'i18n'`,
62 [I18nWarnCodes.NOT_FOUND_PARENT_SCOPE]: `Not found parent scope. use the global scope.`,
63 [I18nWarnCodes.NOT_SUPPORT_MULTI_I18N_INSTANCE]: `Not support multi i18n instance.`
64};
65function getWarnMessage(code, ...args) {
66 return format(warnMessages[code], ...args);
67}
68
69let code = CompileErrorCodes.__EXTEND_POINT__;
70const inc = () => code++;
71const I18nErrorCodes = {
72 // composer module errors
73 UNEXPECTED_RETURN_TYPE: code,
74 // legacy module errors
75 INVALID_ARGUMENT: inc(),
76 // i18n module errors
77 MUST_BE_CALL_SETUP_TOP: inc(),
78 NOT_INSLALLED: inc(),
79 NOT_AVAILABLE_IN_LEGACY_MODE: inc(),
80 // directive module errors
81 REQUIRED_VALUE: inc(),
82 INVALID_VALUE: inc(),
83 // vue-devtools errors
84 CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN: inc(),
85 NOT_INSLALLED_WITH_PROVIDE: inc(),
86 // unexpected error
87 UNEXPECTED_ERROR: inc(),
88 // not compatible legacy vue-i18n constructor
89 NOT_COMPATIBLE_LEGACY_VUE_I18N: inc(),
90 // bridge support vue 2.x only
91 BRIDGE_SUPPORT_VUE_2_ONLY: inc(),
92 // for enhancement
93 __EXTEND_POINT__: inc() // 27
94};
95function createI18nError(code, ...args) {
96 return createCompileError(code, null, (process.env.NODE_ENV !== 'production') ? { messages: errorMessages, args } : undefined);
97}
98const errorMessages = {
99 [I18nErrorCodes.UNEXPECTED_RETURN_TYPE]: 'Unexpected return type in composer',
100 [I18nErrorCodes.INVALID_ARGUMENT]: 'Invalid argument',
101 [I18nErrorCodes.MUST_BE_CALL_SETUP_TOP]: 'Must be called at the top of a `setup` function',
102 [I18nErrorCodes.NOT_INSLALLED]: 'Need to install with `app.use` function',
103 [I18nErrorCodes.UNEXPECTED_ERROR]: 'Unexpected error',
104 [I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE]: 'Not available in legacy mode',
105 [I18nErrorCodes.REQUIRED_VALUE]: `Required in value: {0}`,
106 [I18nErrorCodes.INVALID_VALUE]: `Invalid value`,
107 [I18nErrorCodes.CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN]: `Cannot setup vue-devtools plugin`,
108 [I18nErrorCodes.NOT_INSLALLED_WITH_PROVIDE]: 'Need to install with `provide` function',
109 [I18nErrorCodes.NOT_COMPATIBLE_LEGACY_VUE_I18N]: 'Not compatible legacy VueI18n.',
110 [I18nErrorCodes.BRIDGE_SUPPORT_VUE_2_ONLY]: 'vue-i18n-bridge support Vue 2.x only'
111};
112
113const SetPluralRulesSymbol = makeSymbol('__setPluralRules');
114makeSymbol('__intlifyMeta');
115const LegacyInstanceSymbol = /* #__PURE__*/ makeSymbol('__legacyVueI18n');
116
117/* eslint-disable @typescript-eslint/no-explicit-any */
118// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
119function isLegacyVueI18n(VueI18n) {
120 if (VueI18n == null || VueI18n.version == null) {
121 return false;
122 }
123 return (Number(VueI18n.version.split('.')[0]) || -1) >= 8;
124}
125/**
126 * Transform flat json in obj to normal json in obj
127 */
128function handleFlatJson(obj) {
129 // check obj
130 if (!isObject(obj)) {
131 return obj;
132 }
133 for (const key in obj) {
134 // check key
135 if (!hasOwn(obj, key)) {
136 continue;
137 }
138 // handle for normal json
139 if (!key.includes('.')) {
140 // recursive process value if value is also a object
141 if (isObject(obj[key])) {
142 handleFlatJson(obj[key]);
143 }
144 }
145 // handle for flat json, transform to normal json
146 else {
147 // go to the last object
148 const subKeys = key.split('.');
149 const lastIndex = subKeys.length - 1;
150 let currentObj = obj;
151 for (let i = 0; i < lastIndex; i++) {
152 if (!(subKeys[i] in currentObj)) {
153 currentObj[subKeys[i]] = {};
154 }
155 currentObj = currentObj[subKeys[i]];
156 }
157 // update last object value, delete old property
158 currentObj[subKeys[lastIndex]] = obj[key];
159 delete obj[key];
160 // recursive process value if value is also a object
161 if (isObject(currentObj[subKeys[lastIndex]])) {
162 handleFlatJson(currentObj[subKeys[lastIndex]]);
163 }
164 }
165 }
166 return obj;
167}
168function getLocaleMessages(locale, options) {
169 const { messages, __i18n, messageResolver, flatJson } = options;
170 // prettier-ignore
171 const ret = isPlainObject(messages)
172 ? messages
173 : isArray(__i18n)
174 ? {}
175 : { [locale]: {} };
176 // merge locale messages of i18n custom block
177 if (isArray(__i18n)) {
178 __i18n.forEach(({ locale, resource }) => {
179 if (locale) {
180 ret[locale] = ret[locale] || {};
181 deepCopy(resource, ret[locale]);
182 }
183 else {
184 deepCopy(resource, ret);
185 }
186 });
187 }
188 // handle messages for flat json
189 if (messageResolver == null && flatJson) {
190 for (const key in ret) {
191 if (hasOwn(ret, key)) {
192 handleFlatJson(ret[key]);
193 }
194 }
195 }
196 return ret;
197}
198const isNotObjectOrIsArray = (val) => !isObject(val) || isArray(val);
199// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
200function deepCopy(src, des) {
201 // src and des should both be objects, and non of then can be a array
202 if (isNotObjectOrIsArray(src) || isNotObjectOrIsArray(des)) {
203 throw createI18nError(I18nErrorCodes.INVALID_VALUE);
204 }
205 for (const key in src) {
206 if (hasOwn(src, key)) {
207 if (isNotObjectOrIsArray(src[key]) || isNotObjectOrIsArray(des[key])) {
208 // replace with src[key] when:
209 // src[key] or des[key] is not a object, or
210 // src[key] or des[key] is a array
211 des[key] = src[key];
212 }
213 else {
214 // src[key] and des[key] are both object, merge them
215 deepCopy(src[key], des[key]);
216 }
217 }
218 }
219}
220/* eslint-enable @typescript-eslint/no-explicit-any */
221
222/* eslint-disable @typescript-eslint/no-explicit-any */
223const DEVTOOLS_META = '__INTLIFY_META__';
224let composerID = 0;
225function defineCoreMissingHandler(missing) {
226 return ((ctx, locale, key, type) => {
227 return missing(locale, key, getCurrentInstance() || undefined, type);
228 });
229}
230// for Intlify DevTools
231const getMetaInfo = () => {
232 const instance = getCurrentInstance();
233 return instance && instance.type[DEVTOOLS_META] // eslint-disable-line @typescript-eslint/no-explicit-any
234 ? { [DEVTOOLS_META]: instance.type[DEVTOOLS_META] } // eslint-disable-line @typescript-eslint/no-explicit-any
235 : null;
236};
237/**
238 * Create composer interface factory
239 *
240 * @internal
241 */
242// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
243function createComposer(options = {}, VueI18nLegacy) {
244 const { __root } = options;
245 const _isGlobal = __root === undefined;
246 let _inheritLocale = isBoolean(options.inheritLocale)
247 ? options.inheritLocale
248 : true;
249 const _locale = ref(
250 // prettier-ignore
251 __root && _inheritLocale
252 ? __root.locale.value
253 : isString(options.locale)
254 ? options.locale
255 : DEFAULT_LOCALE);
256 const _fallbackLocale = ref(
257 // prettier-ignore
258 __root && _inheritLocale
259 ? __root.fallbackLocale.value
260 : isString(options.fallbackLocale) ||
261 isArray(options.fallbackLocale) ||
262 isPlainObject(options.fallbackLocale) ||
263 options.fallbackLocale === false
264 ? options.fallbackLocale
265 : _locale.value);
266 const _messages = ref(getLocaleMessages(_locale.value, options));
267 // prettier-ignore
268 const _datetimeFormats = ref(isPlainObject(options.datetimeFormats)
269 ? options.datetimeFormats
270 : { [_locale.value]: {} })
271 ;
272 // prettier-ignore
273 const _numberFormats = ref(isPlainObject(options.numberFormats)
274 ? options.numberFormats
275 : { [_locale.value]: {} })
276 ;
277 // warning suppress options
278 // prettier-ignore
279 let _missingWarn = __root
280 ? __root.missingWarn
281 : isBoolean(options.missingWarn) || isRegExp(options.missingWarn)
282 ? options.missingWarn
283 : true;
284 // prettier-ignore
285 let _fallbackWarn = __root
286 ? __root.fallbackWarn
287 : isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn)
288 ? options.fallbackWarn
289 : true;
290 // prettier-ignore
291 let _fallbackRoot = __root
292 ? __root.fallbackRoot
293 : isBoolean(options.fallbackRoot)
294 ? options.fallbackRoot
295 : true;
296 // configure fall back to root
297 let _fallbackFormat = !!options.fallbackFormat;
298 // runtime missing
299 let _missing = isFunction(options.missing) ? options.missing : null;
300 let _runtimeMissing = isFunction(options.missing)
301 ? defineCoreMissingHandler(options.missing)
302 : null;
303 // postTranslation handler
304 let _postTranslation = isFunction(options.postTranslation)
305 ? options.postTranslation
306 : null;
307 let _warnHtmlMessage = isBoolean(options.warnHtmlMessage)
308 ? options.warnHtmlMessage
309 : true;
310 let _escapeParameter = !!options.escapeParameter;
311 // custom linked modifiers
312 // prettier-ignore
313 const _modifiers = __root
314 ? __root.modifiers
315 : isPlainObject(options.modifiers)
316 ? options.modifiers
317 : {};
318 // pluralRules
319 let _pluralRules = options.pluralRules || (__root && __root.pluralRules);
320 // for bridge
321 let __legacy;
322 {
323 if (!isLegacyVueI18n(VueI18nLegacy)) {
324 createI18nError(I18nErrorCodes.NOT_COMPATIBLE_LEGACY_VUE_I18N);
325 }
326 const legacyOptions = {
327 locale: _locale.value,
328 fallbackLocale: _fallbackLocale.value,
329 messages: _messages.value,
330 dateTimeFormats: _datetimeFormats.value,
331 numberFormats: _numberFormats.value,
332 modifiers: _modifiers,
333 missing: _missing,
334 fallbackRoot: _fallbackRoot,
335 postTranslation: _postTranslation,
336 pluralizationRules: _pluralRules,
337 escapeParameterHtml: _escapeParameter,
338 sync: _inheritLocale,
339 silentFallbackWarn: isBoolean(_fallbackWarn)
340 ? !_fallbackWarn
341 : _fallbackWarn,
342 silentTranslationWarn: isBoolean(_missingWarn)
343 ? !_missingWarn
344 : _missingWarn,
345 formatFallbackMessages: isBoolean(_fallbackFormat)
346 ? !_fallbackFormat
347 : _fallbackFormat,
348 warnHtmlInMessage: isBoolean(_warnHtmlMessage)
349 ? _warnHtmlMessage
350 ? 'warn'
351 : 'off'
352 : 'off'
353 };
354 __legacy = new VueI18nLegacy(legacyOptions);
355 }
356 // runtime context
357 // eslint-disable-next-line prefer-const
358 let _context;
359 function getCoreContext() {
360 const ctxOptions = {
361 version: VERSION,
362 locale: _locale.value,
363 fallbackLocale: _fallbackLocale.value,
364 messages: _messages.value,
365 modifiers: _modifiers,
366 pluralRules: _pluralRules,
367 missing: _runtimeMissing === null ? undefined : _runtimeMissing,
368 missingWarn: _missingWarn,
369 fallbackWarn: _fallbackWarn,
370 fallbackFormat: _fallbackFormat,
371 unresolving: true,
372 postTranslation: _postTranslation === null ? undefined : _postTranslation,
373 warnHtmlMessage: _warnHtmlMessage,
374 escapeParameter: _escapeParameter,
375 messageResolver: options.messageResolver,
376 __meta: { framework: 'vue' }
377 };
378 {
379 ctxOptions.datetimeFormats = _datetimeFormats.value;
380 ctxOptions.numberFormats = _numberFormats.value;
381 ctxOptions.__datetimeFormatters = isPlainObject(_context)
382 ? _context.__datetimeFormatters
383 : undefined;
384 ctxOptions.__numberFormatters = isPlainObject(_context)
385 ? _context.__numberFormatters
386 : undefined;
387 }
388 return createCoreContext(ctxOptions);
389 }
390 _context = getCoreContext();
391 updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
392 // track reactivity
393 function trackReactivityValues() {
394 return [
395 _locale.value,
396 _fallbackLocale.value,
397 _messages.value,
398 _datetimeFormats.value,
399 _numberFormats.value
400 ]
401 ;
402 }
403 // locale
404 const locale = computed({
405 get: () => _locale.value,
406 set: val => {
407 _locale.value = val;
408 {
409 if (__legacy) {
410 __legacy.locale = val;
411 }
412 }
413 _context.locale = _locale.value;
414 }
415 });
416 // fallbackLocale
417 const fallbackLocale = computed({
418 get: () => _fallbackLocale.value,
419 set: val => {
420 _fallbackLocale.value = val;
421 {
422 if (__legacy) {
423 __legacy.fallbackLocale = val;
424 }
425 }
426 _context.fallbackLocale = _fallbackLocale.value;
427 updateFallbackLocale(_context, _locale.value, val);
428 }
429 });
430 // messages
431 const messages = computed(() => _messages.value);
432 // datetimeFormats
433 const datetimeFormats = /* #__PURE__*/ computed(() => _datetimeFormats.value);
434 // numberFormats
435 const numberFormats = /* #__PURE__*/ computed(() => _numberFormats.value);
436 // getPostTranslationHandler
437 function getPostTranslationHandler() {
438 return isFunction(_postTranslation) ? _postTranslation : null;
439 }
440 // setPostTranslationHandler
441 function setPostTranslationHandler(handler) {
442 _postTranslation = handler;
443 _context.postTranslation = handler;
444 }
445 // getMissingHandler
446 function getMissingHandler() {
447 return _missing;
448 }
449 // setMissingHandler
450 function setMissingHandler(handler) {
451 if (handler !== null) {
452 _runtimeMissing = defineCoreMissingHandler(handler);
453 }
454 _missing = handler;
455 _context.missing = _runtimeMissing;
456 }
457 function isResolvedTranslateMessage(type, arg // eslint-disable-line @typescript-eslint/no-explicit-any
458 ) {
459 return type !== 'translate' || !arg.resolvedMessage;
460 }
461 function wrapWithDeps(fn, argumentParser, warnType, fallbackSuccess, fallbackFail, successCondition) {
462 trackReactivityValues(); // track reactive dependency
463 // NOTE: experimental !!
464 let ret;
465 if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
466 try {
467 setAdditionalMeta(getMetaInfo());
468 ret = fn(_context);
469 }
470 finally {
471 setAdditionalMeta(null);
472 }
473 }
474 else {
475 ret = fn(_context);
476 }
477 if (isNumber(ret) && ret === NOT_REOSLVED) {
478 const [key, arg2] = argumentParser();
479 if ((process.env.NODE_ENV !== 'production') &&
480 __root &&
481 isString(key) &&
482 isResolvedTranslateMessage(warnType, arg2)) {
483 if (_fallbackRoot &&
484 (isTranslateFallbackWarn(_fallbackWarn, key) ||
485 isTranslateMissingWarn(_missingWarn, key))) {
486 warn(getWarnMessage(I18nWarnCodes.FALLBACK_TO_ROOT, {
487 key,
488 type: warnType
489 }));
490 }
491 }
492 return __root && _fallbackRoot
493 ? fallbackSuccess(__root)
494 : fallbackFail(key);
495 }
496 else if (successCondition(ret)) {
497 return ret;
498 }
499 else {
500 /* istanbul ignore next */
501 throw createI18nError(I18nErrorCodes.UNEXPECTED_RETURN_TYPE);
502 }
503 }
504 // t
505 function t(...args) {
506 return wrapWithDeps(context => Reflect.apply(translate, null, [context, ...args]), () => parseTranslateArgs(...args), 'translate', root => Reflect.apply(root.t, root, [...args]), key => key, val => isString(val));
507 }
508 // rt
509 function rt(...args) {
510 const [arg1, arg2, arg3] = args;
511 if (arg3 && !isObject(arg3)) {
512 throw createI18nError(I18nErrorCodes.INVALID_ARGUMENT);
513 }
514 return t(...[arg1, arg2, assign({ resolvedMessage: true }, arg3 || {})]);
515 }
516 // d
517 function d(...args) {
518 return wrapWithDeps(context => Reflect.apply(datetime, null, [context, ...args]), () => parseDateTimeArgs(...args), 'datetime format', root => Reflect.apply(root.d, root, [...args]), () => MISSING_RESOLVE_VALUE, val => isString(val));
519 }
520 // n
521 function n(...args) {
522 return wrapWithDeps(context => Reflect.apply(number, null, [context, ...args]), () => parseNumberArgs(...args), 'number format', root => Reflect.apply(root.n, root, [...args]), () => MISSING_RESOLVE_VALUE, val => isString(val));
523 }
524 function setPluralRules(rules) {
525 _pluralRules = rules;
526 _context.pluralRules = _pluralRules;
527 }
528 // te
529 function te(key, locale) {
530 const targetLocale = isString(locale) ? locale : _locale.value;
531 const message = getLocaleMessage(targetLocale);
532 return _context.messageResolver(message, key) !== null;
533 }
534 function resolveMessages(key) {
535 let messages = null;
536 const locales = fallbackWithLocaleChain(_context, _fallbackLocale.value, _locale.value);
537 for (let i = 0; i < locales.length; i++) {
538 const targetLocaleMessages = _messages.value[locales[i]] || {};
539 const messageValue = _context.messageResolver(targetLocaleMessages, key);
540 if (messageValue != null) {
541 messages = messageValue;
542 break;
543 }
544 }
545 return messages;
546 }
547 // tm
548 function tm(key) {
549 const messages = resolveMessages(key);
550 // prettier-ignore
551 return messages != null
552 ? messages
553 : __root
554 ? __root.tm(key) || {}
555 : {};
556 }
557 // getLocaleMessage
558 function getLocaleMessage(locale) {
559 return (_messages.value[locale] || {});
560 }
561 // setLocaleMessage
562 function setLocaleMessage(locale, message) {
563 _messages.value[locale] = message;
564 {
565 __legacy && __legacy.setLocaleMessage(locale, message);
566 }
567 _context.messages = _messages.value;
568 }
569 // mergeLocaleMessage
570 function mergeLocaleMessage(locale, message) {
571 _messages.value[locale] = _messages.value[locale] || {};
572 {
573 __legacy && __legacy.mergeLocaleMessage(locale, message);
574 }
575 deepCopy(message, _messages.value[locale]);
576 _context.messages = _messages.value;
577 }
578 // getDateTimeFormat
579 function getDateTimeFormat(locale) {
580 return _datetimeFormats.value[locale] || {};
581 }
582 // setDateTimeFormat
583 function setDateTimeFormat(locale, format) {
584 _datetimeFormats.value[locale] = format;
585 {
586 __legacy && __legacy.setDateTimeFormat(locale, format);
587 }
588 _context.datetimeFormats = _datetimeFormats.value;
589 clearDateTimeFormat(_context, locale, format);
590 }
591 // mergeDateTimeFormat
592 function mergeDateTimeFormat(locale, format) {
593 _datetimeFormats.value[locale] = assign(_datetimeFormats.value[locale] || {}, format);
594 {
595 __legacy && __legacy.mergeDateTimeFormat(locale, format);
596 }
597 _context.datetimeFormats = _datetimeFormats.value;
598 clearDateTimeFormat(_context, locale, format);
599 }
600 // getNumberFormat
601 function getNumberFormat(locale) {
602 return _numberFormats.value[locale] || {};
603 }
604 // setNumberFormat
605 function setNumberFormat(locale, format) {
606 _numberFormats.value[locale] = format;
607 {
608 __legacy && __legacy.setNumberFormat(locale, format);
609 }
610 _context.numberFormats = _numberFormats.value;
611 clearNumberFormat(_context, locale, format);
612 }
613 // mergeNumberFormat
614 function mergeNumberFormat(locale, format) {
615 _numberFormats.value[locale] = assign(_numberFormats.value[locale] || {}, format);
616 {
617 __legacy && __legacy.mergeNumberFormat(locale, format);
618 }
619 _context.numberFormats = _numberFormats.value;
620 clearNumberFormat(_context, locale, format);
621 }
622 // for debug
623 composerID++;
624 // watch root locale & fallbackLocale
625 if (__root) {
626 watch(__root.locale, (val) => {
627 if (_inheritLocale) {
628 _locale.value = val;
629 {
630 if (__legacy) {
631 __legacy.locale = val;
632 }
633 }
634 _context.locale = val;
635 updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
636 }
637 });
638 watch(__root.fallbackLocale, (val) => {
639 if (_inheritLocale) {
640 _fallbackLocale.value = val;
641 {
642 if (__legacy) {
643 __legacy.fallbackLocale = val;
644 }
645 }
646 _context.fallbackLocale = val;
647 updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
648 }
649 });
650 }
651 // define basic composition API!
652 const composer = {
653 id: composerID,
654 locale,
655 fallbackLocale,
656 get inheritLocale() {
657 return _inheritLocale;
658 },
659 set inheritLocale(val) {
660 _inheritLocale = val;
661 {
662 if (__legacy) {
663 __legacy._sync = val;
664 }
665 }
666 if (val && __root) {
667 _locale.value = __root.locale.value;
668 _fallbackLocale.value = __root.fallbackLocale.value;
669 {
670 if (__legacy) {
671 __legacy.locale = __root.locale.value;
672 __legacy.fallbackLocale = __root.fallbackLocale.value;
673 }
674 }
675 updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
676 }
677 },
678 get availableLocales() {
679 return Object.keys(_messages.value).sort();
680 },
681 messages,
682 get modifiers() {
683 return _modifiers;
684 },
685 get pluralRules() {
686 return _pluralRules || {};
687 },
688 get isGlobal() {
689 return _isGlobal;
690 },
691 get missingWarn() {
692 return _missingWarn;
693 },
694 set missingWarn(val) {
695 _missingWarn = val;
696 _context.missingWarn = _missingWarn;
697 },
698 get fallbackWarn() {
699 return _fallbackWarn;
700 },
701 set fallbackWarn(val) {
702 _fallbackWarn = val;
703 _context.fallbackWarn = _fallbackWarn;
704 },
705 get fallbackRoot() {
706 return _fallbackRoot;
707 },
708 set fallbackRoot(val) {
709 _fallbackRoot = val;
710 },
711 get fallbackFormat() {
712 return _fallbackFormat;
713 },
714 set fallbackFormat(val) {
715 _fallbackFormat = val;
716 _context.fallbackFormat = _fallbackFormat;
717 },
718 get warnHtmlMessage() {
719 return _warnHtmlMessage;
720 },
721 set warnHtmlMessage(val) {
722 _warnHtmlMessage = val;
723 _context.warnHtmlMessage = val;
724 },
725 get escapeParameter() {
726 return _escapeParameter;
727 },
728 set escapeParameter(val) {
729 _escapeParameter = val;
730 _context.escapeParameter = val;
731 },
732 t,
733 getLocaleMessage,
734 setLocaleMessage,
735 mergeLocaleMessage,
736 getPostTranslationHandler,
737 setPostTranslationHandler,
738 getMissingHandler,
739 setMissingHandler,
740 [SetPluralRulesSymbol]: setPluralRules
741 };
742 {
743 composer.datetimeFormats = datetimeFormats;
744 composer.numberFormats = numberFormats;
745 composer.rt = rt;
746 composer.te = te;
747 composer.tm = tm;
748 composer.d = d;
749 composer.n = n;
750 composer.getDateTimeFormat = getDateTimeFormat;
751 composer.setDateTimeFormat = setDateTimeFormat;
752 composer.mergeDateTimeFormat = mergeDateTimeFormat;
753 composer.getNumberFormat = getNumberFormat;
754 composer.setNumberFormat = setNumberFormat;
755 composer.mergeNumberFormat = mergeNumberFormat;
756 }
757 {
758 composer[LegacyInstanceSymbol] = __legacy;
759 }
760 return composer;
761}
762/* eslint-enable @typescript-eslint/no-explicit-any */
763
764/**
765 * Port from vue-i18n@v8.x
766 * This mixin is used when we use vue-i18n-bridge
767 */
768function defineMixin(i18n, VueI18n // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
769) {
770 return {
771 beforeCreate() {
772 const options = this.$options; // eslint-disable-line @typescript-eslint/no-explicit-any
773 if (options.__VUE18N__INSTANCE__) {
774 return;
775 }
776 options.i18n = options.i18n || (options.__i18n ? {} : null);
777 this._i18nBridgeRoot = i18n;
778 if (i18n.mode === 'composition') {
779 this._i18n = i18n;
780 return;
781 }
782 if (options.i18n) {
783 if (options.i18n instanceof VueI18n) {
784 // init locale messages via custom blocks
785 if (options.__i18n) {
786 try {
787 const localeMessages = options.i18n && options.i18n.messages
788 ? options.i18n.messages
789 : {};
790 options.__i18n.forEach(resource => deepCopy(localeMessages, JSON.parse(resource)));
791 Object.keys(localeMessages).forEach((locale) => {
792 options.i18n.mergeLocaleMessage(locale, localeMessages[locale]);
793 });
794 }
795 catch (e) {
796 if ((process.env.NODE_ENV !== 'production')) {
797 console.error(`Cannot parse locale messages via custom blocks.`, e);
798 }
799 }
800 }
801 this._i18n = options.i18n;
802 this._i18nWatcher = this._i18n.watchI18nData();
803 }
804 else if (isPlainObject(options.i18n)) {
805 const rootI18n = this.$root &&
806 this.$root.$i18n &&
807 this.$root.$i18n instanceof VueI18n
808 ? this.$root.$i18n
809 : null;
810 // component local i18n
811 if (rootI18n) {
812 options.i18n.root = this.$root;
813 options.i18n.formatter = rootI18n.formatter;
814 options.i18n.fallbackLocale = rootI18n.fallbackLocale;
815 options.i18n.formatFallbackMessages =
816 rootI18n.formatFallbackMessages;
817 options.i18n.silentTranslationWarn = rootI18n.silentTranslationWarn;
818 options.i18n.silentFallbackWarn = rootI18n.silentFallbackWarn;
819 options.i18n.pluralizationRules = rootI18n.pluralizationRules;
820 options.i18n.preserveDirectiveContent =
821 rootI18n.preserveDirectiveContent;
822 }
823 // init locale messages via custom blocks
824 if (options.__i18n) {
825 try {
826 const localeMessages = options.i18n && options.i18n.messages
827 ? options.i18n.messages
828 : {};
829 options.__i18n.forEach(resource => deepCopy(localeMessages, JSON.parse(resource)));
830 options.i18n.messages = localeMessages;
831 }
832 catch (e) {
833 if ((process.env.NODE_ENV !== 'production')) {
834 warn(`Cannot parse locale messages via custom blocks.`, e);
835 }
836 }
837 }
838 const { sharedMessages } = options.i18n;
839 if (sharedMessages && isPlainObject(sharedMessages)) {
840 deepCopy(options.i18n.messages, sharedMessages);
841 }
842 this._i18n = new VueI18n(options.i18n);
843 this._i18nWatcher = this._i18n.watchI18nData();
844 if (options.i18n.sync === undefined || !!options.i18n.sync) {
845 this._localeWatcher = this.$i18n.watchLocale();
846 }
847 if (rootI18n) {
848 rootI18n.onComponentInstanceCreated(this._i18n);
849 }
850 }
851 else {
852 if ((process.env.NODE_ENV !== 'production')) {
853 warn(`Cannot be interpreted 'i18n' option.`);
854 }
855 }
856 }
857 else if (this.$root &&
858 this.$root.$i18n &&
859 this.$root.$i18n instanceof VueI18n) {
860 // root i18n
861 this._i18n = this.$root.$i18n;
862 }
863 else if (options.parent &&
864 options.parent.$i18n &&
865 options.parent.$i18n instanceof VueI18n) {
866 // parent i18n
867 this._i18n = options.parent.$i18n;
868 }
869 },
870 beforeMount() {
871 const options = this.$options; // eslint-disable-line @typescript-eslint/no-explicit-any
872 if (options.__VUE18N__INSTANCE__) {
873 return;
874 }
875 options.i18n = options.i18n || (options.__i18n ? {} : null);
876 if (options.i18n) {
877 if (options.i18n instanceof VueI18n) {
878 // init locale messages via custom blocks
879 this._i18n.subscribeDataChanging(this);
880 this._subscribing = true;
881 }
882 else if (isPlainObject(options.i18n)) {
883 this._i18n.subscribeDataChanging(this);
884 this._subscribing = true;
885 }
886 else {
887 if ((process.env.NODE_ENV !== 'production')) {
888 warn(`Cannot be interpreted 'i18n' option.`);
889 }
890 }
891 }
892 else if (this.$root &&
893 this.$root.$i18n &&
894 this.$root.$i18n instanceof VueI18n) {
895 this._i18n.subscribeDataChanging(this);
896 this._subscribing = true;
897 }
898 else if (options.parent &&
899 options.parent.$i18n &&
900 options.parent.$i18n instanceof VueI18n) {
901 this._i18n.subscribeDataChanging(this);
902 this._subscribing = true;
903 }
904 },
905 beforeDestroy() {
906 const options = this.$options; // eslint-disable-line @typescript-eslint/no-explicit-any
907 if (options.__VUE18N__INSTANCE__) {
908 return;
909 }
910 if (this._i18nBridgeRoot) {
911 delete this._i18nBridgeRoot;
912 return;
913 }
914 if (i18n.mode === 'composition') {
915 delete this._i18n;
916 return;
917 }
918 if (!this._i18n) {
919 return;
920 }
921 const self = this; // eslint-disable-line @typescript-eslint/no-explicit-any
922 this.$nextTick(() => {
923 if (self._subscribing) {
924 self._i18n.unsubscribeDataChanging(self);
925 delete self._subscribing;
926 }
927 if (self._i18nWatcher) {
928 self._i18nWatcher();
929 self._i18n.destroyVM();
930 delete self._i18nWatcher;
931 }
932 if (self._localeWatcher) {
933 self._localeWatcher();
934 delete self._localeWatcher;
935 }
936 });
937 }
938 };
939}
940
941// for bridge
942let _legacyVueI18n = null; // eslint-disable-line @typescript-eslint/no-explicit-any
943let _legacyI18n = null; // eslint-disable-line @typescript-eslint/no-explicit-any
944/**
945 * Injection key for {@link useI18n}
946 *
947 * @remarks
948 * The global injection key for I18n instances with `useI18n`. this injection key is used in Web Components.
949 * Specify the i18n instance created by {@link createI18n} together with `provide` function.
950 *
951 * @VueI18nGeneral
952 */
953const I18nInjectionKey =
954/* #__PURE__*/ makeSymbol('global-vue-i18n');
955// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
956function createI18n(options = {}, VueI18nLegacy) {
957 if (_legacyI18n) {
958 (process.env.NODE_ENV !== 'production') &&
959 warn(getWarnMessage(I18nWarnCodes.NOT_SUPPORT_MULTI_I18N_INSTANCE));
960 return _legacyI18n;
961 }
962 {
963 _legacyVueI18n = VueI18nLegacy;
964 }
965 // prettier-ignore
966 const __legacyMode = __VUE_I18N_LEGACY_API__ && isBoolean(options.legacy)
967 ? options.legacy
968 : __VUE_I18N_LEGACY_API__;
969 !!options.globalInjection;
970 const __instances = new Map();
971 const __global = createGlobal(options, __legacyMode, VueI18nLegacy);
972 makeSymbol((process.env.NODE_ENV !== 'production') ? 'vue-i18n' : '');
973 function __getInstance(component) {
974 return __instances.get(component) || null;
975 }
976 function __setInstance(component, instance) {
977 __instances.set(component, instance);
978 }
979 function __deleteInstance(component) {
980 __instances.delete(component);
981 }
982 {
983 // extend legacy VueI18n instance
984 const i18n = __global[LegacyInstanceSymbol]; // eslint-disable-line @typescript-eslint/no-explicit-any
985 Object.defineProperty(i18n, 'global', {
986 get() {
987 return __global;
988 }
989 });
990 Object.defineProperty(i18n, 'mode', {
991 get() {
992 return __legacyMode ? 'legacy' : 'composition';
993 }
994 });
995 Object.defineProperty(i18n, '__instances', {
996 get() {
997 return __instances;
998 }
999 });
1000 Object.defineProperty(i18n, 'install', {
1001 // eslint-disable-next-line @typescript-eslint/no-explicit-any
1002 value: (Vue) => {
1003 const version = (Vue && Vue.version && Number(Vue.version.split('.')[0])) || -1;
1004 if (version !== 2) {
1005 throw createI18nError(I18nErrorCodes.BRIDGE_SUPPORT_VUE_2_ONLY);
1006 }
1007 Vue.mixin(defineMixin(i18n, _legacyVueI18n));
1008 }
1009 });
1010 const methodMap = {
1011 __getInstance,
1012 __setInstance,
1013 __deleteInstance
1014 };
1015 Object.keys(methodMap).forEach(key => Object.defineProperty(i18n, key, { value: methodMap[key] }) // eslint-disable-line @typescript-eslint/no-explicit-any
1016 );
1017 _legacyI18n = i18n;
1018 return i18n;
1019 }
1020}
1021// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
1022function useI18n(options = {}) {
1023 const instance = getCurrentInstance();
1024 if (instance == null) {
1025 throw createI18nError(I18nErrorCodes.MUST_BE_CALL_SETUP_TOP);
1026 }
1027 {
1028 if (_legacyVueI18n == null || _legacyI18n == null) {
1029 throw createI18nError(I18nErrorCodes.NOT_INSLALLED);
1030 }
1031 }
1032 const i18n = getI18nInstance(instance);
1033 const global = getGlobalComposer(i18n);
1034 const componentOptions = getComponentOptions(instance);
1035 const scope = getScope(options, componentOptions);
1036 if (scope === 'global') {
1037 adjustI18nResources(global, options, componentOptions);
1038 return global;
1039 }
1040 if (scope === 'parent') {
1041 let composer = getComposer(i18n, instance);
1042 if (composer == null) {
1043 if ((process.env.NODE_ENV !== 'production')) {
1044 warn(getWarnMessage(I18nWarnCodes.NOT_FOUND_PARENT_SCOPE));
1045 }
1046 composer = global;
1047 }
1048 return composer;
1049 }
1050 // scope 'local' case
1051 if (i18n.mode === 'legacy') {
1052 throw createI18nError(I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE);
1053 }
1054 const i18nInternal = i18n;
1055 let composer = i18nInternal.__getInstance(instance);
1056 if (composer == null) {
1057 const composerOptions = assign({}, options);
1058 if ('__i18n' in componentOptions) {
1059 composerOptions.__i18n = componentOptions.__i18n;
1060 }
1061 if (global) {
1062 composerOptions.__root = global;
1063 }
1064 composer = createComposer(composerOptions, _legacyVueI18n);
1065 setupLifeCycle(i18nInternal, instance, composer);
1066 i18nInternal.__setInstance(instance, composer);
1067 }
1068 return composer;
1069}
1070function createGlobal(options, legacyMode, VueI18nLegacy // eslint-disable-line @typescript-eslint/no-explicit-any
1071) {
1072 {
1073 if (!isLegacyVueI18n(VueI18nLegacy)) {
1074 throw createI18nError(I18nErrorCodes.NOT_COMPATIBLE_LEGACY_VUE_I18N);
1075 }
1076 return createComposer(options, VueI18nLegacy);
1077 }
1078}
1079function getI18nInstance(instance) {
1080 {
1081 const vm = instance.proxy;
1082 /* istanbul ignore if */
1083 if (vm == null) {
1084 throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
1085 }
1086 const i18n = vm._i18nBridgeRoot; // eslint-disable-line @typescript-eslint/no-explicit-any
1087 /* istanbul ignore if */
1088 if (!i18n) {
1089 throw createI18nError(I18nErrorCodes.NOT_INSLALLED);
1090 }
1091 return i18n;
1092 }
1093}
1094// eslint-disable-next-line @typescript-eslint/no-explicit-any
1095function getComponentOptions(instance) {
1096 return instance.proxy.$options;
1097}
1098// eslint-disable-next-line @typescript-eslint/no-explicit-any
1099function getScope(options, componentOptions) {
1100 // prettier-ignore
1101 return isEmptyObject(options)
1102 ? ('__i18n' in componentOptions)
1103 ? 'local'
1104 : 'global'
1105 : !options.useScope
1106 ? 'local'
1107 : options.useScope;
1108}
1109function getGlobalComposer(i18n) {
1110 // prettier-ignore
1111 return i18n.global;
1112}
1113function adjustI18nResources(global, options, componentOptions // eslint-disable-line @typescript-eslint/no-explicit-any
1114) {
1115 let messages = isObject(options.messages) ? options.messages : {};
1116 if ('__i18nGlobal' in componentOptions) {
1117 messages = getLocaleMessages(global.locale.value, {
1118 messages,
1119 __i18n: componentOptions.__i18nGlobal
1120 });
1121 }
1122 // merge locale messages
1123 const locales = Object.keys(messages);
1124 if (locales.length) {
1125 locales.forEach(locale => {
1126 global.mergeLocaleMessage(locale, messages[locale]);
1127 });
1128 }
1129 {
1130 // merge datetime formats
1131 if (isObject(options.datetimeFormats)) {
1132 const locales = Object.keys(options.datetimeFormats);
1133 if (locales.length) {
1134 locales.forEach(locale => {
1135 global.mergeDateTimeFormat(locale, options.datetimeFormats[locale]);
1136 });
1137 }
1138 }
1139 // merge number formats
1140 if (isObject(options.numberFormats)) {
1141 const locales = Object.keys(options.numberFormats);
1142 if (locales.length) {
1143 locales.forEach(locale => {
1144 global.mergeNumberFormat(locale, options.numberFormats[locale]);
1145 });
1146 }
1147 }
1148 }
1149}
1150function getComposer(i18n, target) {
1151 let composer = null;
1152 const root = target.root;
1153 let current = target.parent;
1154 while (current != null) {
1155 const i18nInternal = i18n;
1156 if (i18n.mode === 'composition') {
1157 composer = i18nInternal.__getInstance(current);
1158 }
1159 else {
1160 if (__VUE_I18N_LEGACY_API__) {
1161 const vueI18n = i18nInternal.__getInstance(current);
1162 if (vueI18n != null) {
1163 composer = vueI18n
1164 .__composer;
1165 }
1166 }
1167 }
1168 if (composer != null) {
1169 break;
1170 }
1171 if (root === current) {
1172 break;
1173 }
1174 current = current.parent;
1175 }
1176 return composer;
1177}
1178function setupLifeCycle(i18n, target, composer) {
1179 {
1180 // assign legacy VueI18n instance to Vue2 instance
1181 // eslint-disable-next-line @typescript-eslint/no-explicit-any
1182 const vm = target.proxy;
1183 if (vm == null) {
1184 throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
1185 }
1186 // eslint-disable-next-line @typescript-eslint/no-explicit-any
1187 const _i18n = composer[LegacyInstanceSymbol];
1188 if (_i18n === i18n) {
1189 throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
1190 }
1191 vm._i18n = _i18n;
1192 vm._i18n_bridge = true;
1193 vm._i18nWatcher = vm._i18n.watchI18nData();
1194 if (vm._i18n._sync) {
1195 vm._localeWatcher = vm._i18n.watchLocale();
1196 }
1197 let subscribing = false;
1198 onBeforeMount(() => {
1199 vm._i18n.subscribeDataChanging(vm);
1200 subscribing = true;
1201 }, target);
1202 onUnmounted(() => {
1203 if (subscribing) {
1204 vm._i18n.unsubscribeDataChanging(vm);
1205 subscribing = false;
1206 }
1207 if (vm._i18nWatcher) {
1208 vm._i18nWatcher();
1209 vm._i18n.destroyVM();
1210 delete vm._i18nWatcher;
1211 }
1212 if (vm._localeWatcher) {
1213 vm._localeWatcher();
1214 delete vm._localeWatcher;
1215 }
1216 delete vm._i18n_bridge;
1217 delete vm._i18n;
1218 }, target);
1219 }
1220}
1221
1222// register message compiler at vue-i18n
1223registerMessageCompiler(compileToFunction);
1224// register message resolver at vue-i18n
1225registerMessageResolver(resolveValue);
1226// register fallback locale at vue-i18n
1227registerLocaleFallbacker(fallbackWithLocaleChain);
1228{
1229 initFeatureFlags();
1230}
1231// NOTE: experimental !!
1232if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
1233 const target = getGlobalThis();
1234 target.__INTLIFY__ = true;
1235 setDevToolsHook(target.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__);
1236}
1237if ((process.env.NODE_ENV !== 'production')) ;
1238
1239export { I18nInjectionKey, VERSION, createI18n, useI18n };