I18n

国際化とローカライゼーション

国際化とローカライゼーションは、複数の地域と言語向けのウェブアプリを作成するための支援を目的としています。i18n(国際化の略称)のサポートは、@adonisjs/i18nパッケージによって提供されます。

  • ローカライゼーションは、アプリケーションのテキストを複数の言語に翻訳するプロセスです。各言語用にコピーを作成し、Edgeテンプレート、バリデーションエラーメッセージ、またはi18n APIを使用してそれらを参照する必要があります。

  • 国際化は、日付時間数値などの値を特定の地域や国に基づいてフォーマットするプロセスです。

インストール

次のコマンドを使用してパッケージをインストールして設定します:

node ace add @adonisjs/i18n
  1. 検出されたパッケージマネージャを使用して@adonisjs/i18nパッケージをインストールします。

  2. adonisrc.tsファイル内に次のサービスプロバイダを登録します。

    {
    providers: [
    // ...他のプロバイダ
    () => import('@adonisjs/i18n/i18n_provider')
    ]
    }
  3. config/i18n.tsファイルを作成します。

  4. middlewareディレクトリ内にdetect_user_locale_middlewareを作成します。

  5. start/kernel.tsファイル内に次のミドルウェアを登録します。

    router.use([
    () => import('#middleware/detect_user_locale_middleware')
    ])

設定

i18nパッケージの設定は、config/i18n.tsファイルに保存されます。

参照:Config stub

import app from '@adonisjs/core/services/app'
import { defineConfig, formatters, loaders } from '@adonisjs/i18n'
const i18nConfig = defineConfig({
defaultLocale: 'en',
formatter: formatters.icu(),
loaders: [
loaders.fs({
location: app.languageFilesPath()
})
],
})
export default i18nConfig

formatter

翻訳を保存するために使用するフォーマットを定義します。AdonisJSは、ICUメッセージフォーマットをサポートしています。

ICUメッセージフォーマットは、CrowdinやLokaliseなどの多くの翻訳サービスでサポートされている広く受け入れられた標準です。

また、カスタムメッセージフォーマッターを追加することもできます。

defaultLocale

アプリケーションのデフォルトのロケールです。ユーザーの言語をサポートしていない場合、翻訳と値のフォーマットはこのロケールにフォールバックします。

fallbackLocales

ロケールとそのフォールバックロケールのコレクションを定義するキーバリューペアです。たとえば、アプリケーションがスペイン語をサポートしている場合、カタルーニャ語のフォールバックとして定義できます。

export default defineConfig({
formatter: formatters.icu(),
defaultLocale: 'en',
fallbackLocales: {
ca: 'es' // カタルーニャ語を話すユーザーにスペイン語のコンテンツを表示
}
})

supportedLocales

アプリケーションでサポートされているロケールの配列です。

export default defineConfig({
formatter: formatters.icu(),
defaultLocale: 'en',
supportedLocales: ['en', 'fr', 'it']
})

この値を定義しない場合、翻訳からsupportedLocalesを推測します。たとえば、英語、フランス語、スペイン語の翻訳が定義されている場合、supportedLocalesの値は['en', 'es', 'fr']になります。

loaders

翻訳を読み込むために使用するローダーのコレクションです。デフォルトでは、ファイルシステムローダーのみをサポートしています。ただし、カスタムローダーを追加することもできます。

翻訳の保存

翻訳はresources/langディレクトリ内に保存されます。IETF言語タグ形式にしたがって、各言語ごとにサブディレクトリを作成する必要があります。例:

resources
├── lang
│ ├── en
│ └── fr

特定の地域のための翻訳を定義するには、地域コードを持つサブディレクトリを作成します。次の例では、英語(グローバル)英語(アメリカ合衆国)、**英語(イギリス)**の異なる翻訳を定義しています。

AdonisJSは、リージョン固有の翻訳セットで翻訳が見つからない場合、**英語(グローバル)**にフォールバックします。

参照:ISO言語コード

resources
├── lang
│ ├── en
│ ├── en-us
│ ├── en-uk

ファイル形式

翻訳は.jsonまたは.yamlファイルに保存する必要があります。より良い整理のために、ネストされたディレクトリ構造を作成しても構いません。

resources
├── lang
│ ├── en
│ │ └── messages.json
│ └── fr
│ └── messages.json

翻訳は、ICUメッセージ構文にしたがってフォーマットする必要があります。

resources/lang/en/messages.json
{
"greeting": "Hello world"
}
resources/lang/fr/messages.json
{
"greeting": "Bonjour le monde"
}

翻訳の解決

翻訳を検索してフォーマットする前に、i18nManager.localeメソッドを使用してロケール固有のI18nクラスのインスタンスを作成する必要があります。

import i18nManager from '@adonisjs/i18n/services/main'
// 英語用のI18nインスタンス
const en = i18nManager.locale('en')
// フランス語用のI18nインスタンス
const fr = i18nManager.locale('fr')

I18nクラスのインスタンスを取得したら、.tメソッドを使用して翻訳をフォーマットできます。

const i18n = i18nManager.locale('en')
i18n.t('messages.greeting') // Hello world
const i18n = i18nManager.locale('fr')
i18n.t('messages.greeting') // Bonjour le monde

フォールバックロケール

各インスタンスには、config.fallbackLocalesコレクションに基づいて事前に設定されたフォールバック言語があります。メインの言語に翻訳がない場合に使用されます。

export default defineConfig({
fallbackLocales: {
'de-CH': 'de',
'fr-CH': 'fr'
}
})
const i18n = i18nManager.locale('de-CH')
i18n.fallbackLocale // de(フォールバックコレクションを使用)
const i18n = i18nManager.locale('fr-CH')
i18n.fallbackLocale // fr(フォールバックコレクションを使用)
const i18n = i18nManager.locale('en')
i18n.fallbackLocale // en(デフォルトのロケールを使用)

翻訳が見つからない場合

メインとフォールバックのロケールの両方で翻訳が見つからない場合、.tメソッドは次のようにフォーマットされたエラー文字列を返します。

const i18n = i18nManager.locale('en')
i18n.t('messages.hero_title')
// translation missing: en, messages.hero_title

2番目のパラメータとしてフォールバック値または空の文字列を指定することで、このメッセージを別のメッセージまたは空の文字列に置き換えることができます。

const fallbackValue = ''
i18n.t('messages.hero_title', fallbackValue)
// 出力: ''

また、設定ファイルを介してグローバルにフォールバック値を計算することもできます。fallbackメソッドは、最初のパラメータとして翻訳パス、2番目のパラメータとしてロケールコードを受け取ります。常に文字列値を返すようにしてください。

import { defineConfig } from '@adonisjs/i18n'
export default defineConfig({
fallback: (identifier, locale) => {
return ''
},
})

HTTPリクエスト中のユーザーロケールの検出

初期設定時に、detect_user_locale_middleware.tsファイルを./app/middlewareディレクトリ内に作成します。このミドルウェアは、次のアクションを実行します。

  • Accept-languageヘッダーを使用してリクエストのロケールを検出します。

  • リクエストロケールのI18nクラスのインスタンスを作成し、HTTPコンテキストを介してリクエストパイプラインの残りの部分と共有します。

  • グローバルなi18nプロパティとしてEdgeテンプレートと共有するために、同じインスタンスを使用します。

  • 最後に、リクエストバリデータにフックして、翻訳ファイルを使用してバリデーションメッセージを提供します。

このミドルウェアがアクティブな場合、コントローラやEdgeテンプレート内で次のようにメッセージを翻訳できます。

import { HttpContext } from '@adonisjs/core/http'
export default class PostsController {
async store({ i18n, session }: HttpContext) {
session.flash('success', {
message: i18n.t('post.created')
})
}
}
<h1> {{ t('messages.heroTitle') }} </h1>

ユーザー言語の検出コードの変更

detect_user_locale_middlewareはアプリケーションのコードベースの一部であるため、getRequestLocaleメソッドを変更し、ユーザー言語を検出するためのカスタムロジックを使用できます。

バリデーションメッセージの翻訳

detect_user_locale_middlewareリクエストバリデータにフックし、翻訳ファイルを使用してバリデーションメッセージを提供します。

export default class DetectUserLocaleMiddleware {
static {
RequestValidator.messagesProvider = (ctx) => {
return ctx.i18n.createMessagesProvider()
}
}
}

