Skip to content

v12 破壊的変更

Legacy API モードの廃止

理由: Legacy API モードは、v11 破壊的変更で発表されたように、v11 で非推奨になりました。これは、Vue 2 用の Vue I18n v8 と互換性のある API モードであり、v8 から v9 への移行をスムーズにするために提供されていました。

v12 では、Legacy API モードは完全に削除されました。createI18nlegacy オプションは使用できなくなり、すべてのアプリケーションは Composition API モードを使用する必要があります。

削除されたもの

  • createI18nlegacy: true オプション
  • VueI18n インスタンス(レガシーインターフェース)
  • VueI18nOptions
  • allowComposition オプション(Composition API が唯一のモードであるため不要)
  • VueI18n インスタンスに依存していたレガシー固有の注入 API

以前 (v11)

ts
import { createI18n } from 'vue-i18n'

// Legacy API モード
const i18n = createI18n({
  legacy: true, // 以前のバージョンではこれがデフォルトでした
  locale: 'en',
  messages: {
    en: { hello: 'Hello!' },
    ja: { hello: 'こんにちは!' }
  }
})

// VueI18n インスタンス経由のアクセス
i18n.global.locale = 'ja'
html
<!-- Options API コンポーネント内 -->
<template>
  <p>{{ $t('hello') }}</p>
</template>

<script>
export default {
  mounted() {
    // this.$i18n (VueI18n インスタンス) 経由のアクセス
    console.log(this.$i18n.locale)
    this.$i18n.locale = 'ja'
  }
}
</script>

以後 (v12)

ts
import { createI18n } from 'vue-i18n'

// Composition API モード (利用可能な唯一のモード)
const i18n = createI18n({
  locale: 'en',
  messages: {
    en: { hello: 'Hello!' },
    ja: { hello: 'こんにちは!' }
  }
})

// Composer インスタンス経由のアクセス
i18n.global.locale.value = 'ja'
html
<!-- Composition API の使用 -->
<template>
  <p>{{ t('hello') }}</p>
</template>

<script setup>
import { useI18n } from 'vue-i18n'

const { t, locale } = useI18n()

// ロケールの変更
locale.value = 'ja'
</script>
html
<!-- setup で useI18n を使用する Options API -->
<template>
  <p>{{ t('hello') }}</p>
</template>

<script>
import { useI18n } from 'vue-i18n'

export default {
  setup() {
    const { t, locale } = useI18n()
    return { t, locale }
  }
}
</script>

移行

  1. createI18n から legacy: true オプションを削除します
  2. ロケールアクセスを i18n.global.locale から i18n.global.locale.value に変更します
  3. setup 関数内の this.$i18n の使用を useI18n() に置き換えます
  4. this.$t()useI18n()t() に置き換えます

詳細な移行ガイドについては、以下を参照してください。

詳細な移行ガイド

テンプレートでの $t / $d / $n の使用

v12 では、globalInjection: true(デフォルト)の場合、テンプレート内で $t()$d()$n()$rt()$tm()$te() が引き続き利用可能です。これらはグローバルスコープの Composer を参照します。コンポーネントローカルのスコープを使用するには、useI18n()t() を使用してください。

html
<!-- v12: テンプレートで $t は引き続き使用可能(グローバルスコープ) -->
<template>
  <p>{{ $t('hello') }}</p>
</template>

ただし、JavaScript コード(methodscomputedwatch、ライフサイクルフック)内での this.$t() は使用できなくなりました。代わりに setup() 内で useI18n() を使用する必要があります。

以前 (v11):

js
export default {
  methods: {
    greet() {
      return this.$t('hello')
    }
  },
  computed: {
    message() {
      return this.$t('welcome', { name: this.user })
    }
  },
  watch: {
    lang(val) {
      this.$i18n.locale = val
    }
  },
  mounted() {
    console.log(this.$t('ready'))
    console.log(this.$d(new Date(), 'long'))
    console.log(this.$n(1000, 'currency'))
  }
}

