vue-i18n 8.9.0 → 8.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,54 @@
1
+ <a name="8.11.2"></a>
2
+ ## [8.11.2](https://github.com/kazupon/vue-i18n/compare/v8.11.1...v8.11.2) (2019-04-30)
3
+
4
+
5
+ ### :bug: Bug Fixes
6
+
7
+ * bug(mixin): fix SSR memory leak by moving subscribeDataChanging calls into beforeMount ([#572](https://github.com/kazupon/vue-i18n/issues/572)) by [@Pindar](https://github.com/Pindar) ([32b5795](https://github.com/kazupon/vue-i18n/commit/32b5795)), closes [#572](https://github.com/kazupon/vue-i18n/issues/572)
8
+
9
+
10
+
11
+ <a name="8.11.1"></a>
12
+ ## [8.11.1](https://github.com/kazupon/vue-i18n/compare/v8.11.0...v8.11.1) (2019-04-26)
13
+
14
+
15
+ ### :bug: Bug Fixes
16
+
17
+ * fix ES Modules distribution ([bb631a1](https://github.com/kazupon/vue-i18n/commit/bb631a1))
18
+
19
+
20
+
21
+ <a name="8.11.0"></a>
22
+ # [8.11.0](https://github.com/kazupon/vue-i18n/compare/v8.10.0...v8.11.0) (2019-04-26)
23
+
24
+
25
+ ### :star: New Features
26
+
27
+ * ES modules for browser ([#561](https://github.com/kazupon/vue-i18n/issues/561)) ([c9b9adf](https://github.com/kazupon/vue-i18n/commit/c9b9adf)), closes [#561](https://github.com/kazupon/vue-i18n/issues/561)
28
+ * HTML locale message warning option ([#567](https://github.com/kazupon/vue-i18n/issues/567)) ([4aecf03](https://github.com/kazupon/vue-i18n/commit/4aecf03)), closes [#567](https://github.com/kazupon/vue-i18n/issues/567)
29
+
30
+
31
+
32
+ <a name="8.10.0"></a>
33
+ # [8.10.0](https://github.com/kazupon/vue-i18n/compare/v8.9.0...v8.10.0) (2019-03-28)
34
+
35
+
36
+ ### :star: New Features
37
+
38
+ * **number:** i18n-n functional component ([#541](https://github.com/kazupon/vue-i18n/issues/541)) by [@bponomarenko](https://github.com/bponomarenko) ([b33579d](https://github.com/kazupon/vue-i18n/commit/b33579d)), closes [#541](https://github.com/kazupon/vue-i18n/issues/541)
39
+ * **path:** Keypath should parse if sub path contains spaces. ([#533](https://github.com/kazupon/vue-i18n/issues/533)) by [@exoego](https://github.com/exoego) ([640daaf](https://github.com/kazupon/vue-i18n/commit/640daaf)), closes [#533](https://github.com/kazupon/vue-i18n/issues/533)
40
+
41
+
42
+ ### :zap: Improvements
43
+
44
+ * **number:** support data fall through in i18n-n ([#545](https://github.com/kazupon/vue-i18n/issues/545)) ([71cadbf](https://github.com/kazupon/vue-i18n/commit/71cadbf)), closes [#545](https://github.com/kazupon/vue-i18n/issues/545)
45
+
46
+
47
+ ### :pencil: docs
48
+
49
+ * **vuepress:** translate documents for chinese ([#536](https://github.com/kazupon/vue-i18n/issues/536)) by [@xuhongbo](https://github.com/xuhongbo) ([ccf29f8](https://github.com/kazupon/vue-i18n/commit/ccf29f8)), closes [#536](https://github.com/kazupon/vue-i18n/issues/536) [#531](https://github.com/kazupon/vue-i18n/issues/531) [#1](https://github.com/kazupon/vue-i18n/issues/1) [#533](https://github.com/kazupon/vue-i18n/issues/533) [#540](https://github.com/kazupon/vue-i18n/issues/540) [#541](https://github.com/kazupon/vue-i18n/issues/541) [#1](https://github.com/kazupon/vue-i18n/issues/1) [#2](https://github.com/kazupon/vue-i18n/issues/2)
50
+
51
+
1
52
  <a name="8.9.0"></a>
2
53
  # [8.9.0](https://github.com/kazupon/vue-i18n/compare/v8.8.2...v8.9.0) (2019-03-08)
3
54
 
package/decls/i18n.js CHANGED
@@ -50,6 +50,17 @@ declare type DateTimeFormatResult = string;
50
50
  declare type NumberFormatResult = string;
51
51
  declare type MissingHandler = (locale: Locale, key: Path, vm?: any) => string | void;
52
52
 
53
+ declare type FormattedNumberPartType = 'currency' | 'decimal' | 'fraction' | 'group' | 'infinity' | 'integer' | 'literal' | 'minusSign' | 'nan' | 'plusSign' | 'percentSign';
54
+ declare type FormattedNumberPart = {
55
+ type: FormattedNumberPartType,
56
+ value: string,
57
+ };
58
+ // This array is the same as Intl.NumberFormat.formatToParts() return value:
59
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat/formatToParts#Return_value
60
+ declare type NumberFormatToPartsResult = Array<FormattedNumberPart>;
61
+
62
+ declare type WarnHtmlInMessageLevel = 'off' | 'warn' | 'error';
63
+
53
64
  declare type I18nOptions = {
54
65
  locale?: Locale,
55
66
  fallbackLocale?: Locale,
@@ -65,6 +76,7 @@ declare type I18nOptions = {
65
76
  silentFallbackWarn?: boolean,
66
77
  pluralizationRules?: PluralizationRules,
67
78
  preserveDirectiveContent?: boolean,
79
+ warnHtmlInMessage?: WarnHtmlInMessageLevel,
68
80
  };
69
81
 
70
82
  declare type IntlAvailability = {
@@ -101,6 +113,8 @@ declare interface I18n {
101
113
  set pluralizationRules (rules: PluralizationRules): void,
102
114
  get preserveDirectiveContent (): boolean,
103
115
  set preserveDirectiveContent (preserve: boolean): void,
116
+ get warnHtmlInMessage (): WarnHtmlInMessageLevel,
117
+ set warnHtmlInMessage (level: WarnHtmlInMessageLevel): void,
104
118
 
105
119
  getLocaleMessage (locale: Locale): LocaleMessageObject,
106
120
  setLocaleMessage (locale: Locale, message: LocaleMessageObject): void,
package/dist/README.md CHANGED
@@ -1,8 +1,9 @@
1
- ## Explanation of Build Files
1
+ ## Explanation of Different Builds
2
2
 
3
- - UMD: vue-i18n.js
4
- - CommonJS: vue-i18n.common.js
5
- - ES Module: vue-i18n.esm.js
3
+ - UMD: `vue-i18n.js`
4
+ - CommonJS: `vue-i18n.common.js`
5
+ - ES Module for bundlers: `vue-i18n.esm.js`
6
+ - ES Module for browsers: `vue-i18n.esm.browser.js`
6
7
 
7
8
  ### Terms
8
9
 
@@ -10,4 +11,6 @@
10
11
 
11
12
  - **[CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1)**: CommonJS builds are intended for use with older bundlers like [browserify](http://browserify.org/) or [webpack 1](https://webpack.github.io). The default file for these bundlers (`pkg.main`) is the Runtime only CommonJS build (`vue-i18n.common.js`).
12
13
 
13
- - **[ES Module](http://exploringjs.com/es6/ch_modules.html)**: ES module builds are intended for use with modern bundlers like [webpack 2](https://webpack.js.org) or [rollup](http://rollupjs.org/). The default file for these bundlers (`pkg.module`) is the Runtime only ES Module build (`vue-i18n.esm.js`).
14
+ - **[ES Module](http://exploringjs.com/es6/ch_modules.html)**: starting in 8.11 VueI18n provides two ES Modules (ESM) builds:
15
+ - ESM for bundlers: intended for use with modern bundlers like [webpack 2](https://webpack.js.org) or [Rollup](https://rollupjs.org/). ESM format is designed to be statically analyzable so the bundlers can take advantage of that to perform "tree-shaking" and eliminate unused code from your final bundle. The default file for these bundlers (`pkg.module`) is the Runtime only ES Module build (`vue-i18n.esm.js`).
16
+ - ESM for browsers (8.11+ only, `vue-i18n.esm.browser.js`): intended for direct imports in modern browsers via `<script type="module">`.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * vue-i18n v8.9.0
2
+ * vue-i18n v8.11.2
3
3
  * (c) 2019 kazuya kawaguchi
4
4
  * Released under the MIT License.
5
5
  */
@@ -7,6 +7,24 @@
7
7
 
8
8
  /* */
9
9
 
10
+ /**
11
+ * constants
12
+ */
13
+
14
+ var 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
+
10
28
  /**
11
29
  * utilities
12
30
  */
@@ -21,6 +39,16 @@ function warn (msg, err) {
21
39
  }
22
40
  }
23
41
 
42
+ function 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
+
24
52
  function isObject (obj) {
25
53
  return obj !== null && typeof obj === 'object'
26
54
  }
@@ -208,8 +236,6 @@ var mixin = {
208
236
  }
209
237
  this._i18n = options.i18n;
210
238
  this._i18nWatcher = this._i18n.watchI18nData();
211
- this._i18n.subscribeDataChanging(this);
212
- this._subscribing = true;
213
239
  } else if (isPlainObject(options.i18n)) {
214
240
  // component local i18n
215
241
  if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
@@ -239,8 +265,6 @@ var mixin = {
239
265
 
240
266
  this._i18n = new VueI18n(options.i18n);
241
267
  this._i18nWatcher = this._i18n.watchI18nData();
242
- this._i18n.subscribeDataChanging(this);
243
- this._subscribing = true;
244
268
 
245
269
  if (options.i18n.sync === undefined || !!options.i18n.sync) {
246
270
  this._localeWatcher = this.$i18n.watchLocale();
@@ -253,11 +277,33 @@ var mixin = {
253
277
  } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
254
278
  // root i18n
255
279
  this._i18n = this.$root.$i18n;
256
- this._i18n.subscribeDataChanging(this);
257
- this._subscribing = true;
258
280
  } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
259
281
  // parent i18n
260
282
  this._i18n = options.parent.$i18n;
283
+ }
284
+ },
285
+
286
+ beforeMount: function beforeMount () {
287
+ var options = this.$options;
288
+ options.i18n = options.i18n || (options.__i18n ? {} : null);
289
+
290
+ if (options.i18n) {
291
+ if (options.i18n instanceof VueI18n) {
292
+ // init locale messages via custom blocks
293
+ this._i18n.subscribeDataChanging(this);
294
+ this._subscribing = true;
295
+ } else if (isPlainObject(options.i18n)) {
296
+ this._i18n.subscribeDataChanging(this);
297
+ this._subscribing = true;
298
+ } else {
299
+ if (process.env.NODE_ENV !== 'production') {
300
+ warn("Cannot be interpreted 'i18n' option.");
301
+ }
302
+ }
303
+ } else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
304
+ this._i18n.subscribeDataChanging(this);
305
+ this._subscribing = true;
306
+ } else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
261
307
  this._i18n.subscribeDataChanging(this);
262
308
  this._subscribing = true;
263
309
  }
@@ -291,7 +337,7 @@ var mixin = {
291
337
 
292
338
  /* */
293
339
 
294
- var component = {
340
+ var interpolationComponent = {
295
341
  name: 'i18n',
296
342
  functional: true,
297
343
  props: {
@@ -373,6 +419,80 @@ var component = {
373
419
 
374
420
  /* */
375
421
 
422
+ var numberComponent = {
423
+ name: 'i18n-n',
424
+ functional: true,
425
+ props: {
426
+ tag: {
427
+ type: String,
428
+ default: 'span'
429
+ },
430
+ value: {
431
+ type: Number,
432
+ required: true
433
+ },
434
+ format: {
435
+ type: [String, Object]
436
+ },
437
+ locale: {
438
+ type: String
439
+ }
440
+ },
441
+ render: function render (h, ref) {
442
+ var props = ref.props;
443
+ var parent = ref.parent;
444
+ var data = ref.data;
445
+
446
+ var i18n = parent.$i18n;
447
+
448
+ if (!i18n) {
449
+ if (process.env.NODE_ENV !== 'production') {
450
+ warn('Cannot find VueI18n instance!');
451
+ }
452
+ return null
453
+ }
454
+
455
+ var key = null;
456
+ var options = null;
457
+
458
+ if (typeof props.format === 'string') {
459
+ key = props.format;
460
+ } else if (isObject(props.format)) {
461
+ if (props.format.key) {
462
+ key = props.format.key;
463
+ }
464
+
465
+ // Filter out number format options only
466
+ options = Object.keys(props.format).reduce(function (acc, prop) {
467
+ var obj;
468
+
469
+ if (numberFormatKeys.includes(prop)) {
470
+ return Object.assign({}, acc, ( obj = {}, obj[prop] = props.format[prop], obj ))
471
+ }
472
+ return acc
473
+ }, null);
474
+ }
475
+
476
+ var locale = props.locale || i18n.locale;
477
+ var parts = i18n._ntp(props.value, locale, key, options);
478
+
479
+ var values = parts.map(function (part, index) {
480
+ var obj;
481
+
482
+ var slot = data.scopedSlots && data.scopedSlots[part.type];
483
+ return slot ? slot(( obj = {}, obj[part.type] = part.value, obj.index = index, obj.parts = parts, obj )) : part.value
484
+ });
485
+
486
+ return h(props.tag, {
487
+ attrs: data.attrs,
488
+ 'class': data['class'],
489
+ staticClass: data.staticClass
490
+ }, values)
491
+ }
492
+ };
493
+
494
+ /* */
495
+
376
496
  function bind (el, binding, vnode) {
377
497
  if (!assert(el, vnode)) { return }
378
498
 
@@ -510,7 +630,8 @@ function install (_Vue) {
510
630
  extend(Vue);
511
631
  Vue.mixin(mixin);
512
632
  Vue.directive('t', { bind: bind, update: update, unbind: unbind });
513
- Vue.component(component.name, component);
633
+ Vue.component(interpolationComponent.name, interpolationComponent);
634
+ Vue.component(numberComponent.name, numberComponent);
514
635
 
515
636
  // use simple mergeStrategies to prevent i18n instance lose '__proto__'
516
637
  var strats = Vue.config.optionMergeStrategies;
@@ -749,7 +870,6 @@ function getPathCharType (ch) {
749
870
  case 0x2D: // -
750
871
  return 'ident'
751
872
 
752
- case 0x20: // Space
753
873
  case 0x09: // Tab
754
874
  case 0x0A: // Newline
755
875
  case 0x0D: // Return
@@ -928,19 +1048,7 @@ I18nPath.prototype.getPathValue = function getPathValue (obj, path) {
928
1048
 
929
1049
 
930
1050
 
931
- var numberFormatKeys = [
932
- 'style',
933
- 'currency',
934
- 'currencyDisplay',
935
- 'useGrouping',
936
- 'minimumIntegerDigits',
937
- 'minimumFractionDigits',
938
- 'maximumFractionDigits',
939
- 'minimumSignificantDigits',
940
- 'maximumSignificantDigits',
941
- 'localeMatcher',
942
- 'formatMatcher'
943
- ];
1051
+ var htmlTagMatcher = /<\/?[\w\s="/.':;#-\/]+>/;
944
1052
  var linkKeyMatcher = /(?:@(?:\.[a-z]+)?:(?:[\w\-_|.]+|\([\w\-_|.]+\)))/g;
945
1053
  var linkKeyPrefixMatcher = /^@(?:\.([a-z]+))?:/;
946
1054
  var bracketsMatcher = /[()]/g;
@@ -991,6 +1099,7 @@ var VueI18n = function VueI18n (options) {
991
1099
  ? false
992
1100
  : !!options.preserveDirectiveContent;
993
1101
  this.pluralizationRules = options.pluralizationRules || {};
1102
+ this._warnHtmlInMessage = options.warnHtmlInMessage || 'off';
994
1103
 
995
1104
  this._exist = function (message, key) {
996
1105
  if (!message || !key) { return false }
@@ -1000,6 +1109,12 @@ var VueI18n = function VueI18n (options) {
1000
1109
  return false
1001
1110
  };
1002
1111
 
1112
+ if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
1113
+ Object.keys(messages).forEach(function (locale) {
1114
+ this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
1115
+ });
1116
+ }
1117
+
1003
1118
  this._initVM({
1004
1119
  locale: locale,
1005
1120
  fallbackLocale: fallbackLocale,
@@ -1009,7 +1124,56 @@ var VueI18n = function VueI18n (options) {
1009
1124
  });
1010
1125
  };
1011
1126
 
1012
- var prototypeAccessors = { vm: { configurable: true },messages: { configurable: true },dateTimeFormats: { configurable: true },numberFormats: { configurable: true },availableLocales: { configurable: true },locale: { configurable: true },fallbackLocale: { configurable: true },missing: { configurable: true },formatter: { configurable: true },silentTranslationWarn: { configurable: true },silentFallbackWarn: { configurable: true },preserveDirectiveContent: { configurable: true } };
1127
+ var prototypeAccessors = { vm: { configurable: true },messages: { configurable: true },dateTimeFormats: { configurable: true },numberFormats: { configurable: true },availableLocales: { configurable: true },locale: { configurable: true },fallbackLocale: { configurable: true },missing: { configurable: true },formatter: { configurable: true },silentTranslationWarn: { configurable: true },silentFallbackWarn: { configurable: true },preserveDirectiveContent: { configurable: true },warnHtmlInMessage: { configurable: true } };
1128
+
1129
+ VueI18n.prototype._checkLocaleMessage = function _checkLocaleMessage (locale, level, message) {
1130
+ var paths = [];
1131
+
1132
+ var fn = function (level, locale, message, paths) {
1133
+ if (isPlainObject(message)) {
1134
+ Object.keys(message).forEach(function (key) {
1135
+ var val = message[key];
1136
+ if (isPlainObject(val)) {
1137
+ paths.push(key);
1138
+ paths.push('.');
1139
+ fn(level, locale, val, paths);
1140
+ paths.pop();
1141
+ paths.pop();
1142
+ } else {
1143
+ paths.push(key);
1144
+ fn(level, locale, val, paths);
1145
+ paths.pop();
1146
+ }
1147
+ });
1148
+ } else if (Array.isArray(message)) {
1149
+ message.forEach(function (item, index) {
1150
+ if (isPlainObject(item)) {
1151
+ paths.push(("[" + index + "]"));
1152
+ paths.push('.');
1153
+ fn(level, locale, item, paths);
1154
+ paths.pop();
1155
+ paths.pop();
1156
+ } else {
1157
+ paths.push(("[" + index + "]"));
1158
+ fn(level, locale, item, paths);
1159
+ paths.pop();
1160
+ }
1161
+ });
1162
+ } else if (typeof message === 'string') {
1163
+ var ret = htmlTagMatcher.test(message);
1164
+ if (ret) {
1165
+ 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";
1166
+ if (level === 'warn') {
1167
+ warn(msg);
1168
+ } else if (level === 'error') {
1169
+ error(msg);
1170
+ }
1171
+ }
1172
+ }
1173
+ };
1174
+
1175
+ fn(level, locale, message, paths);
1176
+ };
1013
1177
 
1014
1178
  VueI18n.prototype._initVM = function _initVM (data) {
1015
1179
  var silent = Vue.config.silent;
@@ -1084,6 +1248,20 @@ prototypeAccessors.silentFallbackWarn.set = function (silent) { this._silentFall
1084
1248
  prototypeAccessors.preserveDirectiveContent.get = function () { return this._preserveDirectiveContent };
1085
1249
  prototypeAccessors.preserveDirectiveContent.set = function (preserve) { this._preserveDirectiveContent = preserve; };
1086
1250
 
1251
+ prototypeAccessors.warnHtmlInMessage.get = function () { return this._warnHtmlInMessage };
1252
+ prototypeAccessors.warnHtmlInMessage.set = function (level) {
1253
+ var this$1 = this;
1254
+
1255
+ var orgLevel = this._warnHtmlInMessage;
1256
+ this._warnHtmlInMessage = level;
1257
+ if (orgLevel !== level && (level === 'warn' || level === 'error')) {
1258
+ var messages = this._getMessages();
1259
+ Object.keys(messages).forEach(function (locale) {
1260
+ this$1._checkLocaleMessage(locale, this$1._warnHtmlInMessage, messages[locale]);
1261
+ });
1262
+ }
1263
+ };
1264
+
1087
1265
  VueI18n.prototype._getMessages = function _getMessages () { return this._vm.messages };
1088
1266
  VueI18n.prototype._getDateTimeFormats = function _getDateTimeFormats () { return this._vm.dateTimeFormats };
1089
1267
  VueI18n.prototype._getNumberFormats = function _getNumberFormats () { return this._vm.numberFormats };
@@ -1171,8 +1349,6 @@ VueI18n.prototype._link = function _link (
1171
1349
  values,
1172
1350
  visitedLinkStack
1173
1351
  ) {
1174
- var this$1 = this;
1175
-
1176
1352
  var ret = str;
1177
1353
 
1178
1354
  // Match all the links within the local
@@ -1202,26 +1378,26 @@ VueI18n.prototype._link = function _link (
1202
1378
  visitedLinkStack.push(linkPlaceholder);
1203
1379
 
1204
1380
  // Translate the link
1205
- var translated = this$1._interpolate(
1381
+ var translated = this._interpolate(
1206
1382
  locale, message, linkPlaceholder, host,
1207
1383
  interpolateMode === 'raw' ? 'string' : interpolateMode,
1208
1384
  interpolateMode === 'raw' ? undefined : values,
1209
1385
  visitedLinkStack
1210
1386
  );
1211
1387
 
1212
- if (this$1._isFallbackRoot(translated)) {
1213
- if (process.env.NODE_ENV !== 'production' && !this$1._silentTranslationWarn) {
1388
+ if (this._isFallbackRoot(translated)) {
1389
+ if (process.env.NODE_ENV !== 'production' && !this._silentTranslationWarn) {
1214
1390
  warn(("Fall back to translate the link placeholder '" + linkPlaceholder + "' with root locale."));
1215
1391
  }
1216
1392
  /* istanbul ignore if */
1217
- if (!this$1._root) { throw Error('unexpected error') }
1218
- var root = this$1._root.$i18n;
1393
+ if (!this._root) { throw Error('unexpected error') }
1394
+ var root = this._root.$i18n;
1219
1395
  translated = root._translate(
1220
1396
  root._getMessages(), root.locale, root.fallbackLocale,
1221
1397
  linkPlaceholder, host, interpolateMode, values
1222
1398
  );
1223
1399
  }
1224
- translated = this$1._warnDefault(
1400
+ translated = this._warnDefault(
1225
1401
  locale, linkPlaceholder, translated, host,
1226
1402
  Array.isArray(values) ? values : [values]
1227
1403
  );
@@ -1420,10 +1596,18 @@ VueI18n.prototype.getLocaleMessage = function getLocaleMessage (locale) {
1420
1596
  };
1421
1597
 
1422
1598
  VueI18n.prototype.setLocaleMessage = function setLocaleMessage (locale, message) {
1599
+ if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
1600
+ this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
1601
+ if (this._warnHtmlInMessage === 'error') { return }
1602
+ }
1423
1603
  this._vm.$set(this._vm.messages, locale, message);
1424
1604
  };
1425
1605
 
1426
1606
  VueI18n.prototype.mergeLocaleMessage = function mergeLocaleMessage (locale, message) {
1607
+ if (this._warnHtmlInMessage === 'warn' || this._warnHtmlInMessage === 'error') {
1608
+ this._checkLocaleMessage(locale, this._warnHtmlInMessage, message);
1609
+ if (this._warnHtmlInMessage === 'error') { return }
1610
+ }
1427
1611
  this._vm.$set(this._vm.messages, locale, merge(this._vm.messages[locale] || {}, message));
1428
1612
  };
1429
1613
 
@@ -1538,7 +1722,7 @@ VueI18n.prototype.mergeNumberFormat = function mergeNumberFormat (locale, format
1538
1722
  this._vm.$set(this._vm.numberFormats, locale, merge(this._vm.numberFormats[locale] || {}, format));
1539
1723
  };
1540
1724
 
1541
- VueI18n.prototype._localizeNumber = function _localizeNumber (
1725
+ VueI18n.prototype._getNumberFormatter = function _getNumberFormatter (
1542
1726
  value,
1543
1727
  locale,
1544
1728
  fallback,
@@ -1574,7 +1758,7 @@ VueI18n.prototype._localizeNumber = function _localizeNumber (
1574
1758
  formatter = this._numberFormatters[id] = new Intl.NumberFormat(_locale, format);
1575
1759
  }
1576
1760
  }
1577
- return formatter.format(value)
1761
+ return formatter
1578
1762
  }
1579
1763
  };
1580
1764
 
@@ -1592,8 +1776,8 @@ VueI18n.prototype._n = function _n (value, locale, key, options) {
1592
1776
  return nf.format(value)
1593
1777
  }
1594
1778
 
1595
- var ret =
1596
- this._localizeNumber(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
1779
+ var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
1780
+ var ret = formatter && formatter.format(value);
1597
1781
  if (this._isFallbackRoot(ret)) {
1598
1782
  if (process.env.NODE_ENV !== 'production' && !this._silentTranslationWarn) {
1599
1783
  warn(("Fall back to number localization of root: key '" + key + "' ."));
@@ -1647,6 +1831,34 @@ VueI18n.prototype.n = function n (value) {
1647
1831
  return this._n(value, locale, key, options)
1648
1832
  };
1649
1833
 
1834
+ VueI18n.prototype._ntp = function _ntp (value, locale, key, options) {
1835
+ /* istanbul ignore if */
1836
+ if (!VueI18n.availabilities.numberFormat) {
1837
+ if (process.env.NODE_ENV !== 'production') {
1838
+ warn('Cannot format to parts a Number value due to not supported Intl.NumberFormat.');
1839
+ }
1840
+ return []
1841
+ }
1842
+
1843
+ if (!key) {
1844
+ var nf = !options ? new Intl.NumberFormat(locale) : new Intl.NumberFormat(locale, options);
1845
+ return nf.formatToParts(value)
1846
+ }
1847
+
1848
+ var formatter = this._getNumberFormatter(value, locale, this.fallbackLocale, this._getNumberFormats(), key, options);
1849
+ var ret = formatter && formatter.formatToParts(value);
1850
+ if (this._isFallbackRoot(ret)) {
1851
+ if (process.env.NODE_ENV !== 'production' && !this._silentTranslationWarn) {
1852
+ warn(("Fall back to format number to parts of root: key '" + key + "' ."));
1853
+ }
1854
+ /* istanbul ignore if */
1855
+ if (!this._root) { throw Error('unexpected error') }
1856
+ return this._root.$i18n._ntp(value, locale, key, options)
1857
+ } else {
1858
+ return ret || []
1859
+ }
1860
+ };
1861
+
1650
1862
  Object.defineProperties( VueI18n.prototype, prototypeAccessors );
1651
1863
 
1652
1864
  var availabilities;
@@ -1666,6 +1878,6 @@ Object.defineProperty(VueI18n, 'availabilities', {
1666
1878
  });
1667
1879
 
1668
1880
  VueI18n.install = install;
1669
- VueI18n.version = '8.9.0';
1881
+ VueI18n.version = '8.11.2';
1670
1882
 
1671
1883
  module.exports = VueI18n;