UNPKG

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