diff --git a/packages/vue-i18n-core/src/utils.ts b/packages/vue-i18n-core/src/utils.ts index 5a6aa6184..6af257bf6 100644 --- a/packages/vue-i18n-core/src/utils.ts +++ b/packages/vue-i18n-core/src/utils.ts @@ -4,10 +4,12 @@ import { isObject, hasOwn, isPlainObject, - isString + isString, + warn } from '@intlify/shared' import { Text, createVNode } from 'vue' import { I18nErrorCodes, createI18nError } from './errors' +import { I18nWarnCodes, getWarnMessage } from './warnings' import type { Locale, MessageResolver } from '@intlify/core-base' import type { @@ -72,15 +74,28 @@ export function handleFlatJson(obj: unknown): unknown { const subKeys = key.split('.') const lastIndex = subKeys.length - 1 let currentObj = obj + let hasStringValue = false for (let i = 0; i < lastIndex; i++) { if (!(subKeys[i] in currentObj)) { currentObj[subKeys[i]] = {} } + if (!isObject(currentObj[subKeys[i]])) { + __DEV__ && + warn( + getWarnMessage(I18nWarnCodes.IGNORE_OBJ_FLATTEN, { + key: subKeys[i] + }) + ) + hasStringValue = true + break + } currentObj = currentObj[subKeys[i]] } // update last object value, delete old property - currentObj[subKeys[lastIndex]] = obj[key] - delete obj[key] + if (!hasStringValue) { + currentObj[subKeys[lastIndex]] = obj[key] + delete obj[key] + } // recursive process value if value is also a object if (isObject(currentObj[subKeys[lastIndex]])) { handleFlatJson(currentObj[subKeys[lastIndex]]) diff --git a/packages/vue-i18n-core/src/warnings.ts b/packages/vue-i18n-core/src/warnings.ts index d5bde3b86..b5bb046f9 100644 --- a/packages/vue-i18n-core/src/warnings.ts +++ b/packages/vue-i18n-core/src/warnings.ts @@ -11,7 +11,8 @@ export const I18nWarnCodes = { NOT_SUPPORTED_PRESERVE_DIRECTIVE: inc(), // 10 NOT_SUPPORTED_GET_CHOICE_INDEX: inc(), // 11 COMPONENT_NAME_LEGACY_COMPATIBLE: inc(), // 12 - NOT_FOUND_PARENT_SCOPE: inc() // 13 + NOT_FOUND_PARENT_SCOPE: inc(), // 13 + IGNORE_OBJ_FLATTEN: inc() // 14 } as const type I18nWarnCodes = (typeof I18nWarnCodes)[keyof typeof I18nWarnCodes] @@ -23,7 +24,8 @@ export const warnMessages: { [code: number]: string } = { [I18nWarnCodes.NOT_SUPPORTED_PRESERVE_DIRECTIVE]: `Not supported 'preserveDirectiveContent'.`, [I18nWarnCodes.NOT_SUPPORTED_GET_CHOICE_INDEX]: `Not supported 'getChoiceIndex'.`, [I18nWarnCodes.COMPONENT_NAME_LEGACY_COMPATIBLE]: `Component name legacy compatible: '{name}' -> 'i18n'`, - [I18nWarnCodes.NOT_FOUND_PARENT_SCOPE]: `Not found parent scope. use the global scope.` + [I18nWarnCodes.NOT_FOUND_PARENT_SCOPE]: `Not found parent scope. use the global scope.`, + [I18nWarnCodes.IGNORE_OBJ_FLATTEN]: `Ignore object flatten: '{key}' key has an string value` } export function getWarnMessage( diff --git a/packages/vue-i18n-core/test/__snapshots__/issues.test.ts.snap b/packages/vue-i18n-core/test/__snapshots__/issues.test.ts.snap index ccfb64a21..a994c70c7 100644 --- a/packages/vue-i18n-core/test/__snapshots__/issues.test.ts.snap +++ b/packages/vue-i18n-core/test/__snapshots__/issues.test.ts.snap @@ -8,4 +8,6 @@ exports[`issue #1054, #1053 1`] = `"
+$123,456.79
+$123,456.79 exports[`issue #1055 1`] = `"John opened issue 123
"`; -exports[`issue #1373 1`] = `"hello, kazupon!
6/2/2023
$100.00
"`; +exports[`issue #1365 1`] = `"Animal
"`; + +exports[`issue #1373 1`] = `"hello, kazupon!
6/5/2023
$100.00
"`; diff --git a/packages/vue-i18n-core/test/issues.test.ts b/packages/vue-i18n-core/test/issues.test.ts index 23d19e760..39f7159a0 100644 --- a/packages/vue-i18n-core/test/issues.test.ts +++ b/packages/vue-i18n-core/test/issues.test.ts @@ -872,6 +872,29 @@ test('issue #1123', async () => { ) }) +test('issue #1365', async () => { + const i18n = createI18n({ + legacy: false, + locale: 'en', + flatJson: true, + messages: { + en: { + 'animal.dog': 'Dog', + animal: 'Animal' + } + } + }) + const App = defineComponent({ + template: ` +{{ $t('animal') }}
+ ` + }) + + const wrapper = await mount(App, i18n) + + expect(wrapper.html()).toMatchSnapshot() +}) + test('issue #1373', async () => { const i18n = createI18n({ locale: 'en-US', @@ -887,7 +910,7 @@ test('issue #1373', async () => { kazupon -