Search code examples
vue.jsvuejs2vuejs3vue-i18nvue-class-components

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


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.


Solution

  • 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 :)