How to use vue-i18n in Class Style Component(vue3)

140 views Asked by At

I'm trying to migrate vue2 to vue3 which is "Class Style Component".

It is using vue-i18n. Can I use vue-i18n in Vue3?

package.json

  "dependencies": {

    "vue": "^3.3.4",
    "vue-class-component": "^8.0.0-0",
    "vue-i18n": "^9.5.0",
    "vue-property-decorator": "^10.0.0-rc.3",

I am facing the following error in browser console.

Uncaught SyntaxError: Must be called at the top of a `setup` function
    at createCompileError (message-compiler.esm-browser.js:99:19)
    at createI18nError (vue-i18n.mjs:101:12)
    at useI18n (vue-i18n.mjs:2294:15)
    at TestXXXXXX.vue:20:9

It is saying "Must be called at the top of a setup function". Is it possible to use "setup function" in Class Style Component?

The following is my code sample.

<script lang="ts">

import { useI18n } from 'vue-i18n';

@Component({
  i18n: useI18n()
})
export default class TestXXXXXX extends Vue {
:

Can someone please help me? Thanks in advance.

1

There are 1 answers

0
ArrayConstructor On BEST ANSWER

Despite my comment, it's still possible to use vue-i18n with vue-class-component. In Vue3 useI18n need to be use at the top of a setup function like said in your error message. vue-class-component export a setup function that you can use in different ways, we're going to use that. Here is how to do it.

First, you need to create your app and install vue-i18n:

In your main.ts or whatever is the entry of your app:

import { createApp } from "vue";
import App from "./App.vue";
import { createI18n } from "vue-i18n";

const i18n = createI18n({
  locale: "en",
  legacy: false,
  messages: { // add your messages here
    en: {
      common: {
        message: "Hello world!",
      },
    },
  },
});

createApp(App).use(i18n).mount("#app");

Now you can use $t and useI18n in your project, here is how to do it:

In your App.vue :

<template>
  <HelloWorld msg="common.message"/> <!-- The traduction key -->
</template>

<script lang="ts">
import { Options, Vue } from 'vue-class-component';
import HelloWorld from './components/HelloWorld.vue';

@Options({
  components: {
    HelloWorld,
  },
})
export default class App extends Vue {}
</script>

And now in the component HelloWorld.vue here is the two ways to use it:

<template>
  <div>
    <h1>{{ $t(msg) }}</h1>
    <h2>{{ i18n.t('common.message') }}</h2>
  </div>
</template>

<script lang="ts">
import { Options, Vue, setup } from 'vue-class-component';
import { useI18n } from 'vue-i18n'

@Options({
  props: {
    msg: String
  }
})
export default class HelloWorld extends Vue {
  msg!: string      

  i18n = setup(() => {
    return useI18n()
  })
}
</script>

I strongly not recommend you to use vue-class-component, but more to use composition API with Vue3 and Typescript.

However, hope it helps you :)