以後 (v12) - <script setup>:

vue
<script setup>
import { useI18n } from 'vue-i18n'
import { watch, onMounted, computed } from 'vue'

const { t, d, n, locale } = useI18n()

function greet() {
  return t('hello')
}

const message = computed(() => t('welcome', { name: user.value }))

watch(lang, (val) => {
  locale.value = val
})

onMounted(() => {
  console.log(t('ready'))
  console.log(d(new Date(), 'long'))
  console.log(n(1000, 'currency'))
})
</script>

以後 (v12) - setup() を使用する Options API:

js
import { useI18n } from 'vue-i18n'
import { watch, onMounted, computed } from 'vue'

export default {
  setup() {
    const { t, d, n, locale } = useI18n()

    function greet() {
      return t('hello')
    }

    const message = computed(() => t('welcome', { name: user.value }))

    watch(lang, (val) => {
      locale.value = val
    })

    onMounted(() => {
      console.log(t('ready'))
      console.log(d(new Date(), 'long'))
      console.log(n(1000, 'currency'))
    })

    return { t, d, n, locale, greet, message }
  }
}

$i18n プロパティの変更

v11 では、this.$i18n はすべてのメソッドとプロパティにアクセスできる VueI18n インスタンスでした。v12 では、$i18nExportedGlobalComposer 型に変更され、以下のプロパティのみが公開されます。

プロパティ説明
$i18n.localeLocale (string)現在のロケール(get/set)
$i18n.fallbackLocaleFallbackLocaleフォールバックロケール(get/set)
$i18n.availableLocalesLocale[]利用可能なロケール一覧(読み取り専用)

this.$i18n.t()this.$i18n.setLocaleMessage() などのメソッドは、$i18n 経由ではアクセスできなくなりました。代わりに useI18n() を使用してください。

以前 (v11):

js
export default {
  mounted() {
    // VueI18n インスタンス - すべてのメソッドにアクセス可能
    this.$i18n.locale = 'ja'
    this.$i18n.setLocaleMessage('fr', { hello: 'Bonjour' })
    this.$i18n.mergeLocaleMessage('en', { goodbye: 'Goodbye' })
    console.log(this.$i18n.getLocaleMessage('en'))
    console.log(this.$i18n.t('hello'))
    console.log(this.$i18n.te('hello'))
    console.log(this.$i18n.tm('messages'))
    console.log(this.$i18n.d(new Date(), 'long'))
    console.log(this.$i18n.n(1000, 'currency'))
    this.$i18n.setDateTimeFormat('ja', { long: { /* ... */ } })
    this.$i18n.setNumberFormat('ja', { currency: { /* ... */ } })
    console.log(this.$i18n.silentTranslationWarn)
    console.log(this.$i18n.missing)
  }
}

以後 (v12):

vue
<script setup>
import { useI18n } from 'vue-i18n'
import { onMounted } from 'vue'

const {
  locale,
  t, te, tm, d, n,
  setLocaleMessage, mergeLocaleMessage, getLocaleMessage,
  setDateTimeFormat, setNumberFormat,
  getMissingHandler
} = useI18n()

onMounted(() => {
  locale.value = 'ja'
  setLocaleMessage('fr', { hello: 'Bonjour' })
  mergeLocaleMessage('en', { goodbye: 'Goodbye' })
  console.log(getLocaleMessage('en'))
  console.log(t('hello'))
  console.log(te('hello'))
  console.log(tm('messages'))
  console.log(d(new Date(), 'long'))
  console.log(n(1000, 'currency'))
  setDateTimeFormat('ja', { long: { /* ... */ } })
  setNumberFormat('ja', { currency: { /* ... */ } })
  console.log(getMissingHandler())
})
</script>

コンポーネントローカルメッセージ

v11 では、i18n コンポーネントオプションでローカルメッセージを定義できました。v12 では、i18n コンポーネントオプションは ComponentCustomOptions から削除されました。

