diff --git a/packages/vue-i18n-core/src/composer.ts b/packages/vue-i18n-core/src/composer.ts index df29a5c4e..4a24ecd9c 100644 --- a/packages/vue-i18n-core/src/composer.ts +++ b/packages/vue-i18n-core/src/composer.ts @@ -11,7 +11,8 @@ import { isPlainObject, isObject, assign, - inBrowser + inBrowser, + hasOwn } from '@intlify/shared' import { isTranslateFallbackWarn, @@ -53,7 +54,8 @@ import { deepCopy, getLocaleMessages, getComponentOptions, - createTextNode + createTextNode, + handleFlatJson } from './utils' import { VERSION } from './misc' @@ -1848,6 +1850,7 @@ export function createComposer(options: any = {}, VueI18nLegacy?: any): any { NumberFormatsType > const _isGlobal = __root === undefined + const flatJson = options.flatJson let _inheritLocale = isBoolean(options.inheritLocale) ? options.inheritLocale @@ -2375,6 +2378,15 @@ export function createComposer(options: any = {}, VueI18nLegacy?: any): any { // setLocaleMessage function setLocaleMessage(locale: Locale, message: LocaleMessage) { + if (flatJson) { + const _message = { [locale]: message } + for (const key in _message) { + if (hasOwn(_message, key)) { + handleFlatJson(_message[key]) + } + } + message = _message[locale] + } _messages.value[locale] = message if (__BRIDGE__) { __legacy && __legacy.setLocaleMessage(locale, message) @@ -2391,6 +2403,13 @@ export function createComposer(options: any = {}, VueI18nLegacy?: any): any { if (__BRIDGE__) { __legacy && __legacy.mergeLocaleMessage(locale, message) } + const _message = { [locale]: message } + for (const key in _message) { + if (hasOwn(_message, key)) { + handleFlatJson(_message[key]) + } + } + message = _message[locale] deepCopy(message, _messages.value[locale]) _context.messages = _messages.value as typeof _context.messages } diff --git a/packages/vue-i18n-core/test/issues.test.ts b/packages/vue-i18n-core/test/issues.test.ts index 6b31b691a..83a4900f2 100644 --- a/packages/vue-i18n-core/test/issues.test.ts +++ b/packages/vue-i18n-core/test/issues.test.ts @@ -1049,3 +1049,119 @@ test('issue #1547', async () => { expect(wrapper.html()).toEqual('
Deep Linked message
') }) + +test('issue #1595', async () => { + const i18n = createI18n({ + legacy: false, + locale: 'en', + flatJson: true, + messages: { + en: { + simple: 'Simple', + 'deep.key': 'Deep', + content: '@:simple @:deep.key' + } + } + }) + + const ja = { + simple: 'シンプル', + 'deep.key': 'ディープ', + content: '@:simple @:deep.key' + } + i18n.global.setLocaleMessage('ja', ja) + + const App = defineComponent({ + setup() { + const { t, locale } = useI18n() + return { t, locale } + }, + template: `
+ +
+{{ t('content') }} +` + }) + + expect(i18n.global.getLocaleMessage('ja')).toEqual({ + simple: 'シンプル', + deep: { + key: 'ディープ' + }, + content: '@:simple @:deep.key' + }) + + const wrapper = await mount(App, i18n) + expect(wrapper.html()).toEqual( + '
Simple Deep' + ) + // @ts-ignore + i18n.global.locale.value = 'ja' + await nextTick() + + expect(wrapper.html()).toEqual( + '
シンプル ディープ' + ) +}) + +test('issue #1595 merge case', async () => { + const i18n = createI18n({ + legacy: false, + locale: 'en', + flatJson: true, + messages: { + en: { + simple: 'Simple', + 'deep.key': 'Deep', + content: '@:simple @:deep.key' + }, + ja: { + simple: 'シンプル', + content: '@:simple @:deep.key' + } + } + }) + + const ja = { + 'deep.key': 'ディープ' + } + i18n.global.mergeLocaleMessage('ja', ja) + + const App = defineComponent({ + setup() { + const { t, locale } = useI18n() + return { t, locale } + }, + template: `
+ +
+{{ $t('content') }} +` + }) + + expect(i18n.global.getLocaleMessage('ja')).toEqual({ + simple: 'シンプル', + deep: { + key: 'ディープ' + }, + content: '@:simple @:deep.key' + }) + + const wrapper = await mount(App, i18n) + expect(wrapper.html()).toEqual( + '
Simple Deep' + ) + // @ts-ignore + i18n.global.locale.value = 'ja' + await nextTick() + + expect(wrapper.html()).toEqual( + '
シンプル ディープ' + ) +})