Search code examples
vue.jsvuejs2web-componentvue-i18n

How can I use vue-i18n in a Vue web component?


I'm creating a Vue web component using vue-cli 3 and the --target wc option. I also need the component to use the vue-i18n plugin, which requires some options to be passed to the main Vue instance like this:

new Vue({
    i18n: new VueI18n({ ... ])
    ...
})

In a regular Vue app this is fine because I control construction of the main Vue instance. However, when building as a web component, the construction of the main Vue object is generated by vue-web-component-wrapper and I don't see any obvious way to affect it.

How can I use the vue-18n plugin in my web component?


Solution

  • The i18n plugin needs to be initialized on the "entry" component (i.e. the one that forms the base of the web component) instead of the root component.

    But even doing that, it's important that all messages are defined on the entry component. Defining messages on a child component, either directly in the component or using the <i18n> element, effectively overrides the vue-i18n config from the entry component and causes that child component to use the default language of en-US.

    Here is a simple working example:

    Entry Component

    <template>
      <div>
        <p>{{ $t('hello') }}</p>
        <child-component />
      </div>
    </template>
    
    <script>
    import ChildComponent from "./child.vue"
    import Vue from "vue"
    import VueI18n from "vue-i18n"
    Vue.use(VueI18n)
    
    export default {
      name: "App",
      i18n: new VueI18n({
        locale: 'ja',
        messages: {
          en: {
            hello: "hello in en",
            test: "test in en"
          },
          ja: {
            hello: "hello in ja",
            test: "test in ja"
          },
        }
      }),
      components: { ChildComponent }
    };
    </script>
    

    Child Component

    <template>
      <div>{{ $t("test") }}</div>
    </template>
    
    <script>
    export default {
      name: "child-component"
    };
    </script>