v12 破壊的変更
Legacy API モードの廃止
理由: Legacy API モードは、v11 破壊的変更で発表されたように、v11 で非推奨になりました。これは、Vue 2 用の Vue I18n v8 と互換性のある API モードであり、v8 から v9 への移行をスムーズにするために提供されていました。
v12 では、Legacy API モードは完全に削除されました。createI18n の legacy オプションは使用できなくなり、すべてのアプリケーションは Composition API モードを使用する必要があります。
削除されたもの
createI18nのlegacy: trueオプションVueI18nインスタンス(レガシーインターフェース)VueI18nOptions型allowCompositionオプション(Composition API が唯一のモードであるため不要)VueI18nインスタンスに依存していたレガシー固有の注入 API
以前 (v11)
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'<!-- 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)
import { createI18n } from 'vue-i18n'
// Composition API モード (利用可能な唯一のモード)
const i18n = createI18n({
locale: 'en',
messages: {
en: { hello: 'Hello!' },
ja: { hello: 'こんにちは!' }
}
})
// Composer インスタンス経由のアクセス
i18n.global.locale.value = 'ja'<!-- Composition API の使用 -->
<template>
<p>{{ t('hello') }}</p>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
// ロケールの変更
locale.value = 'ja'
</script><!-- 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>移行
createI18nからlegacy: trueオプションを削除します- ロケールアクセスを
i18n.global.localeからi18n.global.locale.valueに変更します - setup 関数内の
this.$i18nの使用をuseI18n()に置き換えます this.$t()をuseI18n()のt()に置き換えます
詳細な移行ガイドについては、以下を参照してください。
詳細な移行ガイド
テンプレートでの $t / $d / $n の使用
v12 では、globalInjection: true(デフォルト)の場合、テンプレート内で $t()、$d()、$n()、$rt()、$tm()、$te() が引き続き利用可能です。これらはグローバルスコープの Composer を参照します。コンポーネントローカルのスコープを使用するには、useI18n() の t() を使用してください。
<!-- v12: テンプレートで $t は引き続き使用可能(グローバルスコープ) -->
<template>
<p>{{ $t('hello') }}</p>
</template>ただし、JavaScript コード(methods、computed、watch、ライフサイクルフック)内での this.$t() は使用できなくなりました。代わりに setup() 内で useI18n() を使用する必要があります。
以前 (v11):
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>:
<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:
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 では、$i18n は ExportedGlobalComposer 型に変更され、以下のプロパティのみが公開されます。
| プロパティ | 型 | 説明 |
|---|---|---|
$i18n.locale | Locale (string) | 現在のロケール(get/set) |
$i18n.fallbackLocale | FallbackLocale | フォールバックロケール(get/set) |
$i18n.availableLocales | Locale[] | 利用可能なロケール一覧(読み取り専用) |
this.$i18n.t()、this.$i18n.setLocaleMessage() などのメソッドは、$i18n 経由ではアクセスできなくなりました。代わりに useI18n() を使用してください。
以前 (v11):
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):
<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):
export default {
i18n: {
messages: {
en: { title: 'My Component' },
ja: { title: 'マイコンポーネント' }
}
},
template: '<h1>{{ $t("title") }}</h1>'
}以後 (v12) - useI18n で useScope: 'local' を使用:
<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> カスタムブロックを使用:
<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 のみ |
silentTranslationWarn | missingWarn | 論理が反転(true → false、false → true) |
silentFallbackWarn | fallbackWarn | 論理が反転 |
formatFallbackMessages | fallbackFormat | 名前変更 |
warnHtmlInMessage | warnHtmlMessage | 型変更: 'off'|'warn' → boolean('off' → false、'warn' → true) |
escapeParameterHtml | escapeParameter | 名前変更 |
sync | inheritLocale | 名前変更 |
pluralizationRules | pluralRules | 名前変更 |
sharedMessages | (削除) | messages に直接マージして使用 |
以前 (v11):
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):
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):
// createI18n で生成した i18n インスタンス経由
i18n.global.locale = 'ja'
i18n.global.setLocaleMessage('fr', { hello: 'Bonjour' })
i18n.global.missing = (locale, key) => { /* ... */ }以後 (v12):
// 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.global は VueI18n インスタンスを返していました。v12 では、Composer インスタンスを返します。
主な違い:
i18n.global.locale—stringからWritableComputedRef<string>に変更(.valueが必要)i18n.global.fallbackLocale—WritableComputedRefに変更(.valueが必要)i18n.global.messages—ComputedRefに変更(.valueが必要、読み取り専用)i18n.global.availableLocales—ComputedRefに変更(.valueが必要、読み取り専用)
カスタムディレクティブ v-t の廃止
理由: v-t カスタムディレクティブは v11 で非推奨となり、v12 で削除されるという警告が表示されていました。詳細は v11 破壊的変更 を参照してください。
すべての v-t ディレクティブの使用を $t()(グローバルスコープ)または useI18n() の t() に置き換えてください。
文字列構文
<!-- 以前 (v11) -->
<p v-t="'hello'"></p>
<!-- 以後 (v12) -->
<p>{{ $t('hello') }}</p>
<!-- または useI18n() を使用 -->
<p>{{ t('hello') }}</p>オブジェクト構文(名前付き引数)
<!-- 以前 (v11) -->
<p v-t="{ path: 'hello', args: { name: userName } }"></p>
<!-- 以後 (v12) -->
<p>{{ $t('hello', { name: userName }) }}</p>オブジェクト構文(複数形)
<!-- 以前 (v11) -->
<p v-t="{ path: 'car', plural: count }"></p>
<!-- または -->
<p v-t="{ path: 'car', choice: count }"></p>
<!-- 以後 (v12) -->
<p>{{ $t('car', count) }}</p>オブジェクト構文(ロケール指定)
<!-- 以前 (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 不要):
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)
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)
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 に置き換えます。
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)
$t<
Key extends string,
DefinedLocaleMessage extends ...,
Keys = ...,
ResourceKeys extends Keys = ...
>(
key: Key | ResourceKeys | number
): string変更後 (v12)
$t<
DefinedLocaleMessage extends ...,
Keys = ...,
ResourceKeys extends Keys = ...
>(
key: ResourceKeys | (string & {}) | number
): string影響
- IDE 自動補完:
DefineLocaleMessageで定義されたリソースキーが候補として表示されるようになりました - 任意の文字列は引き続き受け付け:
string & {}はstringと互換性があるため、既存のコードはそのまま動作します - ジェネリック型パラメータの削除:
Keyジェネリックを明示的に指定していた場合(例:$t<'myKey'>(...))、削除が必要です
移行方法
ほとんどのコードは変更不要です。Key ジェネリック型パラメータを明示的に渡していた場合は削除してください:
- $t<'myKey'>('myKey')
+ $t('myKey')