Return to Linux Life Edit

  ホーム · 全てのクラス · メインのクラス · 注釈付き · グループ別 · 関数一覧

Qtと国際化

アプリケーションの国際化は、アプリケーションの作成された言語以外でアプリケーションを使用しやすいようにするプロセスです。

いくつかの場合、国際化は簡単です、例えば、米国のアプリケーションを豪州人や英国人が利用しやすくするにはいくつかのスペル修正で済むでしょう。しかし米国のアプリケーションを日本人が使いやすくしたり、韓国語のアプリケーションを独逸人に使いやすくしたりするのは言語の違いだけでなく入力の方法、文字エンコーディングや表示変換なども変更しなくてはなりません。

Qtは国際化をできるだけ開発者にとって苦痛のないようにしようとします。Qtにおいて、全てのサポートされた言語で、入力ウィジェットとテキスト描画法は標準装備を提供します。ビルトインフォントエンジンは同時に、さまざまな異なった書記体系からキャラクタを含むテキストを正しく魅力的に表すことができます。

Qtは今日、使用中のほとんどの言語をサポートします、特に:

Windows NT/2000/XPとXft(クライアントサイドフォントサポート)を伴うUnix/X11で  以下の言語はサポートされます:

これらのwriting systemsの多くに特殊な特徴が存在します:

Qt では上に上げた特徴の全てを利用できる. Qt の入力ウィジェット (たとえば QLineEdit, QTextEdit, および派生クラス) と表示ウィジェット (たとえば QLabel) を利用する上で、これらの特徴について通常は気に掛ける必要はない。

これらの記法のサポートはプログラマから見て透過的であり、 Qt's text engineに完全にカプセル化されている. 以下の小さな点を除いては、特定の言語で使われる記法に関して知っておく必要はない:

以下のセクションでは Qt がサポートする国際化 (i18n) の状況に関する情報を扱う. Qt Linguist manualも参照のこと.

段階的に

Qt を使ってクロスプラットフォームの国際化されたソフトウェアを書くには、簡単かつ緩やかなプロセスを踏む. 以下のステージを辿ることでソフトウェアを国際化することができる:

ユーザが目にするテキストは全て QString とする

QString は内部的に Unicode 4.0 のエンコードを使っていることから、世界中の言語を理解しやすいテキスト処理操作で透過的に処理することができる. ユーザにテキストを表示する全ての Qt の関数では、その引数に QString を取るようになっており、 char * QString に変換するオーバーヘッドなどは生じない.

"プログラム領域" にある文字列 ( QObject の名前や、ファイルフォーマットのテキストなど) では QStringを使う必要はなく、伝統的な char * QByteArray クラスで十分である.

あえて Unicode を利用していると意識する必要はなく、 QString QChar は、伝統的な C 言語での const char * をより簡単にしたものとして利用できる.

全てのリテラル文字に tr() を使用する

ユーザが目にする "クォートで囲まれたテキスト" をプログラム中に書く場合には、それらが QCoreApplication::translate() 関数で処理される必要がある. 実際には、これは QObject::tr() を使うことでおこなう. たとえば、 LoginWidget QWidget のサブクラスであるとすると:

    LoginWidget::LoginWidget()
    {
        QLabel *label = new QLabel(tr("Password:"));
        ...
    }

This accounts for 99% of the user-visible strings you're likely to write.

クォートされたテキストが QObject サブクラスのメンバ関数内にない場合は、適当なクラスの tr() 関数を使うか、直接 QCoreApplication::translate() 関数を用いること:

    void some_global_function(LoginWidget *logwid)
    {
        QLabel *label = new QLabel(
                    LoginWidget::tr("Password:"), logwid);
    }
    void same_global_function(LoginWidget *logwid)
    {
        QLabel *label = new QLabel(
                    qApp->translate("LoginWidget", "Password:"), logwid);
    }

