Skip to content

Web Components

対応バージョン

🆕 9.2+

TIP

この章の完全な例コードはこちらにあります

Vue 3.2以降、公式ドキュメントで説明されているように、Web Componentsを使用することが可能です。

これにより、Vue I18n v9.2以降からWeb ComponentsにおけるVue I18nの利用が可能になります。

Web ComponentsでVue I18nを使用する際には、いくつかの点に注意する必要があります。

Web Componentsの準備:I18nインスタンスをホストする

Vue 3.2以降でサポートされるdefineCustomElementを使用することで、SFCで実装されたVueコンポーネントをWeb Componentsとして提供できます。これは、useI18nを使用して実装されたVueコンポーネントをi18nサポート付きのWeb Componentsとして提供できることを意味します。

ただし、提供されたWeb ComponentsはHTMLに直接挿入することはできません。createI18nによって作成されたi18nインスタンスをホストするために以下のWeb Componentsを準備する必要があります。

i18nインスタンスをホストするWeb Components:

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

/**
 * 他のWeb Componentsのためにホストするためのi18nインスタンスを作成
 */
const i18n = createI18n<false>({
  legacy: false, // 必ず`false`に設定する
  locale: 'en',
  messages: {
    en: {
      hello: 'Hello!'
    },
    ja: {
      hello: 'こんにちは!'
    }
  }
})

/**
 * `I18nInjectionKey`を使って他のWeb Componentsのためにi18nインスタンスを提供
 */
provide(I18nInjectionKey, i18n)
</script>

<!-- コンテンツをスロットするためのテンプレート -->
<template>
  <slot />
</template>

上記のコードには以下の3つのポイントがあります。

  • createI18nを呼び出してi18nインスタンスを作成
  • setup内で、createI18nによって作成されたi18nインスタンスをI18nInjectionKeyとともにprovideに指定
  • テンプレートにはslot要素のみが含まれる

scriptブロック内では、まずcreateI18nを使ってi18nインスタンスを初期化します。Vueアプリケーションでは、createI18nによって作成されたi18nインスタンスは、Vueアプリケーションapp.usecreateAppによって生成された)に指定することで、Vueプラグインとして利用できます。Vue I18nをVueアプリケーションにインストールするには、app.useを使ってi18nインスタンスを登録する必要があります。

defineCustomElementを使用する場合、VueコンポーネントはVueアプリケーション側からは制御できなくなります。そのため、Vueアプリケーション内でWeb Components版のコンポーネントを実行しても、Vueアプリケーション側からapp.useを使ってcreateI18nによって作成されたi18nインスタンスをターゲットのWeb Componentsにアタッチすることはできません。

そのため、Web Componentsにi18nインスタンスをアタッチするために、setupprovideを使用して、他のWeb Componentsにi18nインスタンスを公開します。これにより、useI18nでi18nを実装したWeb Componentsが、provideを実装したWeb Componentsによってホストされることで動作できるようになります。

次に、他のWeb Componentsをホストするためには、templateブロックでslot要素を使用することで可能です。

このホストされたWeb Componentsを以下のようにエクスポートします:

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

const I18nHostElement = defineCustomElement(I18nHost)

export { I18nHostElement }

次のuseI18nが実装し、エクスポートするWeb Componentsは以下の通りです:

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

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

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

const HelloI18nElement = defineCustomElement(HelloI18n)
export { HelloI18nElement }

次のVueアプリケーションがWeb Componentsのカスタム要素として登録される場合:

js
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')

そのため、VueアプリケーションのエントリーポイントであるApp.vueでは、以下のテンプレートが動作します:

vue
<template>
  <i18n-host>
    <h1>Web componentにおけるVue I18n</h1>
    <hello-i18n />
  </i18n-host>
</template>

これまでに説明した完全な例はこちらで確認できます。

制限事項

  1. Web Componentsを実装するために使用できるVue I18nはComposition APIのみです。
  2. Web Componentsを実装する際、useI18nで実装されたVueコンポーネントを一緒にインポートして使用することはできません。これは、Vue.jsのWeb Componentsに対するProvide / Injectの制限によるものです。