Qt5再入門: Qt DesignerでNotes C APIコンバートシミュレーターダイアログを作る(その12/翻訳機能1)
Qtには文字列を翻訳する仕組みが備わっていて、手軽に多言語化に対応したアプリケーションを作成できます。
Qtの翻訳システムを利用するには、以下のステップを踏みます。
1. 翻訳文字列のマーク・・・何を翻訳するか、対象を決める
2. 対訳情報の作成/更新・・・翻訳する
3. 翻訳情報のリリース・・・アプリケーションで利用な形式にする
4. 翻訳情報のインストール・・・アプリケーションで対訳情報を利用する
ひとつひとつ見ていきます。
1. 翻訳文字列のマーク
コーディングをしていて翻訳したい文字列を入力する時、以下のいずれかのメソッドを使って文字列を囲み、後に処理する翻訳システムにわかるようにマークします。
1. QObject::tr()静的メソッドを使う
2. QCoreApplication::translate()静的メソッドを使う
これらは、いずれも与えた文字列の翻訳情報があれば置き換え、なければ与えられた文字列がそのまま返されます。個人的には、2番目のtranslate関数を使うことは皆無です。打鍵数の節約面でも、引数の数でも、何より見た目を邪魔しないのですべてtr関数を使っています。
tr関数はリテラル文字列を受け取り、QStringを返します。
ui->textBrowser->append(tr("An error occurred."));
原則的に変数を渡すことはできません。後述する翻訳文字列を抽出するツールが、翻訳対象となる文字列を認識できないからです。
const char *msg = "An error occurred.";
ui->textBrowser->append(tr(msg)); // ダメ
const char *err = "division by zero";
ui->textBrowser->append(tr("The error \"" + err + "\" occurred.")); // NG!
しかし、2番目のケースのようにある文字列変数を翻訳した文字列に組み込むことはよくあります。短絡的に以下のようにしても意味がありません。
const char *err = "division by zero";
ui->textBrowser->append(tr("The error \"") + err + tr("\" occurred.")); // 何が起きるか想像してみよう
tr関数の中身はリテラル文字列になっているので、その点では問題ないですが、翻訳自体がおかしなことになります。例えば「○○というエラーが発生しました。」というように、日本語としては次のような構文になっていて欲しいわけですから。
const char *err = "division by zero";
ui->textBrowser->append(err + tr("というエラーが発生しました。"));
このように、変化する文字列を翻訳文字列に含みたいけど、言語によってその位置が移動する場合、QString::argメソッドを使えばうまくいきます。
const char *err = "division by zero";
ui->textBrowser->append(tr("The error \"%1\" occurred.").arg(err)); // OK!
// 日本語で『「%1」というエラーが発生しました。』と訳せば・・・
// in English. => The error "division by zero" occurred.
// in Japanese. => 「division by zero」というエラーが発生しました。
このように、訳文内に翻訳前と同じマーカー(%1, %2, ..., %99)を含めることで、訳文内に自由に変数を配置することができます。
さらにエラー文字列も以下のようにすれば翻訳できます。
auto err = tr("division by zero"); // OK!
ui->textBrowser->append(tr("The error \"%1\" occurred.").arg(err)); // OK!
// in English. => The error "division by zero" occurred.
// in Japanese. => 「ゼロ除算」というエラーが発生しました。
tr、translate関数による翻訳文字列のマーキングには、実際に翻訳する文字列以外に「コンテキスト」と「コメント」を渡しますが、ここまでの例ではいずれも省略して記述しました。普段は意識しなくてもいいですが、規模が大きくなったり、複数人で翻訳を進めたりした時にこれらの情報が意味を持ってくるので、必要に応じてこれらも勉強するといいでしょう。
(次回に続く)