翻訳は、validator.jsonファイル内のsharedキーに保存する必要があります。バリデーションメッセージは、バリデーションルールまたはfield + ruleの組み合わせに対して定義できます。

resources/lang/en/validator.json
{
"shared": {
"fields": {
"first_name": "first name"
},
"messages": {
"required": "Enter {field}",
"username.required": "Choose a username for your account",
"email": "The email must be valid"
}
}
}
resources/lang/fr/validator.json
{
"shared": {
"fields": {
"first_name": "Prénom"
},
"messages": {
"required": "Remplisser le champ {field}",
"username.required": "Choissisez un nom d'utilisateur pour votre compte",
"email": "L'email doit être valide"
}
}
}

VineJSを直接使用して翻訳を利用する

HTTPリクエスト中、detect_user_locale_middlewareはリクエストバリデータにフックし、翻訳ファイルからバリデーションエラーを提供するためのカスタムメッセージプロバイダを登録します。

ただし、HTTPリクエストの外部でVineJSを使用する場合、Aceコマンドやキュージョブなど、validator.validateメソッドを呼び出す際に明示的にカスタムメッセージプロバイダを登録する必要があります。

import { createJobValidator } from '#validators/jobs'
import i18nManager from '@adonisjs/i18n/services/main'
/**
* 特定のロケールに対する i18n インスタンスを取得します。
*/
const i18n = i18nManager.locale('fr')
await createJobValidator.validate(data, {
/**
* 翻訳を使用するためのメッセージプロバイダを登録します。
*/
messagesProvider: i18n.createMessagesProvider()
})

ICU メッセージフォーマット

インターポレーション

ICU メッセージの構文では、動的な値を参照するために単一の中括弧を使用します。

例:

ICU メッセージの構文はネストされたデータセットをサポートしていませんので、インターポレーション中にはフラットなオブジェクトのプロパティにしかアクセスできません。

{
"greeting": "こんにちは { username }"
}
{{ t('messages.greeting', { username: 'Virk' }) }}

メッセージ内にHTMLを記述することもできます。ただし、Edgeテンプレート内では、HTMLをエスケープせずにレンダリングするために、3つの中括弧を使用します。

{
"greeting": "<p> こんにちは { username } </p>"
}
{{{ t('messages.greeting', { username: 'Virk' }) }}}

数値フォーマット

数値のフォーマットは、{key, type, format} の構文を使用して翻訳メッセージ内で行うことができます。以下の例では:

  • amount は実行時の値です。
  • number はフォーマットの種類です。
  • ::currency/USD は通貨フォーマットと 数値スケルトン です。
{
"bagel_price": "このベーグルの価格は {amount, number, ::currency/USD} です"
}
{{ t('bagel_price', { amount: 2.49 }) }}
このベーグルの価格は $2.49 です

以下は、異なるフォーマットスタイルと数値スケルトンを使用した number フォーマットの例です。

ポールの長さ: {price, number, ::measure-unit/length-meter}
口座残高: {price, number, ::currency/USD compact-long}

日付/時刻フォーマット

{key, type, format} の構文を使用して、Date インスタンスまたは luxon DateTime インスタンスをフォーマットできます。以下の例では:

  • expectedDate は実行時の値です。
  • date はフォーマットの種類です。
  • medium は日付のフォーマットです。
{
"shipment_update": "ご注文の商品は {expectedDate, date, medium} に到着予定です"
}
{{ t('shipment_update', { expectedDate: luxonDateTime }) }}
ご注文の商品は 2023年10月16日 に到着予定です

time フォーマットを使用して、値を時刻としてフォーマットすることもできます。

{
"appointment": "今日は {appointmentAt, time, ::h:m a} に予約があります"
}
今日は 午後2:48 に予約があります

ICUは、日付時刻のフォーマットをカスタマイズするための多くのパターンを提供しています。ただし、それらのすべてが ECMA402 の Intl API で利用できるわけではありません。したがって、以下のパターンのみをサポートしています。

シンボル説明
G時代指定子
y
M
L単独の月
d
E曜日
eローカルの曜日 (e..eee はサポートされていません)
c単独のローカルの曜日 (c..ccc はサポートされていません)
aAM/PM マーカー
h時 (1-12)
H時 (0-23)
K時 (0-11)
k時 (1-24)
m
s
zタイムゾーン

複数形のルール

ICUメッセージの構文では、複数形のルールをメッセージ内で定義できます。

例:

以下の例では、複数行のテキストをYAMLで書く方が簡単なため、YAMLを使用しています。

cart_summary:
"カートには {itemsCount, plural,
=0 {アイテムはありません}
one {1つのアイテム}
other {#個のアイテム}
} があります"
{{ t('messages.cart_summary', { itemsCount: 1 }) }}
カートには 1つのアイテム があります

# は数値のプレースホルダーとして使用されます。これは {key, number} としてフォーマットされます。

{{ t('messages.cart_summary', { itemsCount: 1000 }) }}
{{-- 出力 --}}
{{-- カートには 1,000個のアイテム があります --}}

複数形のルールは {key, plural, matches} の構文を使用します。matches は、以下の複数のカテゴリのいずれかに一致するリテラル値です。

カテゴリ説明
zero0個のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やラトビア語などの例)
one1つのアイテムに明示的に特化した文法を持つ言語で使用されます。多くの言語がこの複数形カテゴリを使用しますが、すべての言語が使用するわけではありません。 (中国語や日本語などの多くの人気のあるアジア言語はこのカテゴリを使用しません)
two2つのアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やウェールズ語などの例)
few少数のアイテムに特化した文法を持つ言語で使用されます。一部の言語では 2-4 個のアイテムに使用され、一部の言語では 3-10 個のアイテムに使用されます。他の言語ではさらに複雑なルールがあります。
many多数のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やポーランド語、ロシア語などの例)
other値が他の複数形カテゴリと一致しない場合に使用されます。これは、単純な「単数形」と「複数形」の二分法を持つ言語 (英語など) で「複数形」に使用されます。
=value現在のロケールの複数形カテゴリに関係なく、特定の値に一致するために使用されます。

この表の内容は formatjs.io を参照しています

選択

select フォーマットを使用すると、値を複数の選択肢のいずれかに一致させて出力を選択できます。性別に基づいたテキストを書くのに select フォーマットは非常に便利です。

Yaml
auto_reply:
"{gender, select,
male {彼}
female {彼女}
other {彼ら}
} がすぐに返信します。"
{{ t('messages.auto_reply', { gender: 'female' }) }}
彼女 がすぐに返信します。

選択序数

select ordinal フォーマットを使用すると、序数の複数形ルールに基づいて出力を選択できます。フォーマットは select フォーマットと似ていますが、値は序数の複数形カテゴリにマップされます。

anniversary_greeting:
"私の {years, selectordinal,
one {#周年}
two {#周年}
few {#周年}
other {#周年}
} です"
{{ t('messages.anniversary_greeting', { years: 2 }) }}
私の 2周年 です

select ordinal フォーマットは {key, selectordinal, matches} の構文を使用します。matches はリテラル値であり、以下の複数のカテゴリのいずれかに一致します。

カテゴリ説明
zero0個のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やラトビア語などの例)
one1つのアイテムに明示的に特化した文法を持つ言語で使用されます。多くの言語がこの複数形カテゴリを使用しますが、すべての言語が使用するわけではありません。 (中国語や日本語などの多くの人気のあるアジア言語はこのカテゴリを使用しません)
two2つのアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やウェールズ語などの例)
few少数のアイテムに特化した文法を持つ言語で使用されます。一部の言語では 2-4 個のアイテムに使用され、一部の言語では 3-10 個のアイテムに使用されます。他の言語ではさらに複雑なルールがあります。
many多数のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やポーランド語、ロシア語などの例)
other値が他の複数形カテゴリと一致しない場合に使用されます。これは、単純な「単数形」と「複数形」の二分法を持つ言語 (英語など) で「複数形」に使用されます。
=value現在のロケールの複数形カテゴリに関係なく、特定の値に一致するために使用されます。

この表の内容は formatjs.io を参照しています

値のフォーマット

以下のメソッドは、Node.js Intl API を使用して値をフォーマットしますが、パフォーマンスが向上しています。ベンチマークを参照

formatNumber

Intl.NumberFormat クラスを使用して数値をフォーマットします。以下の引数を渡すことができます。

  1. フォーマットする値。
  2. オプションの options オブジェクト
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatNumber(123456.789, {
maximumSignificantDigits: 3
})

