Skip to content

国際化 (i18n)#

View Markdown

Ox Content は ICU MessageFormat 2(MF2) を中心にした i18n ツールキット一式を載せます。

  • JSON / YAML から入れ子キーで読む、複数ロケールの 辞書
  • 手書きの MF2 パーサ(単純メッセージ、.input / .local 宣言、.match 分岐)。
  • ビルド時の 静的チェッカー(欠けているキー、使われていないキー、ロケール間の変数不一致、MF2 構文エラー)。
  • t()Intl バックのフォーマッタを持つ ランタイム仮想モジュール
  • CLIvpx 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 のエディタ支援節を見てください。

Last updated: