@dcloudio/uni-i18n 2.0.0 → 2.0.1-32920211122002

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.
@@ -2,18 +2,20 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ const isArray = Array.isArray;
5
6
  const isObject = (val) => val !== null && typeof val === 'object';
7
+ const defaultDelimiters = ['{', '}'];
6
8
  class BaseFormatter {
7
9
  constructor() {
8
10
  this._caches = Object.create(null);
9
11
  }
10
- interpolate(message, values) {
12
+ interpolate(message, values, delimiters = defaultDelimiters) {
11
13
  if (!values) {
12
14
  return [message];
13
15
  }
14
16
  let tokens = this._caches[message];
15
17
  if (!tokens) {
16
- tokens = parse(message);
18
+ tokens = parse(message, delimiters);
17
19
  this._caches[message] = tokens;
18
20
  }
19
21
  return compile(tokens, values);
@@ -21,24 +23,24 @@ class BaseFormatter {
21
23
  }
22
24
  const RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
23
25
  const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
24
- function parse(format) {
26
+ function parse(format, [startDelimiter, endDelimiter]) {
25
27
  const tokens = [];
26
28
  let position = 0;
27
29
  let text = '';
28
30
  while (position < format.length) {
29
31
  let char = format[position++];
30
- if (char === '{') {
32
+ if (char === startDelimiter) {
31
33
  if (text) {
32
34
  tokens.push({ type: 'text', value: text });
33
35
  }
34
36
  text = '';
35
37
  let sub = '';
36
38
  char = format[position++];
37
- while (char !== undefined && char !== '}') {
39
+ while (char !== undefined && char !== endDelimiter) {
38
40
  sub += char;
39
41
  char = format[position++];
40
42
  }
41
- const isClosed = char === '}';
43
+ const isClosed = char === endDelimiter;
42
44
  const type = RE_TOKEN_LIST_VALUE.test(sub)
43
45
  ? 'list'
44
46
  : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
@@ -46,12 +48,12 @@ function parse(format) {
46
48
  : 'unknown';
47
49
  tokens.push({ value: sub, type });
48
50
  }
49
- else if (char === '%') {
50
- // when found rails i18n syntax, skip text capture
51
- if (format[position] !== '{') {
52
- text += char;
53
- }
54
- }
51
+ // else if (char === '%') {
52
+ // // when found rails i18n syntax, skip text capture
53
+ // if (format[position] !== '{') {
54
+ // text += char
55
+ // }
56
+ // }
55
57
  else {
56
58
  text += char;
57
59
  }
@@ -62,7 +64,7 @@ function parse(format) {
62
64
  function compile(tokens, values) {
63
65
  const compiled = [];
64
66
  let index = 0;
65
- const mode = Array.isArray(values)
67
+ const mode = isArray(values)
66
68
  ? 'list'
67
69
  : isObject(values)
68
70
  ? 'named'
@@ -100,6 +102,11 @@ function compile(tokens, values) {
100
102
  return compiled;
101
103
  }
102
104
 
105
+ const LOCALE_ZH_HANS = 'zh-Hans';
106
+ const LOCALE_ZH_HANT = 'zh-Hant';
107
+ const LOCALE_EN = 'en';
108
+ const LOCALE_FR = 'fr';
109
+ const LOCALE_ES = 'es';
103
110
  const hasOwnProperty = Object.prototype.hasOwnProperty;
104
111
  const hasOwn = (val, key) => hasOwnProperty.call(val, key);
105
112
  const defaultFormatter = new BaseFormatter();
@@ -114,31 +121,31 @@ function normalizeLocale(locale, messages) {
114
121
  return;
115
122
  }
116
123
  locale = locale.trim().replace(/_/g, '-');
117
- if (messages[locale]) {
124
+ if (messages && messages[locale]) {
118
125
  return locale;
119
126
  }
120
127
  locale = locale.toLowerCase();
121
128
  if (locale.indexOf('zh') === 0) {
122
- if (locale.indexOf('-hans') !== -1) {
123
- return 'zh-Hans';
129
+ if (locale.indexOf('-hans') > -1) {
130
+ return LOCALE_ZH_HANS;
124
131
  }
125
- if (locale.indexOf('-hant') !== -1) {
126
- return 'zh-Hant';
132
+ if (locale.indexOf('-hant') > -1) {
133
+ return LOCALE_ZH_HANT;
127
134
  }
128
135
  if (include(locale, ['-tw', '-hk', '-mo', '-cht'])) {
129
- return 'zh-Hant';
136
+ return LOCALE_ZH_HANT;
130
137
  }
131
- return 'zh-Hans';
138
+ return LOCALE_ZH_HANS;
132
139
  }
133
- const lang = startsWith(locale, ['en', 'fr', 'es']);
140
+ const lang = startsWith(locale, [LOCALE_EN, LOCALE_FR, LOCALE_ES]);
134
141
  if (lang) {
135
142
  return lang;
136
143
  }
137
144
  }
138
145
  class I18n {
139
146
  constructor({ locale, fallbackLocale, messages, watcher, formater, }) {
140
- this.locale = 'en';
141
- this.fallbackLocale = 'en';
147
+ this.locale = LOCALE_EN;
148
+ this.fallbackLocale = LOCALE_EN;
142
149
  this.message = {};
143
150
  this.messages = {};
144
151
  this.watchers = [];
@@ -146,8 +153,8 @@ class I18n {
146
153
  this.fallbackLocale = fallbackLocale;
147
154
  }
148
155
  this.formater = formater || defaultFormatter;
149
- this.messages = messages;
150
- this.setLocale(locale);
156
+ this.messages = messages || {};
157
+ this.setLocale(locale || LOCALE_EN);
151
158
  if (watcher) {
152
159
  this.watchLocale(watcher);
153
160
  }
@@ -155,10 +162,17 @@ class I18n {
155
162
  setLocale(locale) {
156
163
  const oldLocale = this.locale;
157
164
  this.locale = normalizeLocale(locale, this.messages) || this.fallbackLocale;
165
+ if (!this.messages[this.locale]) {
166
+ // 可能初始化时不存在
167
+ this.messages[this.locale] = {};
168
+ }
158
169
  this.message = this.messages[this.locale];
159
- this.watchers.forEach((watcher) => {
160
- watcher(this.locale, oldLocale);
161
- });
170
+ // 仅发生变化时,通知
171
+ if (oldLocale !== this.locale) {
172
+ this.watchers.forEach((watcher) => {
173
+ watcher(this.locale, oldLocale);
174
+ });
175
+ }
162
176
  }
163
177
  getLocale() {
164
178
  return this.locale;
@@ -169,6 +183,27 @@ class I18n {
169
183
  this.watchers.splice(index, 1);
170
184
  };
171
185
  }
186
+ add(locale, message, override = true) {
187
+ const curMessages = this.messages[locale];
188
+ if (curMessages) {
189
+ if (override) {
190
+ Object.assign(curMessages, message);
191
+ }
192
+ else {
193
+ Object.keys(message).forEach((key) => {
194
+ if (!hasOwn(curMessages, key)) {
195
+ curMessages[key] = message[key];
196
+ }
197
+ });
198
+ }
199
+ }
200
+ else {
201
+ this.messages[locale] = message;
202
+ }
203
+ }
204
+ f(message, values, delimiters) {
205
+ return this.formater.interpolate(message, values, delimiters).join('');
206
+ }
172
207
  t(key, locale, values) {
173
208
  let message = this.message;
174
209
  if (typeof locale === 'string') {
@@ -186,94 +221,252 @@ class I18n {
186
221
  }
187
222
  }
188
223
 
189
- function initLocaleWatcher(appVm, i18n) {
190
- appVm.$i18n &&
191
- appVm.$i18n.vm.$watch('locale', (newLocale) => {
224
+ function watchAppLocale(appVm, i18n) {
225
+ // 需要保证 watch 的触发在组件渲染之前
226
+ if (appVm.$watchLocale) {
227
+ // vue2
228
+ appVm.$watchLocale((newLocale) => {
192
229
  i18n.setLocale(newLocale);
193
- }, {
194
- immediate: true,
195
230
  });
231
+ }
232
+ else {
233
+ appVm.$watch(() => appVm.$locale, (newLocale) => {
234
+ i18n.setLocale(newLocale);
235
+ });
236
+ }
196
237
  }
197
238
  function getDefaultLocale() {
198
- if (typeof navigator !== 'undefined') {
199
- return navigator.userLanguage || navigator.language;
239
+ if (typeof uni !== 'undefined' && uni.getLocale) {
240
+ return uni.getLocale();
200
241
  }
201
- if (typeof plus !== 'undefined') {
202
- // TODO 待调整为最新的获取语言代码
203
- return plus.os.language;
242
+ // 小程序平台,uni 和 uni-i18n 互相引用,导致访问不到 uni,故在 global 上挂了 getLocale
243
+ if (typeof global !== 'undefined' && global.getLocale) {
244
+ return global.getLocale();
204
245
  }
205
- return uni.getSystemInfoSync().language;
246
+ return LOCALE_EN;
206
247
  }
207
- function initVueI18n(messages, fallbackLocale = 'en', locale) {
248
+ function initVueI18n(locale, messages = {}, fallbackLocale, watcher) {
249
+ // 兼容旧版本入参
250
+ if (typeof locale !== 'string') {
251
+ [locale, messages] = [
252
+ messages,
253
+ locale,
254
+ ];
255
+ }
256
+ if (typeof locale !== 'string') {
257
+ // 因为小程序平台,uni-i18n 和 uni 互相引用,导致此时访问 uni 时,为 undefined
258
+ locale = getDefaultLocale();
259
+ }
260
+ if (typeof fallbackLocale !== 'string') {
261
+ fallbackLocale =
262
+ (typeof __uniConfig !== 'undefined' && __uniConfig.fallbackLocale) ||
263
+ LOCALE_EN;
264
+ }
208
265
  const i18n = new I18n({
209
- locale: locale || fallbackLocale,
266
+ locale,
210
267
  fallbackLocale,
211
268
  messages,
269
+ watcher,
212
270
  });
213
271
  let t = (key, values) => {
214
272
  if (typeof getApp !== 'function') {
215
- // app-plus view
273
+ // app view
216
274
  /* eslint-disable no-func-assign */
217
275
  t = function (key, values) {
218
276
  return i18n.t(key, values);
219
277
  };
220
278
  }
221
279
  else {
222
- const appVm = getApp().$vm;
223
- if (!appVm.$t || !appVm.$i18n) {
224
- if (!locale) {
225
- i18n.setLocale(getDefaultLocale());
226
- }
227
- /* eslint-disable no-func-assign */
228
- t = function (key, values) {
229
- return i18n.t(key, values);
230
- };
231
- }
232
- else {
233
- initLocaleWatcher(appVm, i18n);
234
- /* eslint-disable no-func-assign */
235
- t = function (key, values) {
236
- const $i18n = appVm.$i18n;
237
- const silentTranslationWarn = $i18n.silentTranslationWarn;
238
- $i18n.silentTranslationWarn = true;
239
- const msg = appVm.$t(key, values);
240
- $i18n.silentTranslationWarn = silentTranslationWarn;
241
- if (msg !== key) {
242
- return msg;
280
+ let isWatchedAppLocale = false;
281
+ t = function (key, values) {
282
+ const appVm = getApp().$vm;
283
+ // 可能$vm还不存在,比如在支付宝小程序中,组件定义较早,在props的default里使用了t()函数(如uni-goods-nav),此时app还未初始化
284
+ // options: {
285
+ // type: Array,
286
+ // default () {
287
+ // return [{
288
+ // icon: 'shop',
289
+ // text: t("uni-goods-nav.options.shop"),
290
+ // }, {
291
+ // icon: 'cart',
292
+ // text: t("uni-goods-nav.options.cart")
293
+ // }]
294
+ // }
295
+ // },
296
+ if (appVm) {
297
+ // 触发响应式
298
+ appVm.$locale;
299
+ if (!isWatchedAppLocale) {
300
+ isWatchedAppLocale = true;
301
+ watchAppLocale(appVm, i18n);
243
302
  }
244
- return i18n.t(key, $i18n.locale, values);
245
- };
246
- }
303
+ }
304
+ return i18n.t(key, values);
305
+ };
247
306
  }
248
307
  return t(key, values);
249
308
  };
250
309
  return {
310
+ i18n,
311
+ f(message, values, delimiters) {
312
+ return i18n.f(message, values, delimiters);
313
+ },
251
314
  t(key, values) {
252
315
  return t(key, values);
253
316
  },
317
+ add(locale, message, override = true) {
318
+ return i18n.add(locale, message, override);
319
+ },
320
+ watch(fn) {
321
+ return i18n.watchLocale(fn);
322
+ },
254
323
  getLocale() {
255
324
  return i18n.getLocale();
256
325
  },
257
326
  setLocale(newLocale) {
258
327
  return i18n.setLocale(newLocale);
259
328
  },
260
- mixin: {
261
- beforeCreate() {
262
- const unwatch = i18n.watchLocale(() => {
263
- this.$forceUpdate();
264
- });
265
- this.$once('hook:beforeDestroy', function () {
266
- unwatch();
329
+ };
330
+ }
331
+
332
+ const isString = (val) => typeof val === 'string';
333
+ let formater;
334
+ function hasI18nJson(jsonObj, delimiters) {
335
+ if (!formater) {
336
+ formater = new BaseFormatter();
337
+ }
338
+ return walkJsonObj(jsonObj, (jsonObj, key) => {
339
+ const value = jsonObj[key];
340
+ if (isString(value)) {
341
+ if (isI18nStr(value, delimiters)) {
342
+ return true;
343
+ }
344
+ }
345
+ else {
346
+ return hasI18nJson(value, delimiters);
347
+ }
348
+ });
349
+ }
350
+ function parseI18nJson(jsonObj, values, delimiters) {
351
+ if (!formater) {
352
+ formater = new BaseFormatter();
353
+ }
354
+ walkJsonObj(jsonObj, (jsonObj, key) => {
355
+ const value = jsonObj[key];
356
+ if (isString(value)) {
357
+ if (isI18nStr(value, delimiters)) {
358
+ jsonObj[key] = compileStr(value, values, delimiters);
359
+ }
360
+ }
361
+ else {
362
+ parseI18nJson(value, values, delimiters);
363
+ }
364
+ });
365
+ return jsonObj;
366
+ }
367
+ function compileI18nJsonStr(jsonStr, { locale, locales, delimiters, }) {
368
+ if (!isI18nStr(jsonStr, delimiters)) {
369
+ return jsonStr;
370
+ }
371
+ if (!formater) {
372
+ formater = new BaseFormatter();
373
+ }
374
+ const localeValues = [];
375
+ Object.keys(locales).forEach((name) => {
376
+ if (name !== locale) {
377
+ localeValues.push({
378
+ locale: name,
379
+ values: locales[name],
380
+ });
381
+ }
382
+ });
383
+ localeValues.unshift({ locale, values: locales[locale] });
384
+ try {
385
+ return JSON.stringify(compileJsonObj(JSON.parse(jsonStr), localeValues, delimiters), null, 2);
386
+ }
387
+ catch (e) { }
388
+ return jsonStr;
389
+ }
390
+ function isI18nStr(value, delimiters) {
391
+ return value.indexOf(delimiters[0]) > -1;
392
+ }
393
+ function compileStr(value, values, delimiters) {
394
+ return formater.interpolate(value, values, delimiters).join('');
395
+ }
396
+ function compileValue(jsonObj, key, localeValues, delimiters) {
397
+ const value = jsonObj[key];
398
+ if (isString(value)) {
399
+ // 存在国际化
400
+ if (isI18nStr(value, delimiters)) {
401
+ jsonObj[key] = compileStr(value, localeValues[0].values, delimiters);
402
+ if (localeValues.length > 1) {
403
+ // 格式化国际化语言
404
+ const valueLocales = (jsonObj[key + 'Locales'] = {});
405
+ localeValues.forEach((localValue) => {
406
+ valueLocales[localValue.locale] = compileStr(value, localValue.values, delimiters);
267
407
  });
268
- },
269
- methods: {
270
- $$t(key, values) {
271
- return t(key, values);
272
- },
273
- },
274
- },
408
+ }
409
+ }
410
+ }
411
+ else {
412
+ compileJsonObj(value, localeValues, delimiters);
413
+ }
414
+ }
415
+ function compileJsonObj(jsonObj, localeValues, delimiters) {
416
+ walkJsonObj(jsonObj, (jsonObj, key) => {
417
+ compileValue(jsonObj, key, localeValues, delimiters);
418
+ });
419
+ return jsonObj;
420
+ }
421
+ function walkJsonObj(jsonObj, walk) {
422
+ if (isArray(jsonObj)) {
423
+ for (let i = 0; i < jsonObj.length; i++) {
424
+ if (walk(jsonObj, i)) {
425
+ return true;
426
+ }
427
+ }
428
+ }
429
+ else if (isObject(jsonObj)) {
430
+ for (const key in jsonObj) {
431
+ if (walk(jsonObj, key)) {
432
+ return true;
433
+ }
434
+ }
435
+ }
436
+ return false;
437
+ }
438
+
439
+ function resolveLocale(locales) {
440
+ return (locale) => {
441
+ if (!locale) {
442
+ return locale;
443
+ }
444
+ locale = normalizeLocale(locale) || locale;
445
+ return resolveLocaleChain(locale).find((locale) => locales.indexOf(locale) > -1);
275
446
  };
447
+ }
448
+ function resolveLocaleChain(locale) {
449
+ const chain = [];
450
+ const tokens = locale.split('-');
451
+ while (tokens.length) {
452
+ chain.push(tokens.join('-'));
453
+ tokens.pop();
454
+ }
455
+ return chain;
276
456
  }
277
457
 
458
+ exports.Formatter = BaseFormatter;
278
459
  exports.I18n = I18n;
460
+ exports.LOCALE_EN = LOCALE_EN;
461
+ exports.LOCALE_ES = LOCALE_ES;
462
+ exports.LOCALE_FR = LOCALE_FR;
463
+ exports.LOCALE_ZH_HANS = LOCALE_ZH_HANS;
464
+ exports.LOCALE_ZH_HANT = LOCALE_ZH_HANT;
465
+ exports.compileI18nJsonStr = compileI18nJsonStr;
466
+ exports.hasI18nJson = hasI18nJson;
279
467
  exports.initVueI18n = initVueI18n;
468
+ exports.isI18nStr = isI18nStr;
469
+ exports.isString = isString;
470
+ exports.normalizeLocale = normalizeLocale;
471
+ exports.parseI18nJson = parseI18nJson;
472
+ exports.resolveLocale = resolveLocale;
@@ -1,10 +1,25 @@
1
+ export declare type BuiltInLocale = typeof LOCALE_ZH_HANS | typeof LOCALE_ZH_HANT | typeof LOCALE_EN | typeof LOCALE_FR | typeof LOCALE_ES;
1
2
 
2
- export declare type BuiltInLocale = 'zh-Hans' | 'zh-Hant' | 'en' | 'fr' | 'es';
3
+ export declare function compileI18nJsonStr(jsonStr: string, { locale, locales, delimiters, }: {
4
+ locale: string;
5
+ locales: Record<string, Record<string, string>>;
6
+ delimiters: [string, string];
7
+ }): string;
3
8
 
4
- export declare interface Formatter {
5
- interpolate: (message: string, values?: Record<string, unknown> | Array<unknown>) => Array<unknown>;
9
+ export declare class Formatter {
10
+ _caches: {
11
+ [key: string]: Array<Token>;
12
+ };
13
+ constructor();
14
+ interpolate(message: string, values?: Record<string, unknown> | Array<unknown>, delimiters?: [string, string]): Array<unknown>;
15
+ }
16
+
17
+ declare interface Formatter_2 {
18
+ interpolate: (message: string, values?: Record<string, unknown> | Array<unknown>, delimiters?: [string, string]) => Array<unknown>;
6
19
  }
7
20
 
21
+ export declare function hasI18nJson(jsonObj: unknown, delimiters: [string, string]): boolean;
22
+
8
23
  export declare class I18n {
9
24
  private locale;
10
25
  private fallbackLocale;
@@ -14,36 +29,61 @@ export declare class I18n {
14
29
  private formater;
15
30
  constructor({ locale, fallbackLocale, messages, watcher, formater, }: I18nOptions);
16
31
  setLocale(locale: string): void;
17
- getLocale(): BuiltInLocale;
32
+ getLocale(): string;
18
33
  watchLocale(fn: LocaleWatcher): () => void;
34
+ add(locale: BuiltInLocale, message: Record<string, string>, override?: boolean): void;
35
+ f(message: string, values?: Record<string, unknown> | Array<unknown>, delimiters?: [string, string]): string;
19
36
  t(key: string, values?: Record<string, unknown> | Array<unknown> | BuiltInLocale): string;
20
37
  t(key: string, locale?: BuiltInLocale, values?: Record<string, unknown> | Array<unknown>): string;
21
38
  }
22
39
 
23
40
  export declare interface I18nOptions {
24
- locale: BuiltInLocale;
25
- fallbackLocale?: BuiltInLocale;
26
- messages: LocaleMessages;
27
- formater?: Formatter;
41
+ locale: string;
42
+ fallbackLocale?: string;
43
+ messages?: LocaleMessages;
44
+ formater?: Formatter_2;
28
45
  watcher?: LocaleWatcher;
29
46
  }
30
47
 
31
- export declare function initVueI18n(messages: LocaleMessages, fallbackLocale?: BuiltInLocale, locale?: BuiltInLocale): {
48
+ export declare function initVueI18n(locale?: string, messages?: LocaleMessages, fallbackLocale?: string, watcher?: (locale: string) => void): {
49
+ i18n: I18n;
50
+ f(message: string, values?: Record<string, unknown> | unknown[] | undefined, delimiters?: [string, string] | undefined): string;
32
51
  t(key: string, values?: Record<string, unknown> | unknown[] | undefined): string;
33
- getLocale(): BuiltInLocale;
34
- setLocale(newLocale: BuiltInLocale): void;
35
- mixin: {
36
- beforeCreate(): void;
37
- methods: {
38
- $$t(key: string, values?: any): string;
39
- };
40
- };
52
+ add(locale: BuiltInLocale, message: Record<string, string>, override?: boolean): void;
53
+ watch(fn: LocaleWatcher): () => void;
54
+ getLocale(): string;
55
+ setLocale(newLocale: string): void;
41
56
  };
42
57
 
43
- export declare type LocaleMessages = {
44
- [name in BuiltInLocale]?: Record<string, string>;
45
- };
58
+ export declare function isI18nStr(value: string, delimiters: [string, string]): boolean;
59
+
60
+ export declare const isString: (val: unknown) => val is string;
61
+
62
+ declare type Locale = string;
63
+
64
+ export declare const LOCALE_EN = "en";
65
+
66
+ export declare const LOCALE_ES = "es";
46
67
 
47
- export declare type LocaleWatcher = (newLocale: BuiltInLocale, oldLocale: BuiltInLocale) => void;
68
+ export declare const LOCALE_FR = "fr";
69
+
70
+ export declare const LOCALE_ZH_HANS = "zh-Hans";
71
+
72
+ export declare const LOCALE_ZH_HANT = "zh-Hant";
73
+
74
+ export declare type LocaleMessages = Record<string, Record<string, string>>;
75
+
76
+ export declare type LocaleWatcher = (newLocale: string, oldLocale: string) => void;
77
+
78
+ export declare function normalizeLocale(locale: string, messages?: LocaleMessages): BuiltInLocale | undefined;
79
+
80
+ export declare function parseI18nJson(jsonObj: unknown, values: Record<string, string>, delimiters: [string, string]): unknown;
81
+
82
+ export declare function resolveLocale(locales: Locale[]): (locale: Locale) => string | undefined;
83
+
84
+ declare type Token = {
85
+ type: 'text' | 'named' | 'list' | 'unknown';
86
+ value: string;
87
+ };
48
88
 
49
89
  export { }
@@ -0,0 +1,454 @@
1
+ const isArray = Array.isArray;
2
+ const isObject = (val) => val !== null && typeof val === 'object';
3
+ const defaultDelimiters = ['{', '}'];
4
+ class BaseFormatter {
5
+ constructor() {
6
+ this._caches = Object.create(null);
7
+ }
8
+ interpolate(message, values, delimiters = defaultDelimiters) {
9
+ if (!values) {
10
+ return [message];
11
+ }
12
+ let tokens = this._caches[message];
13
+ if (!tokens) {
14
+ tokens = parse(message, delimiters);
15
+ this._caches[message] = tokens;
16
+ }
17
+ return compile(tokens, values);
18
+ }
19
+ }
20
+ const RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
21
+ const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
22
+ function parse(format, [startDelimiter, endDelimiter]) {
23
+ const tokens = [];
24
+ let position = 0;
25
+ let text = '';
26
+ while (position < format.length) {
27
+ let char = format[position++];
28
+ if (char === startDelimiter) {
29
+ if (text) {
30
+ tokens.push({ type: 'text', value: text });
31
+ }
32
+ text = '';
33
+ let sub = '';
34
+ char = format[position++];
35
+ while (char !== undefined && char !== endDelimiter) {
36
+ sub += char;
37
+ char = format[position++];
38
+ }
39
+ const isClosed = char === endDelimiter;
40
+ const type = RE_TOKEN_LIST_VALUE.test(sub)
41
+ ? 'list'
42
+ : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
43
+ ? 'named'
44
+ : 'unknown';
45
+ tokens.push({ value: sub, type });
46
+ }
47
+ // else if (char === '%') {
48
+ // // when found rails i18n syntax, skip text capture
49
+ // if (format[position] !== '{') {
50
+ // text += char
51
+ // }
52
+ // }
53
+ else {
54
+ text += char;
55
+ }
56
+ }
57
+ text && tokens.push({ type: 'text', value: text });
58
+ return tokens;
59
+ }
60
+ function compile(tokens, values) {
61
+ const compiled = [];
62
+ let index = 0;
63
+ const mode = isArray(values)
64
+ ? 'list'
65
+ : isObject(values)
66
+ ? 'named'
67
+ : 'unknown';
68
+ if (mode === 'unknown') {
69
+ return compiled;
70
+ }
71
+ while (index < tokens.length) {
72
+ const token = tokens[index];
73
+ switch (token.type) {
74
+ case 'text':
75
+ compiled.push(token.value);
76
+ break;
77
+ case 'list':
78
+ compiled.push(values[parseInt(token.value, 10)]);
79
+ break;
80
+ case 'named':
81
+ if (mode === 'named') {
82
+ compiled.push(values[token.value]);
83
+ }
84
+ else {
85
+ if (process.env.NODE_ENV !== 'production') {
86
+ console.warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`);
87
+ }
88
+ }
89
+ break;
90
+ case 'unknown':
91
+ if (process.env.NODE_ENV !== 'production') {
92
+ console.warn(`Detect 'unknown' type of token!`);
93
+ }
94
+ break;
95
+ }
96
+ index++;
97
+ }
98
+ return compiled;
99
+ }
100
+
101
+ const LOCALE_ZH_HANS = 'zh-Hans';
102
+ const LOCALE_ZH_HANT = 'zh-Hant';
103
+ const LOCALE_EN = 'en';
104
+ const LOCALE_FR = 'fr';
105
+ const LOCALE_ES = 'es';
106
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
107
+ const hasOwn = (val, key) => hasOwnProperty.call(val, key);
108
+ const defaultFormatter = new BaseFormatter();
109
+ function include(str, parts) {
110
+ return !!parts.find((part) => str.indexOf(part) !== -1);
111
+ }
112
+ function startsWith(str, parts) {
113
+ return parts.find((part) => str.indexOf(part) === 0);
114
+ }
115
+ function normalizeLocale(locale, messages) {
116
+ if (!locale) {
117
+ return;
118
+ }
119
+ locale = locale.trim().replace(/_/g, '-');
120
+ if (messages && messages[locale]) {
121
+ return locale;
122
+ }
123
+ locale = locale.toLowerCase();
124
+ if (locale.indexOf('zh') === 0) {
125
+ if (locale.indexOf('-hans') > -1) {
126
+ return LOCALE_ZH_HANS;
127
+ }
128
+ if (locale.indexOf('-hant') > -1) {
129
+ return LOCALE_ZH_HANT;
130
+ }
131
+ if (include(locale, ['-tw', '-hk', '-mo', '-cht'])) {
132
+ return LOCALE_ZH_HANT;
133
+ }
134
+ return LOCALE_ZH_HANS;
135
+ }
136
+ const lang = startsWith(locale, [LOCALE_EN, LOCALE_FR, LOCALE_ES]);
137
+ if (lang) {
138
+ return lang;
139
+ }
140
+ }
141
+ class I18n {
142
+ constructor({ locale, fallbackLocale, messages, watcher, formater, }) {
143
+ this.locale = LOCALE_EN;
144
+ this.fallbackLocale = LOCALE_EN;
145
+ this.message = {};
146
+ this.messages = {};
147
+ this.watchers = [];
148
+ if (fallbackLocale) {
149
+ this.fallbackLocale = fallbackLocale;
150
+ }
151
+ this.formater = formater || defaultFormatter;
152
+ this.messages = messages || {};
153
+ this.setLocale(locale || LOCALE_EN);
154
+ if (watcher) {
155
+ this.watchLocale(watcher);
156
+ }
157
+ }
158
+ setLocale(locale) {
159
+ const oldLocale = this.locale;
160
+ this.locale = normalizeLocale(locale, this.messages) || this.fallbackLocale;
161
+ if (!this.messages[this.locale]) {
162
+ // 可能初始化时不存在
163
+ this.messages[this.locale] = {};
164
+ }
165
+ this.message = this.messages[this.locale];
166
+ // 仅发生变化时,通知
167
+ if (oldLocale !== this.locale) {
168
+ this.watchers.forEach((watcher) => {
169
+ watcher(this.locale, oldLocale);
170
+ });
171
+ }
172
+ }
173
+ getLocale() {
174
+ return this.locale;
175
+ }
176
+ watchLocale(fn) {
177
+ const index = this.watchers.push(fn) - 1;
178
+ return () => {
179
+ this.watchers.splice(index, 1);
180
+ };
181
+ }
182
+ add(locale, message, override = true) {
183
+ const curMessages = this.messages[locale];
184
+ if (curMessages) {
185
+ if (override) {
186
+ Object.assign(curMessages, message);
187
+ }
188
+ else {
189
+ Object.keys(message).forEach((key) => {
190
+ if (!hasOwn(curMessages, key)) {
191
+ curMessages[key] = message[key];
192
+ }
193
+ });
194
+ }
195
+ }
196
+ else {
197
+ this.messages[locale] = message;
198
+ }
199
+ }
200
+ f(message, values, delimiters) {
201
+ return this.formater.interpolate(message, values, delimiters).join('');
202
+ }
203
+ t(key, locale, values) {
204
+ let message = this.message;
205
+ if (typeof locale === 'string') {
206
+ locale = normalizeLocale(locale, this.messages);
207
+ locale && (message = this.messages[locale]);
208
+ }
209
+ else {
210
+ values = locale;
211
+ }
212
+ if (!hasOwn(message, key)) {
213
+ console.warn(`Cannot translate the value of keypath ${key}. Use the value of keypath as default.`);
214
+ return key;
215
+ }
216
+ return this.formater.interpolate(message[key], values).join('');
217
+ }
218
+ }
219
+
220
+ function watchAppLocale(appVm, i18n) {
221
+ // 需要保证 watch 的触发在组件渲染之前
222
+ if (appVm.$watchLocale) {
223
+ // vue2
224
+ appVm.$watchLocale((newLocale) => {
225
+ i18n.setLocale(newLocale);
226
+ });
227
+ }
228
+ else {
229
+ appVm.$watch(() => appVm.$locale, (newLocale) => {
230
+ i18n.setLocale(newLocale);
231
+ });
232
+ }
233
+ }
234
+ function getDefaultLocale() {
235
+ if (typeof uni !== 'undefined' && uni.getLocale) {
236
+ return uni.getLocale();
237
+ }
238
+ // 小程序平台,uni 和 uni-i18n 互相引用,导致访问不到 uni,故在 global 上挂了 getLocale
239
+ if (typeof global !== 'undefined' && global.getLocale) {
240
+ return global.getLocale();
241
+ }
242
+ return LOCALE_EN;
243
+ }
244
+ function initVueI18n(locale, messages = {}, fallbackLocale, watcher) {
245
+ // 兼容旧版本入参
246
+ if (typeof locale !== 'string') {
247
+ [locale, messages] = [
248
+ messages,
249
+ locale,
250
+ ];
251
+ }
252
+ if (typeof locale !== 'string') {
253
+ // 因为小程序平台,uni-i18n 和 uni 互相引用,导致此时访问 uni 时,为 undefined
254
+ locale = getDefaultLocale();
255
+ }
256
+ if (typeof fallbackLocale !== 'string') {
257
+ fallbackLocale =
258
+ (typeof __uniConfig !== 'undefined' && __uniConfig.fallbackLocale) ||
259
+ LOCALE_EN;
260
+ }
261
+ const i18n = new I18n({
262
+ locale,
263
+ fallbackLocale,
264
+ messages,
265
+ watcher,
266
+ });
267
+ let t = (key, values) => {
268
+ if (typeof getApp !== 'function') {
269
+ // app view
270
+ /* eslint-disable no-func-assign */
271
+ t = function (key, values) {
272
+ return i18n.t(key, values);
273
+ };
274
+ }
275
+ else {
276
+ let isWatchedAppLocale = false;
277
+ t = function (key, values) {
278
+ const appVm = getApp().$vm;
279
+ // 可能$vm还不存在,比如在支付宝小程序中,组件定义较早,在props的default里使用了t()函数(如uni-goods-nav),此时app还未初始化
280
+ // options: {
281
+ // type: Array,
282
+ // default () {
283
+ // return [{
284
+ // icon: 'shop',
285
+ // text: t("uni-goods-nav.options.shop"),
286
+ // }, {
287
+ // icon: 'cart',
288
+ // text: t("uni-goods-nav.options.cart")
289
+ // }]
290
+ // }
291
+ // },
292
+ if (appVm) {
293
+ // 触发响应式
294
+ appVm.$locale;
295
+ if (!isWatchedAppLocale) {
296
+ isWatchedAppLocale = true;
297
+ watchAppLocale(appVm, i18n);
298
+ }
299
+ }
300
+ return i18n.t(key, values);
301
+ };
302
+ }
303
+ return t(key, values);
304
+ };
305
+ return {
306
+ i18n,
307
+ f(message, values, delimiters) {
308
+ return i18n.f(message, values, delimiters);
309
+ },
310
+ t(key, values) {
311
+ return t(key, values);
312
+ },
313
+ add(locale, message, override = true) {
314
+ return i18n.add(locale, message, override);
315
+ },
316
+ watch(fn) {
317
+ return i18n.watchLocale(fn);
318
+ },
319
+ getLocale() {
320
+ return i18n.getLocale();
321
+ },
322
+ setLocale(newLocale) {
323
+ return i18n.setLocale(newLocale);
324
+ },
325
+ };
326
+ }
327
+
328
+ const isString = (val) => typeof val === 'string';
329
+ let formater;
330
+ function hasI18nJson(jsonObj, delimiters) {
331
+ if (!formater) {
332
+ formater = new BaseFormatter();
333
+ }
334
+ return walkJsonObj(jsonObj, (jsonObj, key) => {
335
+ const value = jsonObj[key];
336
+ if (isString(value)) {
337
+ if (isI18nStr(value, delimiters)) {
338
+ return true;
339
+ }
340
+ }
341
+ else {
342
+ return hasI18nJson(value, delimiters);
343
+ }
344
+ });
345
+ }
346
+ function parseI18nJson(jsonObj, values, delimiters) {
347
+ if (!formater) {
348
+ formater = new BaseFormatter();
349
+ }
350
+ walkJsonObj(jsonObj, (jsonObj, key) => {
351
+ const value = jsonObj[key];
352
+ if (isString(value)) {
353
+ if (isI18nStr(value, delimiters)) {
354
+ jsonObj[key] = compileStr(value, values, delimiters);
355
+ }
356
+ }
357
+ else {
358
+ parseI18nJson(value, values, delimiters);
359
+ }
360
+ });
361
+ return jsonObj;
362
+ }
363
+ function compileI18nJsonStr(jsonStr, { locale, locales, delimiters, }) {
364
+ if (!isI18nStr(jsonStr, delimiters)) {
365
+ return jsonStr;
366
+ }
367
+ if (!formater) {
368
+ formater = new BaseFormatter();
369
+ }
370
+ const localeValues = [];
371
+ Object.keys(locales).forEach((name) => {
372
+ if (name !== locale) {
373
+ localeValues.push({
374
+ locale: name,
375
+ values: locales[name],
376
+ });
377
+ }
378
+ });
379
+ localeValues.unshift({ locale, values: locales[locale] });
380
+ try {
381
+ return JSON.stringify(compileJsonObj(JSON.parse(jsonStr), localeValues, delimiters), null, 2);
382
+ }
383
+ catch (e) { }
384
+ return jsonStr;
385
+ }
386
+ function isI18nStr(value, delimiters) {
387
+ return value.indexOf(delimiters[0]) > -1;
388
+ }
389
+ function compileStr(value, values, delimiters) {
390
+ return formater.interpolate(value, values, delimiters).join('');
391
+ }
392
+ function compileValue(jsonObj, key, localeValues, delimiters) {
393
+ const value = jsonObj[key];
394
+ if (isString(value)) {
395
+ // 存在国际化
396
+ if (isI18nStr(value, delimiters)) {
397
+ jsonObj[key] = compileStr(value, localeValues[0].values, delimiters);
398
+ if (localeValues.length > 1) {
399
+ // 格式化国际化语言
400
+ const valueLocales = (jsonObj[key + 'Locales'] = {});
401
+ localeValues.forEach((localValue) => {
402
+ valueLocales[localValue.locale] = compileStr(value, localValue.values, delimiters);
403
+ });
404
+ }
405
+ }
406
+ }
407
+ else {
408
+ compileJsonObj(value, localeValues, delimiters);
409
+ }
410
+ }
411
+ function compileJsonObj(jsonObj, localeValues, delimiters) {
412
+ walkJsonObj(jsonObj, (jsonObj, key) => {
413
+ compileValue(jsonObj, key, localeValues, delimiters);
414
+ });
415
+ return jsonObj;
416
+ }
417
+ function walkJsonObj(jsonObj, walk) {
418
+ if (isArray(jsonObj)) {
419
+ for (let i = 0; i < jsonObj.length; i++) {
420
+ if (walk(jsonObj, i)) {
421
+ return true;
422
+ }
423
+ }
424
+ }
425
+ else if (isObject(jsonObj)) {
426
+ for (const key in jsonObj) {
427
+ if (walk(jsonObj, key)) {
428
+ return true;
429
+ }
430
+ }
431
+ }
432
+ return false;
433
+ }
434
+
435
+ function resolveLocale(locales) {
436
+ return (locale) => {
437
+ if (!locale) {
438
+ return locale;
439
+ }
440
+ locale = normalizeLocale(locale) || locale;
441
+ return resolveLocaleChain(locale).find((locale) => locales.indexOf(locale) > -1);
442
+ };
443
+ }
444
+ function resolveLocaleChain(locale) {
445
+ const chain = [];
446
+ const tokens = locale.split('-');
447
+ while (tokens.length) {
448
+ chain.push(tokens.join('-'));
449
+ tokens.pop();
450
+ }
451
+ return chain;
452
+ }
453
+
454
+ export { BaseFormatter as Formatter, I18n, LOCALE_EN, LOCALE_ES, LOCALE_FR, LOCALE_ZH_HANS, LOCALE_ZH_HANT, compileI18nJsonStr, hasI18nJson, initVueI18n, isI18nStr, isString, normalizeLocale, parseI18nJson, resolveLocale };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dcloudio/uni-i18n",
3
- "version": "2.0.0",
3
+ "version": "2.0.1-32920211122002",
4
4
  "description": "@dcloudio/uni-i18n",
5
- "main": "dist/uni-i18n.cjs.js",
6
- "module": "dist/uni-i18n.esm.js",
7
- "types": "dist/uni-i18n.d.ts",
5
+ "main": "./dist/uni-i18n.cjs.js",
6
+ "module": "./dist/uni-i18n.es.js",
7
+ "types": "./dist/uni-i18n.d.ts",
8
8
  "files": [
9
9
  "dist"
10
10
  ],
@@ -18,5 +18,5 @@
18
18
  "bugs": {
19
19
  "url": "https://github.com/dcloudio/uni-app/issues"
20
20
  },
21
- "gitHead": "b1bdfb4de3f518c1c0fbab242403ea05feced4e3"
21
+ "gitHead": "dc33ced4b2fff3063385d9eda8dd1f3539133a67"
22
22
  }
@@ -1,274 +0,0 @@
1
- const isObject = (val) => val !== null && typeof val === 'object';
2
- class BaseFormatter {
3
- constructor() {
4
- this._caches = Object.create(null);
5
- }
6
- interpolate(message, values) {
7
- if (!values) {
8
- return [message];
9
- }
10
- let tokens = this._caches[message];
11
- if (!tokens) {
12
- tokens = parse(message);
13
- this._caches[message] = tokens;
14
- }
15
- return compile(tokens, values);
16
- }
17
- }
18
- const RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
19
- const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
20
- function parse(format) {
21
- const tokens = [];
22
- let position = 0;
23
- let text = '';
24
- while (position < format.length) {
25
- let char = format[position++];
26
- if (char === '{') {
27
- if (text) {
28
- tokens.push({ type: 'text', value: text });
29
- }
30
- text = '';
31
- let sub = '';
32
- char = format[position++];
33
- while (char !== undefined && char !== '}') {
34
- sub += char;
35
- char = format[position++];
36
- }
37
- const isClosed = char === '}';
38
- const type = RE_TOKEN_LIST_VALUE.test(sub)
39
- ? 'list'
40
- : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
41
- ? 'named'
42
- : 'unknown';
43
- tokens.push({ value: sub, type });
44
- }
45
- else if (char === '%') {
46
- // when found rails i18n syntax, skip text capture
47
- if (format[position] !== '{') {
48
- text += char;
49
- }
50
- }
51
- else {
52
- text += char;
53
- }
54
- }
55
- text && tokens.push({ type: 'text', value: text });
56
- return tokens;
57
- }
58
- function compile(tokens, values) {
59
- const compiled = [];
60
- let index = 0;
61
- const mode = Array.isArray(values)
62
- ? 'list'
63
- : isObject(values)
64
- ? 'named'
65
- : 'unknown';
66
- if (mode === 'unknown') {
67
- return compiled;
68
- }
69
- while (index < tokens.length) {
70
- const token = tokens[index];
71
- switch (token.type) {
72
- case 'text':
73
- compiled.push(token.value);
74
- break;
75
- case 'list':
76
- compiled.push(values[parseInt(token.value, 10)]);
77
- break;
78
- case 'named':
79
- if (mode === 'named') {
80
- compiled.push(values[token.value]);
81
- }
82
- else {
83
- if (process.env.NODE_ENV !== 'production') {
84
- console.warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`);
85
- }
86
- }
87
- break;
88
- case 'unknown':
89
- if (process.env.NODE_ENV !== 'production') {
90
- console.warn(`Detect 'unknown' type of token!`);
91
- }
92
- break;
93
- }
94
- index++;
95
- }
96
- return compiled;
97
- }
98
-
99
- const hasOwnProperty = Object.prototype.hasOwnProperty;
100
- const hasOwn = (val, key) => hasOwnProperty.call(val, key);
101
- const defaultFormatter = new BaseFormatter();
102
- function include(str, parts) {
103
- return !!parts.find((part) => str.indexOf(part) !== -1);
104
- }
105
- function startsWith(str, parts) {
106
- return parts.find((part) => str.indexOf(part) === 0);
107
- }
108
- function normalizeLocale(locale, messages) {
109
- if (!locale) {
110
- return;
111
- }
112
- locale = locale.trim().replace(/_/g, '-');
113
- if (messages[locale]) {
114
- return locale;
115
- }
116
- locale = locale.toLowerCase();
117
- if (locale.indexOf('zh') === 0) {
118
- if (locale.indexOf('-hans') !== -1) {
119
- return 'zh-Hans';
120
- }
121
- if (locale.indexOf('-hant') !== -1) {
122
- return 'zh-Hant';
123
- }
124
- if (include(locale, ['-tw', '-hk', '-mo', '-cht'])) {
125
- return 'zh-Hant';
126
- }
127
- return 'zh-Hans';
128
- }
129
- const lang = startsWith(locale, ['en', 'fr', 'es']);
130
- if (lang) {
131
- return lang;
132
- }
133
- }
134
- class I18n {
135
- constructor({ locale, fallbackLocale, messages, watcher, formater, }) {
136
- this.locale = 'en';
137
- this.fallbackLocale = 'en';
138
- this.message = {};
139
- this.messages = {};
140
- this.watchers = [];
141
- if (fallbackLocale) {
142
- this.fallbackLocale = fallbackLocale;
143
- }
144
- this.formater = formater || defaultFormatter;
145
- this.messages = messages;
146
- this.setLocale(locale);
147
- if (watcher) {
148
- this.watchLocale(watcher);
149
- }
150
- }
151
- setLocale(locale) {
152
- const oldLocale = this.locale;
153
- this.locale = normalizeLocale(locale, this.messages) || this.fallbackLocale;
154
- this.message = this.messages[this.locale];
155
- this.watchers.forEach((watcher) => {
156
- watcher(this.locale, oldLocale);
157
- });
158
- }
159
- getLocale() {
160
- return this.locale;
161
- }
162
- watchLocale(fn) {
163
- const index = this.watchers.push(fn) - 1;
164
- return () => {
165
- this.watchers.splice(index, 1);
166
- };
167
- }
168
- t(key, locale, values) {
169
- let message = this.message;
170
- if (typeof locale === 'string') {
171
- locale = normalizeLocale(locale, this.messages);
172
- locale && (message = this.messages[locale]);
173
- }
174
- else {
175
- values = locale;
176
- }
177
- if (!hasOwn(message, key)) {
178
- console.warn(`Cannot translate the value of keypath ${key}. Use the value of keypath as default.`);
179
- return key;
180
- }
181
- return this.formater.interpolate(message[key], values).join('');
182
- }
183
- }
184
-
185
- function initLocaleWatcher(appVm, i18n) {
186
- appVm.$i18n &&
187
- appVm.$i18n.vm.$watch('locale', (newLocale) => {
188
- i18n.setLocale(newLocale);
189
- }, {
190
- immediate: true,
191
- });
192
- }
193
- function getDefaultLocale() {
194
- if (typeof navigator !== 'undefined') {
195
- return navigator.userLanguage || navigator.language;
196
- }
197
- if (typeof plus !== 'undefined') {
198
- // TODO 待调整为最新的获取语言代码
199
- return plus.os.language;
200
- }
201
- return uni.getSystemInfoSync().language;
202
- }
203
- function initVueI18n(messages, fallbackLocale = 'en', locale) {
204
- const i18n = new I18n({
205
- locale: locale || fallbackLocale,
206
- fallbackLocale,
207
- messages,
208
- });
209
- let t = (key, values) => {
210
- if (typeof getApp !== 'function') {
211
- // app-plus view
212
- /* eslint-disable no-func-assign */
213
- t = function (key, values) {
214
- return i18n.t(key, values);
215
- };
216
- }
217
- else {
218
- const appVm = getApp().$vm;
219
- if (!appVm.$t || !appVm.$i18n) {
220
- if (!locale) {
221
- i18n.setLocale(getDefaultLocale());
222
- }
223
- /* eslint-disable no-func-assign */
224
- t = function (key, values) {
225
- return i18n.t(key, values);
226
- };
227
- }
228
- else {
229
- initLocaleWatcher(appVm, i18n);
230
- /* eslint-disable no-func-assign */
231
- t = function (key, values) {
232
- const $i18n = appVm.$i18n;
233
- const silentTranslationWarn = $i18n.silentTranslationWarn;
234
- $i18n.silentTranslationWarn = true;
235
- const msg = appVm.$t(key, values);
236
- $i18n.silentTranslationWarn = silentTranslationWarn;
237
- if (msg !== key) {
238
- return msg;
239
- }
240
- return i18n.t(key, $i18n.locale, values);
241
- };
242
- }
243
- }
244
- return t(key, values);
245
- };
246
- return {
247
- t(key, values) {
248
- return t(key, values);
249
- },
250
- getLocale() {
251
- return i18n.getLocale();
252
- },
253
- setLocale(newLocale) {
254
- return i18n.setLocale(newLocale);
255
- },
256
- mixin: {
257
- beforeCreate() {
258
- const unwatch = i18n.watchLocale(() => {
259
- this.$forceUpdate();
260
- });
261
- this.$once('hook:beforeDestroy', function () {
262
- unwatch();
263
- });
264
- },
265
- methods: {
266
- $$t(key, values) {
267
- return t(key, values);
268
- },
269
- },
270
- },
271
- };
272
- }
273
-
274
- export { I18n, initVueI18n };