🦔

Vue3 に向けて - vue-i18n-bridge による移行準備

2022/08/25に公開

ロンラン株式会社 CEO 兼 CTO の武部です。

この記事は、私たちのチームのように「諸事情でまだ Vue2 を使っているが、Vue3 への移行のための準備はぬかりなく進めたい」方向けです。

前回は、はじめに取り掛かりたい&恩恵の大きい Vite 化対応について記しました。

https://zenn.dev/nuichi/articles/7974bd1101fe9d

今回は Vue-i18n の移行です。

あくまでも移行中のため、次のニーズを満たせるようにします。

  • 新しい実装や移行対象の Vue ファイル:setup script または Composition API での setup() を前提とし、t を使い $t はもう使わない
  • それ以外:何も触る必要なし。$t そのまま使い、コード移行の順番を待つ

では早速はじめてゆきましょう!

パッケージ構成

あらためて確認ですが、今回は次のパッケージとバージョンで構成します。

  • Vue2
  • Vue-i18n@8
  • vue-i18n-bridge

Vue-i18n そのものは、8.x 系から 9 系へアップデートしないように気をつけましょう。

vue-i18n-bridge の導入

今回の主役、vue-i18n-bridge をインストールします。

yarn add vue-i18n-bridge

Weekly Downloads が伸びまくっていますね。同じように Vue3 移行準備を進めているプロジェクトが多いのかなと推察します。

ここから先は、注意深く vue-i18n-bridge と本家 vue-i18n のサイト両方を読み込んでゆくと紹介されている内容で、特殊なことは何ひとつありません。

main.(ts|js) 構成

main.(ts|js) が TypeScript か JavaScript かで少し異なります。

TS の場合は、castToVueI18n() しておかないと new Vue() 内で型エラーが出てしまいます。JS の場合は不要です。

import VueI18n from 'vue-i18n'
import { createI18n, castToVueI18n } from 'vue-i18n-bridge'
import i18nConfig from './your-i18n-config'

Vue.use(VueI18n, { bridge: true })
const i18n = castToVueI18n(createI18n(i18nConfig, VueI18n))
Vue.use(i18n)  // こちらも Vue.use する

// ...

new Vue({
  i18n,
  store,
  router,
  vuetify,
  // ...
}).$mount('#app')

上記例で createI18n() に渡している i18nConfig は、次のような構造のデータです。

const locales = {
  ja: {
    // 略
  },
  en: {
    // 略
  },
}

const datetimeFormats = {
  ja: // 略。DateTimeFormat 型
  en: // 略。DateTimeFormat 型
} as DateTimeFormats

const DEFAULT_LANG = navigator.language

const i18nConfig = {
  locale: DEFAULT_LANG,
  legacy: false,
  fallbackLocale: ['ja'],
  messages: locales,
  datetimeFormats,
}

export default i18nConfig

ポイントは次の二点です。

  1. legacy: false で Vue-i18n Legacy API を無効化します。こうしないと $tt は共存できません
  2. Datetime フォーマッタ(すなわち $d / d)を使う場合、dateTimeFormats から datetimeFormats に修正します(違いはよーく見て!)

利用側の Vue コンポーネント

useI18n() を通じて td を取得します。

useI18n() は setup 内でなければ実行できないことに注意してください。

setup script スタイルの場合:

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

const { t } = useI18n()

Composition API スタイルの場合:

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

export default {
  setup () {
    const { t } = useI18n()
    return { t }
  }
}

Datetime フォーマッタも必要なら const { t, d } = useI18n() のようにして取得しましょう。

これで、template 内で t が参照できるようになりました。

<h1>{{ t('messages.featureA.title') }}</h1>

既存のコードで、グローバルスコープの $t$d を使っている箇所に影響が出ていないことも確認しましょう。

おわりに

着々と Vue コンポーネントの修正を進めておければ、将来 Vue3 / Vue-i18n@9 へ移行するタイミングでは、'vue-i18n-bridge''vue-i18n' に一括置換するだけで済みそうですね。

以上です!

参考情報

ロンラン Tech Zenn

Discussion