翻訳対象となるテキストが完全に関数の外となる場合には、2つのマクロ QT_TR_NOOP() と QT_TRANSLATE_NOOP() がその助けとなる. これらのマクロでは、テキストが以下で説明する lupdate ユーティリティによって摘出されるよう、単純に印を付けるだけにすぎない. マクロはテキストのみを処理対象として扱う (コンテキストは処理されない).

QT_TR_NOOP() の例:

    QString FriendlyConversation::greeting(int type)
    {
        static const char *greeting_strings[] = {
            QT_TR_NOOP("Hello"),
            QT_TR_NOOP("Goodbye")
        };
        return tr(greeting_strings[type]);
    }

QT_TRANSLATE_NOOP() の例:

    static const char *greeting_strings[] = {
        QT_TRANSLATE_NOOP("FriendlyConversation", "Hello"),
        QT_TRANSLATE_NOOP("FriendlyConversation", "Goodbye")
    };
    QString FriendlyConversation::greeting(int type)
    {
        return tr(greeting_strings[type]);
    }
    QString global_greeting(int type)
    {
        return qApp->translate("FriendlyConversation",
                               greeting_strings[type]);
    }

マクロ QT_NO_CAST_ASCII を定義して、 const char * から QString への自動変換を無効にした状態でソフトウェアをコンパイルすると、 文字列の見落としを検出しやすくなる. 詳細については QString::fromLatin1() を参照されたい. ただし変換を無効にすることで、プログラミングが若干煩わしくなる.

ソースコードを Latin1 以外の文字を使って記述する場合には、 QObject::trUtf8 QObject::trよりも便利でtr() は QTextCodec::codecForTr() に依存して動作するので、 QObject::trUtf8() よりも壊れやすいという側面がある.

アクセラレータの値には QKeySequence() を使う

Ctrl+Q や Alt+F といったアクセラレータの値も翻訳される必要がある. アプリケーションで Qt::CTRL + Qt::Key_Q が "quit" となるようにハードコードしてしまうと、トランスレータがオーバーライドできなくなってしまう. 正しい実装は以下のようにする

        exitAct = new QAction(tr("E&xit"), this);
        exitAct->setShortcut(tr("Ctrl+Q"));

動的なテキストには QString::arg() を使う

QString::arg() 関数を使えば、引数の置き換えを簡単におこなえる:

    void FileCopier::showProgress(int done, int total,
                                  const QString ¤tFile)
    {
        label.setText(tr("%1 of %2 files copied.\nCopying: %3")
                      .arg(done)
                      .arg(total)
                      .arg(currentFile));
    }

In some languages the order of arguments may need to change, and this can easily be achieved by changing the order of the % arguments. For example:

    QString s1 = "%1 of %2 files copied. Copying: %3";
    QString s2 = "Kopierer nu %3. Av totalt %2 filer er %1 kopiert.";
    qDebug() << s1.arg(5).arg(10).arg("somefile.txt");
    qDebug() << s2.arg(5).arg(10).arg("somefile.txt");

これで英語からノルウェー語への変換を正しくおこなうことができる:

    5 of 10 files copied. Copying: somefile.txt
    Kopierer nu somefile.txt. Av totalt 10 filer er 5 kopiert.

訳文を用意

アプリケーションの隅々にいたるまで tr() の適用が終われば、プログラム内にあるユーザが目にするテキストの翻訳に着手することができる.

Qt Linguist マニュアル には Qt の翻訳ツールである Qt Linguist, lupdate および lreleaseに関する詳細な情報が載っている.

Qt アプリケーションの翻訳は3つのステップのプロセスからなる:

  1. lupdate を実行することで Qt アプリケーションの C++ ソースコードから翻訳対象となるテキストを抽出し、トランスレータに読み込ませるためのメッセージファイル (. .ts ファイル) を生成する. このユーティリティプログラムは上で説明した tr() と QT_TR*_NOOP() マクロを認識し、 .ts ファイルを (通常言語毎に) 生成する.
  2. Qt Linguistを用い、.ts ファイル中のソーステキストに対する訳文を提供する. .ts ファイルは XML フォーマットで記述されているので、手で書き換えることもできる.
  3. lrelease を実行して .ts ファイルから実際の利用に適した軽量のメッセージファイル (a .qm ファイル) を用意する.         .ts ファイルは "ソースファイル" であり、. .qm ファイルは "オブジェクトファイル" に相当すると考えると判りやすい. 翻訳者は .ts ファイルを編集するが、アプリケーションの利用者は .qm ファイルのみを必要とする. どちらの種類のファイルもプラットフォーム独立であり、特定のロケールに依存するようなこともない.

