機械翻訳であり、ネイティブスピーカーによる確認は行われていません。英語版が基準です。

はじめにまだ GitHub にはありません出典:docs/i18n.md

エンジンのローカライズ

エンジンの人が読むテキストは、英語に加えて 17 言語で提供されます:nl、pl、pt-BR、pt-PT、fi、sv、da、nb、cs、uk、ru、de、fr、es、et、ja、zh-Hans。英語が元です。en-XAは、すべてのメッセージにアクセントを付け、括弧で囲み、パディングする疑似ロケールで、テキストがカタログに移ったかどうかをテストで確認できます。フレームワークはProject Fluent(fluent-bundle、unic-langid)で、コードはsrc/i18n/にあります。

ローカライズされるものと、決してされないもの#

ローカライズされるもの(人が読む) 決してローカライズされないもの(プログラムが読む)
コマンドラインのメッセージとエラー result.jsonとreport.jsonの JSON のキーと値
すべての実行のサマリー行 CSV のヘッダーと行
SVG チャートのテキスト(タイトル、軸、凡例、キャプション) ファイル名
report.html:見出し、表、注記、キャプション エラーコード(E-CLOCK-VERSION)
判定の語(VALIDATED、MODELLED、PARTIAL) 検証マトリクス、単位の定義、出所
シナリオ kind の説明(list_kinds(lang))
助言、免責事項、通知(engine-legal-*) JSON の中の同じテキスト(英語のまま)
iq キャンペーンのreport.html、スタディ比較ページ、ベンチのリーダーボード、レジリエンスレポート エビデンスパックのsummary.htmlとオブザバトリーの PNG:どちらもマニフェストにハッシュされ(パックのものは署名もされます)、言語にかかわらず英語で作られます

人が読むテキストの数値は、その言語の小数点記号を使います(18 言語のうち 15 言語ではカンマで、en、ja、zh-Hans、en-XA ではピリオドです)。機械可読ファイルの数値は、常にピリオドを使います。件数(n、count、n_*、num_*、*_countという名前の変数)は数値として Fluent に渡されるため、翻訳では{ $n -> [one] ... [few] ... *[other] ... }と書くことができます。

言語の選択#

  • コマンドライン:--lang <tag>、次にKSHANA_LANG、LC_ALL、LC_MESSAGES、LANG、最後に英語。ptは pt-BR で、ポルトガルのものはpt-PTだけです。zhは簡体字で、繁体字は、対応するタグの一覧とともに拒否されます。
  • ライブラリ:api::run_toml_lang(toml, lang)、run_toml_bilingual、run_toml_human、run_scenario_lang、list_scenario_kinds_json_lang(lang)。
  • Python:run、run_full、run_typed、validate_toml、error_kind、list_kinds、scenario_kindsでのlang=None、run_human(toml, lang)、error_info(toml, lang)。
  • WebAssembly:run_typed、run、chart_svg、summary、table_csv、run_all、error_kind、list_kinds、scenario_kindsの末尾に付ける任意のlang、run_human(toml, lang)、error_info(toml, lang)、register_catalogue(tag, ftl_text)。
  • MCP:run_scenarioとlist_scenario_kindsでのlang。

エラーとそのコード#

すべてのエラーメッセージには安定したコードがあります。大文字のメッセージ ID(e-clock-versionはE-CLOCK-VERSION)で、どの言語でも同じです。英語のコマンドラインのテキストは変わりません。他の言語では、その行はtext [E-CODE]です。--verboseを付けると、すべての言語で二行目のcode: E-CODEが続きます。API はKshanaError::code()とerror_info({kind, code, message})を返し、MCP のエラーはエラーデータとして{kind, code, message}を持ちます。照合にはコードを使い、テキストは使わないでください。

他の言語での実行の仕組み(二回実行の規則)#

機械可読ファイルは、言語に依存してはなりません。そのため、他の言語での実行では、シナリオを二回実行します。一回は英語で、そのresult.json、report.json、CSV が機械可読ファイルになり、もう一回は利用者の言語で、サマリー、チャート、report.htmlのためのものです。英語は一回の実行で、以前とバイト単位で同じです。

実測値、ネイティブ、リリースビルド、英語の後に--lang de(秒):leo-navmsg-fit-interval-trade 9.2 -> 17.9、cislunar-arc-recovery 7.8 -> 14.1、lunar-station-coverage 7.8 -> 15.0、clock-ensemble 5.8 -> 11.6、leo-navmsg-model-comparison 5.1 -> 10.5、leo-ppp-convergence 2.8 -> 6.2。同梱されているその他のシナリオはすべて 4 秒未満で、これを測定した時点で同梱されていた 173 件のシナリオは、英語では合計 64 秒でした。他の言語では、コストはちょうど二倍です。WebAssembly は測定していません(ここでは wasm-bindgen がありません)。ブラウザーの係数約 4 を当てはめると、最も遅い kind で一分になります。