以前 (v11):

js
export default {
  i18n: {
    messages: {
      en: { title: 'My Component' },
      ja: { title: 'マイコンポーネント' }
    }
  },
  template: '<h1>{{ $t("title") }}</h1>'
}

以後 (v12) - useI18nuseScope: 'local' を使用:

vue
<script setup>
import { useI18n } from 'vue-i18n'

const { t } = useI18n({
  useScope: 'local',
  messages: {
    en: { title: 'My Component' },
    ja: { title: 'マイコンポーネント' }
  }
})
</script>

<template>
  <h1>{{ t('title') }}</h1>
</template>

以後 (v12) - SFC <i18n> カスタムブロックを使用:

vue
<script setup>
import { useI18n } from 'vue-i18n'

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

<template>
  <h1>{{ t('title') }}</h1>
</template>

<i18n>
{
  "en": { "title": "My Component" },
  "ja": { "title": "マイコンポーネント" }
}
</i18n>

<i18n> カスタムブロックが存在する場合、useI18n() は自動的にローカルスコープを使用します。

createI18n オプション名の変更

以下の表は、v11 Legacy API のオプション名と v12 Composition API の対応するオプション名のマッピングです。

v11 (VueI18nOptions)v12 (ComposerOptions)変更内容
legacy: true(削除)Composition API のみ
silentTranslationWarnmissingWarn論理が反転(truefalsefalsetrue
silentFallbackWarnfallbackWarn論理が反転
formatFallbackMessagesfallbackFormat名前変更
warnHtmlInMessagewarnHtmlMessage型変更: 'off'|'warn'boolean'off'false'warn'true
escapeParameterHtmlescapeParameter名前変更
syncinheritLocale名前変更
pluralizationRulespluralRules名前変更
sharedMessages(削除)messages に直接マージして使用

以前 (v11):

js
const i18n = createI18n({
  legacy: true,
  locale: 'en',
  silentTranslationWarn: true,
  silentFallbackWarn: true,
  formatFallbackMessages: true,
  warnHtmlInMessage: 'off',
  escapeParameterHtml: true,
  sync: false,
  pluralizationRules: { ru: customRule },
  sharedMessages: { en: { shared: 'Shared' } },
  messages: { en: { hello: 'Hello' } }
})

以後 (v12):

js
const i18n = createI18n({
  locale: 'en',
  missingWarn: false,          // silentTranslationWarn: true → missingWarn: false
  fallbackWarn: false,         // silentFallbackWarn: true → fallbackWarn: false
  fallbackFormat: true,        // formatFallbackMessages → fallbackFormat
  warnHtmlMessage: false,      // warnHtmlInMessage: 'off' → warnHtmlMessage: false
  escapeParameter: true,       // escapeParameterHtml → escapeParameter
  inheritLocale: false,        // sync → inheritLocale
  pluralRules: { ru: customRule },  // pluralizationRules → pluralRules
  messages: {
    en: {
      hello: 'Hello',
      shared: 'Shared'          // sharedMessages は messages に直接マージ
    }
  }
})

VueI18n インスタンスメソッド

v11 では、メッセージ管理は VueI18n インスタンス経由で行われていました。v12 では、Composer の同等のメソッドを使用します。

VueI18n メソッドComposer メソッド変更
t()t()同じ
rt()rt()同じ
te()te()同じ
tm()tm()同じ
d()d()同じ
n()n()同じ
getLocaleMessage()getLocaleMessage()同じ
setLocaleMessage()setLocaleMessage()同じ
mergeLocaleMessage()mergeLocaleMessage()同じ
getDateTimeFormat()getDateTimeFormat()同じ
setDateTimeFormat()setDateTimeFormat()同じ
mergeDateTimeFormat()mergeDateTimeFormat()同じ
getNumberFormat()getNumberFormat()同じ
setNumberFormat()setNumberFormat()同じ
mergeNumberFormat()mergeNumberFormat()同じ
missing(プロパティ)getMissingHandler() / setMissingHandler()プロパティ → メソッド
postTranslation(プロパティ)getPostTranslationHandler() / setPostTranslationHandler()プロパティ → メソッド

以前 (v11):

js
// createI18n で生成した i18n インスタンス経由
i18n.global.locale = 'ja'
i18n.global.setLocaleMessage('fr', { hello: 'Bonjour' })
i18n.global.missing = (locale, key) => { /* ... */ }

以後 (v12):

js
// locale は Ref になったため .value が必要
i18n.global.locale.value = 'ja'
// メソッドは同名で利用可能
i18n.global.setLocaleMessage('fr', { hello: 'Bonjour' })
// missing はメソッド経由でアクセス
i18n.global.setMissingHandler((locale, key) => { /* ... */ })

i18n.global の変更

v11 Legacy API では、i18n.globalVueI18n インスタンスを返していました。v12 では、Composer インスタンスを返します。

主な違い:

  • i18n.global.localestring から WritableComputedRef<string> に変更(.value が必要)
  • i18n.global.fallbackLocaleWritableComputedRef に変更(.value が必要)
  • i18n.global.messagesComputedRef に変更(.value が必要、読み取り専用)
  • i18n.global.availableLocalesComputedRef に変更(.value が必要、読み取り専用)

カスタムディレクティブ v-t の廃止

理由: v-t カスタムディレクティブは v11 で非推奨となり、v12 で削除されるという警告が表示されていました。詳細は v11 破壊的変更 を参照してください。

すべての v-t ディレクティブの使用を $t()(グローバルスコープ)または useI18n()t() に置き換えてください。

文字列構文

html
<!-- 以前 (v11) -->
<p v-t="'hello'"></p>

<!-- 以後 (v12) -->
<p>{{ $t('hello') }}</p>
<!-- または useI18n() を使用 -->
<p>{{ t('hello') }}</p>

オブジェクト構文(名前付き引数)

html
<!-- 以前 (v11) -->
<p v-t="{ path: 'hello', args: { name: userName } }"></p>

<!-- 以後 (v12) -->
<p>{{ $t('hello', { name: userName }) }}</p>

オブジェクト構文(複数形)

html
<!-- 以前 (v11) -->
<p v-t="{ path: 'car', plural: count }"></p>
<!-- または -->
<p v-t="{ path: 'car', choice: count }"></p>

<!-- 以後 (v12) -->
<p>{{ $t('car', count) }}</p>

オブジェクト構文(ロケール指定)

html
<!-- 以前 (v11) -->
<p v-t="{ path: 'hello', locale: 'ja' }"></p>

<!-- 以後 (v12) -->
<p>{{ $t('hello', {}, { locale: 'ja' }) }}</p>
<!-- または useI18n() を使用 -->
<p>{{ t('hello', {}, { locale: 'ja' }) }}</p>

eslint-plugin-vue-i18n による検出

@intlify/vue-i18n/no-deprecated-v-t ルールを使用して、コードベース内のすべての v-t の使用箇所を検出できます。

デフォルトの複数形が Intl.PluralRules を使用するようになりました

理由: 以前のデフォルト複数形ルールは英語専用の単純な実装で、複雑な複数形カテゴリを持つ言語(ロシア語、アラビア語、ポーランド語など)を正しく処理できませんでした。Vue I18n v12 では、現在のロケールに基づいて正しい複数形を自動的に選択するために Intl.PluralRules を使用します。

変更点

  • ロケールにカスタム pluralRules が設定されていない場合、Vue I18n は自動的に Intl.PluralRules を使用して正しい複数形カテゴリ(zero, one, two, few, many, other)を決定します
  • メッセージのケースは CLDR 複数形カテゴリの順序に従って並べる必要があります: zero | one | two | few | many | other(ロケールに存在するカテゴリのみ含む)
  • メッセージのケース数がロケールの複数形カテゴリ数を超える場合、Vue I18n は以前のデフォルトルールにフォールバックします
  • ランタイム環境で Intl.PluralRules が利用できない場合、Vue I18n は以前のデフォルトルールにフォールバックします

移行

カスタム pluralRules なしで英語以外のロケールの以前のデフォルトルールに依存していた場合、メッセージのケースをロケールの CLDR 複数形カテゴリの順序に合わせて並べ替える必要があります。

以前 (v11) — カスタム pluralRules 付きのロシア語:

変更不要。カスタム pluralRules が優先され、以前と同様に動作します。

以後 (v12) — ロシア語(自動、カスタム pluralRules 不要):

js
const i18n = createI18n({
  locale: 'ru',
  // pluralRules 不要 — Intl.PluralRules が自動的に処理します
  messages: {
    ru: {
      // 順序: one | few | many | other(ロシア語の CLDR 順序)
      car: '{n} машина | {n} машины | {n} машин | {n} машин'
    }
  }
})

MissingHandler シグネチャの変更

理由: Vue 3.6+ では getCurrentInstance() API が非推奨になります。MissingHandler 型は以前、3 番目のパラメータとして ComponentInternalInstance を受け取っていましたが、これは使用できなくなりました。

以前 (v11)

ts
type MissingHandler = (
  locale: Locale,
  key: Path,
  instance?: ComponentInternalInstance,
  type?: string
) => string | void

const i18n = createI18n({
  missing: (locale, key, instance, type) => {
    // instance は ComponentInternalInstance でした
    console.warn(`Missing: ${key}`, instance?.uid)
  }
})

以後 (v12)

ts
type MissingHandler = (
  locale: Locale,
  key: Path,
  uid?: number,
  type?: string
) => string | void

const i18n = createI18n({
  missing: (locale, key, uid, type) => {
    // uid は数値として直接渡されるようになりました
    console.warn(`Missing: ${key}`, uid)
  }
})

移行

instance パラメータを uid に置き換えます。

diff
 const i18n = createI18n({
-  missing: (locale, key, instance, type) => {
-    console.warn(`Missing key "${key}" in ${locale}`, instance?.uid)
+  missing: (locale, key, uid, type) => {
+    console.warn(`Missing key "${key}" in ${locale}`, uid)
   }
 })

$t / t() のキー補完改善に伴う型シグネチャの変更

理由: $t および t() 関数のオーバーロードにおけるジェネリック型パラメータ Key extends string が、IDE の自動補完で DefineLocaleMessage のリソースキーを表示することを妨げていました。Key 型が広すぎる(string)ため、IDE が具体的なリソースキーリテラルを優先表示できませんでした。

変更内容

Key extends string ジェネリックパラメータがすべての $t および t() オーバーロードから削除されました。key パラメータの型が Key | ResourceKeys | number から ResourceKeys | (string & {}) | number に変更されました。

変更前 (v11)

ts
$t<
  Key extends string,
  DefinedLocaleMessage extends ...,
  Keys = ...,
  ResourceKeys extends Keys = ...
>(
  key: Key | ResourceKeys | number
): string

変更後 (v12)

ts
$t<
  DefinedLocaleMessage extends ...,
  Keys = ...,
  ResourceKeys extends Keys = ...
>(
  key: ResourceKeys | (string & {}) | number
): string

影響

  • IDE 自動補完: DefineLocaleMessage で定義されたリソースキーが候補として表示されるようになりました
  • 任意の文字列は引き続き受け付け: string & {}string と互換性があるため、既存のコードはそのまま動作します
  • ジェネリック型パラメータの削除: Key ジェネリックを明示的に指定していた場合(例: $t<'myKey'>(...))、削除が必要です

移行方法

ほとんどのコードは変更不要です。Key ジェネリック型パラメータを明示的に渡していた場合は削除してください:

diff
- $t<'myKey'>('myKey')
+ $t('myKey')

Released under the MIT License.