intlify / vue-i18n

Vue I18n for Vue 3

Home Page:https://vue-i18n.intlify.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`te` returns invalid value when the given value (or "branch") is an object

sybrendotinga opened this issue · comments

Reporting a bug?

After upgrading to v9.6 we are experiencing that the te does not recognize changes anymore.

Expected behavior

After mergeLocaleMessages is called we expect te to return true, because the message now exists

Reproduction

  1. Load translations via an API
  2. Merge the message with the mergeLocaleMessages
  3. The value from te('common') should now be true

In this example you can see that the "Terug"-translation is loaded, via the external package.
The first true is the te('common.action.cancel.label') from the portal, the second false-value te('common').

image

Stackblitz: https://stackblitz.com/edit/vitejs-vite-gyzvu8?file=package.json
When downgrading to ~9.5 all values are true.

System Info

System:
    OS: macOS 14.0
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 217.91 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.15.0 - ~/Library/pnpm/node
    Yarn: 1.22.19 - ~/.yarn/bin/yarn
    npm: 8.19.4 - ~/Documents/frontend/.../node_modules/.bin/npm
    pnpm: 8.15.1 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 121.0.6167.160
    Safari: 17.0
  npmPackages:
    @vitejs/plugin-vue: ^5.0.3 => 5.0.3 
    @vue/eslint-config-prettier: ^8.0.0 => 8.0.0 
    @vue/eslint-config-typescript: ^11.0.3 => 11.0.3 
    @vue/test-utils: ^2.4.1 => 2.4.1 
    @vue/tsconfig: ^0.1.3 => 0.1.3 
    vite: ^5.0.12 => 5.0.12 
    vite-plugin-dts: ^3.7.2 => 3.7.2 
    vitest: ^1.2.2 => 1.2.2 
    vue: ^3.4.15 => 3.4.15 
    vue-good-table-next: ^0.2.1 => 0.2.1 
    vue-i18n: ^9.9.1 => 9.9.1 
    vue-router: ^4.2.5 => 4.2.5 
    vue-tsc: ^1.8.27 => 1.8.27 
    vue3-apexcharts: ^1.4.4 => 1.4.4

Screenshot

Scherm­afbeelding 2024-02-13 om 14 15 05

Additional context

Because we have a lot of translations, we load them from the API, based on a given prefix. For example "load all translations for the employee-prefix"

We use the following setup:

  1. A (private) library (installed with pnpm) that loads translations based on a prefix. e.g. entity.employee
  2. We use mergeLocaleMessage to merge the new translations into the existing translations:
const { data } = await axios.get<TranslationsResponse>(`${url}?prefix=${prefix}`)
for (const key in data) {
  const language = key as Language // (for example `nl` or `en` or `es`)
  const translations = data[language]
  mergeLocaleMessage(key, translations)
}

The private library aswel as vue-i18n is installed in the project.
I discovered that it returns false because te('common') is not very specific to a translation, but to a branch of translations.

Validations

I've updated the issue based on my new discoveries. It has mainly to do with checking a "branch" of translations:

image

In this scenario te('editor') will return false, but te('editor.actions.cancel.label') will return true:

{{ te('editor') }} // false
{{ te('editor.actions.cancel.label') }} // true
image

Reading more about this, I've found that this works:

const translations = computed(() => tm('editor'))
const showTools = computed(() => Object.keys(translations.value).length >= 1)

But, maybe that is not the nicest solution, because it adds a lot more operations than it previously was

@kazupon It seems very related to #1602

I've added a very simple Stackblitz reproduction: https://stackblitz.com/edit/vitejs-vite-gyzvu8?file=src%2FApp.vue
te is broken after updating to 9.6. You can install 9.5 in de stackblitz and all checks become true again.

Thank you for your reporting!

te('common') -> false
te('common.actions') -> false

This is the result of your reproduction above, which is the correct behavior.
Until now, true was returned even if the value of the key was not translatable, i.e., not a string.
So, I've fixed in #1559

I will put this notice in te API documentation.

Thanks!

Hi @kazupon is there an alternative? Or can one be provided? Because our applications rely on this check and therefore are now broken on this version.

@sybrendotinga
I'll give translateExistCompatible option, a compatibility flag that will result in pre-9.6 behavior. You can specify that option to createI18n.

We will remove that option in the next major version v10, so please migrate at some point.

That would be great, thank you. Nonetheless, we would still appreciate an alternative after that. Can vue-i18n provide an alternaive to check if a branch exists (aka is an object)? Or should we build something like this ourself?

const translations = computed(() => tm('editor'))
const showTools = computed(() => Object.keys(translations.value).length >= 1)

vue-i18n v9 is giving us tm for getting object or array.
https://vue-i18n.intlify.dev/guide/migration/breaking.html#translation-api-return-value

Like the code you presented, we can check if there is a branch by using computed.