般に、アプリケーションのリリース毎にこれらのステップを踏むことになる. lupdate ユーティリティは以前のリリースからの翻訳を再使用しやすくなっている.

lupdate を実行する前に、プロジェクトファイルを用意しなければならない. プロジェクトファイル (.pro ファイル) の例を次に挙げる:

        HEADERS         = funnydialog.h \
                          wackywidget.h
        SOURCES         = funnydialog.cpp \
                          main.cpp \
                          wackywidget.cpp
        FORMS           = fancybox.ui
        TRANSLATIONS    = superapp_dk.ts \
                          superapp_fi.ts \
                          superapp_no.ts \
                          superapp_se.ts

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

この例では、4つの外国語がサポートされている: デンマーク語, フィンランド語, ノルウェー語 そして スウェーデン語. qmakeを利用する場合には、通常 lupdateに関する別のプロジェクトファイルを用意する必要はない. qmake のプロジェクトファイルに TRANSLATIONS エントリを追加してやれば、上手く動作するはずだ.

アプリケーション側では、 QTranslator::load() で言語に合致した翻訳ファイルを読み込み、 QCoreApplication::installTranslatorを使ってインストールする必要がある.

linguist, lupdate および lrelease は Qt のインストールされたベースディレクトリの bin subdirectory of the base directory Qt is installed into. Click Help|Manual in Qt Linguist の Help|Manual をクリックすること. マニュアルにはチュートリアルが掲載されている.

Qt 自身にも翻訳される必要のある 400 以上の文字列が含まれている. フランス語とドイツ語に対する翻訳ファイルは $QTDIR/translations に用意されており、他の言語へ翻訳する際のテンプレートも同梱されている. (このディレクトリにはサポート外ではあるが有用な翻訳ファイルも含まれている.)

一般に、アプリケーションの main() 関数は以下のようになる:

        int main(int argc, char *argv[])
        {
            QApplication app(argc, argv);
            QTranslator qtTranslator;
            qtTranslator.load("qt_" + QLocale::system());
            app.installTranslator(&qtTranslator);
            QTranslator myappTranslator;
            myappTranslator.load("myapp_" + QLocale::system());
            app.installTranslator(&myappTranslator);
            ...
            return app.exec();
        }

エンコードのサポート

QTextCodec クラスと QTextStream の機能を使うことで、ユーザのデータを入出力する際に利用される多数のエンコードを容易にサポートすることができる. アプリケーションの起動後、フォントの選択・テキストの表示・8ビットのテキスト入出力・文字入力などで8ビットのデータが取り扱われた場合には、マシンのロケールとして8ビットエンコードが使われていると判断する.

アプリケーションは時としてデフォルトのローカルな8ビットエンコード以外のエンコードを必要とすることがある. たとえば、キリル文字の KOI8-R ロケール (ロシアにおけるデファクトスタンダードのロケール) で動くアプリケーションでは、キリル文字を出力するのに ISO 8859-5 エンコードでおこなう場合がある. これを実現するコードとしては次のとおり:

        QString string = ...; // some Unicode text
        QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5");
        QByteArray encodedString = codec->fromUnicode(string);

Unicode をローカルな8ビットエンコードに変換する場合、ショートカットが利用できる: QString::toLocal8Bit() 関数はそうした8ビットデータを返す. ほかの便利なショートカットには QString::toUtf8() があり、これはテキストを8ビットの UTF-8 エンコードで返す. このエンコードは Unicode の情報を完全に保ちつつ、テキストが完全に ASCII コードで書かれている場合には、素の ASCII 文字列であるように見える.

