国際化 (i18n)#
Ox Content は ICU MessageFormat 2(MF2) を中心にした i18n ツールキット一式を載せます。
- JSON / YAML から入れ子キーで読む、複数ロケールの 辞書。
- 手書きの MF2 パーサ(単純メッセージ、
.input/.local宣言、.match分岐)。 - ビルド時の 静的チェッカー(欠けているキー、使われていないキー、ロケール間の変数不一致、MF2 構文エラー)。
t()とIntlバックのフォーマッタを持つ ランタイム仮想モジュール。- CLI(
vpx oxct i18n)と、エディタ連携用の LSP。
このドキュメントサイトはファイルツリーのロケール配置です。英語ページは /…、日本語ページは /ja/… です。ヘッダーのロケールスイッチャーは、兄弟ページがあればそこへ飛びます。サイドバーとヘッダーのリンクは、兄弟があれば現在ロケールに留まります。手書きの日本語ガイドは英語と同じ深さです。生成 API ページは英語のままです。
有効化#
// vite.config.ts
import { oxContent } from "@ox-content/vite-plugin";
export default {
plugins: [
oxContent({
i18n: {
enabled: true,
dir: "content/i18n",
defaultLocale: "en",
locales: [
{ code: "en", name: "English" },
{ code: "ja", name: "日本語" },
{ code: "ar", name: "العربية", dir: "rtl" },
],
},
}),
],
};
オプション#
| オプション | 既定 | 説明 |
|---|---|---|
enabled |
false |
i18n を有効にする。 |
dir |
'content/i18n' |
プロジェクトルートからの相対辞書ディレクトリ。 |
defaultLocale |
'en' |
既定ロケールタグ(BCP 47)。 |
locales |
— | 使えるロケール: { code, name, dir? }(dir は 'ltr' / 'rtl')。 |
hideDefaultLocale |
true |
true なら /page が既定ロケール、/ja/page はプレフィックス付き。false ならすべてのロケールにプレフィックス。 |
check |
true |
ビルド中に静的チェッカーを走らせる。 |
functionNames |
['t', '$t'] |
ソースから使われたキーを探すときに検出する翻訳関数名。 |
辞書#
各ロケールは dir 以下の JSON または YAML ファイルです。入れ子キーはドットで平坦化されるので、辞書と呼び出し側は同じキー空間を共有します。
# content/i18n/en.yaml
nav:
home: "Home"
docs: "Documentation"
cart:
items: "{$count :number} items in your cart"
// content/i18n/ja.json
{
"nav": { "home": "ホーム", "docs": "ドキュメント" },
"cart": { "items": "カートに {$count :number} 件" },
}
既定ロケール以外で欠けているキーは、実行時に既定ロケールへ落ちます。
MessageFormat 2 メッセージ#
値は MF2 メッセージです。プレーンテキスト以外では次が使えます。
# 書式関数付きの補間
{$count :number} items
# 宣言 + マッチ(複数形 / 選択)
.input {$count :number}
.match $count
one {{You have {$count} item.}}
* {{You have {$count} items.}}
CLI からメッセージを検証します。
vpx oxct i18n validate "{$count :number} items"
vpx oxct i18n validate ".match {$n}\n one {{1}}\n * {{many}}" --ast
静的チェック#
check: true のとき、ビルドはソースから使われたキーを拾い、辞書と突き合わせて 4 種類の問題を報告します。
- 欠けているキー — コードで使われているが、あるロケールにない。
- 使われていないキー — 辞書にあるが、一度も参照されていない。
- 型の不一致 — 同じキーでプレースホルダ / 変数集合がロケール間で違う。
- 構文エラー — 辞書値の不正な MF2。
@ox-content/vite-plugin がインストールする oxct バイナリとして単体でも走れます(CI でも便利です。エラーがある場合のみ非ゼロで終了し、警告だけの場合は正常終了します)。
vpx oxct i18n check --dict-dir content/i18n --src src
vpx oxct i18n check --dict-dir content/i18n --src src --format json
vpx oxct i18n check --dict-dir content/i18n --src src --default-locale en
キーは OXC パーサ経由で TS / JS の呼び出し(t(...)、$t(...)、this.t(...)、i18n.t(...))と、Markdown({{t(...)}})から集めます。検出する関数名は functionNames で変えられます。
ランタイムモジュール#
仮想モジュールを import すると、読み込んだ辞書とプラットフォームの Intl API を後ろに持つ翻訳・書式ヘルパーが得られます。
import {
t,
localePath,
getLocaleFromPath,
formatDate,
formatNumber,
formatRelativeTime,
formatList,
formatDisplayName,
i18nConfig,
} from "virtual:ox-content/i18n";
t("cart.items", { count: 3 }); // "3 items in your cart"
t("nav.home", {}, "ja"); // ロケールを強制 → "ホーム"
localePath("/docs", "ja"); // "/ja/docs"
getLocaleFromPath("/ja/docs"); // "ja"
formatNumber(1234.5, "ja"); // "1,234.5"
formatRelativeTime(-2, "day", "en"); // "2 days ago"
Intl フォーマッタはロケールごとにキャッシュされます。ロケールメタデータは任意の文字方向も持つので、RTL ロケールは正しく描画されます。
エディタ支援#
同梱の言語サーバ(vpx oxct lsp)は、辞書キーの補完、各ロケールの翻訳ホバー、辞書ファイルへの定義ジャンプ、既定ロケール値を出すインレイヒント、チェッカーと同じ欠けている / 使われていないキー診断を提供します。stdio で動きます。
vpx oxct lsp
VS Code、Zed、Neovim と連携します。配線はプロジェクト README のエディタ支援節を見てください。