formatCurrency

Intl.NumberFormat クラスを使用して数値を通貨としてフォーマットします。formatCurrency メソッドは暗黙的に style = currency オプションを定義します。

import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatCurrency(200, {
currency: 'USD'
})

formatDate

Intl.DateTimeFormat クラスを使用して日付または luxon の日時オブジェクトをフォーマットします。以下の引数を渡すことができます。

  1. フォーマットする値。Date オブジェクトまたは luxon DateTime オブジェクトです。
  2. オプションの options オブジェクト
import i18nManager from '@adonisjs/i18n/services/main'
import { DateTime } from 'luxon'
i18nManager
.locale('en')
.locale('en')
.formatDate(new Date(), {
dateStyle: 'long'
})
// もっともluxonの日時インスタンスをフォーマットする
i18nManager
.locale('en')
.formatDate(DateTime.local(), {
dateStyle: 'long'
})

formatTime

Intl.DateTimeFormatクラスを使用して、日付の値を時刻の文字列にフォーマットします。formatTimeメソッドは、暗黙的にtimeStyle = mediumオプションを定義します。

import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatTime(new Date())

formatRelativeTime

formatRelativeTimeメソッドは、Intl.RelativeTimeFormatクラスを使用して値を相対時間表現の文字列にフォーマットします。メソッドは以下の引数を受け入れます。

import { DateTime } from 'luxon'
import i18nManager from '@adonisjs/i18n/services/main'
const luxonDate = DateTime.local().plus({ hours: 2 })
i18nManager
.locale('en')
.formatRelativeTime(luxonDate, 'hours')

単位の値をautoに設定すると、最適な一致する単位で差分を表示します。

const luxonDate = DateTime.local().plus({ hours: 2 })
I18n
.locale('en')
.formatRelativeTime(luxonDate, 'auto')
// 2時間後 👈
const luxonDate = DateTime.local().plus({ hours: 200 })
I18n
.locale('en')
.formatRelativeTime(luxonDate, 'auto')
// 8日後 👈

formatPlural

Intl.PluralRulesクラスを使用して、数値の複数形カテゴリを見つけます。以下の引数を渡すことができます。

  1. 複数形カテゴリを見つけるための数値。
  2. オプションのoptionsオブジェクト。
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager.i18nManager('en').formatPlural(0)
// other
i18nManager.i18nManager('en').formatPlural(1)
// one
i18nManager.i18nManager('en').formatPlural(2)
// other

formatList

Intl.ListFormatクラスを使用して、文字列の配列を文にフォーマットします。以下の引数を渡すことができます。

  1. フォーマットする値。
  2. オプションのoptionsオブジェクト。
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatList(['Me', 'myself', 'I'], { type: 'conjunction' })
// Me, myself and I
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatList(['5 hours', '3 minutes'], { type: 'unit' })
// 5 hours, 3 minutes

formatDisplayNames

Intl.DisplayNamesクラスを使用して、currencylanguageregion、およびcalendarコードを表示名にフォーマットします。以下の引数を渡すことができます。

  1. フォーマットするコード。typeのフォーマットによって値が異なります
  2. Optionsオブジェクト。
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatDisplayNames('INR', { type: 'currency' })
// Indian Rupee
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatDisplayNames('en-US', { type: 'language' })
// American English

i18n Ally VSCode拡張機能の設定

VSCodeのi18n Ally拡張機能は、コードエディタでの翻訳の「保存」、「検査」、「参照」のワークフローを提供します。

AdonisJSとシームレスに連携するために、プロジェクトのルートディレクトリの.vscodeディレクトリ内に次のファイルを作成する必要があります。

mkdir .vscode
touch .vscode/i18n-ally-custom-framework.yml
touch .vscode/settings.json

settings.jsonファイルに以下の内容をコピーして貼り付けます。

.vscode/settings.json
{
"i18n-ally.localesPaths": [
"resources/lang"
],
"i18n-ally.keystyle": "nested",
"i18n-ally.namespace": true,
"i18n-ally.editor.preferEditor": true,
"i18n-ally.refactor.templates": [
{
"templates": [
"{{ t('{key}'{args}) }}"
],
"include": [
"**/*.edge",
],
},
]
}

.vscode/i18n-ally-custom-framework.ymlファイルに以下の内容をコピーして貼り付けます。

.vscode/i18n-ally-custom-framework.yml
languageIds:
- edge
usageMatchRegex:
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
sortKeys: true

不足している翻訳イベントのリスニング

i18n:missing:translationイベントをリッスンして、アプリ内の不足している翻訳について通知を受けることができます。

import emitter from '@adonisjs/core/services/emitter'
emitter.on('i18n:missing:translation', function (event) {
console.log(event.identifier)
console.log(event.hasFallback)
console.log(event.locale)
})

翻訳の再読み込みを強制する

@adonisjs/i18nパッケージは、アプリケーションの起動時に翻訳ファイルを読み込み、クイックアクセスのためにメモリ内に保存します。

ただし、アプリケーションが実行中の状態で翻訳ファイルを変更した場合は、reloadTranslationsメソッドを使用してメモリ内のキャッシュを更新できます。

import i18nManager from '@adonisjs/i18n/services/main'
await i18nManager.reloadTranslations()

カスタム翻訳ローダーの作成

翻訳ローダーは、永続ストアから翻訳を読み込む責任を持ちます。ファイルシステムローダーを提供していますが、カスタムローダーを登録するためのAPIも提供しています。

ローダーはTranslationsLoaderContractインターフェースを実装し、loadメソッドを定義して、キーと値のペアを持つオブジェクトを返す必要があります。キーはロケールコードであり、値は翻訳のリストを持つフラットなオブジェクトです。

import type {
LoaderFactory,
TranslationsLoaderContract,
} from '@adonisjs/i18n/types'
/**
* 設定のためのTypeScriptの型
*/
export type DbLoaderConfig = {
connection: string
tableName: string
}
/**
* ローダーの実装
*/
export class DbLoader implements TranslationsLoaderContract {
constructor(public config: DbLoaderConfig) {
}
async load() {
return {
en: {
'messages.greeting': 'Hello world',
},
fr: {
'messages.greeting': 'Bonjour le monde',
}
}
}
}
/**
* ファクトリ関数を使用してローダーを参照する
* 設定ファイル内でローダーを参照するためのものです。
*/
export function dbLoader(config: DbLoaderConfig): LoaderFactory {
return () => {
return new DbLoader(config)
}
}

上記のコード例では、次の値をエクスポートしています。

  • DbLoaderConfig: 受け入れる設定のためのTypeScriptの型。
  • DbLoader: クラスとしてのローダーの実装。TranslationsLoaderContractインターフェースに準拠する必要があります。
  • dbLoader: 最後に、設定ファイル内でローダーを参照するためのファクトリ関数です。

ローダーの使用

ローダーが作成されたら、設定ファイル内でdbLoaderファクトリ関数を使用して参照できます。

import { defineConfig } from '@adonisjs/i18n'
import { dbLoader } from 'my-custom-package'
const i18nConfig = defineConfig({
loaders: [
dbLoader({
connection: 'pg',
tableName: 'translations'
})
]
})

カスタム翻訳フォーマッタの作成

翻訳フォーマッタは、特定の形式にしたがって翻訳をフォーマットする責任を持ちます。ICUメッセージ構文の実装を提供していますが、カスタムフォーマッタを登録するための追加のAPIも提供しています。

フォーマッタはTranslationsFormatterContractインターフェースを実装し、formatメソッドを定義して翻訳メッセージをフォーマットする必要があります。

import type {
FormatterFactory,
TranslationsLoaderContract,
} from '@adonisjs/i18n/types'
/**
* フォーマッタの実装
*/
export class FluentFormatter implements TranslationsFormatterContract {
format(
message: string,
locale: string,
data?: Record<string, any>
): string {
// フォーマットされた値を返す
}
}
/**
* ファクトリ関数を使用してフォーマッタを参照する
* 設定ファイル内でフォーマッタを参照するためのものです。
*/
export function fluentFormatter(): FormatterFactory {
return () => {
return new FluentFormatter()
}
}

フォーマッタの使用

フォーマッタが作成されたら、設定ファイル内でfluentFormatterファクトリ関数を使用して参照できます。

import { defineConfig } from '@adonisjs/i18n'
import { fluentFormatter } from 'my-custom-package'
const i18nConfig = defineConfig({
formatter: fluentFormatter()
})