UNPKG

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