Web components
Supported Versions
🆕 9.2+
TIP
The fully example codes of this chapter is here
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 preparation 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 setup lang="ts">
import { 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: 'こんにちは!'
}
}
})
/**
* provide i18n instance with `I18nInjectionKey` for other web components
*/
provide(I18nInjectionKey, i18n)
</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 withcreateI18n
along withI18nInjectionKey
inprovide
- 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 './path/to/I18nHostElement'
import { HelloI18nElement } from './path/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
- The Vue I18n that can be used to implement Web Components is only Composition API.
- 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.