Skip to content

コンポジション API

setup と Vue の Composition API の導入により、新たな可能性が広がります。Vue I18n から最大限の効果を得るためには、this へのアクセスを置き換えるためのいくつかの新しい関数を使用する必要があります。

これまで Vue I18n の機能は、vue-i18n v8.x 互換のレガシー API を使用して説明してきました。それでは、コンポジション API 向けの Vue I18n useI18n を見ていきましょう。

基本的な使い方

Vue I18n コンポジション API の基本的な使い方を見てみましょう!ここでは、始める で紹介したコードを修正することで、基本的な使い方を学びます。

Vue 3 の setupuseI18n を使用するには、createI18n 関数の legacy オプションを false に設定する必要があります。

createI18nlegacy オプションを追加する例は以下の通りです:

js
// ...
const i18n = VueI18n.createI18n({
  legacy: false, // コンポジション API 使用時は `false` に設定する必要があります
  locale: 'ja',
  fallbackLocale: 'en',
  messages: {
    en: {
      message: {
        hello: 'hello world'
      }
    },
    ja: {
      message: {
        hello: 'こんにちは、世界'
      }
    }
  }
})

// ...

legacy: false を設定することで、Vue I18n はレガシーアイテムモードからコンポジション API モードに切り替えることができます。

注意

createI18n によって作成された i18n インスタンスの以下のプロパティは動作が変わります:

  • mode プロパティ: "legacy" から "composition"
  • global プロパティ: VueI18n インスタンスから Composer インスタンスへ

これで、App.vue コンポーネントで useI18n を使用する準備ができました。コードは次のようになります:

vue
<script setup> 
import { useI18n } from 'vue-i18n'
const { t } = useI18n() 
</script> // [!code ++]

<template>
  <h1>{{ $t("message.hello") }}</h1>
</template>

<script setup> の先頭で useI18n を呼び出す必要があります。

useI18n は Composer インスタンスを返します。Composer インスタンスは、t 関数などの翻訳 API および localefallbackLocale などのプロパティを提供します。これらは VueI18n インスタンスと同様です。Composer インスタンスの詳細については、API リファレンス を参照してください。

上記の例では、useI18n にオプションが指定されていないため、グローバルスコープの Composer インスタンスが返されます。その結果、t 関数による翻訳は createI18n で定義されたメッセージを使用します。

コンポーネントのテンプレートで t を使用できます:

vue
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

<template>
  <h1>{{ $t("message.hello") }}</h1> // [!code --]
  <h1>{{ t("message.hello") }}</h1> // [!code ++]
</template>

出力は以下の通りです:

vue
<div id="app">
  <h1>こんにちは、世界</h1>
</div>

メッセージ翻訳

レガシー API モードでは、メッセージは $t または VueI18n インスタンスの t を使用して翻訳されました。

コンポジション API モードでは、メッセージフォーマット構文はレガシー API モードと同じままです。以下のように Composer インスタンス t を使用してメッセージを翻訳できます:

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

const { t } = useI18n({
  locale: 'en',
  messages: {
    en: {
      msg: 'hello',
      named: '{msg} world!',
      list: '{0} world!',
      literal: "{'hello'} world!",
      the_world: 'the world',
      dio: 'DIO:',
      linked: '@:dio @:the_world !!!!'
    },
    ja: {
      msg: 'こんにちは',
      named: '{msg} 世界!',
      list: '{0} 世界!',
      literal: "{'こんにちは'} 世界!",
      the_world: 'ザ・ワールド!',
      dio: 'ディオ:',
      linked: '@:dio @:the_world !!!!'
    }
  }
})

const msg = computed(() => t('msg'))
</script>

<template>
  <p>{{ t('named', { msg }) }}</p>
  <p>{{ t('list', [msg]) }}</p>
  <p>{{ t('literal') }}</p>
  <p>{{ t('linked') }}</p>
</template>

t の詳細については、API リファレンス を参照してください。

複数形

コンポジション API モードでは、メッセージの複数形表記もレガシー API モードと同じ構文で、Composer インスタンスの t を使用して翻訳されます:

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

