Skip to content

TypeScript サポート

対応バージョン

🆕 9.2+

VueI18n は、ロケールメッセージ、日時フォーマット、数値フォーマットなどのリソースを使用します。 特に、ロケールメッセージは json ファイルなどとして i18n リソースとして外部化でき、ローカライズサービスを使用して翻訳者と協力できます。そしてこれらのリソースをインポートして協力できます。

ローカライズサービスとの連携により、スムーズなローカリゼーションワークフローを実現するためには、外部化された i18n リソースのローカリゼーション不足やリソース定義不足を防ぐ必要があるかもしれません。 開発時には、翻訳関数 $t の使用におけるキー文字列の誤りを防ぐことで、開発体験を損ないたくないでしょう。

スキーマによる型安全なリソース

TypeScript を使用することで、リソーススキーマで型安全なリソースをサポートできます。

createI18n での型安全なリソース

createI18n オプションで定義された messages の型安全なリソースを定義する例です。

ロケールメッセージリソース:

json
{
  "world": "the world!"
}

アプリケーションエントリポイント:

ts
import { createI18n } from 'vue-i18n'
import enUS from './locales/en-US.json'

// 'en-US' をリソースのマスタースキーマとして型定義
type MessageSchema = typeof enUS

const i18n = createI18n<[MessageSchema], 'en-US' | 'ja-JP'>({
  locale: 'en-US',
  messages: {
    'en-US': enUS
  }
})

上記コードは、createI18nmessages オプションで指定された en-US メッセージリソースから型を定義します。この定義された型は、VueI18n で処理されるメッセージリソースのマスターライクなスキーマです。つまり、アプリケーション内で 単一の真実のソース リソースとして定義できるということです。メッセージリソースからスキーマとして定義された型を createI18n の型パラメータの最初の引数として指定することで、他のロケールで型安全なリソースを定義できます。

createI18n の型パラメータの第二引数は処理するロケールです。これにより、第一引数で指定されたリソースの型に基づいて、第二引数で指定された各ロケールに対して型チェックが実行されます。上記コード例では、en-USja-JP がメインロケールとして指定されており、これは locale オプションにも指定されています。この状態で Typescript をコンパイルすると、messages オプションに ja-JP リソースが定義されていないことを確認するためのエラーが発生します。

sh
$ npx tsc
npx tsc
src/main.ts:11:3 - error TS2741: Property '"ja-JP"' is missing in type '{ 'en-US': { world: string; }; }' but required in type '{ "en-US": { world: string; }; "ja-JP": { world: string; }; }'.

