diff --git a/packages/uni-i18n/dist/uni-i18n.cjs.js b/packages/uni-i18n/dist/uni-i18n.cjs.js index d2fd405df6ded854d3f433715cb339fccf5f5656..5e7e69eff833211662038cbb3a0f942dce6dd2d7 100644 --- a/packages/uni-i18n/dist/uni-i18n.cjs.js +++ b/packages/uni-i18n/dist/uni-i18n.cjs.js @@ -1,19 +1,21 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +const isArray = Array.isArray; const isObject = (val) => val !== null && typeof val === 'object'; +const defaultDelimiters = ['{', '}']; class BaseFormatter { constructor() { this._caches = Object.create(null); } - interpolate(message, values) { + interpolate(message, values, delimiters = defaultDelimiters) { if (!values) { return [message]; } let tokens = this._caches[message]; if (!tokens) { - tokens = parse(message); + tokens = parse(message, delimiters); this._caches[message] = tokens; } return compile(tokens, values); @@ -21,24 +23,24 @@ class BaseFormatter { } const RE_TOKEN_LIST_VALUE = /^(?:\d)+/; const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/; -function parse(format) { +function parse(format, [startDelimiter, endDelimiter]) { const tokens = []; let position = 0; let text = ''; while (position < format.length) { let char = format[position++]; - if (char === '{') { + if (char === startDelimiter) { if (text) { tokens.push({ type: 'text', value: text }); } text = ''; let sub = ''; char = format[position++]; - while (char !== undefined && char !== '}') { + while (char !== undefined && char !== endDelimiter) { sub += char; char = format[position++]; } - const isClosed = char === '}'; + const isClosed = char === endDelimiter; const type = RE_TOKEN_LIST_VALUE.test(sub) ? 'list' : isClosed && RE_TOKEN_NAMED_VALUE.test(sub) @@ -46,12 +48,12 @@ function parse(format) { : 'unknown'; tokens.push({ value: sub, type }); } - else if (char === '%') { - // when found rails i18n syntax, skip text capture - if (format[position] !== '{') { - text += char; - } - } + // else if (char === '%') { + // // when found rails i18n syntax, skip text capture + // if (format[position] !== '{') { + // text += char + // } + // } else { text += char; } @@ -62,7 +64,7 @@ function parse(format) { function compile(tokens, values) { const compiled = []; let index = 0; - const mode = Array.isArray(values) + const mode = isArray(values) ? 'list' : isObject(values) ? 'named' @@ -98,8 +100,8 @@ function compile(tokens, values) { index++; } return compiled; -} - +} + const LOCALE_ZH_HANS = 'zh-Hans'; const LOCALE_ZH_HANT = 'zh-Hant'; const LOCALE_EN = 'en'; @@ -119,7 +121,7 @@ function normalizeLocale(locale, messages) { return; } locale = locale.trim().replace(/_/g, '-'); - if (messages[locale]) { + if (messages && messages[locale]) { return locale; } locale = locale.toLowerCase(); @@ -152,7 +154,7 @@ class I18n { } this.formater = formater || defaultFormatter; this.messages = messages || {}; - this.setLocale(locale); + this.setLocale(locale || LOCALE_EN); if (watcher) { this.watchLocale(watcher); } @@ -165,9 +167,12 @@ class I18n { this.messages[this.locale] = {}; } this.message = this.messages[this.locale]; - this.watchers.forEach((watcher) => { - watcher(this.locale, oldLocale); - }); + // 仅发生变化时,通知 + if (oldLocale !== this.locale) { + this.watchers.forEach((watcher) => { + watcher(this.locale, oldLocale); + }); + } } getLocale() { return this.locale; @@ -178,14 +183,27 @@ class I18n { this.watchers.splice(index, 1); }; } - add(locale, message) { - if (this.messages[locale]) { - Object.assign(this.messages[locale], message); + add(locale, message, override = true) { + const curMessages = this.messages[locale]; + if (curMessages) { + if (override) { + Object.assign(curMessages, message); + } + else { + Object.keys(message).forEach((key) => { + if (!hasOwn(curMessages, key)) { + curMessages[key] = message[key]; + } + }); + } } else { this.messages[locale] = message; } } + f(message, values, delimiters) { + return this.formater.interpolate(message, values, delimiters).join(''); + } t(key, locale, values) { let message = this.message; if (typeof locale === 'string') { @@ -201,39 +219,34 @@ class I18n { } return this.formater.interpolate(message[key], values).join(''); } -} - +} + const ignoreVueI18n = true; -function initLocaleWatcher(appVm, i18n) { - if (appVm.$i18n) { - const vm = appVm.$i18n.vm ? appVm.$i18n.vm : appVm; - vm.$watch(appVm.$i18n.vm ? 'locale' : () => appVm.$i18n.locale, (newLocale) => { - i18n.setLocale(newLocale); - }, { - immediate: true, - }); - } +function watchAppLocale(appVm, i18n) { + appVm.$watch(() => appVm.$locale, (newLocale) => { + i18n.setLocale(newLocale); + }); } -// function getDefaultLocale() { -// if (typeof navigator !== 'undefined') { -// return (navigator as any).userLanguage || navigator.language -// } -// if (typeof plus !== 'undefined') { -// // TODO 待调整为最新的获取语言代码 -// return plus.os.language -// } -// return uni.getSystemInfoSync().language -// } -function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_EN, watcher) { +function initVueI18n(locale, messages = {}, fallbackLocale, watcher) { // 兼容旧版本入参 if (typeof locale !== 'string') { - [locale, messages] = [messages, locale]; + [locale, messages] = [ + messages, + locale, + ]; } if (typeof locale !== 'string') { - locale = fallbackLocale; + locale = + (typeof uni !== 'undefined' && uni.getLocale && uni.getLocale()) || + LOCALE_EN; + } + if (typeof fallbackLocale !== 'string') { + fallbackLocale = + (typeof __uniConfig !== 'undefined' && __uniConfig.fallbackLocale) || + LOCALE_EN; } const i18n = new I18n({ - locale: locale || fallbackLocale, + locale, fallbackLocale, messages, watcher, @@ -248,17 +261,19 @@ function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_ } else { const appVm = getApp().$vm; + watchAppLocale(appVm, i18n); if (!appVm.$t || !appVm.$i18n || ignoreVueI18n) { // if (!locale) { // i18n.setLocale(getDefaultLocale()) // } /* eslint-disable no-func-assign */ t = function (key, values) { + // 触发响应式 + appVm.$locale; return i18n.t(key, values); }; } else { - initLocaleWatcher(appVm, i18n); /* eslint-disable no-func-assign */ t = function (key, values) { const $i18n = appVm.$i18n; @@ -277,11 +292,17 @@ function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_ }; return { i18n, + f(message, values, delimiters) { + return i18n.f(message, values, delimiters); + }, t(key, values) { return t(key, values); }, - add(locale, message) { - return i18n.add(locale, message); + add(locale, message, override = true) { + return i18n.add(locale, message, override); + }, + watch(fn) { + return i18n.watchLocale(fn); }, getLocale() { return i18n.getLocale(); @@ -290,12 +311,126 @@ function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_ return i18n.setLocale(newLocale); }, }; +} + +const isString = (val) => typeof val === 'string'; +let formater; +function hasI18nJson(jsonObj, delimiters) { + if (!formater) { + formater = new BaseFormatter(); + } + return walkJsonObj(jsonObj, (jsonObj, key) => { + const value = jsonObj[key]; + if (isString(value)) { + if (isI18nStr(value, delimiters)) { + return true; + } + } + else { + return hasI18nJson(value, delimiters); + } + }); } - -exports.I18n = I18n; -exports.LOCALE_EN = LOCALE_EN; -exports.LOCALE_ES = LOCALE_ES; -exports.LOCALE_FR = LOCALE_FR; -exports.LOCALE_ZH_HANS = LOCALE_ZH_HANS; -exports.LOCALE_ZH_HANT = LOCALE_ZH_HANT; -exports.initVueI18n = initVueI18n; +function parseI18nJson(jsonObj, values, delimiters) { + if (!formater) { + formater = new BaseFormatter(); + } + walkJsonObj(jsonObj, (jsonObj, key) => { + const value = jsonObj[key]; + if (isString(value)) { + if (isI18nStr(value, delimiters)) { + jsonObj[key] = compileStr(value, values, delimiters); + } + } + else { + parseI18nJson(value, values, delimiters); + } + }); + return jsonObj; +} +function compileI18nJsonStr(jsonStr, { locale, locales, delimiters, }) { + if (!isI18nStr(jsonStr, delimiters)) { + return jsonStr; + } + if (!formater) { + formater = new BaseFormatter(); + } + const localeValues = []; + Object.keys(locales).forEach((name) => { + if (name !== locale) { + localeValues.push({ + locale: name, + values: locales[name], + }); + } + }); + localeValues.unshift({ locale, values: locales[locale] }); + try { + return JSON.stringify(compileJsonObj(JSON.parse(jsonStr), localeValues, delimiters), null, 2); + } + catch (e) { } + return jsonStr; +} +function isI18nStr(value, delimiters) { + return value.indexOf(delimiters[0]) > -1; +} +function compileStr(value, values, delimiters) { + return formater.interpolate(value, values, delimiters).join(''); +} +function compileValue(jsonObj, key, localeValues, delimiters) { + const value = jsonObj[key]; + if (isString(value)) { + // 存在国际化 + if (isI18nStr(value, delimiters)) { + jsonObj[key] = compileStr(value, localeValues[0].values, delimiters); + if (localeValues.length > 1) { + // 格式化国际化语言 + const valueLocales = (jsonObj[key + 'Locales'] = {}); + localeValues.forEach((localValue) => { + valueLocales[localValue.locale] = compileStr(value, localValue.values, delimiters); + }); + } + } + } + else { + compileJsonObj(value, localeValues, delimiters); + } +} +function compileJsonObj(jsonObj, localeValues, delimiters) { + walkJsonObj(jsonObj, (jsonObj, key) => { + compileValue(jsonObj, key, localeValues, delimiters); + }); + return jsonObj; +} +function walkJsonObj(jsonObj, walk) { + if (isArray(jsonObj)) { + for (let i = 0; i < jsonObj.length; i++) { + if (walk(jsonObj, i)) { + return true; + } + } + } + else if (isObject(jsonObj)) { + for (const key in jsonObj) { + if (walk(jsonObj, key)) { + return true; + } + } + } + return false; +} + +exports.Formatter = BaseFormatter; +exports.I18n = I18n; +exports.LOCALE_EN = LOCALE_EN; +exports.LOCALE_ES = LOCALE_ES; +exports.LOCALE_FR = LOCALE_FR; +exports.LOCALE_ZH_HANS = LOCALE_ZH_HANS; +exports.LOCALE_ZH_HANT = LOCALE_ZH_HANT; +exports.compileI18nJsonStr = compileI18nJsonStr; +exports.hasI18nJson = hasI18nJson; +exports.initVueI18n = initVueI18n; +exports.isI18nStr = isI18nStr; +exports.isString = isString; +exports.normalizeLocale = normalizeLocale; +exports.parseI18nJson = parseI18nJson; diff --git a/packages/uni-i18n/dist/uni-i18n.d.ts b/packages/uni-i18n/dist/uni-i18n.d.ts index b2152ac27c86ce1dc4bb1994ca678882f265e549..85c675ab66acb230bcbe5ce71de840c7921a2780 100644 --- a/packages/uni-i18n/dist/uni-i18n.d.ts +++ b/packages/uni-i18n/dist/uni-i18n.d.ts @@ -1,9 +1,25 @@ export declare type BuiltInLocale = typeof LOCALE_ZH_HANS | typeof LOCALE_ZH_HANT | typeof LOCALE_EN | typeof LOCALE_FR | typeof LOCALE_ES; -export declare interface Formatter { - interpolate: (message: string, values?: Record | Array) => Array; +export declare function compileI18nJsonStr(jsonStr: string, { locale, locales, delimiters, }: { + locale: string; + locales: Record>; + delimiters: [string, string]; +}): string; + +export declare class Formatter { + _caches: { + [key: string]: Array; + }; + constructor(); + interpolate(message: string, values?: Record | Array, delimiters?: [string, string]): Array; +} + +declare interface Formatter_2 { + interpolate: (message: string, values?: Record | Array, delimiters?: [string, string]) => Array; } +export declare function hasI18nJson(jsonObj: unknown, delimiters: [string, string]): boolean; + export declare class I18n { private locale; private fallbackLocale; @@ -13,29 +29,36 @@ export declare class I18n { private formater; constructor({ locale, fallbackLocale, messages, watcher, formater, }: I18nOptions); setLocale(locale: string): void; - getLocale(): BuiltInLocale; + getLocale(): string; watchLocale(fn: LocaleWatcher): () => void; - add(locale: BuiltInLocale, message: Record): void; + add(locale: BuiltInLocale, message: Record, override?: boolean): void; + f(message: string, values?: Record | Array, delimiters?: [string, string]): string; t(key: string, values?: Record | Array | BuiltInLocale): string; t(key: string, locale?: BuiltInLocale, values?: Record | Array): string; } export declare interface I18nOptions { - locale: BuiltInLocale; - fallbackLocale?: BuiltInLocale; + locale: string; + fallbackLocale?: string; messages?: LocaleMessages; - formater?: Formatter; + formater?: Formatter_2; watcher?: LocaleWatcher; } -export declare function initVueI18n(locale?: BuiltInLocale, messages?: LocaleMessages, fallbackLocale?: BuiltInLocale, watcher?: (locale: BuiltInLocale) => void): { +export declare function initVueI18n(locale?: string, messages?: LocaleMessages, fallbackLocale?: string, watcher?: (locale: string) => void): { i18n: I18n; + f(message: string, values?: Record | unknown[] | undefined, delimiters?: [string, string] | undefined): string; t(key: string, values?: Record | unknown[] | undefined): string; - add(locale: BuiltInLocale, message: Record): void; - getLocale(): BuiltInLocale; - setLocale(newLocale: BuiltInLocale): void; + add(locale: BuiltInLocale, message: Record, override?: boolean): void; + watch(fn: LocaleWatcher): () => void; + getLocale(): string; + setLocale(newLocale: string): void; }; +export declare function isI18nStr(value: string, delimiters: [string, string]): boolean; + +export declare const isString: (val: unknown) => val is string; + export declare const LOCALE_EN = "en"; export declare const LOCALE_ES = "es"; @@ -46,10 +69,17 @@ export declare const LOCALE_ZH_HANS = "zh-Hans"; export declare const LOCALE_ZH_HANT = "zh-Hant"; -export declare type LocaleMessages = { - [name in BuiltInLocale]?: Record; -}; +export declare type LocaleMessages = Record>; + +export declare type LocaleWatcher = (newLocale: string, oldLocale: string) => void; + +export declare function normalizeLocale(locale: string, messages?: LocaleMessages): BuiltInLocale | undefined; -export declare type LocaleWatcher = (newLocale: BuiltInLocale, oldLocale: BuiltInLocale) => void; +export declare function parseI18nJson(jsonObj: unknown, values: Record, delimiters: [string, string]): unknown; + +declare type Token = { + type: 'text' | 'named' | 'list' | 'unknown'; + value: string; +}; export { } diff --git a/packages/uni-i18n/dist/uni-i18n.esm.js b/packages/uni-i18n/dist/uni-i18n.es.js similarity index 53% rename from packages/uni-i18n/dist/uni-i18n.esm.js rename to packages/uni-i18n/dist/uni-i18n.es.js index 36c2d5a96c82d0cefe27c3aeb52e272319b23631..d4d1d6331893ba7849f54fc18d7afb11fadd6b68 100644 --- a/packages/uni-i18n/dist/uni-i18n.esm.js +++ b/packages/uni-i18n/dist/uni-i18n.es.js @@ -1,15 +1,17 @@ +const isArray = Array.isArray; const isObject = (val) => val !== null && typeof val === 'object'; +const defaultDelimiters = ['{', '}']; class BaseFormatter { constructor() { this._caches = Object.create(null); } - interpolate(message, values) { + interpolate(message, values, delimiters = defaultDelimiters) { if (!values) { return [message]; } let tokens = this._caches[message]; if (!tokens) { - tokens = parse(message); + tokens = parse(message, delimiters); this._caches[message] = tokens; } return compile(tokens, values); @@ -17,24 +19,24 @@ class BaseFormatter { } const RE_TOKEN_LIST_VALUE = /^(?:\d)+/; const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/; -function parse(format) { +function parse(format, [startDelimiter, endDelimiter]) { const tokens = []; let position = 0; let text = ''; while (position < format.length) { let char = format[position++]; - if (char === '{') { + if (char === startDelimiter) { if (text) { tokens.push({ type: 'text', value: text }); } text = ''; let sub = ''; char = format[position++]; - while (char !== undefined && char !== '}') { + while (char !== undefined && char !== endDelimiter) { sub += char; char = format[position++]; } - const isClosed = char === '}'; + const isClosed = char === endDelimiter; const type = RE_TOKEN_LIST_VALUE.test(sub) ? 'list' : isClosed && RE_TOKEN_NAMED_VALUE.test(sub) @@ -42,12 +44,12 @@ function parse(format) { : 'unknown'; tokens.push({ value: sub, type }); } - else if (char === '%') { - // when found rails i18n syntax, skip text capture - if (format[position] !== '{') { - text += char; - } - } + // else if (char === '%') { + // // when found rails i18n syntax, skip text capture + // if (format[position] !== '{') { + // text += char + // } + // } else { text += char; } @@ -58,7 +60,7 @@ function parse(format) { function compile(tokens, values) { const compiled = []; let index = 0; - const mode = Array.isArray(values) + const mode = isArray(values) ? 'list' : isObject(values) ? 'named' @@ -115,7 +117,7 @@ function normalizeLocale(locale, messages) { return; } locale = locale.trim().replace(/_/g, '-'); - if (messages[locale]) { + if (messages && messages[locale]) { return locale; } locale = locale.toLowerCase(); @@ -148,7 +150,7 @@ class I18n { } this.formater = formater || defaultFormatter; this.messages = messages || {}; - this.setLocale(locale); + this.setLocale(locale || LOCALE_EN); if (watcher) { this.watchLocale(watcher); } @@ -161,9 +163,12 @@ class I18n { this.messages[this.locale] = {}; } this.message = this.messages[this.locale]; - this.watchers.forEach((watcher) => { - watcher(this.locale, oldLocale); - }); + // 仅发生变化时,通知 + if (oldLocale !== this.locale) { + this.watchers.forEach((watcher) => { + watcher(this.locale, oldLocale); + }); + } } getLocale() { return this.locale; @@ -174,14 +179,27 @@ class I18n { this.watchers.splice(index, 1); }; } - add(locale, message) { - if (this.messages[locale]) { - Object.assign(this.messages[locale], message); + add(locale, message, override = true) { + const curMessages = this.messages[locale]; + if (curMessages) { + if (override) { + Object.assign(curMessages, message); + } + else { + Object.keys(message).forEach((key) => { + if (!hasOwn(curMessages, key)) { + curMessages[key] = message[key]; + } + }); + } } else { this.messages[locale] = message; } } + f(message, values, delimiters) { + return this.formater.interpolate(message, values, delimiters).join(''); + } t(key, locale, values) { let message = this.message; if (typeof locale === 'string') { @@ -200,36 +218,31 @@ class I18n { } const ignoreVueI18n = true; -function initLocaleWatcher(appVm, i18n) { - if (appVm.$i18n) { - const vm = appVm.$i18n.vm ? appVm.$i18n.vm : appVm; - vm.$watch(appVm.$i18n.vm ? 'locale' : () => appVm.$i18n.locale, (newLocale) => { - i18n.setLocale(newLocale); - }, { - immediate: true, - }); - } +function watchAppLocale(appVm, i18n) { + appVm.$watch(() => appVm.$locale, (newLocale) => { + i18n.setLocale(newLocale); + }); } -// function getDefaultLocale() { -// if (typeof navigator !== 'undefined') { -// return (navigator as any).userLanguage || navigator.language -// } -// if (typeof plus !== 'undefined') { -// // TODO 待调整为最新的获取语言代码 -// return plus.os.language -// } -// return uni.getSystemInfoSync().language -// } -function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_EN, watcher) { +function initVueI18n(locale, messages = {}, fallbackLocale, watcher) { // 兼容旧版本入参 if (typeof locale !== 'string') { - [locale, messages] = [messages, locale]; + [locale, messages] = [ + messages, + locale, + ]; } if (typeof locale !== 'string') { - locale = fallbackLocale; + locale = + (typeof uni !== 'undefined' && uni.getLocale && uni.getLocale()) || + LOCALE_EN; + } + if (typeof fallbackLocale !== 'string') { + fallbackLocale = + (typeof __uniConfig !== 'undefined' && __uniConfig.fallbackLocale) || + LOCALE_EN; } const i18n = new I18n({ - locale: locale || fallbackLocale, + locale, fallbackLocale, messages, watcher, @@ -244,17 +257,19 @@ function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_ } else { const appVm = getApp().$vm; + watchAppLocale(appVm, i18n); if (!appVm.$t || !appVm.$i18n || ignoreVueI18n) { // if (!locale) { // i18n.setLocale(getDefaultLocale()) // } /* eslint-disable no-func-assign */ t = function (key, values) { + // 触发响应式 + appVm.$locale; return i18n.t(key, values); }; } else { - initLocaleWatcher(appVm, i18n); /* eslint-disable no-func-assign */ t = function (key, values) { const $i18n = appVm.$i18n; @@ -273,11 +288,17 @@ function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_ }; return { i18n, + f(message, values, delimiters) { + return i18n.f(message, values, delimiters); + }, t(key, values) { return t(key, values); }, - add(locale, message) { - return i18n.add(locale, message); + add(locale, message, override = true) { + return i18n.add(locale, message, override); + }, + watch(fn) { + return i18n.watchLocale(fn); }, getLocale() { return i18n.getLocale(); @@ -288,4 +309,111 @@ function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_ }; } -export { I18n, LOCALE_EN, LOCALE_ES, LOCALE_FR, LOCALE_ZH_HANS, LOCALE_ZH_HANT, initVueI18n }; +const isString = (val) => typeof val === 'string'; +let formater; +function hasI18nJson(jsonObj, delimiters) { + if (!formater) { + formater = new BaseFormatter(); + } + return walkJsonObj(jsonObj, (jsonObj, key) => { + const value = jsonObj[key]; + if (isString(value)) { + if (isI18nStr(value, delimiters)) { + return true; + } + } + else { + return hasI18nJson(value, delimiters); + } + }); +} +function parseI18nJson(jsonObj, values, delimiters) { + if (!formater) { + formater = new BaseFormatter(); + } + walkJsonObj(jsonObj, (jsonObj, key) => { + const value = jsonObj[key]; + if (isString(value)) { + if (isI18nStr(value, delimiters)) { + jsonObj[key] = compileStr(value, values, delimiters); + } + } + else { + parseI18nJson(value, values, delimiters); + } + }); + return jsonObj; +} +function compileI18nJsonStr(jsonStr, { locale, locales, delimiters, }) { + if (!isI18nStr(jsonStr, delimiters)) { + return jsonStr; + } + if (!formater) { + formater = new BaseFormatter(); + } + const localeValues = []; + Object.keys(locales).forEach((name) => { + if (name !== locale) { + localeValues.push({ + locale: name, + values: locales[name], + }); + } + }); + localeValues.unshift({ locale, values: locales[locale] }); + try { + return JSON.stringify(compileJsonObj(JSON.parse(jsonStr), localeValues, delimiters), null, 2); + } + catch (e) { } + return jsonStr; +} +function isI18nStr(value, delimiters) { + return value.indexOf(delimiters[0]) > -1; +} +function compileStr(value, values, delimiters) { + return formater.interpolate(value, values, delimiters).join(''); +} +function compileValue(jsonObj, key, localeValues, delimiters) { + const value = jsonObj[key]; + if (isString(value)) { + // 存在国际化 + if (isI18nStr(value, delimiters)) { + jsonObj[key] = compileStr(value, localeValues[0].values, delimiters); + if (localeValues.length > 1) { + // 格式化国际化语言 + const valueLocales = (jsonObj[key + 'Locales'] = {}); + localeValues.forEach((localValue) => { + valueLocales[localValue.locale] = compileStr(value, localValue.values, delimiters); + }); + } + } + } + else { + compileJsonObj(value, localeValues, delimiters); + } +} +function compileJsonObj(jsonObj, localeValues, delimiters) { + walkJsonObj(jsonObj, (jsonObj, key) => { + compileValue(jsonObj, key, localeValues, delimiters); + }); + return jsonObj; +} +function walkJsonObj(jsonObj, walk) { + if (isArray(jsonObj)) { + for (let i = 0; i < jsonObj.length; i++) { + if (walk(jsonObj, i)) { + return true; + } + } + } + else if (isObject(jsonObj)) { + for (const key in jsonObj) { + if (walk(jsonObj, key)) { + return true; + } + } + } + return false; +} + +export { BaseFormatter as Formatter, I18n, LOCALE_EN, LOCALE_ES, LOCALE_FR, LOCALE_ZH_HANS, LOCALE_ZH_HANT, compileI18nJsonStr, hasI18nJson, initVueI18n, isI18nStr, isString, normalizeLocale, parseI18nJson }; diff --git a/packages/uni-i18n/package.json b/packages/uni-i18n/package.json index 3e3dac291e831f99677ca4f48f75e9ca82098045..706c8765043365181a0ac007e98ff9b8300bb46a 100644 --- a/packages/uni-i18n/package.json +++ b/packages/uni-i18n/package.json @@ -2,9 +2,9 @@ "name": "@dcloudio/uni-i18n", "version": "2.0.0-31920210709003", "description": "@dcloudio/uni-i18n", - "main": "dist/uni-i18n.cjs.js", - "module": "dist/uni-i18n.esm.js", - "types": "dist/uni-i18n.d.ts", + "main": "./dist/uni-i18n.cjs.js", + "module": "./dist/uni-i18n.es.js", + "types": "./dist/uni-i18n.d.ts", "files": [ "dist" ], diff --git a/packages/uni-mp-alipay/dist/uni.api.esm.js b/packages/uni-mp-alipay/dist/uni.api.esm.js index cbee7b1c7791b415f9731daab3a502b5f3a2b751..b319981ff37174b1434b8eb6a3d0c24af60e0397 100644 --- a/packages/uni-mp-alipay/dist/uni.api.esm.js +++ b/packages/uni-mp-alipay/dist/uni.api.esm.js @@ -583,7 +583,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -727,6 +727,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -736,6 +760,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); @@ -929,7 +956,7 @@ function handleSystemInfo(fromRes, toRes) { } toRes.platform = platform; } -function returnValue(methodName, res) { +function returnValue(methodName, res = {}) { // 通用 returnValue 解析 if (res.error || res.errorMessage) { res.errMsg = `${methodName}:fail ${res.errorMessage || res.error}`; @@ -1107,8 +1134,18 @@ const connectSocket = { // TODO 有没有返回值还需要测试下 }; const chooseImage = { - returnValue: { - apFilePaths: 'tempFilePaths', + returnValue(result) { + var _a, _b; + const hasTempFilePaths = hasOwn(result, 'tempFilePaths') && result.tempFilePaths; + if (hasOwn(result, 'apFilePaths') && !hasTempFilePaths) { + result.tempFilePaths = []; + (_a = result.apFilePaths) === null || _a === void 0 ? void 0 : _a.forEach((apFilePath) => { var _a; return (_a = result.tempFilePaths) === null || _a === void 0 ? void 0 : _a.push(apFilePath); }); + } + if (!hasOwn(result, 'tempFiles') && hasTempFilePaths) { + result.tempFiles = []; + (_b = result.tempFilePaths) === null || _b === void 0 ? void 0 : _b.forEach((tempFilePath) => { var _a; return (_a = result.tempFiles) === null || _a === void 0 ? void 0 : _a.push({ path: tempFilePath }); }); + } + return {}; }, }; const previewImage = { diff --git a/packages/uni-mp-alipay/dist/uni.mp.esm.js b/packages/uni-mp-alipay/dist/uni.mp.esm.js index a04f9acf31ce9e3a510bc1d0db42757cc7d7fb36..93b8781bc5c7c0daa6060a2ae918a4729603d111 100644 --- a/packages/uni-mp-alipay/dist/uni.mp.esm.js +++ b/packages/uni-mp-alipay/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, isArray, extend, hyphenate, isObject, hasOwn, toNumber, capitalize, isFunction, NOOP, EMPTY_OBJ, camelize } from '@vue/shared'; -import { onUnmounted, injectHook } from 'vue'; +import { onUnmounted, injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -578,6 +578,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -594,6 +595,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; diff --git a/packages/uni-mp-baidu/dist/uni.api.esm.js b/packages/uni-mp-baidu/dist/uni.api.esm.js index d60c8db10911e460a176cdefa0cf33a1b63005d3..65a5f130802dc46a77815bb876600cab06d8fa3e 100644 --- a/packages/uni-mp-baidu/dist/uni.api.esm.js +++ b/packages/uni-mp-baidu/dist/uni.api.esm.js @@ -583,7 +583,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -727,6 +727,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -736,6 +760,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); diff --git a/packages/uni-mp-baidu/dist/uni.mp.esm.js b/packages/uni-mp-baidu/dist/uni.mp.esm.js index 5b473541558e1131871df23c700e7f614dae98f2..bcaa5f73461c7f7f62e4e01497ee05d857fa609d 100644 --- a/packages/uni-mp-baidu/dist/uni.mp.esm.js +++ b/packages/uni-mp-baidu/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, hasOwn, isArray, extend, hyphenate, isObject, toNumber, isFunction, NOOP, camelize } from '@vue/shared'; -import { onUnmounted, injectHook } from 'vue'; +import { onUnmounted, injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -603,6 +603,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -619,6 +620,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; @@ -1179,6 +1191,45 @@ var parseAppOptions = /*#__PURE__*/Object.freeze({ parse: parse$2 }); +/** + * 用于延迟调用 setData + * 在 setData 真实调用的时机需执行 fixSetDataEnd + * @param {*} mpInstance + */ +function fixSetDataStart(mpInstance) { + const setData = mpInstance.setData; + const setDataArgs = []; + mpInstance.setData = function () { + setDataArgs.push(arguments); + }; + mpInstance.__fixInitData = function () { + this.setData = setData; + const fn = () => { + setDataArgs.forEach((args) => { + setData.apply(this, args); + }); + }; + if (setDataArgs.length) { + if (this.groupSetData) { + this.groupSetData(fn); + } + else { + fn(); + } + } + }; +} +/** + * 恢复真实的 setData 方法 + * @param {*} mpInstance + */ +function fixSetDataEnd(mpInstance) { + if (mpInstance.__fixInitData) { + mpInstance.__fixInitData(); + delete mpInstance.__fixInitData; + } +} + function initLifetimes({ mocks, isPage, initRelation, vueOptions, }) { return { attached() { @@ -1250,10 +1301,29 @@ function parse$1(componentOptions) { // lifetimes:attached --> methods:onShow --> methods:onLoad --> methods:onReady // 这里在强制将onShow挪到onLoad之后触发,另外一处修改在page-parser.js const oldAttached = lifetimes.attached; - lifetimes.attached = function attached() { + // 百度小程序基础库 3.260 以上支持页面 onInit 生命周期,提前创建 vm 实例 + lifetimes.onInit = function onInit(query) { + // 百度小程序后续可能移除 pageinstance 属性,为向后兼容进行补充 + if (!this.pageinstance || !this.pageinstance.setData) { + const pages = getCurrentPages(); + this.pageinstance = pages[pages.length - 1]; + } + // 处理百度小程序 onInit 生命周期调用 setData 无效的问题 + fixSetDataStart(this); oldAttached.call(this); + this.pageinstance.$vm = this.$vm; + this.$vm.__call_hook('onInit', query); + }; + lifetimes.attached = function attached() { + if (!this.$vm) { + oldAttached.call(this); + } + else { + initMocks(this.$vm.$, this, mocks); + fixSetDataEnd(this); + } if (isPage(this) && this.$vm) { - // 百度 onLoad 在 attached 之前触发 + // 百度 onLoad 在 attached 之前触发(基础库小于 3.70) // 百度 当组件作为页面时 pageinstance 不是原来组件的 instance const pageInstance = this.pageinstance; pageInstance.$vm = this.$vm; diff --git a/packages/uni-mp-kuaishou/dist/uni.api.esm.js b/packages/uni-mp-kuaishou/dist/uni.api.esm.js index a71abe19788af49d6b83156ca0e48259ae6d5bfe..7ad77fc218800258db99e27aa250920f139b2c8a 100644 --- a/packages/uni-mp-kuaishou/dist/uni.api.esm.js +++ b/packages/uni-mp-kuaishou/dist/uni.api.esm.js @@ -583,7 +583,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -727,6 +727,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -736,6 +760,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); diff --git a/packages/uni-mp-kuaishou/dist/uni.mp.esm.js b/packages/uni-mp-kuaishou/dist/uni.mp.esm.js index 860f9bf9a464c76be791b18c482d08f5d0116950..87ce3029afc74970e1a4da125b96c42db213e403 100644 --- a/packages/uni-mp-kuaishou/dist/uni.mp.esm.js +++ b/packages/uni-mp-kuaishou/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, hasOwn, isArray, extend, hyphenate, isObject, toNumber, isFunction, NOOP, camelize } from '@vue/shared'; -import { onUnmounted, injectHook } from 'vue'; +import { onUnmounted, injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -603,6 +603,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -619,6 +620,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; diff --git a/packages/uni-mp-qq/dist/uni.api.esm.js b/packages/uni-mp-qq/dist/uni.api.esm.js index 6ee33ac8fabbf3bfbc3b7018e0193af230522a1e..9941b76b8dc205554573e3463cee83a4034a4f96 100644 --- a/packages/uni-mp-qq/dist/uni.api.esm.js +++ b/packages/uni-mp-qq/dist/uni.api.esm.js @@ -583,7 +583,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -727,6 +727,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -736,6 +760,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); diff --git a/packages/uni-mp-qq/dist/uni.mp.esm.js b/packages/uni-mp-qq/dist/uni.mp.esm.js index ea73fc1e344f37b13cbe0e2c3772d257b0b5d7a5..d21075e70b357f3097c614fa030aed791f0e4d76 100644 --- a/packages/uni-mp-qq/dist/uni.mp.esm.js +++ b/packages/uni-mp-qq/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, hasOwn, isArray, extend, hyphenate, isObject, toNumber, isFunction, NOOP, camelize } from '@vue/shared'; -import { onUnmounted, injectHook } from 'vue'; +import { onUnmounted, injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -603,6 +603,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -619,6 +620,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; diff --git a/packages/uni-mp-toutiao/dist/uni.api.esm.js b/packages/uni-mp-toutiao/dist/uni.api.esm.js index 758ac002d89bcab69f3aa9d501b5a8626c7f1ef9..bae0f52686fa972c905adc09750812cab13dbb4e 100644 --- a/packages/uni-mp-toutiao/dist/uni.api.esm.js +++ b/packages/uni-mp-toutiao/dist/uni.api.esm.js @@ -583,7 +583,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -727,6 +727,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -736,6 +760,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); diff --git a/packages/uni-mp-toutiao/dist/uni.mp.esm.js b/packages/uni-mp-toutiao/dist/uni.mp.esm.js index c8cc1366d384df7113c9316b77649037496e8d66..de97b679926b8b5a4763255ca9966a4f1e51aa84 100644 --- a/packages/uni-mp-toutiao/dist/uni.mp.esm.js +++ b/packages/uni-mp-toutiao/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, hasOwn, isArray, extend, hyphenate, isObject, toNumber, isFunction, NOOP, camelize } from '@vue/shared'; -import { onUnmounted, injectHook } from 'vue'; +import { onUnmounted, injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -606,6 +606,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -622,6 +623,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; diff --git a/packages/uni-mp-weixin/dist/uni.api.esm.js b/packages/uni-mp-weixin/dist/uni.api.esm.js index 429473fb040a1e6b930bd3cb0bbfc7143eed0ccc..d05147288a89a468a2a3e4d830dd94068c9d6b26 100644 --- a/packages/uni-mp-weixin/dist/uni.api.esm.js +++ b/packages/uni-mp-weixin/dist/uni.api.esm.js @@ -547,7 +547,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -691,6 +691,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -700,6 +724,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); diff --git a/packages/uni-mp-weixin/dist/uni.mp.esm.js b/packages/uni-mp-weixin/dist/uni.mp.esm.js index e0ecaf6650cc4334d0ee4709b14c68d2b546e6ed..4fcc49a7f72540babd8ebd074c291c3745bba1c8 100644 --- a/packages/uni-mp-weixin/dist/uni.mp.esm.js +++ b/packages/uni-mp-weixin/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, hasOwn, isArray, extend, hyphenate, isObject, toNumber, isFunction, NOOP, camelize } from '@vue/shared'; -import { onUnmounted, injectHook } from 'vue'; +import { onUnmounted, injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -549,6 +549,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -565,6 +566,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null]; diff --git a/packages/uni-quickapp-webview/dist/uni.api.esm.js b/packages/uni-quickapp-webview/dist/uni.api.esm.js index d6efb2763126e7689038078c20f1c0885614a9db..44740deda87fbd26971a86a7f04ee81b616dce0d 100644 --- a/packages/uni-quickapp-webview/dist/uni.api.esm.js +++ b/packages/uni-quickapp-webview/dist/uni.api.esm.js @@ -583,7 +583,7 @@ const $emit = defineSyncApi(API_EMIT, (name, ...args) => { emitter.emit(name, ...args); }, EmitProtocol); -const SYNC_API_RE = /^\$|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; +const SYNC_API_RE = /^\$|getLocale|setLocale|sendNativeEvent|restoreGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64/; const CONTEXT_API_RE = /^create|Manager$/; // Context例外情况 const CONTEXT_API_RE_EXC = ['createBLEConnection']; @@ -727,6 +727,30 @@ function initWrapper(protocols) { }; } +const getLocale = () => { + // 优先使用 $locale + const app = getApp({ allowDefault: true }); + if (app && app.$vm) { + return app.$vm.$locale; + } + return uni.getSystemInfoSync().language || 'zh-Hans'; +}; +const setLocale = (locale) => { + const oldLocale = getApp().$vm.$locale; + if (oldLocale !== locale) { + getApp().$vm.$locale = locale; + onLocaleChangeCallbacks.forEach((fn) => fn({ locale })); + return true; + } + return false; +}; +const onLocaleChangeCallbacks = []; +const onLocaleChange = (fn) => { + if (onLocaleChangeCallbacks.indexOf(fn) === -1) { + onLocaleChangeCallbacks.push(fn); + } +}; + const baseApis = { $on, $off, @@ -736,6 +760,9 @@ const baseApis = { addInterceptor, removeInterceptor, onAppLaunch, + getLocale, + setLocale, + onLocaleChange, }; function initUni(api, protocols) { const wrapper = initWrapper(protocols); diff --git a/packages/uni-quickapp-webview/dist/uni.mp.esm.js b/packages/uni-quickapp-webview/dist/uni.mp.esm.js index 84d914f82c0ea1b099e56afce29d649e0adaeabc..5542f38f092dca004d5d3834cdbc1a5f01bd7ddb 100644 --- a/packages/uni-quickapp-webview/dist/uni.mp.esm.js +++ b/packages/uni-quickapp-webview/dist/uni.mp.esm.js @@ -1,5 +1,5 @@ import { isPlainObject, hasOwn, isArray, extend, hyphenate, isObject, toNumber, isFunction, NOOP, camelize } from '@vue/shared'; -import { injectHook } from 'vue'; +import { injectHook, ref } from 'vue'; const encode = encodeURIComponent; function stringifyQuery(obj, encodeStr = encode) { @@ -534,6 +534,7 @@ function parseApp(instance, parseAppOptions) { instance.$callHook(ON_LAUNCH, extend({ app: this }, options)); }, }; + initLocale(instance); const vueOptions = instance.$.type; initHooks(appOptions, HOOKS); initUnknownHooks(appOptions, vueOptions); @@ -550,6 +551,17 @@ function initCreateApp(parseAppOptions) { return function createApp(vm) { return App(parseApp(vm, parseAppOptions)); }; +} +function initLocale(appVm) { + const locale = ref(uni.getSystemInfoSync().language || 'zh-Hans'); + Object.defineProperty(appVm, '$locale', { + get() { + return locale.value; + }, + set(v) { + locale.value = v; + }, + }); } const PROP_TYPES = [String, Number, Boolean, Object, Array, null];