const { t } = useI18n({
  locale: 'en',
  messages: {
    en: {
      car: 'car | cars',
      apple: 'no apples | one apple | {count} apples',
      banana: 'no bananas | {n} banana | {n} bananas'
    }
  }
})
</script>

<template>
  <h2>Car:</h2>
  <p>{{ t('car', 1) }}</p>
  <p>{{ t('car', 2) }}</p>
  <h2>Apple:</h2>
  <p>{{ t('apple', 0) }}</p>
  <p>{{ t('apple', 1) }}</p>
  <p>{{ t('apple', { count: 10 }, 10) }}</p>
  <p>{{ t('apple', 10) }}</p>
  <h2>Banana:</h2>
  <p>{{ t('banana', { n: 1 }, 1) }}</p>
  <p>{{ t('banana', 1) }}</p>
  <p>{{ t('banana', { n: 'too many' }, 100) }}</p>
</template>

注意

コンポジション API モードでは、複数形翻訳が t に統合されました。

日時フォーマット

レガシー API モードでは、日時値は $d または VueI18n インスタンスの d を使用してフォーマットされていました。

コンポジション API モードでは、Composer インスタンスの d を使用してフォーマットします:

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

const { t, d } = useI18n({
  locale: 'en-US',
  messages: {
    'en-US': {
      current: 'Current Datetime'
    }
  },
  datetimeFormats: {
    'en-US': {
      long: {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      }
    }
  }
})

const now = ref(new Date())
</script>

<template>
  <p>{{ t('current') }}: {{ d(now, 'long') }}</p>
</template>

d の詳細については、API リファレンス を参照してください。

数値フォーマット

レガシー API モードでは、数値は $n または VueI18n インスタンスの n を使用してフォーマットされていました。

コンポジション API モードでは、Composer インスタンスの n を使用してフォーマットします:

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

const { t, n } = useI18n({
  locale: 'en-US',
  messages: {
    'en-US': {
      money: 'Money'
    }
  },
  numberFormats: {
    'en-US': {
      currency: {
        style: 'currency',
        currency: 'USD'
      }
    }
  }
})

const money = ref(1000)
</script>

<template>
  <p>{{ t('money') }}: {{ n(money, 'currency') }}</p>
</template>

n の詳細については、API リファレンス を参照してください。

グローバルスコープ

コンポジション API モードでは、createI18n で i18n インスタンスを作成すると、レガシー API モードと同様にグローバルスコープが作成されます。

レガシー API モードの i18n インスタンスの global プロパティは VueI18n インスタンスですが、コンポジション API モードでは Composer インスタンスを参照できるようになります。

コンポーネントでグローバルスコープの Composer インスタンスを参照する方法は二つあります。

明示的に useI18n を使用

前述のように、useI18n を使用する方法があります。

ts
import { useI18n } from 'vue-i18n'

const { t } = useI18n({ useScope: 'global' })

// 何かを行う...

上記のコードは、useI18n オプションに useScope: 'global' を設定し、i18n インスタンスの global プロパティからアクセスできる Composer インスタンスを返すようにします。この Composer インスタンスはグローバルスコープです。

そうすれば、Composer インスタンスから公開された関数やプロパティを使用して構成できます。

注意

useI18nmessagesdatetimeFormatsnumberFormats を同時に useScope: 'global' として設定した場合、これらはグローバルスコープにマージされます。つまり、これらはグローバルスコープの Composer インスタンスの messagesdatetimeFormastsnumberFormats で管理されます。

また、global が i18n カスタムブロックで指定されている場合(例:<i18n global>{ … }</i18n>)、ブロックで定義されたロケールメッセージはグローバルスコープにマージされます。

暗黙的に注入されたプロパティと関数を使用

グローバルスコープの Composer インスタンスを参照するもう一つの方法は、コンポーネントに暗黙的に注入されたプロパティと関数を使用することです。

デフォルトでは無効になっているため、createI18n のオプションとして legacy: false と一緒に globalInjection: true を指定する必要があります。

注意

vue-i18n v9.2-beta.34 以降、globalInjection はデフォルトで true です。