11   messages: {
    ~~~~~~~~

  node_modules/vue-i18n/dist/vue-i18n.d.ts:712:5
    712     messages?: {
            ~~~~~~~~
    The expected type comes from property 'messages' which is declared here on type 'I18nOptions<{ message: { world: string; }; datetime: DateTimeFormat; number: NumberFormat; }, { messages: "en-US"; datetimeFormats: "en-US"; numberFormats: "en-US"; } | { ...; }, ComposerOptions<...> | VueI18nOptions<...>>'

Found 1 error.

Visual Studio Code をエディターとして使用している場合、Typescript コンパイルを実行する前に、以下のエラーでリソース定義の省略をエディター上で気づくことができます。

VSCode-Type-Error1VSCode-Type-Error2

useI18n での型安全なリソース

型安全なリソースは createI18n だけでなく、Composition API とともに使用される useI18n でコンポーネントごとに定義できます。

ローカルメッセージに加えて、リソースタイプ定義には日付時間フォーマットと数値フォーマットも含めることができます。

以下は、useI18n でロケールメッセージと数値フォーマットの型安全なリソースをコンポーネントごとに定義するコード例です。

Vue コンポーネントでインポートするロケールメッセージ:

json
{
  "messages": {
    "hello": "Hello, {name}!"
  }
}

型安全なリソースを持つ Vue コンポーネント:

vue
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import enUS from './en-US.json' // Vue コンポーネント用のロケールメッセージをインポート

// Vue コンポーネント用のメッセージスキーマを定義
type MessageSchema = typeof enUS

// Vue コンポーネント用の数値フォーマットスキーマを定義
type NumberSchema = {
  currency: {
    style: 'currency'
    currencyDisplay: 'symbol'
    currency: string
  }
}

/*
 * 型パラメータの最初にオブジェクトリテラルでスキーマを指定できます
 * 型パラメータについては、http://vue-i18n.intlify.dev/api/composition.html#usei18n を参照してください
 */
const { t, n } = useI18n<{
  message: MessageSchema,
  number: NumberSchema
}, 'en-US'>({
  inheritLocale: true,
  messages: {
    'en-US': enUS
  },
  numberFormats: {
    'en-US': {
      currency: {
        style: 'currency',
        currencyDisplay: 'symbol',
        currency: 'USD'
      }
    }
  }
})
</script>

<template>
  <p>message: {{ t('messages.hello', { name: 'kazupon' }) }}</p>
  <p>currency: {{ n(1000, 'currency') }}</p>
</template>

上記コードでは、useI18n の最初の型パラメータとして定義されたスキーマを指定することで、ロケールメッセージと数値フォーマットの未定義リソースを TypeScript でチェックできます。また、第二型パラメータに定義するロケールを指定することで、未定義のロケールを TypeScript でチェックできます。

制限事項

  • SFC の i18n カスタムブロックでは型安全性がサポートされていません。今後の対応予定です。
  • 現在は JSON フォーマットのみをサポートしています。

これまで記述したコードは example として利用可能です。確認してみてください!

型安全をサポートする API

他の API は、型安全なリソース操作のためにリソーススキーマを指定できる型パラメータをサポートしており、以下のようになります:

  • getLocaleMessage
  • setLocaleMessage
  • mergeLocaleMessage
  • getDateTimeFormat
  • setDateTimeFormat
  • mergeDateTimeFormat
  • getNumberFormat
  • setNumberFormat
  • mergeNumberFormat

詳細については、以下の API ドキュメントページをご確認ください。

リソースキー補完のサポート

注意

リソースキー補完は Visual Studio Code を使用している場合にのみ使用できます

型安全なリソース定義のサポートとともに、VueI18n は Composition API でリソースキーを補完するための API(td など)を提供しています。

以下の例は、上記のローカルスコープ Vue コンポーネントで Visual Studio Code でリソースキーを補完する方法を示しています。

VSCode-Resource-Completion

リソースキーの補完サポートにより、翻訳ミスを防止できます。

プロジェクトでの使用ケースとして、ローカルスコープを使わず、すべてグローバルスコープを使用する Vue コンポーネントがあるかもしれません。

そのようなケースでは、useI18n の型パラメータにグローバルスコープ用に定義されたスキーマを明示的に指定することで、リソースキーの補完をサポートできます。

グローバルスコープ用のスキーマを定義:

ts
/**
 * リソーススキーマを定義
 */

import enUS from './en-US.json'

// メッセージスキーマをマスターメッセージスキーマとして定義
export type MessageSchema = typeof enUS

// 数値フォーマットスキーマを定義
export type NumberSchema = {
  currency: {
    style: 'currency'
    currencyDisplay: 'symbol'
    currency: string
  }
}

それから、定義されたスキーマをインポートし、useI18n の型パラメータとして使用します。以下のような Vue コンポーネントのように:

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

// グローバルスコープ用のリソーススキーマをインポート
import type { MessageSchema, NumberSchema } from '../locales/schema'

const { t, n } = useI18n<{ message: MessageSchema, number: NumberSchema }>({
  useScope: 'global'
})
</script>

<template>
  <p>message: {{ t('hello') }}</p>
  <p>currency: {{ n(1000, 'currency') }}</p>
</template>

結果として、tn といった VueI18n が提供する API でリソースキーの補完を使用できるようになります。

注意

レガシーモード、および Composition API の globalInjection: true によってコンポーネントに注入される $t$d などの API のリソースキー補完には、明示的に型パラメータを指定する必要があります。

詳細については API ドキュメントを参照してください。 https://vue-i18n.intlify.dev/api/injection.html

グローバルリソーススキーマ型定義

VueI18n では、TypeScript の機能を使ってインターフェースを拡張することで、グローバルスコープレベルでリソースタイプを定義できます。

プロジェクト全体でリソースをグローバルスコープとして使用する場合、型安全なリソースを簡単に扱うのが非常に便利です。

VueI18n は以下のインターフェースを提供しています:

  • DefineLocaleMessage:ロケールメッセージ用のグローバルスキーマを定義するインターフェース
  • DefineDateTimeFormat:日時フォーマット用のグローバルスキーマを定義するインターフェース
  • DefineNumberFormat:数値フォーマット用のグローバルスキーマを定義するインターフェース

これらのインターフェースと declare module を使用することで、VueI18n のためのグローバルスキーマを定義できます。

以下は d.ts に定義されたグローバルスキーマの例です:

ts
/**
 * 必要なインターフェースをインポートする必要があります
 */



declare module 'vue-i18n' {
  // ロケールメッセージスキーマを定義
  export interface DefineLocaleMessage {
    hello: string
    menu: {
      login: string
    }
    errors: string[]
  }

  // 日時フォーマットスキーマを定義
  export interface DefineDateTimeFormat {
    short: {
      hour: 'numeric'
      minute: 'numeric'
      second: 'numeric'
      timeZoneName: 'short'
      timezone: string
    }
  }

  // 数値フォーマットスキーマを定義
  export interface DefineNumberFormat {
    currency: {
      style: 'currency'
      currencyDisplay: 'symbol'
      currency: string
    }
  }
}

declare module と VueI18n が提供するインターフェースを使用することで、グローバルリソースのスキーマを定義できます。

以前は、グローバルスコープリソースの型定義とともに createI18nuseI18n を使用する際に、それぞれを型パラメータとして指定する必要がありました。 この方法ではそれをする必要はありません。

以下は createI18n での例です:

ts
import { createI18n, type I18nOptions } from 'vue-i18n'

/**
 * json からグローバルスコープ用のロケールメッセージリソースをインポート
 */
import enUS from './locales/en-US.json'
import jaJP from './locales/ja-JP.json'

const options: I18nOptions = {
  legacy: false,
  locale: 'ja-JP',
  fallbackLocale: 'en-US',
  messages: {
    'en-US': enUS,
    'ja-JP': jaJP
  },
  datetimeFormats: {
    'ja-JP': {
      short: {
        hour: 'numeric',
        minute: 'numeric',
        second: 'numeric',
        timeZoneName: 'short',
        timezone: 'Asia/Tokyo'
      }
    }
  },
  numberFormats: {
    'ja-JP': {
      currency: {
        style: 'currency',
        currencyDisplay: 'symbol',
        currency: 'JPY'
      }
    }
  }
}

/**
 * グローバル型定義付き i18n リソースで vue-i18n をセットアップ。
 * `*.d.ts` で i18n リソーススキーマを定義した場合、これらは TypeScript でチェックされます。
 */
const i18n = createI18n<false, typeof options>(options)

上記の createI18n の最初の型パラメータは、リソーススキーマの型を指定しません。上記は createI18n によって作成される i18n インスタンスの global プロパティの型ヒントのみを指定しています。 (false の場合は Composition API 用の Composer インスタンス、true の場合はレガシー API 用の VueI18n インスタンス)

createI18n の第二型パラメータはオプションの型ヒントを指定します。

Vue コンポーネントで使用される useI18n の場合、以下のようになります:

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

// グローバルスコープを使用
const { t, d, n } = useI18n({
  inheritLocale: true
})
</script>

<template>
  <p>`t` リソースキー補完: {{ t('menu.login') }}</p>
  <p>`d` リソースキー補完: {{ d(new Date(), 'short') }}</p>
  <p>`n` リソースキー補完: {{ n(1000, 'currency') }}</p>
</template>

上記コードからわかるように、useI18n の型パラメータには何も指定する必要がありません。tdn などの API リソースキーを指定することなく補完できます。