翻訳
ステータス更新については、トラッキング issue https://github.com/rust-lang/rust/issues/132181 を参照してください。
翻訳インフラは、まだ提案されていない再設計とそれに伴う手直しを待っているため、現在の翻訳インフラの使用を 必須にはしていません。 そのインフラを 使いたい 場合、または そうすることでコードがより明確になる場合は使用してください。しかし、より柔軟性が必要な場合は 翻訳インフラを迂回してください。
rustc の診断インフラストラクチャは、Fluent を使用した翻訳可能な診断をサポートしています。
翻訳可能な診断を書く
翻訳可能な診断を書く方法は 2 つあります。
- 単純な診断では、診断(またはサブ診断)の derive を使用します。 (「単純な」診断とは、サブ診断を発行するかどうかを決める際に多くのロジックを必要とせず、 したがって診断構造体として表現できるものです)。 診断構造体とサブ診断構造体のドキュメントを参照してください。
DiagAPI(DiagnosticまたはSubdiagnosticの実装内)で型付き識別子を使用します。
翻訳可能な診断を追加または変更するとき、 翻訳について心配する必要はありません。 元の英語メッセージを更新するだけで十分です。
Fluent
Fluent は「非対称ローカライゼーション」という考え方を中心に構築されています。これは、 翻訳の表現力をソース言語(rustc の場合は英語)の文法から 切り離すことを目的としています。 翻訳以前は、rustc の診断は、 ユーザーに表示されるメッセージを構築するために補間に大きく依存していました。 補間された文字列は翻訳が困難です。自然に聞こえる 翻訳を書くには、英語の文字列よりも多い、少ない、または単に異なる補間が 必要になる場合があり、そのいずれもサポートするにはコンパイラのソースコードの変更が必要になるためです。
診断メッセージは Fluent リソースで定義されます。
特定のロケール(例: en-US)に対する Fluent
リソースの結合された集合は、Fluent バンドルとして知られています。
typeck_address_of_temporary_taken = cannot take address of a temporary
上記の例では、typeck_address_of_temporary_taken は
Fluent メッセージの識別子であり、英語の診断メッセージに対応しています。
別の言語のメッセージに対応する、他の Fluent リソースを書くことができます。
したがって、各診断には少なくとも 1 つの Fluent メッセージがあります。
typeck_address_of_temporary_taken = cannot take address of a temporary
.label = temporary value
慣例として、サブ診断の診断メッセージは
Fluent メッセージ上の「属性」として指定されます(追加の関連メッセージであり、
.<attribute-name> 構文で示されます)。
上記の例では、label は
typeck_address_of_temporary_taken の属性であり、この診断に追加される
ラベルのメッセージに対応しています。
診断メッセージでは、型名や変数名など、 ユーザーに表示されるメッセージに追加のコンテキストを補間することがよくあります。 Fluent メッセージへの追加のコンテキストは、診断への「引数」として提供されます。
typeck_struct_expr_non_exhaustive =
cannot create non-exhaustive {$what} using struct expression
上記の例では、Fluent メッセージは what という名前の引数を参照しており、
その引数が存在することが期待されています(診断に引数を提供する方法については後で詳しく説明します)。
Fluent とその構文の他の使用例については、Fluent のドキュメントを参照できます。
メッセージ命名のガイドライン
通常、fluent はメッセージ名内の単語を区切るために - を使用します。
しかし、
_ も fluent で受け入れられます。
Rust 側の識別子でも _ が使用されるため、
_ は Rust のユースケースにより適しています。そのため rustc 内では、単語を区切るための - は
許可されておらず、代わりに _ が推奨されます。
唯一の例外は、-passes_see_issue のようなメッセージ名における先頭の - です。
翻訳可能なメッセージを書くためのガイドライン
メッセージをさまざまな言語に翻訳可能にするには、どの言語でも必要となる すべての情報を、診断への 引数として提供しなければなりません(英語メッセージで必要な情報だけではありません)。
コンパイラチームが、さまざまな言語に翻訳するために必要なすべての 情報を備えた診断を書く経験を積むにつれて、このページは より多くのガイダンスで更新されます。 現時点では、Fluent のドキュメントに、 メッセージを異なるロケールに翻訳する優れた例と、それを行うために コードから提供する必要がある情報が掲載されています。
コンパイル時検証と型付き識別子
rustc の #[derive(Diagnostic)] マクロは、Fluent メッセージのコンパイル時検証を実行します。
Fluent リソースのコンパイル時検証は、コンパイラのビルド中に
Fluent リソースからの解析エラーをすべて出力し、無効な Fluent
リソースがコンパイラ内でパニックを引き起こすことを防ぎます。
コンパイル時検証は、複数の Fluent メッセージが同じ識別子を持つ場合にもエラーを出力します。
内部
翻訳をサポートするために、rustc の診断内部のさまざまな部分が変更されています。
メッセージ
rustc の従来の診断 API(例: struct_span_err や note)はすべて、
DiagMessage に変換できる任意のメッセージを受け取ります。
rustc_error_messages::DiagMessage は、従来の翻訳不可能な
診断メッセージと翻訳可能なメッセージを表現できます。
翻訳不可能なメッセージは単なる String です。
翻訳可能なメッセージは、Fluent メッセージの
識別子を持つ単なる &'static str です(場合によっては、属性を持つ追加の &'static str も含みます)。
DiagMessage と直接やり取りする必要はありません。
DiagMessage 定数は、
Fluent リソース内の各診断メッセージに対して作成される(以下でより詳しく説明します)か、または DiagMessage は
診断 derive のマクロ生成コード内で作成されます。
DiagMessage は、文字列に変換できる任意の型に対して
Into を実装し、それらを翻訳不可能な診断に変換します。これにより、既存の診断呼び出しはすべて動作し続けます。
引数
メッセージ内容に補間される Fluent メッセージの追加コンテキストは、 翻訳可能な診断に提供する必要があります。
診断には、この追加のコンテキストを診断に提供するために使用できる
set_arg 関数があります。
引数には、名前(前の例の “what” など)と値の両方があります。
引数の値は DiagArgValue 型を使用して表現されます。これは単なる文字列または数値です。
rustc の型は、文字列または数値への
変換を伴う IntoDiagArg を実装でき、Ty<'tcx> のような一般的な型にはすでに
そのような実装があります。
set_arg の呼び出しは診断 derive によって透過的に処理されますが、
診断ビルダー API を使用する場合は手動で追加する必要があります。