これにより、Vue I18n は以下のプロパティと関数をコンポーネントに注入できるようになります:

  • $i18n: 以下のグローバルスコープの Composer インスタンスプロパティをラップしたオブジェクト
    • locale
    • fallbackLocale
    • availableLocales
  • $t: グローバルスコープの Composer の t 関数
  • $rt: グローバルスコープの Composer の rt 関数
  • $d: グローバルスコープの Composer の d 関数
  • $n: グローバルスコープの Composer の n 関数
  • $tm: グローバルスコープの Composer の tm 関数

Vue 3 ランタイムは、app.config.globalProperties で設定されたものをコンポーネントにグローバルに注入します。そのため、上記は Vue 3 ランタイムによって注入され、テンプレート内で暗黙的に使用できます。

注意

  • setup ではコンポーネントに注入されたこれらのプロパティと関数は表示できません
  • レガシー API モードでは $ で始まる Vue I18n API が注入されていましたが、コンポジション API モードで注入される $ で始まるプロパティと関数はレガシー API モードとは異なります。

上記のものに $ が付いていることに気づいたでしょう。これが $ で始まる理由は以下の通りです:

  • setup でレンダーコンテキストから返されるプロパティと関数と競合しない
  • Vue I18n コンポジション API モードにおけるグローバルスコープの識別子

このような設計により、ユーザーにこれらが特別なプロパティと関数であることを示します。

注意

もし Vue アプリケーションがローカルスコープを使わず、すべてをグローバルスコープで処理する場合は、これは非常に便利です。各コンポーネントで setupuseI18n を実行する必要がありません。しかし、この方法にはグローバル変数のような性質があるため注意が必要です。特に大規模な Vue アプリケーションでは慎重に使用すべきです。

一度使用した後、それが使われなくなった場合は、テンプレートで使用されているプロパティや関数を setup コンテキストから返される useI18nuseScope: 'global' オプションを使用して変更する必要があります。

ローカルスコープ

レガシー API モードでは、各コンポーネントに i18n コンポーネントオプションを指定することで VueI18n インスタンスが作成され、VueI18n インスタンスによって管理されるローカルメッセージなどのリソースを対象コンポーネントのみが参照できるローカルスコープにすることができます。

コンポジション API モードでローカルスコープを有効にするには、useI18n にオプションを設定する必要があります。これにより、与えられたロケール、ロケールメッセージなどに基づいて新しい Composer インスタンスが作成されます。オプションが指定された場合、useI18n はロケール、ロケールメッセージ、およびその他のリソースを指定に基づいて新しい Composer インスタンスを作成し、返します。

注意

明示的に useScope: 'local' オプションを指定できます。

以下の例のコード:

js
import { useI18n } from 'vue-i18n'

const { t, d, n, tm, locale } = useI18n({
  locale: 'ja-JP',
  fallbackLocale: 'en-US',
  messages: {
    'en-US': {
      // ....
    },
    'ja-JP': {
      // ...
    }
  },
  datetimeFormats: {
    'en-US': {
      // ....
    },
    'ja-JP': {
      // ...
    }
  },
  numberFormats: {
    'en-US': {
      // ....
    },
    'ja-JP': {
      // ...
    }
  }
})

// 何かを行う...

ロケールメッセージ

SFCで i18n カスタムブロックを使用してロケールメッセージのリソースを使用する場合、useI18nmessages オプションで指定されたロケールメッセージとマージされます。

i18n カスタムブロックと useI18n オプションを使用する例:

vue
<script setup>
import { useI18n } from 'vue-i18n'
import en from './en.json'

const { t, availableLocales, getLocaleMessages } = useI18n({
  locale: 'en',
  messages: {
    en
  }
})

availableLocales.forEach(locale => {
  console.log(`${locale} locale messages`, getLocaleMessages(locale))
})
</script>

<i18n locale="ja">
{
  "hello": "こんにちは!"
}
</i18n>

注意

この例では、リソースの定義は i18n カスタムブロックと useI18nmessages オプションから分離されていますが、ローカルスコープでは、管理上の理由からリソースメッセージを一括で messages オプションに指定するか、すべてのリソースメッセージを i18n カスタムブロックで定義することが推奨されます。

コンポーネント間で共有されるロケールメッセージ

