翻訳のためのソースコードの記述
アプリケーションのローカライズが可能となるよう、Qt QmlおよびQt C++のソースコードを記述してください:
- 翻訳対象の文字列をマークする
- 文字列の連結ではなくパラメータを使用する
- 複数形の扱い
- 地域ごとの数値設定を使用する
- 日付、時刻、通貨の国際化
- 翻訳可能なデータテキスト文字列にマークを付ける
- 翻訳者向けのコメントを追加する
- 同一のテキストの曖昧さを解消する
- キーボードショートカットを翻訳可能にする
- ロケールを使用してローカライズ機能を拡張する
- 翻訳を有効にする
- 動的な言語変更への準備
C++ アプリケーションを開発する際は、「C++ コードに関する追加の考慮事項」も参照してください。
翻訳対象の文字列をマークする
アプリケーション内で翻訳が必要なテキストのほとんどは、単一の単語または短いフレーズで構成されています。これらは通常、ウィンドウタイトル、メニュー項目、ツールチップ、およびボタン、チェックボックス、ラジオボタンのラベルとして表示されます。
Qt は、各ウィンドウが作成される際にそのフレーズを翻訳することで、翻訳使用に伴うパフォーマンスのオーバーヘッドを最小限に抑えます。ほとんどのアプリケーションでは、メインウィンドウは一度だけ作成されます。 ダイアログは、多くの場合一度作成された後、必要に応じて表示・非表示されます。初期の翻訳処理が完了すれば、翻訳済みのウィンドウに関してはそれ以上の実行時のオーバーヘッドは発生しません。翻訳によるパフォーマンスのオーバーヘッドが生じるのは、作成、破棄、そしてその後再度作成されるウィンドウのみです。
実行時に言語を切り替えるアプリケーションを作成することも可能ですが、それには手間がかかり、実行時のパフォーマンスコストも発生します。
Qt Qml および C++ コード内で、ユーザーに表示される UI テキストを翻訳対象としてマークするには、翻訳関数を使用します。Qt では、翻訳可能なテキストを特定するために、テキストベースと ID ベースの 2 つのアプローチをサポートしています。
テキストベースの翻訳アプローチでは、Qtは各翻訳可能な文字列を、翻訳コンテキストおよび(オプションで)それに関連付けられた曖昧さを解消するためのコメントによってインデックス付けします。同じフレーズが複数のコンテキストに現れても競合は発生しません。特定のコンテキスト内で同じフレーズが複数回出現する場合、翻訳は1回のみ行われ、その翻訳はコンテキスト内のすべての出現箇所に適用されます。
IDベースの翻訳アプローチでは、各翻訳は明示的なIDによって一意に識別されます。IDはプロジェクト全体で一意です。プロジェクト内で同じIDが複数回出現した場合、翻訳は1回だけ行われ、その翻訳はプロジェクト内のすべての出現箇所に適用されます。
QML
QML では、.qml ファイル内でユーザーに表示される文字列を翻訳対象としてマークするために、以下の関数を使用できます:
- qsTr():テキストベースの翻訳
- qsTranslate():テキストベースの翻訳
- qsTrId():IDベースの翻訳
テキストベースの qsTr():
Text {
id: txt1
text: qsTr("Back")
}このコードにより、「Back」が翻訳ソース (TS) ファイル内のキーエントリとなります。 実行時、翻訳システムは現在のコンテキスト(後述)内でキーワード「Back」を検索し、現在のシステムロケールに対応する翻訳値を取得します。その結果がtext プロパティに返され、UIには現在のロケールに応じた「Back」の適切な翻訳が表示されます。翻訳が見つからない場合、qsTr() は元の文字列を返します。
特定のファイルに対して翻訳コンテキストを設定するには、次のようにします:
pragma Translator: ChosenContextまたは
pragma Translator: "Chosen::Context"qsTranslate() 経由で設定されたコンテキストは、pragma Translator 経由で設定されたコンテキストよりも優先されます。QMLでは、デフォルトで翻訳コンテキストはファイル名となります。
ID ベースの qsTrId():
Text {
id: txt1
//% "Back"
text: qsTrId("BackID")
}このコードは、翻訳ソース(TS)ファイル内で「BackID」を一意のキーエントリとし、「Back」をソーステキストとして書き込みます。実行時、翻訳システムは ID「BackID」を検索し、現在のシステムロケールに対応する翻訳値(翻訳されていない場合はソーステキスト)を取得します。 結果はtext プロパティに返され、UIには現在のロケールに対応した「BackID」の適切な翻訳が表示されます。TSファイル内にID「BackID」を持つエントリが見つからない場合、qsTrId() はID自体を返します。これは通常の状況では発生しないはずです。
C++
C++ では、以下の関数を使用して、ユーザーに表示される文字列を翻訳対象として指定できます。
- tr():テキストベースの翻訳
- QCoreApplication::translate():テキストベースの翻訳
- QTranslator::translate():テキストベースの翻訳
- qtTrId():ID ベースの翻訳
- その他のオプションについては、linguist-id-based-i18n.htmlを参照してください
テキストベースの tr()
tr() 関数を使用して、テキストを翻訳可能としてマークし、翻訳されたテキストを表示します。翻訳コンテキストは、その文字列が使用される `QObject ` サブクラスの名前です。新しい `QObject` ベースのクラスの翻訳コンテキストを定義するには、各新しいクラス定義で `Q_OBJECT ` マクロを使用してください。
tr() が呼び出されると、この関数はQTranslator オブジェクトを使用して翻訳可能な文字列を検索します。このオブジェクトは、「翻訳の有効化」で説明されているように、アプリケーションオブジェクトにインストールしておく必要があります。
たとえば、LoginWidget がQWidget のサブクラスであると仮定すると:
これにより、ユーザーが目にすることが予想される文字列の 99% をカバーできます。文字列リテラルを翻訳可能としてマークする方法については、「翻訳可能なデータ文字列のマーク」を参照してください。
引用符で囲まれたテキストが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(
QCoreApplication::translate("LoginWidget", "Password:"), logwid);
}ID ベースの qtTrId()
qtTrId() は、ID で識別される翻訳済み文字列を返します。したがって、関数内で翻訳可能な文字列そのものを記述する代わりに、翻訳の ID を記述します。 ソーステキスト(デフォルトの文字列)は、メタ文字列表記//% を使用して記述します。テキストが翻訳されていない場合、//% で注釈が付けられたソーステキストが返されます。一致する ID が見つからない場合は、ID 自体が返されます。通常、このようなことは起こりません。
このコードは、「PasswordID」を翻訳ソース(TS)ファイル内の一意のキーエントリとし、「Password:」をそのソーステキストとして記述します。 実行時、翻訳システムは ID「PasswordID」を検索し、現在のシステムロケールに対応する翻訳値(翻訳されていない場合はソーステキスト)を取得します。
注: マクロ `QT_NO_CAST_FROM_ASCII ` を定義してアプリケーションをコンパイルし、const char * からQString への自動変換を無効にすると、 欠落している文字列をほぼ確実に検出できるようになります。詳細については、QString::fromUtf8() およびQString::fromLatin1() を参照してください。
文字列の連結ではなくパラメータを使用する
言語によって、フレーズ、節、文における単語の並び順が異なるため、単語やデータを連結して文字列を作成しないでください。代わりに、% を使用して、パラメータを文字列に挿入してください。
たとえば、文字列After processing file %1, file %2 is next in line では、%1 および%2 が番号付きパラメータです。実行時には、%1 および%2 が、それぞれ 1 番目と 2 番目のファイル名に置き換えられます。翻訳文には同じ番号のパラメータが含まれている必要がありますが、順序は必ずしも同じである必要はありません。 この文字列のドイツ語訳では、フレーズの順序が逆になる場合があります。例えば、Datei %2 wird bearbeitet, wenn Datei %1 fertig ist のようにです。両方の番号付きパラメータが翻訳に含まれていますが、順序は逆になっています。
QML: .arg() の使用
次のQMLスニペットには、2つの番号付きパラメータ「%1 」と「%2 」を含む文字列があります。これらのパラメータは、.arg() 関数を使用して挿入されます。
Text {
text: qsTr("File %1 of %2").arg(counter).arg(total)
}%1 は最初のパラメータを指し、%2 は2番目のパラメータを指すため、このコードは次のような出力を生成します:File 2 of 3。
引数を含むテンプレート文字列の使用は避けてください。その結果生成される文字列は、コンパイル時ではなく実行時に定義されるため、翻訳ツールがテンプレート文字列に対する正しい翻訳を見つけられなくなります。
C++: QString::arg() を使用する
C++ では、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));
}このコードは次のような出力を生成します:10ファイル中5ファイルをコピーしました。コピー中:somefile.txt。
複数形への対応
翻訳関数に追加の整数パラメータ (n) を渡し、翻訳可能な各文字列内で複数形用の特別な表記 (%n) を使用できます。
nの値に応じて、翻訳関数は対象言語の文法的に正しい数形を用いた異なる翻訳を返します。また、%n の出現箇所はすべてnの値に置き換えられます。
たとえば、文字列「%n message(s) saved 」の英語とフランス語の翻訳では、異なる複数形が必要となります。
| n | 翻訳なし | フランス語 | フランス語 |
|---|---|---|---|
| 0 | 「0件のメッセージが保存されました」 | 「保存されたメッセージ:0件」 | "保存されたメッセージは0件です" |
| 1 | 「1件のメッセージが保存されました」 | 「1件のメッセージが保存されました」 | 「1件のメッセージが保存されました」 |
| 2 | 「2件のメッセージが保存されました」 | 「2 件のメッセージが保存されました」 | 「2件のメッセージが保存されました」 |
| 37 | 「37件のメッセージが保存されました」 | 「37件のメッセージが保存されました」 | 「37件のメッセージが保存されました」 |
このイディオムは、双数形など複数の複数形を持つ対象言語でも機能します。さらに、フランス語のように単数形を必要とする言語においても、n == 0 の場合を正しく処理します。
Qt Linguist およびlrelease が、複数形を含む文字列を翻訳する際に使用するルールの概要については、「複数形の翻訳ルール」を参照してください。
ネイティブ言語の複数形を処理するには、その言語用の TS ファイルも読み込んでください。「lupdate 」ツールの「-pluralonly 」コマンドラインオプションを使用して、複数形のエントリのみを含む TS ファイルを作成します。
あるいは、lconvert ツールの `-pluralonly ` コマンドラインオプションを使用して、既存の TS ファイルから複数形以外の形式をすべて削除することもできます。
QML の例
以下の QML コードスニペットは、ソーステキストを正しい複数形に変換し、%n をtotal の値に置き換えます。
Text {
text: qsTr("%n message(s) saved", "", total)
}C++ の例
以下の C++ コードスニペットは、%n をcount() 関数が返す値に置き換えます:
int n = messages.count();
showMessage(tr("%n message(s) saved", "", n));地域設定に基づく数値のローカライズ
パラメータを指定する際に `%L ` 修飾子を含めると、その数値は現在の地域設定に従ってローカライズされます。変換には、デフォルトのロケールが設定されている場合はそのロケールが使用され、設定されていない場合はシステム全体のロケールが使用されます。
QML: %L を使用する
たとえば、次の QML スニペットでは、%L1 によって、現在選択されているロケール(地理的地域)の数値書式規則に従って最初のパラメータが書式設定されます:
Text {
text: qsTr("%L1").arg(total)
}total が数値4321.56 の場合、英語の地域設定(ロケール)では出力は4,321.56 になりますが、ドイツ語の地域設定では4.321,56 になります。
C++: %Ln を使用する
C++ では、%Ln を使用することで、n のローカライズされた表現を生成できます。デフォルトのロケールを設定するには、QLocale::setDefault() を使用します。
日付、時刻、通貨の国際化
日付、時刻、通貨は、その地域で好まれる形式で表示してください。
QML: QtQml関数の使用
QMLには、日付や時刻の書式設定を行うための文字列内の特別な修飾子はありません。その代わりに、現在のロケール(地理的地域)を取得し、Dateのメソッドを使用して文字列の書式を設定する必要があります。
Qt.locale() は、ロケールに関する情報を含むLocale オブジェクトを返します。特に、Locale.name プロパティには、現在のロケールの言語と国が含まれています。この値をそのまま使用することも、解析して現在のロケールに適した内容を決定することもできます。
次のスニペットでは、Date() を使用して現在の日付と時刻を取得し、それを現在のロケールに合わせた文字列に変換しています。その後、その日付文字列を%1 パラメータに挿入し、適切な翻訳を適用しています。
Text {
text: qsTr("Date %1").arg(Date().toLocaleString(Qt.locale()))
}通貨の数値をローカライズするには、Number型を使用します。この型には、数値をローカライズされた通貨文字列に変換するための、Date 型と同様の関数が備わっています。
C++: QLocale クラスの使用
C++では、QLocale::timeFormat()、QLocale::toString(QTime)、またはtoString(QDate) を使用します:
QLabel *label = new QLabel(this);
label->setText(tr("Date %1").arg(QLocale().toString(QDate::currentDate()));翻訳可能なデータ(テキスト文字列)のマーク付け
_NOOP 関数(QML内)および_NOOP マクロ(C++内)を使用して、lupdate ツールによって抽出される翻訳可能な文字列リテラルをマークします。
QML: _NOOP関数の使用
QMLでは、翻訳可能な文字列リテラルをマークするために以下の関数を使用します:
ユーザーが再起動せずにシステムの言語を変更した場合、システムによっては、配列やリストモデル、その他のデータ構造内の文字列が自動的に更新されないことがあります。UIに表示される際にテキストを強制的に更新させるには、QT_TR_NOOP() 関数を使用して文字列を宣言する必要があります。 その後、表示用にオブジェクトにデータを設定する際、各テキストの翻訳を明示的に取得する必要があります。
例:
ListModel {
id: myListModel
ListElement {
//: Capital city of Finland
name: QT_TR_NOOP("Helsinki")
}
}
...
Text {
text: qsTr(myListModel.get(0).name)
// Get the translation of the name property in element 0
}C++: _NOOP マクロの使用
関数の外側にある翻訳可能なテキストについては、コンテキストを含まないテキストのみに展開されるQT_TR_NOOP()、QT_TRID_NOOP()、およびQT_TRANSLATE_NOOP() マクロを使用します。
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 QCoreApplication::translate("FriendlyConversation",
greeting_strings[type]);
}翻訳者向けのコメントの追加
翻訳対象としてマークした文字列の前に、その目的を明確にするためのコメントをソースコードに追加できます。これらのコメントは、翻訳者に提供する TS ファイルに含まれます。
注: TSファイルは 、ソーステキストと翻訳テキストを格納する領域を持つXMLファイルです。更新されたTSファイルはバイナリ翻訳ファイルに変換され、最終的なアプリケーションの一部として組み込まれます。
QML: //: および //~ の使用
以下のコードスニペットでは、「//: 」行のテキストが、翻訳者向けの主なコメントとなります。
//~ 行のテキストは、任意の補足情報です。このテキストの最初の単語は、TS ファイル内の XML 要素における追加の識別子として使用されるため、最初の単語が文の一部にならないようにしてください。たとえば、「Context Not related to back-stepping」というコメントは、TS ファイル内で「<extra-Context>Not related to back-stepping 」に変換されます。
Text {
id: txt1;
// This UI string is only used here
//: The back of the object, not the front
//~ Context Not related to back-stepping
text: qsTr("Back");
}C++:コメント文字の使用
C++でコメントを追加するには、コード内のtr() 呼び出しに、「//: 」という形式のコメントを付加するか、コメントの開始位置と終了位置を明示してください。
以下の例では、各呼び出しのコンテキストにおいて、tr() に渡される文字列にコメントが関連付けられています:
//: This name refers to a host name.
hostNameLabel->setText(tr("Name:"));
/*: This text refers to a C++ code example. */
QString example = tr("Example");オプションのコメントを追加するには、次のようにします:
//~ <field name> <field contents>フィールド名は、ドメインプレフィックス(そのフィールドのモデルとなったファイル形式の慣例的なファイル拡張子である場合もあります)、ハイフン、およびアンダースコア区切りの表記による実際のフィールド名で構成される必要があります。 TSファイルへの保存においては、フィールド名に接頭辞「extra- 」を組み合わせることで、XML要素名が形成されます。フィールドの内容はXMLエスケープされますが、それ以外は要素の内容としてそのまま表示されます。各メッセージには、一意のフィールドをいくつでも追加できます。
例:
//: This is a comment for the translator.
//~ loc-layout_id foo_dialog
//~ loc-blank False
//~ magic-stuff This might mean something magic.
QString text = MyMagicClass::tr("Sim sala bim.");注: テキストベースの翻訳の ID を設定するための「//= 」メタ文字列コメントの使用は 、Qt 6.10 において非推奨となっており、今後のバージョンで削除される予定です。
翻訳者コメントにはキーワード `TRANSLATOR` を使用できます。`TRANSLATOR` キーワードの直前に記述されたメタデータは、TS ファイル全体に適用されます。
注: TSファイルをQt Linguist で開くと 、//: で注釈が付けられたコメントは、Qt Linguist のメッセージエディタに表示されます。一方、//~ の表記を使用して指定されたテキストは追加情報であり、TSファイル内でのみ生成されます。これらは主に他の形式への変換を目的としており、Qt Linguist では非表示になります。
ID ベースの翻訳のグループ化
各IDベースの翻訳にラベルを割り当てることで、大規模なプロジェクトのIDベースのエントリを小さなグループに整理することができます。
ID ベースのエントリにラベルを割り当てるには、ラベル名を指定した `//@ ` コメントを追加します。例えば C++ では次のようになります:
//% "Open file"
//@ FileOperations
qtTrId("msg.open");または、QMLでは次のようにします:
//% "Open file"
//@ FileOperations
qsTrId("msg.open");TSファイルを Qt LinguistでTSファイルを開くと、同じラベルを持つIDベースのエントリは、コンテキストごとにグループ化されるテキストベースのエントリと同様に、まとめて表示されます。ラベルのない項目はすべて、<unnamed label> の下に表示されます。
注:ラベル名は 検索や一意性には影響しません。IDはグローバルに一意であり、ラベルを参照せずにqtTrId("msgid") 経由で読み込むことも可能です。ラベルタグは翻訳者のナビゲーションを容易にするためだけに使用され、実行時の動作を変更することはありません。
同一テキストの曖昧性解消
翻訳システムは、同じテキストを何度も翻訳する必要がないよう、UIテキスト文字列を一意の項目に統合します。しかし、あるテキストは別のテキストと見た目は同じでも、意味が異なる場合があります。たとえば、英語では「back」は「後退」と「物体の前面と反対側」の両方を意味します。 翻訳者がこれら2つの異なる意味を区別して翻訳できるように、翻訳システムにこれらの意味の違いを明示する必要があります。
QML: qsTr() に曖昧性解消子(disambiguator)を追加する
QMLでは、qsTr() 関数の2番目のパラメータとして、曖昧さを解消するための文字列を追加します。
以下のコードスニペットでは、ID「not front 」によって、この「Back」というテキストと、バックステップを表す「Back」というテキストが区別されています:
Text {
id: txt1
// This UI string is used only here
//: The back of the object, not the front
//~ Context Not related to back-stepping
text: qsTr("Back", "not front")
}C++: tr() に曖昧さ解消子を追加する
C++では、tr()の呼び出し時に、識別用の文字列を渡します。
以下のコードスニペットでは、ID `recipient ` によって、受信者の名前と送信者の名前が区別されています:
MyWindow::MyWindow()
{
QLabel *senderLabel = new QLabel(tr("Name:"));
QLabel *recipientLabel = new QLabel(tr("Name:", "recipient"));
...キーボードショートカットを翻訳可能にする
最も一般的な形式では、キーボードショートカットとは、何らかのアクションを実行するために押すキーの組み合わせを指します。standard shortcuts では、標準キーを使用して、各ショートカットに関連付けられたプラットフォーム固有のキーシーケンスを要求します。
カスタムショートカットについては、Ctrl+QやAlt+F などの人間が読みやすい文字列を使用します。これらを、さまざまな言語を話すユーザー向けに適切なショートカットに翻訳することができます。
アプリケーション内でキーボードショートカットをハードコーディングすると、翻訳者がそれらを上書きできなくなります。
メニュー項目やボタンのテキストでキーボードショートカットを使用する場合、ニーモニック文字(下線付き)は、その下線付き文字とAlt キーまたはCtrl キーを同時に押すと、メニュー項目をクリックしたりボタンを押したりするのと同じ動作が行われることを示します。
たとえば、アプリケーションでは「File 」メニューのニーモニック文字としてF がよく使用されるため、メニュー項目をクリックするか、Alt+F を押すことでメニューを開くことができます。 翻訳可能な文字列(「File」)でニーモニック文字を定義するには、その文字の前にアンパサンドを付けます:"&File" 。この文字列の翻訳にもアンパサンドを含める必要があり、できれば同じ文字の前に配置してください。
QML の例
QML では:
Menu {
id: fileMenu
title: qsTr("&File")
MenuItem {
objectName: "quitMenuItem"
text: qsTr("E&xit")
onTriggered: Qt.quit()
}
}C++: QKeySequence クラスの使用
C++ では、QAction およびQKeySequence オブジェクトを使用して、アクションをトリガーするキーボードショートカットを指定します:
exitAct = new QAction(tr("E&xit"), this);
exitAct->setShortcuts(QKeySequence::Quit);キーボードショートカットの翻訳は、QShortcut コンテキストに関連付けられます。
Locale を使用してローカライゼーション機能を拡張する
地域によって、より適したグラフィックや音声がある場合があります。
一般的には、画像のローカライズは避けるようにしてください。地域特有の言葉遊びや無理のある比喩に頼るのではなく、世界的に通用するアイコンを作成してください。ただし、アラビア語やヘブライ語のロケールでは、左右を指す矢印の画像を左右反転させる必要がある場合があります。
ロケールはデフォルトのファイルセレクタの一つであるため、ファイル選択機能を利用して、システムのロケールに応じてリソースとして提供された異なる画像を表示することができます。
以下のセクションにある QML および C++ のコード例では、アプリケーションリソースに以下のファイルを用意し、サブフォルダ名として言語コードおよび国コードを使用することを前提としています。
images
├── language-icon.png
├── +en_GB
│ └── language-icon.png
└── +fi_FI
└── language-icon.pngQML: 画像ソースの設定
以下のQMLコードスニペットは、現在のロケールに応じてアイコンのソース画像を選択する方法を示しています:
icon.source: "qrc:/images/language-icon.png"C++: QFileSelectorの使用
次のC++コードスニペットでは、QFileSelector を使用して、システムのロケールに応じてimages フォルダから言語アイコンを選択しています:
const QFileSelector selector;
const QIcon languageIcon(selector.select(":/images/language-icon.png"));翻訳を有効にする
TSファイル名には、ISO言語コードおよび国コードを含める必要があります。
たとえば、qml_de.ts はターゲット言語をドイツ語に設定し、qml_de_CH.ts はターゲット言語をドイツ語、ターゲット国をスイスに設定します。lrelease ツールは、qml_de.qm およびqml_de_CH.qm という QM ファイルを生成し、アプリケーションはシステムのロケールに応じてこれらのファイルをロードします。
QML: QQmlApplicationEngine を使用する
QMLでは、QQmlApplicationEngine を使用することで、メインのQMLファイルが含まれるディレクトリ内の「i18n 」というサブディレクトリから翻訳ファイルを自動的に読み込むことができます。翻訳ファイル名には、qml_ というプレフィックスを付ける必要があります。例:qml_en_US.qm 。多言語アプリのセットアップ方法については、以下のCMakeコードスニペットを参照してください:
...
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick LinguistTools)
qt_standard_project_setup(REQUIRES 6.5 I18N_TRANSLATED_LANGUAGES ja_JP)
qt_add_qml_module(appmultilingual_demo
URI multilingual_demo
QML_FILES
Main.qml
)
qt_add_translations(appmultilingual_demo
TS_FILE_BASE qml
TS_FILE_DIR i18n
RESOURCE_PREFIX /qt/qml/multilingual_demo/i18n
)
...アプリケーションは、QJSEngine::uiLanguage またはQt.uiLanguage のプロパティ値が変更された際に、翻訳を再読み込みします。以下のコードスニペットは、ユーザーがボタンをクリックした際に動的に言語を変更するものです:
Button {
anchors.centerIn: parent
text: qsTr("Translate")
onClicked: {
Qt.uiLanguage = Qt.uiLanguage === "en" ? "ja" : "en"
}
}C++: QTranslator を使用する
C++ では、TS ファイル名にアプリケーション名を含める必要があります。例:app_de_DE.ts 。
通常、Qt C++ アプリケーションの `main() ` 関数は次のような形になります:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTranslator myappTranslator;
if (myappTranslator.load(QLocale::system(), u"myapp"_s, u"_"_s, u":/i18n"_s))
app.installTranslator(&myappTranslator);
return app.exec();
}翻訳対応アプリケーションでは、QTranslator オブジェクトを作成し、実行時にユーザーの UI 表示ロケールに基づいて翻訳をload し、その翻訳オブジェクトをアプリケーションにインストールします。
動的な言語変更への備え
Qt Widgets とQt Quick の両方は、Qt のイベントシステムを使用して、翻訳の変更をクラスに通知します。
LanguageChange QCoreApplication::installTranslator() 関数を使用して新しい翻訳をインストールすると、イベントが投稿されます。また、他のアプリケーションコンポーネントも、 イベントを投稿することで、 型から派生したウィジェットや QML タイプに対して、強制的に更新を行うことができます。LanguageChange Item
デフォルトでは、LanguageChange イベントはすべてのトップレベルウィンドウに伝播され、そこからItemを継承したウィジェットやQML型のツリー全体に伝播されます。
Qt Widgets: changeEvent をオーバーライドする
QWidget のサブクラスのデフォルトのイベントハンドラは、QEvent::LanguageChange イベントに応答し、必要に応じてchangeEvent() 関数を呼び出します。
Qt Widgetsに、インストールされたQTranslator オブジェクトの変更を認識させるには、ウィジェットのchangeEvent()関数を再実装し、そのイベントがLanguageChange イベントであるかどうかを確認した上で、tr()関数を使用してウィジェットに表示されるテキストを更新します。例:
void MyWidget::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
titleLabel->setText(tr("Document Title"));
...
okPushButton->setText(tr("&OK"));
} else
QWidget::changeEvent(event);
}Qt Widgets Designer のUIファイル(.ui)とuic を使用する場合、新しい翻訳ファイルを読み込み、ui.retranslateUi(this) を直接呼び出すことができます:
void MyWidget::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
ui.retranslateUi(this);
} else
QWidget::changeEvent(event);
}その他の変更イベントを伝達するには、関数のデフォルトの実装を呼び出します。
インストール済みの翻訳ツールのリストは、LocaleChange イベントに応じて変更される場合や、アプリケーションがユーザーが現在のアプリケーション言語を変更できるUIを提供している場合があります。
QML: `Item` から派生した型に対するイベントのオーバーライド
カスタム C++ 登録型を一切使用しない通常の QML アプリケーションの場合、QQmlApplicationEngine を使用するだけで、すべての翻訳バインディングの更新をトリガーできます。
ただし、QQuickItem から派生した型を登録しており、そのプロパティの 1 つが翻訳済みテキストを公開している(あるいはその他の方法で言語に依存している)場合は、そのevent method をオーバーライドし、その中でプロパティの変更シグナルを発行してください(バインド可能なプロパティの場合は、notify を呼び出してください)。例:
class MyItem : public QQuickItem
{
Q_OJBECT
QML_ELEMENT
Q_PROPERTY(QString greeting READ greeting NOTIFY greetingChanged)
public signals:
void greetingChanged();
public:
QString greeting() const
{
return tr("Hello World!");
}
bool event(QEvent *ev) override
{
if (ev->type() == QEvent::LanguageChange)
emit greetingChanged();
return QQuickItem::event(ev);
}
};これにより、そのプロパティが使用されている QML 内のすべてのバインディングが再評価され、言語の変更が反映されるようになります。
汎用的な QObject 派生クラス:イベントフィルタの使用
QWidget やQQuickItem を継承していないクラスであっても、言語変更イベントを処理する必要がある場合があります。その場合は、QCoreApplication にイベントフィルターを登録してください。
class CustomObject : public QObject
{
Q_OBJECT
public:
QList<QQuickItem *> managedItems;
CustomObject(QOject *parent = nullptr) : QObject(parent)
{
QCoreApplication::instance()->installEventFilter(this);
}
bool eventFilter(QObject *obj, QEvent *ev) override
{
if (obj == QCoreApplication::instance() && ev->type() == QEvent::LanguageChange) {
for (auto item : std::as_const(managedItems))
QCoreApplication::sendEvent(item, ev);
// do any further work on reaction, e.g. emit changed signals
}
return false;
}
};これは、クラスによって翻訳済み文字列が提供され、それが後でユーザーインターフェース(たとえば、カスタムitem model )に表示される場合や、クラスがWidgetやQuick Itemのコンテナとして機能し、それらにイベントを転送する役割を担っている場合に必要となる可能性があります。
C++ コードに関する追加の考慮事項
以下のセクションでは、翻訳可能なアプリケーションでの Qt C++ クラスおよび関数の使用に関する詳細情報を説明しています:
ユーザーに表示されるすべてのテキストには QString を使用する
QString は内部でUnicodeエンコーディングを使用しているため、慣れ親しんだテキスト処理操作を用いて、世界中のあらゆる言語を透過的に処理することができます。また、ユーザーにテキストを表示するすべてのQt関数はQString オブジェクトをパラメータとして受け取るため、char * からQString への変換に伴うオーバーヘッドは発生しません。
翻訳コンテキストの定義
QObject および各QObject サブクラスの翻訳コンテキストは、クラス名そのものです。QObject をサブクラス化する場合、クラス定義内でQ_OBJECT マクロを使用して翻訳コンテキストを上書きします。このマクロは、コンテキストをサブクラスの名前に設定します。
たとえば、次のクラス定義にはQ_OBJECT マクロが含まれており、MainWindow コンテキストを使用する新しいtr() 関数を実装しています:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
...クラス定義でQ_OBJECT を使用しない場合、コンテキストは基底クラスから継承されます。たとえば、QtのQObject を基底とするすべてのクラスはコンテキストを提供しているため、Q_OBJECT マクロを使用せずに定義された新しいQWidget のサブクラスでは、そのtr() 関数を呼び出した際にQWidget コンテキストが使用されます。
Qt以外のクラスの変換
QObject を継承していない、またはQ_OBJECT マクロを使用していないクラスの文字列については、lupdate に対して追加情報を提供する必要があります。非Qtクラスに翻訳サポートを追加するには、Q_DECLARE_TR_FUNCTIONS()マクロを使用できます。例:
class MyClass
{
Q_DECLARE_TR_FUNCTIONS(MyClass)
public:
MyClass();
...
};これにより、そのクラスに関連付けられた文字列の翻訳に使用できる `tr()` 関数がクラスに提供され、lupdate がソースコード内の翻訳可能な文字列を検出できるようになります。
あるいは、lupdate およびQt Linguist が認識する特定のコンテキストを指定して、QCoreApplication::translate() 関数を呼び出すこともできます。
QObjectサブクラス外のテキストを翻訳する
引用されたテキストが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(
QCoreApplication::translate("LoginWidget", "Password:"),
logwid);
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.