Qt 同じ単語に複数の翻訳をあてるのに少し頑張った話1
この記事はQt4.8.4基準で記載します。
Qtにはソース上の文字列を拾い上げて、翻訳用のファイルを作っておくことで、プログラム実行時に動的言語変換ができます。
具体的な手順は割愛しますが、
QLabel text;
text.setText(tr("string"));
のように、trでくくった文字列をlupdateで抜き出し、xml形式の.tsファイルを生成します。
その.tsファイルをQtLinguistで手動翻訳し、lreleaseで.qmファイルを作り、その.qmファイルをプログラムで読み込みます。
.qmファイルがどのように生成されているかわからないので、実際に動作させてみて確かめただけなのですが、.tsファイル上に同じ単語が複数ある場合、別々な翻訳をしても、一番上に書かれたもので表示されてしまうようです。
QLabel text; text.setText(tr("start")); // スタートと表示したい QLabel text2; text2.setText(tr("start")); // 開始と表示したい
このような場合、以下のように.tsファイルを記述しても、一律スタートと表示されてしまいます。
<!-- 日本語でスタートと表示したいやつ。 --> <message> <location filename="xxx" line=""/> <source>start</source> <translation type="unfinished">スタート</translation> </message> <!-- 日本語で開始と表示したいやつ。 --> <message> <location filename="xxx" line=""/> <source>start</source> <translation type="unfinished">開始</translation> </message>
そこで、ソース上に書く文字列は識別用のIDとしてユニークなものとして扱う手段を取りました。
下準備として、以下のものを用意しました。
・文字列を指定するenum
・enumに対応する文字列 QT_TR_NOOP("")の形で記載
・指定されたenumから文字列をsetText(tr(""));へ渡すラッパー関数
typedef enum { E_TEXT_1, E_TEXT_2 }stringId; QString* stringData[] = { QT_TR_NOOP("E_TEXT_1"), QT_TR_NOOP("E_TEXT_2"), };
void setStringId(stringId id) { this->m_pLabel->setText(tr(stringData[id])); //実際は配列直指定はやめましょう }
かなりざっくり書きましたが、いままで""でくくって文字列としていた場所をenumの文字列で書くイメージです。
この場合、文字列が増えるたびにenum、文字列定義、.ts/.qmファイル作成が発生してとても面倒です。
そこで、.ts/.qmファイル作成まで自動でやってしまえ!というのが次回のお話。