レガシー API モードでは、共有ロケールメッセージは sharedMessages オプションを使用してコンポーネントで使用されていました。

コンポジション API モードでは、useI18n からエクスポートされた mergeLocaleMessage を使用します。

共通のロケールメッセージの例:

js
export default {
  en: {
    buttons: {
      save: "Save",
      // ...
    }
  },
  ja: {
    buttons: {
      save: "保存",
      // ...
    }
  }
}

コンポーネントで mergeLocaleMessage を使用:

vue
<script setup>
import { useI18n } from 'vue-i18n'
import commonMessages from './locales/common'

const { t, mergeLocaleMessage } = useI18n({
  locale: 'en',
  messages: {
    en: {
      hello: 'Hello!'
    },
    ja: {
      hello: 'こんにちは!'
    }
  }
})

for (const locale of ['en', 'ja']) {
  mergeLocaleMessage(locale, commonMessages[locale])
}
</script>

ロケールの変更

グローバルスコープ

<script setup> でロケールを変更したい場合、useI18n でグローバル Composer を取得し、インスタンスの locale プロパティを使って変更します。

vue
<script setup>
const { t, locale } = useI18n({ useScope: 'global' })

locale.value = 'en' // 変更!
</script>

テンプレートでもセットアップコンテキストを使用できます。次のように変更できます:

vue
<select v-model="locale">
  <option value="en">en</option>
  <option value="ja">ja</option>
</select>

グローバルスコープのロケールを変更すると、t 翻訳 API などグローバルスコープに依存するコンポーネントは反応的に動作し、表示メッセージを対象のロケールに切り替えます。

暗黙的な方法 を使用している場合は、テンプレートで $i18n.locale で変更することもできます:

vue
<select v-model="$i18n.locale">
  <option value="en">en</option>
  <option value="ja">ja</option>
</select>

ローカルスコープ

ローカルスコープのロケール、つまり useI18n から返される Composer インスタンスの locale プロパティは、レガシー API と同じようにグローバルスコープから継承されます。そのため、グローバルスコープでロケールを変更すると、継承されたローカルスコープのロケールも変更されます。アプリケーション全体のロケールを切り替えたい場合は、useI18n({ useScope: 'global' }) から返される locale を使うか、暗黙的な方法 を使用する場合は $i18n.locale を使用できます。

注意

グローバルスコープからロケールを継承したくない場合は、useI18ninheritLocale オプションを false にする必要があります。

注意

ローカルスコープでの locale の変更は グローバルスコープのロケールには影響せず、ローカルスコープ内でのみ影響します

VueI18n インスタンスと Composer インスタンスとのマッピング

コンポジション API で Composer インスタンスが提供する API は、VueI18n インスタンスが提供する API と非常に似たインターフェースを持っています。

メモ

内部的には、レガシー API モードの VueI18n インスタンスは Composer インスタンスをラップして動作します。 このため、コンポジション API モードではレガシー API モードよりもパフォーマンスオーバーヘッドが少なくなります。

以下がマッピングテーブルです:

VueI18n インスタンスComposer インスタンス
idid
localelocale
fallbackLocalefallbackLocale
availableLocalesavailableLocales
messagesmessages
datetimeFormatsdatetimeFormats
numberFormatsnumberFormats
modifiersmodifiers
missinggetMissingHandler / setMissingHandler
postTranslationgetPostTranslationHandler / setPostTranslationHandler
silentTranslationWarnmissingWarn
silentFallbackWarnfallbackWarn
formatFallbackMessagesfallbackFormat
syncinheritLocale
warnHtmlInMessagewarnHtmlMessage
escapeParameterHtmlescapeParameter
tt
tct
tete
tmtm
getLocaleMessagegetLocaleMessage
setLocaleMessagesetLocaleMessage
mergeLocaleMessagemergeLocaleMessage
dd
getDateTimeFormatgetDateTimeFormat
setDateTimeFormatsetDateTimeFormat
mergeDateTimeFormatmergeDateTimeFormat
nn
getNumberFormatgetNumberFormat
setNumberFormatsetNumberFormat
mergeNumberFormatmergeNumberFormat