Web components

Support Version

🆕 9.2+

Vue 3.2 later, we can use the WebComponents as described in the official documentation.

This will support the use of Vue I18n in Web Components starting with Vue I18n v9.2.

There are a few things to keep in mind when using Vue I18n with Web Components.

Make preparetion for Web Components to host the I18n instance

Using defineCustomElement, which is supported since Vue 3.2, we can provide Vue components implemented in SFC as Web Components. This means that Vue components implemented using useI18n can be served as Web Components with i18n support.

However, the provided Web Components cannot be inserted directly into HTML. You need to prepare the following Web Components to host the i18n instance created by createI18n.

Web Components that host the i18n instance:

<script lang="ts">
import { defineComponent, provide } from 'vue'
import { createI18n, I18nInjectionKey } from 'vue-i18n'

/**
 * create an i18n instance to host for other web components
 */
const i18n = createI18n<false>({
  legacy: false, // must set to `false`
  locale: 'en',
  messages: {
    en: {
      hello: 'Hello!'
    },
    ja: {
      hello: 'こんにちは!'
    }
  }
})

export default defineComponent({
  // ...
  setup(props) {
    /**
     * provide i18n instance with `I18nInjectionKey` for other web components
     */
    provide(I18nInjectionKey, i18n)

    // ...

    return {}
  }
})
</script>

<!-- template to slot the content -->
<template>
  <slot />
</template>

The above code has the following three points.

  • Call createI18n to create an i18n instance
  • In setup, specify the i18n instance created with createI18n along with I18nInjectionKey in provide
  • template has slot element only

In the script block, we first use createI18n to create an i18n instance. In a Vue application, the i18n instance created by createI18n can be used as a Vue plugin by specifying the i18n instance in the Vue application app.use created by createApp. 18n instance to the Vue application app.use generated by createApp, we needed to install Vue I18n as a Vue plugin to the Vue application.

If you use defineCustomElement, the Vue component can no longer be controlled from the Vue application side, so even if you run the Web Components version of the component in your Vue application, you can't attach the i18n instance created with createI18n to the target Web Components via app.use from the Vue application side.

So, in order to attach i18n instances to Web Components, we use provide in setup to expose i18n instances to other Web Components. This allows Web Components that implement i18n with useI18n to work by being hosted by Web Components that work provide.

Then, to host other Web Components, the template block makes it possible by using the slot element.

Export this hosted Web Components as follows:

import { defineCustomElement } from 'vue'
import I18nHost from './components/I18nHost.ce.vue'

const I18nHostElement = defineCustomElement(I18nHost)

export { I18nHostElement }  

The following useI18n implements and exports Web Components to:

<script setup lang="ts">
import { useI18n } from 'vue-i18n'

const { t } = useI18n()
</script>

<template>
  <p>{{ t('hello') }}</p>
</template>
import { defineCustomElement } from 'vue'
import HelloI18n from './components/HelloI18n.ce.vue'

const HelloI18nElement = defineCustomElement(HelloI18n)
export { HelloI18nElement }

When the following Vue application is registered as a custom element of Web Components:

import { createApp } from 'vue'
import { I18nHostElement } from './paht/to/I18nHostElement'
import { HelloI18nElement } from './paht/to/HelloI18nElement'
import App from './App.vue'

customElements.define('i18n-host', I18nHostElement)
customElements.define('hello-i18n', HelloI18nElement)

createApp(App).mount('#app')

So, In App.vue, which is the entry point of a Vue application, the following template will work:

<template>
  <i18n-host>
    <h1>Vue I18n in Web component</h1>
    <hello-i18n />
  </i18n-host>
</template>

The complete example described so far can be looked here.

Limitations

  1. The Vue I18n that can be used to implement Web Components is only Composition API.
  2. When implementing Web Components, Vue components implemented with useI18n cannot be imported and used together. This is due to the Provide / Inject limitations of Vue.js for Web Components.