vue-i18n icon indicating copy to clipboard operation
vue-i18n copied to clipboard

`i18n.global.locale` type definiton wrong

Open WangHansen opened this issue 2 years ago • 15 comments

Reporting a bug?

When I implemented a function to globally switch locale as follows: 截屏2022-05-07 下午11 31 39

The type definition for i18n.global.locale is wrong: 截屏2022-05-07 下午11 32 31

By printing out the console, I was able to see that i18n.global.locale should be a computed value

Expected behavior

TypeScript not throw error

Reproduction

Type definition problem

System Info

System:
  OS: macOS 12.3.1
  CPU: (8) x64 Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
  Memory: 171.65 MB / 16.00 GB
  Shell: 5.8 - /bin/zsh
Binaries:
  Node: 16.13.2 - ~/.nvm/versions/node/v16.13.2/bin/node
  Yarn: 1.22.10 - /usr/local/bin/yarn
  npm: 8.6.0 - ~/.nvm/versions/node/v16.13.2/bin/npm
  Watchman: 2021.10.18.00 - /usr/local/bin/watchman
Browsers:
  Brave Browser: 91.1.26.77
  Chrome: 101.0.4951.54
  Safari: 15.4

"vue": "^3.2.25",
"vue-i18n": "^9.1.10",
"@intlify/vite-plugin-vue-i18n": "^3.4.0",
"@vitejs/plugin-vue": "^2.3.1",

Screenshot

No response

Additional context

No response

Validations

WangHansen avatar May 08 '22 03:05 WangHansen

Thank you for your reporting!

I seem that the i18n instance is created with createI18n with legacy: true option.

The global property can refer to Composer or VueI18n, as described in the API docs. https://vue-i18n.intlify.dev/api/general.html#global

You can check the mode of an i18n instance with mode. https://vue-i18n.intlify.dev/api/general.html#mode

kazupon avatar May 09 '22 02:05 kazupon

Thank you for your reporting!

I seem that the i18n instance is created with createI18n with legacy: true option.

The global property can refer to Composer or VueI18n, as described in the API docs. https://vue-i18n.intlify.dev/api/general.html#global

You can check the mode of an i18n instance with mode. https://vue-i18n.intlify.dev/api/general.html#mode

Sorry, should specify, I actually created with legacy: false:

const i18n = createI18n<I18nOptions, [MessageSchema], 'zh-CN' | 'en-CA'>({
  legacy: false,
  locale: getLang(),
  messages: {
    'zh-CN': zhCN,
    'en-CA': enCA,
  },
  // something vue-i18n options here ...
});

WangHansen avatar May 09 '22 04:05 WangHansen

Hi, I was facing the same problem on vue-i18n 9.2.0-beta.31.

I had a look at the type of i18n.global.locale and it's of type string | WritableComputedRef. So you can't access .value unless you tell Typescript that i18n.global.locale is not a string but a ref. Therefore I just added a typeguard using the isRef function from vue:

export const changeLocale = (i18n: I18n, locale: string) => {
  if (i18n.mode === 'legacy') {
    i18n.global.locale = locale;
  } else if (isRef(i18n.global.locale)) {
    i18n.global.locale.value = locale;
  }
};

That way the type changes to Ref inside the else block. But this behaviour should be documented as the example in the Documentation does currently not work for Typescript.

markbrockhoff avatar May 23 '22 12:05 markbrockhoff

Hi I am facing the same issue.

I'm using i18n 9.1.10 (fixed version)

Here is my i18n setup

const i18n = createI18n({
  locale: 'fr',
  legacy: false,
  fallbackLocale: 'en',
  globalInjection: true,
  messages: messages as LocaleMessages<VueMessageType>,
})

In the same file, I try to access and modify the locale using i18n.global.locale. When I check in my code, the type for i18n.global.locale is a ref but if I try i18n.global.locale.value = 'fr' then I get a console error saying i18n.global.locale is a String and if I log i18n.global.locale.value I get undefined

I've checked and I'm using the composition mode (i18n.mode is composition) . I've tried checking with isRef, and it always returns false even though mode is composition.

Any help is appreciated

leo-martin avatar Jul 06 '22 13:07 leo-martin

Have the same problem with next-version. With legacy: false i have to set it with i18n.global.locale.value = locale;

porkus1990 avatar Jul 29 '22 08:07 porkus1990

I'm facing the same problem I think, getting an unknown type from locale which is causing errors with v-model:

Screenshot 2022-08-05 at 10 21 41 Screenshot 2022-08-05 at 10 23 01

A workaround for me is using the implicit way:

<RadioGroup v-model="$i18n.locale">

valgeirb avatar Aug 05 '22 10:08 valgeirb

To me it’s clear that this bug only occurs when useScope: 'global' in useI18n is specified. That is, with const { locale } = useI18n() I get const locale: WritableComputedRef<string>, while with const { locale } = useI18n({ useScope: 'global' }); I get const locale: WritableComputedRef<unknown>.

timothymctim avatar Aug 23 '22 21:08 timothymctim

I'm using [email protected] and having issues with global.locale type. Type recognition says its a string while with legacy: false should be ref<string>: Zrzut ekranu 2022-08-30 o 19 26 23

it-xtech-dev avatar Aug 30 '22 17:08 it-xtech-dev

@kazupon I believe @timothymctim has laid out the scenario quite well. Non-legacy users are having trouble getting Locale to type correctly to WritableComputedRef<Locale>

rfox12 avatar Sep 03 '22 12:09 rfox12

sorry, I'm focusing on nuxtjs/i18n for v8 alpha release. please

Type definitions in vue-i18n are really complex. I’m not a full-time OSS yet, so it may take some time until I'm starting on this issue.

kazupon avatar Sep 03 '22 13:09 kazupon