UNPKG

56.9 kBJavaScriptView Raw
1/*!
2 * vue-i18n v8.15.1
3 * (c) 2019 kazuya kawaguchi
4 * Released under the MIT License.
5 */
6(function (global, factory) {
7 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8 typeof define === 'function' && define.amd ? define(factory) :
9 (global.VueI18n = factory());
10}(this, (function () { 'use strict';
11
12 /* */
13
14 /**
15 * constants
16 */
17
18 var numberFormatKeys = [
19 'style',
20 'currency',
21 'currencyDisplay',
22 'useGrouping',
23 'minimumIntegerDigits',
24 'minimumFractionDigits',
25 'maximumFractionDigits',
26 'minimumSignificantDigits',
27 'maximumSignificantDigits',
28 'localeMatcher',
29 'formatMatcher'
30 ];
31
32 /**
33 * utilities
34 */
35
36 function warn (msg, err) {
37 if (typeof console !== 'undefined') {
38 console.warn('[vue-i18n] ' + msg);
39 /* istanbul ignore if */
40 if (err) {
41 console.warn(err.stack);
42 }
43 }
44 }
45
46 function error (msg, err) {
47 if (typeof console !== 'undefined') {
48 console.error('[vue-i18n] ' + msg);
49 /* istanbul ignore if */
50 if (err) {
51 console.error(err.stack);
52 }
53 }
54 }
55
56 function isObject (obj) {
57 return obj !== null && typeof obj === 'object'
58 }
59
60 var toString = Object.prototype.toString;
61 var OBJECT_STRING = '[object Object]';
62 function isPlainObject (obj) {
63 return toString.call(obj) === OBJECT_STRING
64 }
65
66 function isNull (val) {
67 return val === null || val === undefined
68 }
69
70 function parseArgs () {
71 var args = [], len = arguments.length;
72 while ( len-- ) args[ len ] = arguments[ len ];
73
74 var locale = null;
75 var params = null;
76 if (args.length === 1) {
77 if (isObject(args[0]) || Array.isArray(args[0])) {
78 params = args[0];
79 } else if (typeof args[0] === 'string') {
80 locale = args[0];
81 }
82 } else if (args.length === 2) {
83 if (typeof args[0] === 'string') {
84 locale = args[0];
85 }
86 /* istanbul ignore if */
87 if (isObject(args[1]) || Array.isArray(args[1])) {
88 params = args[1];
89 }
90 }
91
92 return { locale: locale, params: params }
93 }
94
95 function looseClone (obj) {
96 return JSON.parse(JSON.stringify(obj))
97 }
98
99 function remove (arr, item) {
100 if (arr.length) {
101 var index = arr.indexOf(item);
102 if (index > -1) {
103 return arr.splice(index, 1)
104 }
105 }
106 }
107
108 var hasOwnProperty = Object.prototype.hasOwnProperty;
109 function hasOwn (obj, key) {
110 return hasOwnProperty.call(obj, key)
111 }
112
113 function merge (target) {
114 var arguments$1 = arguments;
115
116 var output = Object(target);
117 for (var i = 1; i < arguments.length; i++) {
118 var source = arguments$1[i];
119 if (source !== undefined && source !== null) {
120 var key = (void 0);
121 for (key in source) {
122 if (hasOwn(source, key)) {
123 if (isObject(source[key])) {
124 output[key] = merge(output[key], source[key]);
125 } else {
126 output[key] = source[key];
127 }
128 }
129 }
130 }
131 }
132 return output
133 }
134
135 function looseEqual (a, b) {
136 if (a === b) { return true }
137 var isObjectA = isObject(a);
138 var isObjectB = isObject(b);
139 if (isObjectA && isObjectB) {
140 try {
141 var isArrayA = Array.isArray(a);
142 var isArrayB = Array.isArray(b);
143 if (isArrayA && isArrayB) {
144 return a.length === b.length && a.every(function (e, i) {
145 return looseEqual(e, b[i])
146 })
147 } else if (!isArrayA && !isArrayB) {
148 var keysA = Object.keys(a);
149 var keysB = Object.keys(b);
150 return keysA.length === keysB.length && keysA.every(function (key) {
151 return looseEqual(a[key], b[key])
152 })
153 } else {
154 /* istanbul ignore next */
155 return false
156 }
157 } catch (e) {
158 /* istanbul ignore next */
159 return false
160 }
161 } else if (!isObjectA && !isObjectB) {
162 return String(a) === String(b)
163 } else {
164 return false
165 }
166 }
167
168 /* */
169
170 function extend (Vue) {
171 if (!Vue.prototype.hasOwnProperty('$i18n')) {
172 // $FlowFixMe
173 Object.defineProperty(Vue.prototype, '$i18n', {
174 get: function get () { return this._i18n }
175 });
176 }
177
178 Vue.prototype.$t = function (key) {
179 var values = [], len = arguments.length - 1;
180 while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
181
182 var i18n = this.$i18n;
183 return i18n._t.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this ].concat( values ))
184 };
185
186 Vue.prototype.$tc = function (key, choice) {
187 var values = [], len = arguments.length - 2;
188 while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
189
190 var i18n = this.$i18n;
191 return i18n._tc.apply(i18n, [ key, i18n.locale, i18n._getMessages(), this, choice ].concat( values ))
192 };
193
194 Vue.prototype.$te = function (key, locale) {
195 var i18n = this.$i18n;
196 return i18n._te(key, i18n.locale, i18n._getMessages(), locale)
197 };
198
199 Vue.prototype.$d = function (value) {
200 var ref;
201
202 var args = [], len = arguments.length - 1;
203 while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
204 return (ref = this.$i18n).d.apply(ref, [ value ].concat( args ))
205 };
206
207 Vue.prototype.$n = function (value) {
208 var ref;
209
210 var args = [], len = arguments.length - 1;
211 while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
212 return (ref = this.$i18n).n.apply(ref, [ value ].concat( args ))
213 };
214 }
215
216 /* */
217
218 var mixin = {
219 beforeCreate: function beforeCreate () {
220 var options = this.$options;
221 options.i18n = options.i18n || (options.__i18n ? {} : null);
222
223 if (options.i18n) {
224 if (options.i18n instanceof VueI18n) {
225 // init locale messages via custom blocks
226 if (options.__i18n) {
227 try {
228 var localeMessages = {};
229 options.__i18n.forEach(function (resource) {
230 localeMessages = merge(localeMessages, JSON.parse(resource));
231 });
232 Object.keys(localeMessages).forEach(function (locale) {
233 options.i18n.mergeLocaleMessage(locale, localeMessages[locale]);
234 });
235 } catch (e) {
236 {
237 error("Cannot parse locale messages via custom blocks.", e);
238 }
239 }
240 }
241 this._i18n = options.i18n;
242 this._i18nWatcher = this._i18n.watchI18nData();
243 } else if (isPlainObject(options.i18n)) {
244 // component local i18n
245 if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
246 options.i18n.root = this.$root;
247 options.i18n.formatter = this.$root.$i18n.formatter;
248 options.i18n.fallbackLocale = this.$root.$i18n.fallbackLocale;
249 options.i18n.formatFallbackMessages = this.$root.$i18n.formatFallbackMessages;
250 options.i18n.silentTranslationWarn = this.$root.$i18n.silentTranslationWarn;
251 options.i18n.silentFallbackWarn = this.$root.$i18n.silentFallbackWarn;
252 options.i18n.pluralizationRules = this.$root.$i18n.pluralizationRules;
253 options.i18n.preserveDirectiveContent = this.$root.$i18n.preserveDirectiveContent;
254 }
255
256 // init locale messages via custom blocks
257 if (options.__i18n) {
258 try {
259 var localeMessages$1 = {};
260 options.__i18n.forEach(function (resource) {
261 localeMessages$1 = merge(localeMessages$1, JSON.parse(resource));
262 });
263 options.i18n.messages = localeMessages$1;
264 } catch (e) {
265 {
266 warn("Cannot parse locale messages via custom blocks.", e);
267 }
268 }
269 }
270
271 var ref = options.i18n;
272 var sharedMessages = ref.sharedMessages;
273 if (sharedMessages && isPlainObject(sharedMessages)) {
274 options.i18n.messages = merge(options.i18n.messages, sharedMessages);
275 }
276
277 this._i18n = new VueI18n(options.i18n);
278 this._i18nWatcher = this._i18n.watchI18nData();
279
280 if (options.i18n.sync === undefined || !!options.i18n.sync) {
281 this._localeWatcher = this.$i18n.watchLocale();
282 }
283 } else {
284 {
285 warn("Cannot be interpreted 'i18n' option.");
286 }
287 }
288 } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
289 // root i18n
290 this._i18n = this.$root.$i18n;
291 } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
292 // parent i18n
293 this._i18n = options.parent.$i18n;
294 }
295 },
296
297 beforeMount: function beforeMount () {
298 var options = this.$options;
299 options.i18n = options.i18n || (options.__i18n ? {} : null);
300
301 if (options.i18n) {
302 if (options.i18n instanceof VueI18n) {
303 // init locale messages via custom blocks
304 this._i18n.subscribeDataChanging(this);
305 this._subscribing = true;
306 } else if (isPlainObject(options.i18n)) {
307 this._i18n.subscribeDataChanging(this);
308 this._subscribing = true;
309 } else {
310 {
311 warn("Cannot be interpreted 'i18n' option.");
312 }
313 }
314 } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
315 this._i18n.subscribeDataChanging(this);
316 this._subscribing = true;
317 } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
318 this._i18n.subscribeDataChanging(this);
319 this._subscribing = true;
320 }
321 },
322
323 beforeDestroy: function beforeDestroy () {
324 if (!this._i18n) { return }
325
326 var self = this;
327 this.$nextTick(function () {
328 if (self._subscribing) {
329 self._i18n.unsubscribeDataChanging(self);
330 delete self._subscribing;
331 }
332
333 if (self._i18nWatcher) {
334 self._i18nWatcher();
335 self._i18n.destroyVM();
336 delete self._i18nWatcher;
337 }
338
339 if (self._localeWatcher) {
340 self._localeWatcher();
341 delete self._localeWatcher;
342 }
343
344 self._i18n = null;
345 });
346 }
347 };
348
349 /* */
350
351 var interpolationComponent = {
352 name: 'i18n',
353 functional: true,
354 props: {
355 tag: {
356 type: String
357 },
358 path: {
359 type: String,
360 required: true
361 },
362 locale: {
363 type: String
364 },
365 places: {
366 type: [Array, Object]
367 }
368 },
369 render: function render (h, ref) {
370 var data = ref.data;
371 var parent = ref.parent;
372 var props = ref.props;
373 var slots = ref.slots;
374
375 var $i18n = parent.$i18n;
376 if (!$i18n) {
377 {
378 warn('Cannot find VueI18n instance!');
379 }
380 return
381 }
382
383 var path = props.path;
384 var locale = props.locale;
385 var places = props.places;
386 var params = slots();
387 var children = $i18n.i(
388 path,
389 locale,
390 onlyHasDefaultPlace(params) || places
391 ? useLegacyPlaces(params.default, places)
392 : params
393 );
394
395 var tag = props.tag || 'span';
396 return tag ? h(tag, data, children) : children
397 }
398 };
399
400 function onlyHasDefaultPlace (params) {
401 var prop;
402 for (prop in params) {
403 if (prop !== 'default') { return false }
404 }
405 return Boolean(prop)
406 }
407
408 function useLegacyPlaces (children, places) {
409 var params = places ? createParamsFromPlaces(places) : {};
410
411 if (!children) { return params }
412
413 // Filter empty text nodes
414 children = children.filter(function (child) {
415 return child.tag || child.text.trim() !== ''
416 });
417
418 var everyPlace = children.every(vnodeHasPlaceAttribute);
419 if (everyPlace) {
420 warn('`place` attribute is deprecated in next major version. Please switch to Vue slots.');
421 }
422
423 return children.reduce(
424 everyPlace ? assignChildPlace : assignChildIndex,
425 params
426 )
427 }
428
429 function createParamsFromPlaces (places) {
430 {
431 warn('`places` prop is deprecated in next major version. Please switch to Vue slots.');
432 }
433
434 return Array.isArray(places)
435 ? places.reduce(assignChildIndex, {})
436 : Object.assign({}, places)
437 }
438
439 function assignChildPlace (params, child) {
440 if (child.data && child.data.attrs && child.data.attrs.place) {
441 params[child.data.attrs.place] = child;
442 }
443 return params
444 }
445
446 function assignChildIndex (params, child, index) {
447 params[index] = child;
448 return params
449 }
450
451 function vnodeHasPlaceAttribute (vnode) {
452 return Boolean(vnode.data && vnode.data.attrs && vnode.data.attrs.place)
453 }
454
455 /* */
456
457 var numberComponent = {
458 name: 'i18n-n',
459 functional: true,
460 props: {
461 tag: {
462 type: String,
463 default: 'span'
464 },
465 value: {
466 type: Number,
467 required: true
468 },
469 format: {
470 type: [String, Object]
471 },
472 locale: {
473 type: String
474 }
475 },
476 render: function render (h, ref) {
477 var props = ref.props;
478 var parent = ref.parent;
479 var data = ref.data;
480
481 var i18n = parent.$i18n;
482
483 if (!i18n) {
484 {
485 warn('Cannot find VueI18n instance!');
486 }
487 return null
488 }
489
490 var key = null;
491 var options = null;
492
493 if (typeof props.format === 'string') {
494 key = props.format;
495 } else if (isObject(props.format)) {
496 if (props.format.key) {
497 key = props.format.key;
498 }
499
500 // Filter out number format options only
501 options = Object.keys(props.format).reduce(function (acc, prop) {
502 var obj;
503
504 if (numberFormatKeys.includes(prop)) {
505 return Object.assign({}, acc, ( obj = {}, obj[prop] = props.format[prop], obj ))
506 }
507 return acc
508 }, null);
509 }
510
511 var locale = props.locale || i18n.locale;
512 var parts = i18n._ntp(props.value, locale, key, options);
513
514 var values = parts.map(function (part, index) {
515 var obj;
516
517 var slot = data.scopedSlots && data.scopedSlots[part.type];
518 return slot ? slot(( obj = {}, obj[part.type] = part.value, obj.index = index, obj.parts = parts, obj )) : part.value
519 });
520
521 return h(props.tag, {
522 attrs: data.attrs,
523 'class': data['class'],
524 staticClass: data.staticClass
525 }, values)
526 }
527 };
528
529 /* */
530
531 function bind (el, binding, vnode) {
532 if (!assert(el, vnode)) { return }
533
534 t(el, binding, vnode);
535 }
536
537 function update (el, binding, vnode, oldVNode) {
538 if (!assert(el, vnode)) { return }
539
540 var i18n = vnode.context.$i18n;
541 if (localeEqual(el, vnode) &&
542 (looseEqual(binding.value, binding.oldValue) &&
543 looseEqual(el._localeMessage, i18n.getLocaleMessage(i18n.locale)))) { return }
544
545 t(el, binding, vnode);
546 }
547
548 function unbind (el, binding, vnode, oldVNode) {
549 var vm = vnode.context;
550 if (!vm) {
551 warn('Vue instance does not exists in VNode context');
552 return
553 }
554
555 var i18n = vnode.context.$i18n || {};
556 if (!binding.modifiers.preserve && !i18n.preserveDirectiveContent) {
557 el.textContent = '';
558 }
559 el._vt = undefined;
560 delete el['_vt'];
561 el._locale = undefined;
562 delete el['_locale'];
563 el._localeMessage = undefined;
564 delete el['_localeMessage'];
565 }
566
567 function assert (el, vnode) {
568 var vm = vnode.context;
569 if (!vm) {
570 warn('Vue instance does not exists in VNode context');
571 return false
572 }
573
574 if (!vm.$i18n) {
575 warn('VueI18n instance does not exists in Vue instance');
576 return false
577 }
578
579 return true
580 }
581
582 function localeEqual (el, vnode) {
583 var vm = vnode.context;
584 return el._locale === vm.$i18n.locale
585 }
586
587 function t (el, binding, vnode) {
588 var ref$1, ref$2;
589
590 var value = binding.value;
591
592 var ref = parseValue(value);
593 var path = ref.path;
594 var locale = ref.locale;
595 var args = ref.args;
596 var choice = ref.choice;
597 if (!path && !locale && !args) {
598 warn('value type not supported');
599 return
600 }
601
602 if (!path) {
603 warn('`path` is required in v-t directive');
604 return
605 }
606
607 var vm = vnode.context;
608 if (choice) {
609 el._vt = el.textContent = (ref$1 = vm.$i18n).tc.apply(ref$1, [ path, choice ].concat( makeParams(locale, args) ));
610 } else {
611 el._vt = el.textContent = (ref$2 = vm.$i18n).t.apply(ref$2, [ path ].concat( makeParams(locale, args) ));
612 }
613 el._locale = vm.$i18n.locale;
614 el._localeMessage = vm.$i18n.getLocaleMessage(vm.$i18n.locale);
615 }
616
617 function parseValue (value) {
618 var path;
619 var locale;
620 var args;
621 var choice;
622
623 if (typeof value === 'string') {
624 path = value;
625 } else if (isPlainObject(value)) {
626 path = value.path;
627 locale = value.locale;
628 args = value.args;
629 choice = value.choice;
630 }
631
632 return { path: path, locale: locale, args: args, choice: choice }
633 }
634
635 function makeParams (locale, args) {
636 var params = [];
637
638 locale && params.push(locale);
639 if (args && (Array.isArray(args) || isPlainObject(args))) {
640 params.push(args);
641 }
642
643 return params
644 }
645
646 var Vue;
647
648 function install (_Vue) {
649 /* istanbul ignore if */
650 if (install.installed && _Vue === Vue) {
651 warn('already installed.');
652 return
653 }
654 install.installed = true;
655
656 Vue = _Vue;
657
658 var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1;
659 /* istanbul ignore if */
660 if (version < 2) {
661 warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ")."));
662 return
663 }
664
665 extend(Vue);
666 Vue.mixin(mixin);
667 Vue.directive('t', { bind: bind, update: update, unbind: unbind });
668 Vue.component(interpolationComponent.name, interpolationComponent);
669 Vue.component(numberComponent.name, numberComponent);
670
671 // use simple mergeStrategies to prevent i18n instance lose '__proto__'
672 var strats = Vue.config.optionMergeStrategies;
673 strats.i18n = function (parentVal, childVal) {
674 return childVal === undefined
675 ? parentVal
676 : childVal
677 };
678 }
679
680 /* */
681
682 var BaseFormatter = function BaseFormatter () {
683 this._caches = Object.create(null);
684 };
685
686 BaseFormatter.prototype.interpolate = function interpolate (message, values) {
687 if (!values) {
688 return [message]
689 }
690 var tokens = this._caches[message];
691 if (!tokens) {
692 tokens = parse(message);
693 this._caches[message] = tokens;
694 }
695 return compile(tokens, values)
696 };
697
698
699
700 var RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
701 var RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
702
703 function parse (format) {
704 var tokens = [];
705 var position = 0;
706
707 var text = '';
708 while (position < format.length) {
709 var char = format[position++];
710 if (char === '{') {
711 if (text) {
712 tokens.push({ type: 'text', value: text });
713 }
714
715 text = '';
716 var sub = '';
717 char = format[position++];
718 while (char !== undefined && char !== '}') {
719 sub += char;
720 char = format[position++];
721 }
722 var isClosed = char === '}';
723
724 var type = RE_TOKEN_LIST_VALUE.test(sub)
725 ? 'list'
726 : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
727 ? 'named'
728 : 'unknown';
729 tokens.push({ value: sub, type: type });
730 } else if (char === '%') {
731 // when found rails i18n syntax, skip text capture
732 if (format[(position)] !== '{') {
733 text += char;
734 }
735 } else {
736 text += char;
737 }
738 }
739
740 text && tokens.push({ type: 'text', value: text });
741
742 return tokens
743 }
744
745 function compile (tokens, values) {
746 var compiled = [];
747 var index = 0;
748
749 var mode = Array.isArray(values)
750 ? 'list'
751 : isObject(values)
752 ? 'named'
753 : 'unknown';
754 if (mode === 'unknown') { return compiled }
755
756 while (index < tokens.length) {
757 var token = tokens[index];
758 switch (token.type) {
759 case 'text':
760 compiled.push(token.value);
761 break
762 case 'list':
763 compiled.push(values[parseInt(token.value, 10)]);
764 break
765 case 'named':
766 if (mode === 'named') {
767 compiled.push((values)[token.value]);
768 } else {
769 {
770 warn(("Type of token '" + (token.type) + "' and format of value '" + mode + "' don't match!"));
771 }
772 }
773 break
774 case 'unknown':
775 {
776 warn("Detect 'unknown' type of token!");
777 }
778 break
779 }
780 index++;
781 }
782
783 return compiled
784 }
785
786 /* */
787
788 /**
789 * Path parser
790 * - Inspired:
791 * Vue.js Path parser
792 */
793
794 // actions
795 var APPEND = 0;
796 var PUSH = 1;
797 var INC_SUB_PATH_DEPTH = 2;
798 var PUSH_SUB_PATH = 3;
799
800 // states
801 var BEFORE_PATH = 0;
802 var IN_PATH = 1;
803 var BEFORE_IDENT = 2;
804 var IN_IDENT = 3;
805 var IN_SUB_PATH = 4;
806 var IN_SINGLE_QUOTE = 5;
807 var IN_DOUBLE_QUOTE = 6;
808 var AFTER_PATH = 7;
809 var ERROR = 8;
810
811 var pathStateMachine = [];
812
813 pathStateMachine[BEFORE_PATH] = {
814 'ws': [BEFORE_PATH],
815 'ident': [IN_IDENT, APPEND],
816 '[': [IN_SUB_PATH],
817 'eof': [AFTER_PATH]
818 };
819
820 pathStateMachine[IN_PATH] = {
821 'ws': [IN_PATH],
822 '.': [BEFORE_IDENT],
823 '[': [IN_SUB_PATH],
824 'eof': [AFTER_PATH]
825 };
826
827 pathStateMachine[BEFORE_IDENT] = {
828 'ws': [BEFORE_IDENT],
829 'ident': [IN_IDENT, APPEND],
830 '0': [IN_IDENT, APPEND],
831 'number': [IN_IDENT, APPEND]
832 };
833
834 pathStateMachine[IN_IDENT] = {
835 'ident': [IN_IDENT, APPEND],
836 '0': [IN_IDENT, APPEND],
837 'number': [IN_IDENT, APPEND],
838 'ws': [IN_PATH, PUSH],
839 '.': [BEFORE_IDENT, PUSH],
840 '[': [IN_SUB_PATH, PUSH],
841 'eof': [AFTER_PATH, PUSH]
842 };
843
844 pathStateMachine[IN_SUB_PATH] = {
845 "'": [IN_SINGLE_QUOTE, APPEND],
846 '"': [IN_DOUBLE_QUOTE, APPEND],
847 '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH],
848 ']': [IN_PATH, PUSH_SUB_PATH],
849 'eof': ERROR,
850 'else': [IN_SUB_PATH, APPEND]
851 };
852
853 pathStateMachine[IN_SINGLE_QUOTE] = {
854 "'": [IN_SUB_PATH, APPEND],
855 'eof': ERROR,
856 'else': [IN_SINGLE_QUOTE, APPEND]
857 };
858
859 pathStateMachine[IN_DOUBLE_QUOTE] = {
860 '"': [IN_SUB_PATH, APPEND],
861 'eof': ERROR,
862 'else': [IN_DOUBLE_QUOTE, APPEND]
863 };
864
865 /**
866 * Check if an expression is a literal value.
867 */
868
869 var literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
870 function isLiteral (exp) {
871 return literalValueRE.test(exp)
872 }
873
874 /**
875 * Strip quotes from a string
876 */
877
878 function stripQuotes (str) {
879 var a = str.charCodeAt(0);
880 var b = str.charCodeAt(str.length - 1);
881 return a === b && (a === 0x22 || a === 0x27)
882 ? str.slice(1, -1)
883 : str
884 }
885
886 /**
887 * Determine the type of a character in a keypath.
888 */
889
890 function getPathCharType (ch) {
891 if (ch === undefined || ch === null) { return 'eof' }
892
893 var code = ch.charCodeAt(0);
894
895 switch (code) {
896 case 0x5B: // [
897 case 0x5D: // ]
898 case 0x2E: // .
899 case 0x22: // "
900 case 0x27: // '
901 return ch
902
903 case 0x5F: // _
904 case 0x24: // $
905 case 0x2D: // -
906 return 'ident'
907
908 case 0x09: // Tab
909 case 0x0A: // Newline
910 case 0x0D: // Return
911 case 0xA0: // No-break space
912 case 0xFEFF: // Byte Order Mark
913 case 0x2028: // Line Separator
914 case 0x2029: // Paragraph Separator
915 return 'ws'
916 }
917
918 return 'ident'
919 }
920
921 /**
922 * Format a subPath, return its plain form if it is
923 * a literal string or number. Otherwise prepend the
924 * dynamic indicator (*).
925 */
926
927 function formatSubPath (path) {
928 var trimmed = path.trim();
929 // invalid leading 0
930 if (path.charAt(0) === '0' && isNaN(path)) { return false }
931
932 return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed
933 }
934
935 /**
936 * Parse a string path into an array of segments
937 */
938
939 function parse$1 (path) {
940 var keys = [];
941 var index = -1;
942 var mode = BEFORE_PATH;
943 var subPathDepth = 0;
944 var c;
945 var key;
946 var newChar;
947 var type;
948 var transition;
949 var action;
950 var typeMap;
951 var actions = [];
952
953 actions[PUSH] = function () {
954 if (key !== undefined) {
955 keys.push(key);
956 key = undefined;
957 }
958 };
959
960 actions[APPEND] = function () {
961 if (key === undefined) {
962 key = newChar;
963 } else {
964 key += newChar;
965 }
966 };
967
968 actions[INC_SUB_PATH_DEPTH] = function () {
969 actions[APPEND]();
970 subPathDepth++;
971 };
972
973 actions[PUSH_SUB_PATH] = function () {
974 if (subPathDepth > 0) {
975 subPathDepth--;
976 mode = IN_SUB_PATH;
977 actions[APPEND]();
978 } else {
979 subPathDepth = 0;
980 if (key === undefined) { return false }
981 key = formatSubPath(key);
982 if (key === false) {
983 return false
984 } else {
985 actions[PUSH]();
986 }
987 }
988 };
989
990 function maybeUnescapeQuote () {
991 var nextChar = path[index + 1];
992 if ((mode === IN_SINGLE_QUOTE && nextChar === "'") ||
993 (mode === IN_DOUBLE_QUOTE && nextChar === '"')) {
994 index++;
995 newChar = '\\' + nextChar;
996 actions[APPEND]();
997 return true
998 }
999 }
1000
1001 while (mode !== null) {
1002 index++;
1003 c = path[index];
1004
1005 if (c === '\\' && maybeUnescapeQuote()) {
1006 continue
1007 }
1008
1009 type = getPathCharType(c);
1010 typeMap = pathStateMachine[mode];
1011 transition = typeMap[type] || typeMap['else'] || ERROR;
1012
1013 if (transition === ERROR) {
1014 return // parse error
1015 }
1016
1017 mode = transition[0];
1018 action = actions[transition[1]];
1019 if (action) {
1020 newChar = transition[2];
1021 newChar = newChar === undefined
1022 ? c
1023 : newChar;
1024 if (action() === false) {
1025 return
1026 }
1027 }
1028
1029 if (mode === AFTER_PATH) {
1030 return keys
1031 }
1032 }
1033 }
1034
1035
1036
1037
1038
1039 var I18nPath = function I18nPath () {
1040 this._cache = Object.create(null);
1041 };
1042
1043 /**
1044 * External parse that check for a cache hit first
1045 */
1046 I18nPath.prototype.parsePath = function parsePath (path) {
1047 var hit = this._cache[path];
1048 if (!hit) {
1049 hit = parse$1(path);
1050 if (hit) {
1051 this._cache[path] = hit;
1052 }
1053 }
1054 return hit || []
1055 };
1056
1057 /**
1058 * Get path value from path string
1059 */
1060 I18nPath.prototype.getPathValue = function getPathValue (obj, path) {
1061 if (!isObject(obj)) { return null }
1062
1063 var paths = this.parsePath(path);
1064 if (paths.length === 0) {
1065 return null
1066 } else {
1067 var length = paths.length;
1068 var last = obj;
1069 var i = 0;
1070 while (i < length) {
1071 var value = last[paths[i]];
1072 if (value === undefined) {
1073 return null
1074 }
1075 last = value;
1076 i++;
1077 }
1078
1079 return last
1080 }
1081 };
1082
1083 /* */
1084
1085
1086
1087 var htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/;
1088 var linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g;
1089 var linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/;
1090 var bracketsMatcher = /[()]/g;
1091 var defaultModifiers = {
1092 'upper': function (str) { return str.toLocaleUpperCase(); },
1093 'lower': function (str) { return str.toLocaleLowerCase(); }
1094 };
1095
1096 var defaultFormatter = new BaseFormatter();
1097
1098 var VueI18n = function VueI18n (options) {
1099 var this$1 = this;
1100 if ( options === void 0 ) options = {};
1101
1102 // Auto install if it is not done yet and `window` has `Vue`.
1103 // To allow users to avoid auto-installation in some cases,
1104 // this code should be placed here. See #290
1105 /* istanbul ignore if */
1106 if (!Vue && typeof window !== 'undefined' && window.Vue) {
1107 install(window.Vue);
1108 }
1109
1110 var locale = options.locale || 'en-US';
1111 var fallbackLocale = options.fallbackLocale || 'en-US';
1112 var messages = options.messages || {};
1113 var dateTimeFormats = options.dateTimeFormats || {};
1114 var numberFormats = options.numberFormats || {};
1115
1116 this._vm = null;
1117 this._formatter = options.formatter || defaultFormatter;
1118 this._modifiers = options.modifiers || {};
1119 this._missing = options.missing || null;
1120 this._root = options.root || null;
1121 this._sync = options.sync === undefined ? true : !!options.sync;
1122 this._fallbackRoot = options.fallbackRoot === undefined
1123 ? true
1124 : !!options.fallbackRoot;
1125 this._formatFallbackMessages = options.formatFallbackMessages === undefined
1126 ? false
1127 : !!options.formatFallbackMessages;
1128 this._silentTranslationWarn = options.silentTranslationWarn === undefined
1129 ? false
1130 : options.silentTranslationWarn;
1131 this._silentFallbackWarn = options.silentFallbackWarn === undefined
1132 ? false
1133 : !!options.silentFallbackWarn;
1134 this._dateTimeFormatters = {};
1135 this._numberFormatters = {};
1136 this._path = new I18nPath();
1137 this._dataListeners = [];
1138 this._preserveDirectiveContent = options.preserveDirectiveContent === undefined
1139 ? false
1140 : !!options.preserveDirectiveContent;
1141 this.pluralizationRules = options.pluralizationRules || {};
1142 this._warnHtmlInMessage = options.warnHtmlInMessage || 'off';
1143
1144 this._exist = function (message, key) {
1145 if (!message || !key) { return false }
1146 if (!isNull(this$1._path.getPathValue(message, key))) { return true }
1147 // fallback for flat key
1148 if (message[key]) { return true }
1149 return false
1150 };
1151
1152 if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
1153 Object.keys(messages).forEach(function (locale) {
1154 this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
1155 });
1156 }
1157
1158 this._initVM({
1159 locale: locale,
1160 fallbackLocale: fallbackLocale,
1161 messages: messages,
1162 dateTimeFormats: dateTimeFormats,
1163 numberFormats: numberFormats
1164 });
1165 };
1166
1167 var prototypeAccessors = { vm: { configurable: true },messages: { configurable: true },dateTimeFormats: { configurable: true },numberFormats: { configurable: true },availableLocales: { configurable: true },locale: { configurable: true },fallbackLocale: { configurable: true },formatFallbackMessages: { configurable: true },missing: { configurable: true },formatter: { configurable: true },silentTranslationWarn: { configurable: true },silentFallbackWarn: { configurable: true },preserveDirectiveContent: { configurable: true },warnHtmlInMessage: { configurable: true } };
1168
1169 VueI18n.prototype._checkLocaleMessage = function _checkLocaleMessage (locale, level, message) {
1170 var paths = [];
1171
1172 var fn = function (level, locale, message, paths) {
1173 if (isPlainObject(message)) {
1174 Object.keys(message).forEach(function (key) {
1175 var val = message[key];
1176 if (isPlainObject(val)) {
1177 paths.push(key);
1178 paths.push('.');
1179 fn(level, locale, val, paths);
1180 paths.pop();
1181 paths.pop();
1182 } else {
1183 paths.push(key);
1184 fn(level, locale, val, paths);
1185 paths.pop();
1186 }
1187 });
1188 } else if (Array.isArray(message)) {
1189 message.forEach(function (item, index) {
1190 if (isPlainObject(item)) {
1191 paths.push(("[" + index + "]"));
1192 paths.push('.');
1193 fn(level, locale, item, paths);
1194 paths.pop();
1195 paths.pop();
1196 } else {
1197 paths.push(("[" + index + "]"));
1198 fn(level, locale, item, paths);
1199 paths.pop();
1200 }
1201 });
1202 } else if (typeof message === 'string') {
1203 var ret = htmlTagMatcher.test(message);
1204 if (ret) {
1205 var msg = "Detected HTML in message '" + message + "' of keypath '" + (paths.join('')) + "' at '" + locale + "'. Consider component interpolation with '<i18n>' to avoid XSS. See https://bit.ly/2ZqJzkp";
1206 if (level === 'warn') {
1207 warn(msg);
1208 } else if (level === 'error') {
1209 error(msg);
1210 }
1211 }
1212 }
1213 };
1214
1215 fn(level, locale, message, paths);
1216 };
1217
1218 VueI18n.prototype._initVM = function _initVM (data) {
1219 var silent = Vue.config.silent;
1220 Vue.config.silent = true;
1221 this._vm = new Vue({ data: data });
1222 Vue.config.silent = silent;
1223 };
1224
1225 VueI18n.prototype.destroyVM = function destroyVM () {
1226 this._vm.$destroy();
1227 };
1228
1229 VueI18n.prototype.subscribeDataChanging = function subscribeDataChanging (vm) {
1230 this._dataListeners.push(vm);
1231 };
1232
1233 VueI18n.prototype.unsubscribeDataChanging = function unsubscribeDataChanging (vm) {
1234 remove(this._dataListeners, vm);
1235 };
1236
1237 VueI18n.prototype.watchI18nData = function watchI18nData () {
1238 var self = this;
1239 return this._vm.$watch('$data', function () {
1240 var i = self._dataListeners.length;
1241 while (i--) {
1242 Vue.nextTick(function () {
1243 self._dataListeners[i] && self._dataListeners[i].$forceUpdate();
1244 });
1245 }
1246 }, { deep: true })
1247 };
1248
1249 VueI18n.prototype.watchLocale = function watchLocale () {
1250 /* istanbul ignore if */
1251 if (!this._sync || !this._root) { return null }
1252 var target = this._vm;
1253 return this._root.$i18n.vm.$watch('locale', function (val) {
1254 target.$set(target, 'locale', val);
1255 target.$forceUpdate();
1256 }, { immediate: true })
1257 };
1258
1259 prototypeAccessors.vm.get = function () { return this._vm };
1260
1261 prototypeAccessors.messages.get = function () { return looseClone(this._getMessages()) };
1262 prototypeAccessors.dateTimeFormats.get = function () { return looseClone(this._getDateTimeFormats()) };
1263 prototypeAccessors.numberFormats.get = function () { return looseClone(this._getNumberFormats()) };
1264 prototypeAccessors.availableLocales.get = function () { return Object.keys(this.messages).sort() };
1265
1266 prototypeAccessors.locale.get = function () { return this._vm.locale };
1267 prototypeAccessors.locale.set = function (locale) {
1268 this._vm.$set(this._vm, 'locale', locale);
1269 };
1270
1271 prototypeAccessors.fallbackLocale.get = function () { return this._vm.fallbackLocale };
1272 prototypeAccessors.fallbackLocale.set = function (locale) {
1273 this._vm.$set(this._vm, 'fallbackLocale', locale);
1274 };
1275
1276 prototypeAccessors.formatFallbackMessages.get = function () { return this._formatFallbackMessages };
1277 prototypeAccessors.formatFallbackMessages.set = function (fallback) { this._formatFallbackMessages = fallback; };
1278
1279 prototypeAccessors.missing.get = function () { return this._missing };
1280 prototypeAccessors.missing.set = function (handler) { this._missing = handler; };
1281
1282 prototypeAccessors.formatter.get = function () { return this._formatter };
1283 prototypeAccessors.formatter.set = function (formatter) { this._formatter = formatter; };
1284
1285 prototypeAccessors.silentTranslationWarn.get = function () { return this._silentTranslationWarn };
1286 prototypeAccessors.silentTranslationWarn.set = function (silent) { this._silentTranslationWarn = silent; };
1287
1288 prototypeAccessors.silentFallbackWarn.get = function () { return this._silentFallbackWarn };
1289 prototypeAccessors.silentFallbackWarn.set = function (silent) { this._silentFallbackWarn = silent; };
1290
1291 prototypeAccessors.preserveDirectiveContent.get = function () { return this._preserveDirectiveContent };
1292 prototypeAccessors.preserveDirectiveContent.set = function (preserve) { this._preserveDirectiveContent = preserve; };
1293
1294 prototypeAccessors.warnHtmlInMessage.get = function () { return this._warnHtmlInMessage };
1295 prototypeAccessors.warnHtmlInMessage.set = function (level) {
1296 var this$1 = this;
1297
1298 var orgLevel = this._warnHtmlInMessage;
1299 this._warnHtmlInMessage = level;
1300 if (orgLevel !== level && (level === 'warn' || level === 'error')) {
1301 var messages = this._getMessages();
1302 Object.keys(messages).forEach(function (locale) {
1303 this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
1304 });
1305 }
1306 };
1307
1308 VueI18n.prototype._getMessages = function _getMessages () { return this._vm.messages };
1309 VueI18n.prototype._getDateTimeFormats = function _getDateTimeFormats () { return this._vm.dateTimeFormats };
1310 VueI18n.prototype._getNumberFormats = function _getNumberFormats () { return this._vm.numberFormats };
1311
1312 VueI18n.prototype._warnDefault = function _warnDefault (locale, key, result, vm, values) {
1313 if (!isNull(result)) { return result }
1314 if (this._missing) {
1315 var missingRet = this._missing.apply(null, [locale, key, vm, values]);
1316 if (typeof missingRet === 'string') {
1317 return missingRet
1318 }
1319 } else {
1320 if (!this._isSilentTranslationWarn(key)) {
1321 warn(
1322 "Cannot translate the value of keypath '" + key + "'. " +
1323 'Use the value of keypath as default.'
1324 );
1325 }
1326 }
1327
1328 if (this._formatFallbackMessages) {
1329 var parsedArgs = parseArgs.apply(void 0, values);
1330 return this._render(key, 'string', parsedArgs.params, key)
1331 } else {
1332 return key
1333 }
1334 };
1335
1336 VueI18n.prototype._isFallbackRoot = function _isFallbackRoot (val) {
1337 return !val && !isNull(this._root) && this._fallbackRoot
1338 };
1339
1340 VueI18n.prototype._isSilentFallbackWarn = function _isSilentFallbackWarn (key) {
1341 return this._silentFallbackWarn instanceof RegExp
1342 ? this._silentFallbackWarn.test(key)
1343 : this._silentFallbackWarn
1344 };
1345
1346 VueI18n.prototype._isSilentFallback = function _isSilentFallback (locale, key) {
1347 return this._isSilentFallbackWarn(key) && (this._isFallbackRoot() || locale !== this.fallbackLocale)
1348 };
1349
1350 VueI18n.prototype._isSilentTranslationWarn = function _isSilentTranslationWarn (key) {
1351 return this._silentTranslationWarn instanceof RegExp
1352 ? this._silentTranslationWarn.test(key)
1353 : this._silentTranslationWarn
1354 };
1355
1356 VueI18n.prototype._interpolate = function _interpolate (
1357 locale,
1358 message,
1359 key,
1360 host,
1361 interpolateMode,
1362 values,
1363 visitedLinkStack
1364 ) {
1365 if (!message) { return null }
1366
1367 var pathRet = this._path.getPathValue(message, key);
1368 if (Array.isArray(pathRet) || isPlainObject(pathRet)) { return pathRet }
1369
1370 var ret;
1371 if (isNull(pathRet)) {
1372 /* istanbul ignore else */
1373 if (isPlainObject(message)) {
1374 ret = message[key];
1375 if (typeof ret !== 'string') {
1376 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
1377 warn(("Value of key '" + key + "' is not a string!"));
1378 }
1379 return null
1380 }
1381 } else {
1382 return null
1383 }
1384 } else {
1385 /* istanbul ignore else */
1386 if (typeof pathRet === 'string') {
1387 ret = pathRet;
1388 } else {
1389 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallback(locale, key)) {
1390 warn(("Value of key '" + key + "' is not a string!"));
1391 }
1392 return null
1393 }
1394 }
1395
1396 // Check for the existence of links within the translated string
1397 if (ret.indexOf('@:') >= 0 || ret.indexOf('@.') >= 0) {
1398 ret = this._link(locale, message, ret, host, 'raw', values, visitedLinkStack);
1399 }
1400
1401 return this._render(ret, interpolateMode, values, key)
1402 };
1403
1404 VueI18n.prototype._link = function _link (
1405 locale,
1406 message,
1407 str,
1408 host,
1409 interpolateMode,
1410 values,
1411 visitedLinkStack
1412 ) {
1413 var ret = str;
1414
1415 // Match all the links within the local
1416 // We are going to replace each of
1417 // them with its translation
1418 var matches = ret.match(linkKeyMatcher);
1419 for (var idx in matches) {
1420 // ie compatible: filter custom array
1421 // prototype method
1422 if (!matches.hasOwnProperty(idx)) {
1423 continue
1424 }
1425 var link = matches[idx];
1426 var linkKeyPrefixMatches = link.match(linkKeyPrefixMatcher);
1427 var linkPrefix = linkKeyPrefixMatches[0];
1428 var formatterName = linkKeyPrefixMatches[1];
1429
1430 // Remove the leading @:, @.case: and the brackets
1431 var linkPlaceholder = link.replace(linkPrefix, '').replace(bracketsMatcher, '');
1432
1433 if (visitedLinkStack.includes(linkPlaceholder)) {
1434 {
1435 warn(("Circular reference found. \"" + link + "\" is already visited in the chain of " + (visitedLinkStack.reverse().join(' <- '))));
1436 }
1437 return ret
1438 }
1439 visitedLinkStack.push(linkPlaceholder);
1440
1441 // Translate the link
1442 var translated = this._interpolate(
1443 locale, message, linkPlaceholder, host,
1444 interpolateMode === 'raw' ? 'string' : interpolateMode,
1445 interpolateMode === 'raw' ? undefined : values,
1446 visitedLinkStack
1447 );
1448
1449 if (this._isFallbackRoot(translated)) {
1450 if (!this._isSilentTranslationWarn(linkPlaceholder)) {
1451 warn(("Fall back to translate the link placeholder '" + linkPlaceholder + "' with root locale."));
1452 }
1453 /* istanbul ignore if */
1454 if (!this._root) { throw Error('unexpected error') }
1455 var root = this._root.$i18n;
1456 translated = root._translate(
1457 root._getMessages(), root.locale, root.fallbackLocale,
1458 linkPlaceholder, host, interpolateMode, values
1459 );
1460 }
1461 translated = this._warnDefault(
1462 locale, linkPlaceholder, translated, host,
1463 Array.isArray(values) ? values : [values]
1464 );
1465
1466 if (this._modifiers.hasOwnProperty(formatterName)) {
1467 translated = this._modifiers[formatterName](translated);
1468 } else if (defaultModifiers.hasOwnProperty(formatterName)) {
1469 translated = defaultModifiers[formatterName](translated);
1470 }
1471
1472 visitedLinkStack.pop();
1473
1474 // Replace the link with the translated
1475 ret = !translated ? ret : ret.replace(link, translated);
1476 }
1477
1478 return ret
1479 };
1480
1481 VueI18n.prototype._render = function _render (message, interpolateMode, values, path) {
1482 var ret = this._formatter.interpolate(message, values, path);
1483
1484 // If the custom formatter refuses to work - apply the default one
1485 if (!ret) {
1486 ret = defaultFormatter.interpolate(message, values, path);
1487 }
1488
1489 // if interpolateMode is **not** 'string' ('row'),
1490 // return the compiled data (e.g. ['foo', VNode, 'bar']) with formatter
1491 return interpolateMode === 'string' ? ret.join('') : ret
1492 };
1493
1494 VueI18n.prototype._translate = function _translate (
1495 messages,
1496 locale,
1497 fallback,
1498 key,
1499 host,
1500 interpolateMode,
1501 args
1502 ) {
1503 var res =
1504 this._interpolate(locale, messages[locale], key, host, interpolateMode, args, [key]);
1505 if (!isNull(res)) { return res }
1506
1507 res = this._interpolate(fallback, messages[fallback], key, host, interpolateMode, args, [key]);
1508 if (!isNull(res)) {
1509 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
1510 warn(("Fall back to translate the keypath '" + key + "' with '" + fallback + "' locale."));
1511 }
1512 return res
1513 } else {
1514 return null
1515 }
1516 };
1517
1518 VueI18n.prototype._t = function _t (key, _locale, messages, host) {
1519 var ref;
1520
1521 var values = [], len = arguments.length - 4;
1522 while ( len-- > 0 ) values[ len ] = arguments[ len + 4 ];
1523 if (!key) { return '' }
1524
1525 var parsedArgs = parseArgs.apply(void 0, values);
1526 var locale = parsedArgs.locale || _locale;
1527
1528 var ret = this._translate(
1529 messages, locale, this.fallbackLocale, key,
1530 host, 'string', parsedArgs.params
1531 );
1532 if (this._isFallbackRoot(ret)) {
1533 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
1534 warn(("Fall back to translate the keypath '" + key + "' with root locale."));
1535 }
1536 /* istanbul ignore if */
1537 if (!this._root) { throw Error('unexpected error') }
1538 return (ref = this._root).$t.apply(ref, [ key ].concat( values ))
1539 } else {
1540 return this._warnDefault(locale, key, ret, host, values)
1541 }
1542 };
1543
1544 VueI18n.prototype.t = function t (key) {
1545 var ref;
1546
1547 var values = [], len = arguments.length - 1;
1548 while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];
1549 return (ref = this)._t.apply(ref, [ key, this.locale, this._getMessages(), null ].concat( values ))
1550 };
1551
1552 VueI18n.prototype._i = function _i (key, locale, messages, host, values) {
1553 var ret =
1554 this._translate(messages, locale, this.fallbackLocale, key, host, 'raw', values);
1555 if (this._isFallbackRoot(ret)) {
1556 if (!this._isSilentTranslationWarn(key)) {
1557 warn(("Fall back to interpolate the keypath '" + key + "' with root locale."));
1558 }
1559 if (!this._root) { throw Error('unexpected error') }
1560 return this._root.$i18n.i(key, locale, values)
1561 } else {
1562 return this._warnDefault(locale, key, ret, host, [values])
1563 }
1564 };
1565
1566 VueI18n.prototype.i = function i (key, locale, values) {
1567 /* istanbul ignore if */
1568 if (!key) { return '' }
1569
1570 if (typeof locale !== 'string') {
1571 locale = this.locale;
1572 }
1573
1574 return this._i(key, locale, this._getMessages(), null, values)
1575 };
1576
1577 VueI18n.prototype._tc = function _tc (
1578 key,
1579 _locale,
1580 messages,
1581 host,
1582 choice
1583 ) {
1584 var ref;
1585
1586 var values = [], len = arguments.length - 5;
1587 while ( len-- > 0 ) values[ len ] = arguments[ len + 5 ];
1588 if (!key) { return '' }
1589 if (choice === undefined) {
1590 choice = 1;
1591 }
1592
1593 var predefined = { 'count': choice, 'n': choice };
1594 var parsedArgs = parseArgs.apply(void 0, values);
1595 parsedArgs.params = Object.assign(predefined, parsedArgs.params);
1596 values = parsedArgs.locale === null ? [parsedArgs.params] : [parsedArgs.locale, parsedArgs.params];
1597 return this.fetchChoice((ref = this)._t.apply(ref, [ key, _locale, messages, host ].concat( values )), choice)
1598 };
1599
1600 VueI18n.prototype.fetchChoice = function fetchChoice (message, choice) {
1601 /* istanbul ignore if */
1602 if (!message && typeof message !== 'string') { return null }
1603 var choices = message.split('|');
1604
1605 choice = this.getChoiceIndex(choice, choices.length);
1606 if (!choices[choice]) { return message }
1607 return choices[choice].trim()
1608 };
1609
1610 /**
1611 * @param choice {number} a choice index given by the input to $tc: `$tc('path.to.rule', choiceIndex)`
1612 * @param choicesLength {number} an overall amount of available choices
1613 * @returns a final choice index
1614 */
1615 VueI18n.prototype.getChoiceIndex = function getChoiceIndex (choice, choicesLength) {
1616 // Default (old) getChoiceIndex implementation - english-compatible
1617 var defaultImpl = function (_choice, _choicesLength) {
1618 _choice = Math.abs(_choice);
1619
1620 if (_choicesLength === 2) {
1621 return _choice
1622 ? _choice > 1
1623 ? 1
1624 : 0
1625 : 1
1626 }
1627
1628 return _choice ? Math.min(_choice, 2) : 0
1629 };
1630
1631 if (this.locale in this.pluralizationRules) {
1632 return this.pluralizationRules[this.locale].apply(this, [choice, choicesLength])
1633 } else {
1634 return defaultImpl(choice, choicesLength)
1635 }
1636 };
1637
1638 VueI18n.prototype.tc = function tc (key, choice) {
1639 var ref;
1640
1641 var values = [], len = arguments.length - 2;
1642 while ( len-- > 0 ) values[ len ] = arguments[ len + 2 ];
1643 return (ref = this)._tc.apply(ref, [ key, this.locale, this._getMessages(), null, choice ].concat( values ))
1644 };
1645
1646 VueI18n.prototype._te = function _te (key, locale, messages) {
1647 var args = [], len = arguments.length - 3;
1648 while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ];
1649
1650 var _locale = parseArgs.apply(void 0, args).locale || locale;
1651 return this._exist(messages[_locale], key)
1652 };
1653
1654 VueI18n.prototype.te = function te (key, locale) {
1655 return this._te(key, this.locale, this._getMessages(), locale)
1656 };
1657
1658 VueI18n.prototype.getLocaleMessage = function getLocaleMessage (locale) {
1659 return looseClone(this._vm.messages[locale] || {})
1660 };
1661
1662 VueI18n.prototype.setLocaleMessage = function setLocaleMessage (locale, message) {
1663 if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
1664 this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
1665 if (this._warnHtmlInMessage === 'error') { return }
1666 }
1667 this._vm.$set(this._vm.messages, locale, message);
1668 };
1669
1670 VueI18n.prototype.mergeLocaleMessage = function mergeLocaleMessage (locale, message) {
1671 if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
1672 this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
1673 if (this._warnHtmlInMessage === 'error') { return }
1674 }
1675 this._vm.$set(this._vm.messages, locale, merge(this._vm.messages[locale] || {}, message));
1676 };
1677
1678 VueI18n.prototype.getDateTimeFormat = function getDateTimeFormat (locale) {
1679 return looseClone(this._vm.dateTimeFormats[locale] || {})
1680 };
1681
1682 VueI18n.prototype.setDateTimeFormat = function setDateTimeFormat (locale, format) {
1683 this._vm.$set(this._vm.dateTimeFormats, locale, format);
1684 };
1685
1686 VueI18n.prototype.mergeDateTimeFormat = function mergeDateTimeFormat (locale, format) {
1687 this._vm.$set(this._vm.dateTimeFormats, locale, merge(this._vm.dateTimeFormats[locale] || {}, format));
1688 };
1689
1690 VueI18n.prototype._localizeDateTime = function _localizeDateTime (
1691 value,
1692 locale,
1693 fallback,
1694 dateTimeFormats,
1695 key
1696 ) {
1697 var _locale = locale;
1698 var formats = dateTimeFormats[_locale];
1699
1700 // fallback locale
1701 if (isNull(formats) || isNull(formats[key])) {
1702 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
1703 warn(("Fall back to '" + fallback + "' datetime formats from '" + locale + "' datetime formats."));
1704 }
1705 _locale = fallback;
1706 formats = dateTimeFormats[_locale];
1707 }
1708
1709 if (isNull(formats) || isNull(formats[key])) {
1710 return null
1711 } else {
1712 var format = formats[key];
1713 var id = _locale + "__" + key;
1714 var formatter = this._dateTimeFormatters[id];
1715 if (!formatter) {
1716 formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format);
1717 }
1718 return formatter.format(value)
1719 }
1720 };
1721
1722 VueI18n.prototype._d = function _d (value, locale, key) {
1723 /* istanbul ignore if */
1724 if (!VueI18n.availabilities.dateTimeFormat) {
1725 warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.');
1726 return ''
1727 }
1728
1729 if (!key) {
1730 return new Intl.DateTimeFormat(locale).format(value)
1731 }
1732
1733 var ret =
1734 this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key);
1735 if (this._isFallbackRoot(ret)) {
1736 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
1737 warn(("Fall back to datetime localization of root: key '" + key + "'."));
1738 }
1739 /* istanbul ignore if */
1740 if (!this._root) { throw Error('unexpected error') }
1741 return this._root.$i18n.d(value, key, locale)
1742 } else {
1743 return ret || ''
1744 }
1745 };
1746
1747 VueI18n.prototype.d = function d (value) {
1748 var args = [], len = arguments.length - 1;
1749 while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
1750
1751 var locale = this.locale;
1752 var key = null;
1753
1754 if (args.length === 1) {
1755 if (typeof args[0] === 'string') {
1756 key = args[0];
1757 } else if (isObject(args[0])) {
1758 if (args[0].locale) {
1759 locale = args[0].locale;
1760 }
1761 if (args[0].key) {
1762 key = args[0].key;
1763 }
1764 }
1765 } else if (args.length === 2) {
1766 if (typeof args[0] === 'string') {
1767 key = args[0];
1768 }
1769 if (typeof args[1] === 'string') {
1770 locale = args[1];
1771 }
1772 }
1773
1774 return this._d(value, locale, key)
1775 };
1776
1777 VueI18n.prototype.getNumberFormat = function getNumberFormat (locale) {
1778 return looseClone(this._vm.numberFormats[locale] || {})
1779 };
1780
1781 VueI18n.prototype.setNumberFormat = function setNumberFormat (locale, format) {
1782 this._vm.$set(this._vm.numberFormats, locale, format);
1783 };
1784
1785 VueI18n.prototype.mergeNumberFormat = function mergeNumberFormat (locale, format) {
1786 this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format));
1787 };
1788
1789 VueI18n.prototype._getNumberFormatter = function _getNumberFormatter (
1790 value,
1791 locale,
1792 fallback,
1793 numberFormats,
1794 key,
1795 options
1796 ) {
1797 var _locale = locale;
1798 var formats = numberFormats[_locale];
1799
1800 // fallback locale
1801 if (isNull(formats) || isNull(formats[key])) {
1802 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
1803 warn(("Fall back to '" + fallback + "' number formats from '" + locale + "' number formats."));
1804 }
1805 _locale = fallback;
1806 formats = numberFormats[_locale];
1807 }
1808
1809 if (isNull(formats) || isNull(formats[key])) {
1810 return null
1811 } else {
1812 var format = formats[key];
1813
1814 var formatter;
1815 if (options) {
1816 // If options specified - create one time number formatter
1817 formatter = new Intl.NumberFormat(_locale, Object.assign({}, format, options));
1818 } else {
1819 var id = _locale + "__" + key;
1820 formatter = this._numberFormatters[id];
1821 if (!formatter) {
1822 formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format);
1823 }
1824 }
1825 return formatter
1826 }
1827 };
1828
1829 VueI18n.prototype._n = function _n (value, locale, key, options) {
1830 /* istanbul ignore if */
1831 if (!VueI18n.availabilities.numberFormat) {
1832 {
1833 warn('Cannot format a Number value due to not supported Intl.NumberFormat.');
1834 }
1835 return ''
1836 }
1837
1838 if (!key) {
1839 var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
1840 return nf.format(value)
1841 }
1842
1843 var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
1844 var ret = formatter && formatter.format(value);
1845 if (this._isFallbackRoot(ret)) {
1846 if (!this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
1847 warn(("Fall back to number localization of root: key '" + key + "'."));
1848 }
1849 /* istanbul ignore if */
1850 if (!this._root) { throw Error('unexpected error') }
1851 return this._root.$i18n.n(value, Object.assign({}, { key: key, locale: locale }, options))
1852 } else {
1853 return ret || ''
1854 }
1855 };
1856
1857 VueI18n.prototype.n = function n (value) {
1858 var args = [], len = arguments.length - 1;
1859 while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
1860
1861 var locale = this.locale;
1862 var key = null;
1863 var options = null;
1864
1865 if (args.length === 1) {
1866 if (typeof args[0] === 'string') {
1867 key = args[0];
1868 } else if (isObject(args[0])) {
1869 if (args[0].locale) {
1870 locale = args[0].locale;
1871 }
1872 if (args[0].key) {
1873 key = args[0].key;
1874 }
1875
1876 // Filter out number format options only
1877 options = Object.keys(args[0]).reduce(function (acc, key) {
1878 var obj;
1879
1880 if (numberFormatKeys.includes(key)) {
1881 return Object.assign({}, acc, ( obj = {}, obj[key] = args[0][key], obj ))
1882 }
1883 return acc
1884 }, null);
1885 }
1886 } else if (args.length === 2) {
1887 if (typeof args[0] === 'string') {
1888 key = args[0];
1889 }
1890 if (typeof args[1] === 'string') {
1891 locale = args[1];
1892 }
1893 }
1894
1895 return this._n(value, locale, key, options)
1896 };
1897
1898 VueI18n.prototype._ntp = function _ntp (value, locale, key, options) {
1899 /* istanbul ignore if */
1900 if (!VueI18n.availabilities.numberFormat) {
1901 {
1902 warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.');
1903 }
1904 return []
1905 }
1906
1907 if (!key) {
1908 var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
1909 return nf.formatToParts(value)
1910 }
1911
1912 var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
1913 var ret = formatter && formatter.formatToParts(value);
1914 if (this._isFallbackRoot(ret)) {
1915 if (!this._isSilentTranslationWarn(key)) {
1916 warn(("Fall back to format number to parts of root: key '" + key + "' ."));
1917 }
1918 /* istanbul ignore if */
1919 if (!this._root) { throw Error('unexpected error') }
1920 return this._root.$i18n._ntp(value, locale, key, options)
1921 } else {
1922 return ret || []
1923 }
1924 };
1925
1926 Object.defineProperties( VueI18n.prototype, prototypeAccessors );
1927
1928 var availabilities;
1929 // $FlowFixMe
1930 Object.defineProperty(VueI18n, 'availabilities', {
1931 get: function get () {
1932 if (!availabilities) {
1933 var intlDefined = typeof Intl !== 'undefined';
1934 availabilities = {
1935 dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
1936 numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
1937 };
1938 }
1939
1940 return availabilities
1941 }
1942 });
1943
1944 VueI18n.install = install;
1945 VueI18n.version = '8.15.1';
1946
1947 return VueI18n;
1948
1949})));