他の変換方法としては、 QString::fromUtf8() と QString::fromLocal8Bit() の変換関数を使うか、一般的なコードを使う方法がある. 後者の方法を使って ISO 8859-5 のキリル文字から Unicode へ変換する例を挙げる:

        QByteArray encodedString = ...; // some ISO 8859-5 encoded text
        QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5");
        QString string = codec->toUnicode(encodedString);

世界中のユーザ間でドキュメントのポータビリティを最大化できることから、理想的には Unicode の入出力が使われるべきであるが、実際にはユーザが既存ドキュメントを処理するうえで必要となる適切な全てのエンコードをサポートするのが望まれる. 一般的に、Unicode (UTF-16 または UTF-8) は任意の人々との間で情報伝送を行う場合に最適であり、対して一つの言語または国家グループの中で閉じるのであれば、ローカルな標準を使ったほうが適切であるといえる. 最も重要なエンコードは QTextCodec::codecForLocale() で返されるものであり、これはユーザが他の人々およびアプリケーションと通信するのに必要となるものである. (これは local8Bit() で使われるコーデック )

Qt は頻繁に利用されるエンコーディングの大部分をネイティブにサポートする. サポートされるエンコードの完全なリストは QTextCodec のドキュメントを参照のこと.

使用される頻度の低いエンコードなどでは、ユーザは独自の QTextCodec サブクラスを書く必要があるかも知れない.急ぐのであれば、Trolltech のテクニカルサポートにコンタクトを取るか、誰かが既にそのエンコーディングをサポートしていないかどうか、 qt-interest メーリングリストに質問を投げてみることができる.

ローカライズ

ローカライズとはローカルな習慣へ適合させるプロセスのことでああり、たとえばローカルでよく使われるフォーマットで日時を表示したりすることである. 適切な tr() 文字列を使うことでローカライズをおこなうことができる.

        void Clock::setTime(const QTime &time)
        {
            if (tr("AMPM") == "AMPM") {
                // 12-hour clock
            } else {
                // 24-hour clock
            }
        }

この例では、US 向けには "AMPM" の翻訳をそのまま残すことで 12時間制の時刻表示を使い、ヨーロッパで向けでは何か別のものに翻訳することで24時間制の時刻表示を使うようにするといった使い方ができる.

数字をローカライズする場合には QLocale クラスを使うこと.

画像をローカライズすることは推奨されない. ある地域でしか使われない表現や判りにくい比喩表現を使ったりせず、全てのロケールで受け入れられる明瞭なアイコンを使うこと. 例外としては、アラビア語とヘブライ語のロケールでは画像の左右の矢印を逆にしなければならない場合がある.

システムのサポート

Qt の動作するオペレーションシステムおよびウィンドウシステムの中には、限定的な Unicode サポートしか提供されないものもある. 一般に Qt アプリケーションはプラットフォーム特有の制限にそれほど左右されることはないが、システム側で利用できるサポートの程度の差によっては Qt がそのプラットフォーム上で提供できるサポートに影響を及ぼす場合もある.

Unix/X11

Windows

X11 におけるロケールの注意点

多くの Unix ディストリビューションでは、いくつかのロケールに関して部分的なサポートしか提供されていない. たとえば、 /usr/share/locale/ja_JP.EUC というディレクトリがあったとしても、それは日本語のテキストを表示できることを必ずしも意味するものではない. 実際には JIS エンコードのフォント (または Unicode フォント) と /usr/share/locale/ja_JP.EUC ディレクトリが必要になる. 最高の結果を得るためには、システムベンダから提供される完全なロケール環境を利用すること.

関連する Qt のクラス

これらは Qt アプリケーションを国際化するのに関連するクラスである.

QInputContextデータとコンポージングステートに依存した入力メソッドの抽象化
QLocale数字と様々な言語における文字列表現との間の変換
QTextCodecテキストエンコード間の変換
QTextDecoderステートベースのデコーダ
QTextEncoderステートベースのエンコーダ
QTranslatorテキスト出力の国際化サポート


Copyright © 2005 Trolltech Trademarks
Qt 4.0.0