Qt-翻訳の難しさ

Qtでプログラムを作成し、それを他の言語に翻訳して、他の国の人々に役立つようにしたいと考えています。 これを行うのは簡単ではありませんが、非常に簡単です。 これを行うには、3つの簡単な手順を実行するだけです。



ソースプログラム



簡単なプログラムを用意しましょう。



#include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  1. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  2. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  3. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  4. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  5. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  6. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  7. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



  8. #include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .



#include <QtGui> #include <QtCore> int main( int argc, char *argv[]) { QApplication app(argc, argv); QLabel label( "Hello, World!" ); label.show(); return app.exec(); } * This source code was highlighted with Source Code Highlighter .







彼女がすることは、「Hello、World!」というウィンドウを作成することだけです。 彼女のためにロシア語に翻訳します。



ステップ1.翻訳するすべての行の表示



ユーザーに表示されるすべての行は、QObject :: tr()またはQcoreApplication :: translate()関数によって処理される必要があります。

QObjectから継承されたすべてのQtクラスには、メンバー関数tr()があります。 どのクラスにも属さないグローバル関数で文字列を操作しているため、translate()関数を使用します。これにより、翻訳のコンテキスト、つまり、それが属するクラス(この場合はQLabel)を指定できます。







  1. #include <QtGui>
  2. #include <QtCore>
  3. int main( int argc、 char * argv []){
  4. QApplicationアプリ(argc、argv);
  5. QLabelラベル(app.translate( "QLabel""Hello、World!" ));
  6. label.show();
  7. return app.exec();
  8. }
*このソースコードは、 ソースコードハイライターで強調表示されました。




関数tr()およびtranslate()では、翻訳された行の後に、アプリケーションを別の言語に翻訳するときに翻訳者に表示されるコメントを指定できます。 コメントはあいまいさを排除するために使用されます。