ページは、英語の結果をすぐに表示し、その後でrun_human(toml, lang)を呼び出すことで、待ち時間を避けられます。これは二回目の実行のみで、{summary, svg}を返し、Studio は結果が届くまで「translating...」と表示できます。

0.41 の項目:一回の実行。両方を(message id, arguments)の記録から描画します。これは検討しましたが、実装していません。t!の結果は、作られた後で検査、測定、ハッシュされます(チャートのテキスト幅、出力テキストに対する出所のハッシュ)。また、num()は呼び出し箇所で書式化するため、記録を使うと機械可読ファイルにプレースホルダーのトークンが入り、そのバイト列が再生に依存することになります。トークンを返すt!/num、すべての書き出し処理でのファイナライザー、書き出し処理ごとのバイト同一性の証明が必要です。

WebAssembly#

wasm ビルドには、英語のカタログだけを組み込みます。他の十六言語を加えると、それぞれ gzip で約 150 kB 増えます。ページは、言語の選択時にi18n/<lang>/engine.ftlを取得してregister_catalogue(tag, text)を呼び出します。取得または登録に失敗した場合、ページは英語のままです。ネイティブ、コマンドライン、Python ホイールは、18 すべてを組み込みます。

cargo build --release --target wasm32-unknown-unknown --features wasm --libからの最適化していない.wasmのサイズ(wasm-bindgen と wasm-opt の前)、基準 bc04e98f と今回のブランチの比較:生で 18.71 MB -> 19.88 MB、gzip で 5.43 MB -> 5.79 MB、gzip で +357 kB。英語のカタログは生で 521 kB、そのうち gzip で 153 kB で、残りはfluent-bundleとその依存関係です。これは測定されたとおりに受け入れています。

カタログ#

i18n/<tag>/engine.ftlはメッセージを保持し、ID には接頭辞engine-が付きます。i18n/en/engine.ftlが元で、他のファイルは翻訳者のもので、メッセージが欠けていることがあります(欠けたものは、メッセージごとに英語に戻ります)。i18n/en/の付随リスト:engine-counts.txt(件数の変数を持つメッセージで、複数形用)、engine-numbers.txt(プレースホルダーとして渡される数値)、engine-fragments.txt(実行時に組み立てられる文の断片であるメッセージで、文全体のメッセージに統合すべきもので、増やしてはなりません)。

テスト#

tests/i18n_catalogue.rsは英語を証明します。すべてのメッセージには記録された元のテンプレートがあり、まさにそのテキストに描画されます。すべての ID が使われ、変数が一致し、疑似ロケールがすべてのメッセージを描画します。i18n_api.rs、i18n_kinds.rs、i18n_legal.rsは、エントリポイント、kind の説明、法的なテキストを対象とします。i18n_ratchet.rsは、人が読む新しい文字列リテラルがカタログを迂回した場合に失敗します。ファイルごとの許容はtests/fixtures/i18n/allow.jsonにあり、減ることはあっても増えることはありません。scripts/i18n_compare.pyは、ベースラインのバイナリと現在のバイナリでシナリオ全体を実行し、すべての出力ファイルを比較します。

文字列をカタログに移す方法:docs/design/i18n-migration.md。

依存関係とライセンス#

フレームワークは、fluent-bundle 0.16(Apache-2.0 OR MIT)とunic-langid 0.9(MIT OR Apache-2.0)を、その推移的なクレートとともに加えます。fluent-syntaxとfluent-langneg(Apache-2.0 OR MIT)、intl-memoizer(Apache-2.0 OR MIT)、intl_pluralrules(Apache-2.0/MIT)、type-map(MIT/Apache-2.0)、self_cell(Apache-2.0 OR GPL-2.0-only:使うのは Apache-2.0 の選択肢で、deny.tomlが許可しています)、tinystrとzerovec(Unicode-3.0)、rustc-hash、smallvec、thiserror、displaydoc(MIT OR Apache-2.0)です。いずれもdeny.tomlのallowリストに照らして寛容なライセンスです。thiserrorは二つのバージョン(1 と 2)で現れますが、multiple-versions = "warn"は報告するだけです。ライセンスのリストはcargo metadataから読み取りました。cargo deny checkは作成環境にインストールされておらず、統合 CI で実行されます。