国際化とローカライゼーション
国際化とローカライゼーションは、複数の地域と言語向けのウェブアプリを作成するための支援を目的としています。i18n(国際化の略称)のサポートは、@adonisjs/i18n
パッケージによって提供されます。
-
ローカライゼーションは、アプリケーションのテキストを複数の言語に翻訳するプロセスです。各言語用にコピーを作成し、Edgeテンプレート、バリデーションエラーメッセージ、または
i18n
APIを使用してそれらを参照する必要があります。 -
国際化は、日付、時間、数値などの値を特定の地域や国に基づいてフォーマットするプロセスです。
インストール
次のコマンドを使用してパッケージをインストールして設定します:
node ace add @adonisjs/i18n
-
検出されたパッケージマネージャを使用して
@adonisjs/i18n
パッケージをインストールします。 -
adonisrc.ts
ファイル内に次のサービスプロバイダを登録します。{providers: [// ...他のプロバイダ() => import('@adonisjs/i18n/i18n_provider')]} -
config/i18n.ts
ファイルを作成します。 -
middleware
ディレクトリ内にdetect_user_locale_middleware
を作成します。 -
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メッセージ構文にしたがってフォーマットする必要があります。
{
"greeting": "Hello world"
}
{
"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
の組み合わせに対して定義できます。
{
"shared": {
"fields": {
"first_name": "first name"
},
"messages": {
"required": "Enter {field}",
"username.required": "Choose a username for your account",
"email": "The email must be valid"
}
}
}
{
"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 はサポートされていません) |
a | AM/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
は、以下の複数のカテゴリのいずれかに一致するリテラル値です。
カテゴリ | 説明 |
---|---|
zero | 0個のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やラトビア語などの例) |
one | 1つのアイテムに明示的に特化した文法を持つ言語で使用されます。多くの言語がこの複数形カテゴリを使用しますが、すべての言語が使用するわけではありません。 (中国語や日本語などの多くの人気のあるアジア言語はこのカテゴリを使用しません) |
two | 2つのアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やウェールズ語などの例) |
few | 少数のアイテムに特化した文法を持つ言語で使用されます。一部の言語では 2-4 個のアイテムに使用され、一部の言語では 3-10 個のアイテムに使用されます。他の言語ではさらに複雑なルールがあります。 |
many | 多数のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やポーランド語、ロシア語などの例) |
other | 値が他の複数形カテゴリと一致しない場合に使用されます。これは、単純な「単数形」と「複数形」の二分法を持つ言語 (英語など) で「複数形」に使用されます。 |
=value | 現在のロケールの複数形カテゴリに関係なく、特定の値に一致するために使用されます。 |
この表の内容は formatjs.io を参照しています
選択
select
フォーマットを使用すると、値を複数の選択肢のいずれかに一致させて出力を選択できます。性別に基づいたテキストを書くのに select
フォーマットは非常に便利です。
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
はリテラル値であり、以下の複数のカテゴリのいずれかに一致します。
カテゴリ | 説明 |
---|---|
zero | 0個のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やラトビア語などの例) |
one | 1つのアイテムに明示的に特化した文法を持つ言語で使用されます。多くの言語がこの複数形カテゴリを使用しますが、すべての言語が使用するわけではありません。 (中国語や日本語などの多くの人気のあるアジア言語はこのカテゴリを使用しません) |
two | 2つのアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やウェールズ語などの例) |
few | 少数のアイテムに特化した文法を持つ言語で使用されます。一部の言語では 2-4 個のアイテムに使用され、一部の言語では 3-10 個のアイテムに使用されます。他の言語ではさらに複雑なルールがあります。 |
many | 多数のアイテムに特化した文法を持つ言語で使用されます。 (アラビア語やポーランド語、ロシア語などの例) |
other | 値が他の複数形カテゴリと一致しない場合に使用されます。これは、単純な「単数形」と「複数形」の二分法を持つ言語 (英語など) で「複数形」に使用されます。 |
=value | 現在のロケールの複数形カテゴリに関係なく、特定の値に一致するために使用されます。 |
この表の内容は formatjs.io を参照しています
値のフォーマット
以下のメソッドは、Node.js Intl API を使用して値をフォーマットしますが、パフォーマンスが向上しています。ベンチマークを参照
formatNumber
Intl.NumberFormat
クラスを使用して数値をフォーマットします。以下の引数を渡すことができます。
- フォーマットする値。
- オプションの
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 の日時オブジェクトをフォーマットします。以下の引数を渡すことができます。
- フォーマットする値。Date オブジェクトまたは luxon DateTime オブジェクトです。
- オプションの
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
クラスを使用して値を相対時間表現の文字列にフォーマットします。メソッドは以下の引数を受け入れます。
- フォーマットする値。
- フォーマットの単位。公式にサポートされている単位に加えて、追加の
auto
単位もサポートしています。 - オプションのoptionsオブジェクト。
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
クラスを使用して、数値の複数形カテゴリを見つけます。以下の引数を渡すことができます。
- 複数形カテゴリを見つけるための数値。
- オプションの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
クラスを使用して、文字列の配列を文にフォーマットします。以下の引数を渡すことができます。
- フォーマットする値。
- オプションの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
クラスを使用して、currency
、language
、region
、およびcalendar
コードを表示名にフォーマットします。以下の引数を渡すことができます。
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
ファイルに以下の内容をコピーして貼り付けます。
{
"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
ファイルに以下の内容をコピーして貼り付けます。
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()
})