関数の外にあるテキストを翻訳する必要がある場合、2つのマクロが役立ちます:QT_TR_NOOP()およびQT_TRANSLATE_NOOP()、tr()およびtranslate()と同様です。 それらは、以下で説明するlupdateユーティリティを使用して、抽出するテキストを静かにマークします。







  1. static const char * greeting_strings [] = {
  2. QT_TR_NOOP( "Hello" )、
  3. QT_TR_NOOP( "さようなら"
  4. };
  5. static const char * greeting_strings [] = {
  6. QT_TRANSLATE_NOOP( "HelloWidget""Hello" )、
  7. QT_TRANSLATE_NOOP( "HelloWidget""Goodbye"
  8. };
*このソースコードは、 ソースコードハイライターで強調表示されました。




特定のマクロQT_NO_CAST_FROM_ASCIIでプログラムをコンパイルしてconst char *からQStringへの自動変換をオフにすると、スキップされたすべての行を見つけることができます。

行の中央に変数の値を挿入する必要がある場合は、arg()関数を使用するのが最適です。 たとえば、ファイルをコピーするとき、次のようにプロセスの進行状況を表示できます。







  1. void FileCopier :: showProgress( int done、 int total、
  2. const QString¤tFile)
  3. {
  4. label.setText(tr( "%1 of%2個のファイルがコピーされました。\ nCopying:%3"
  5. .arg(完了)
  6. .arg(合計)
  7. .arg(currentFile));
  8. }
*このソースコードは、 ソースコードハイライターで強調表示されました。




翻訳中に引数の順序を変更する必要がある場合、翻訳中に、たとえば次のように、変数を場所の%記号と交換する必要があります。



「ファイルをコピー%3。 %1 of%2個のファイルがコピーされました»




このため、プログラムを書き換える必要はありません。



ステップ2.翻訳を作成する



アプリケーション全体でtr()を使用した後、テキストの翻訳を作成する必要があります。 テキストの翻訳にも3つのステップが含まれます。

  1. lupdateを実行して、Qt C ++アプリケーションのソースコードから翻訳されたテキストを抽出し、翻訳者向けのメッセージファイル(.tsファイル)を作成します。 ユーティリティは、上記のtr()およびtranslate()コンストラクターとQT_TR * _NOOP()マクロを認識し、.tsファイル(通常は言語ごとに1つ)を生成します。
  2. Qt Linguistを使用して、.tsファイルでソースの翻訳を提供します。 .tsファイルはXML形式であるため、手動で編集することもできます。
  3. lreleaseを実行して、.tsファイルから軽量のメッセージファイル(.qmファイル)を取得します。これは最終使用にのみ便利です。 .tsファイルを「ソースファイル」、.qmファイルを「オブジェクトファイル」と考えてください。 翻訳者は.tsファイルを編集しますが、アプリケーションのユーザーは.qmファイルのみを必要とします。 どちらのファイルタイプもプラットフォームとロケールに依存しません。




通常、アプリケーションのリリースごとにこれらの手順を繰り返す必要があります。 lupdateユーティリティは、以前のリリースからの翻訳を再利用するために可能なすべてのことを行います。

lupdateを実行する前に、プロジェクトファイルを準備する必要があります。 プロジェクトファイル(helloworld.proファイル)は次のようになります。



TEMPLATE =アプリ

TARGET =リリース

DEPENDPATH + =。

INCLUDEPATH + =。

ソース+ = main.cpp

翻訳+ = helloworld_ru.ts



lupdateまたはlreleaseを実行するときは、コマンドライン引数としてプロジェクトファイル名を指定する必要があります。



ステップ3.アプリケーションで翻訳ファイルをダウンロードします。



このアプリケーションでは、QcoreApplication :: installTranslator()を使用してQTranslator :: load()ファイルをダウンロードする必要があります。 プログラムの最終バージョンは次の形式を取ります。







  1. #include <QtGui>
  2. #include <QtCore>
  3. int main( int argc、 char * argv []){
  4. QApplicationアプリ(argc、argv);
  5. QTranslator myTranslator;
  6. myTranslator.load( "helloworld_" + QLocale :: system()。name());
  7. app.installTranslator(&myTranslator);
  8. QLabelラベル(app.translate( "QLabel""Hello、World!" ));
  9. label.show();
  10. return app.exec();
  11. }
*このソースコードは、 ソースコードハイライターで強調表示されました。




QTranslatorオブジェクトを作成し、load()関数を使用して翻訳ファイルをそのオブジェクトにロードします。 その中で、翻訳のファイル名の始まりを示します。 デフォルトでは、翻訳ファイルはプログラムフォルダーで検索されますが、関数の2番目のパラメーターとして名前を渡すことにより、任意のディレクトリを指定できます。 拡張子「.qm」が自動的に追加されます。 Qlocale :: system()。Name()関数は、現在のロケールの名前(私の場合はru_RU.UTF-8)を返します。 load()関数による翻訳ファイルの検索順序は次のとおりです。



  1. helloworld_ru_RU.UTF-8.qm
  2. helloworld_ru_RU.UTF-8
  3. helloworld_ru_RU.qm
  4. helloworld_ru_RU
  5. helloworld_ru.qm
  6. helloworld_ru
  7. helloworld.qm
  8. こんにちは




しかし、この方法でWindows XPに翻訳ファイルをロードしようとしても、何も起こりませんでした。 (少なくとも私にとっては)Qlocale :: system()。Name()関数は常に値「C」を返していました。 したがって、たとえば、プログラム設定ダイアログまたはコマンドラインパラメーターを使用して、アプリケーションインターフェイスの言語を指定する追加の方法を検討する価値があります。



以上で、アプリケーションはロシア語に翻訳されましたが、この記事で言及する価値のある点がいくつかあります。



追加のテキスト文字列



Qtの内部には約400行が含まれていますが、これも必要な言語に翻訳する必要があります。 $ QTDIR / translationsディレクトリには、フランス語、ドイツ語、簡体字中国語の翻訳ファイルと、他の言語に翻訳するためのテンプレートがあります。 (このディレクトリには、サポートされていない追加の翻訳も含まれています。たとえば、ロシア語への翻訳など)。

通常、これらの翻訳はmain()関数で同じものをロードします:







  1. int main( int argc、 char * argv [])
  2. {
  3. ...
  4. QTranslator qtTranslator;
  5. qtTranslator.load( "qt_" + QLocale :: system()。name()、
  6. QLibraryInfo :: location(QLibraryInfo :: TranslationsPath));
  7. app.installTranslator(&qtTranslator);
  8. ...
  9. }
*このソースコードは、 ソースコードハイライターで強調表示されました。




Qt変換を検出するためにQLibraryInfo :: location()を使用していることに注意してください。 開発者は、アプリケーションでQTDIR環境変数を使用する代わりに、この関数のQLibraryInfo :: TranslationsPathを処理して、変換パスを要求する必要があります。 ユーザーが完全版のQtを持っているかどうかわからない場合でも、この翻訳ファイルをプログラムに提供し、プログラムディレクトリ(または他の選択可能なもの)からダウンロードすることは理にかなっています。



動的翻訳



一部のアプリケーションでは、操作中にユーザーの言語設定を変更する必要があります。 インストールされたQTranslatorsの変更についてウィジェットに警告するには、changeEvent()ウィジェットの関数をやり直してイベントがLanguageChangeイベントかどうかを確認し、通常の方法でtr()関数を使用してウィジェットによって表示されるテキストを更新します。 例:







  1. void MyWidget :: changeEvent(QEvent * event
  2. {
  3. if (e-> type()== QEvent :: LanguageChange){
  4. titleLabel-> setText(tr( "ドキュメントタイトル" ));
  5. ...
  6. okPushButton-> setText(tr( "&OK" ));
  7. } その他
  8. QWidget :: changeEvent( event );
  9. }
*このソースコードは、 ソースコードハイライターで強調表示されました。




他のすべての変更イベントは、この関数のデフォルト実装を呼び出して処理する必要があります。

LocaleChangeイベントに応答して、インストールされた翻訳のリストを変更するか、アプリケーションがユーザーにアプリケーションの現在の言語を変更できるインターフェースを提供できます。

QWidgetのサブクラスのデフォルトイベントハンドラーはQEvent :: LanguageChangeイベントに応答し、必要に応じてこの関数を呼び出します。 アプリケーションの他のコンポーネントでは、ウィジェットにLanguageChangeイベントを送信して、ウィジェットを強制的に更新させることもできます。

UPD: intellinsideが示唆するように、Qt Designerによって生成されたグラフィカルユーザーインターフェイスクラスには、アプリケーション言語を動的に変更するために呼び出すことができるretranslateUi()関数があります。



All Articles