ID に基づく変換機能を備えたローカライズされた時計
この例では、CMakeおよびQt Quick におけるQtのIDベースの翻訳機能の使用に関するベストプラクティスを示しています。これには、各言語における複数形の扱い方や、ローカライズされた時刻形式などが含まれます。
ユーザーインターフェース
この例では、システムのロケールと言語に基づいた現在の日時を表示します。英語、ドイツ語、フランス語、スペイン語、イタリア語、日本語、韓国語、ポルトガル語、アラビア語、中国語の翻訳がサポートされています。デスクトップの言語がこれら以外の言語の場合は、英語にフォールバックします。
また、このサンプルでは、システムを変更することなくさまざまな言語やロケールをテストするために、コマンドライン引数としてロケールを指定することも可能です:localizedClockIdBased --locale en_GB またはlocalizedClockIdBased --locale de
デフォルトでは、アプリケーションは現在のロケールで時刻と日付を表示しますが、タイムゾーンの一覧が表示されるダイアログを開くボタンも用意されています。ユーザーはこのダイアログを使用して、時計のタイムゾーンを変更することができます。
ID ベースの翻訳
この例では、ID ベースの翻訳を使用します。これは、従来の「コンテキスト+テキスト」の組み合わせではなく、一意の IDによって翻訳対象のテキストを識別する方式です(「テキスト ID ベースの翻訳」を参照)。このアプローチにより、異なるコンテキスト間で翻訳を再利用することが可能になります。 この仕組みを実証するために、Main.qmlと「タイムゾーンダイアログ」(C++で記述されたQWidget ベースのフォーム)の間で翻訳を共有します。IDベースの翻訳のもう一つの利点は、UIに表示されるテキストと開発者の作業を分離し、ソースコードをユーザーに提示される実際の言葉から独立させることができる点です。
以下の2つのスクリーンショットは、英語版のアプリケーションのもので、メインウィンドウ(QML)とダイアログ(C++)にある「Select time zone: 」というテキストの2つのインスタンスが、同じIDを使用することで同じ翻訳を共有しています。
英語版のアプリケーションウィンドウのスクリーンショット:

タイムゾーンの一覧が表示されるダイアログ(英語版):

ドイツ語版のアプリケーションのメインウィンドウ:

タイムゾーンの一覧が表示されたダイアログ(ドイツ語版):

実装
このアプリケーションは5つの部分で構成されています:
CMakeLists.txt
このアプリケーションの CMake ファイルでは、Qt の ID ベースの翻訳およびローカライズ機能が有効になっています。関連する部分は以下の通りです:
find_package(Qt6 REQUIRED COMPONENTS Core Linguist Qml Quick):国際化に不可欠なLinguist を含む、必要なQt 6モジュールを検出してリンクします。qt_standard_project_setup():リストされたロケールをサポートするように国際化システムを設定します。ソース言語は英語ですが、IDベースの翻訳を使用する場合でも、英語の翻訳が必要です。 ソースコードにはIDのみが含まれており、ソーステキスト自体は参照されません。そのため、qt_add_translationsが英語用のTSファイルを生成できるよう、プロジェクトに英語の翻訳を設定する必要があります。そうしないと、実行時にそれらのファイルが欠落してしまいます。
qt_standard_project_setup(REQUIRES 6.8
I18N_TRANSLATED_LANGUAGES de ar ko zh ja fr it es pt en)qt_add_translations(...):`lupdate ` および `lrelease ` の機能を統合し、clock を基名として「i18n」ディレクトリ内に翻訳ソースファイル(TSファイル)を生成し、翻訳が含まれている場合はそれらをバイナリ形式の.qm ファイルにコンパイルします。
qt_standard_project_setupのI18N_TRANSLATED_LANGUAGESに記載されている言語ごとに、1つのTSファイルを生成します。MERGE_QT_TRANSLATIONSまた、QT_TRANSLATION_CATALOGS qtbaseには、プロジェクトに Qt 翻訳を含める必要があります。これは、タイムゾーンダイアログ内のQDialogウィジェットのボタンを翻訳するために必要です。これらのボタンのテキストはQDialog によって制御されているため、Qt 翻訳を含めない限り、これらのボタンは翻訳されません(ID ベースの翻訳にあるドイツ語のスクリーンショットで、ダイアログの翻訳済みテキストを参照してください)。
qt_add_translations(localizedClockIdBased
TS_FILE_BASE i18n/clock
MERGE_QT_TRANSLATIONS
QT_TRANSLATION_CATALOGS qtbase
RESOURCE_PREFIX i18n
)qt_add_qml_module(...):URIqtexamples.localizedclock の下に QML モジュールを追加し、Main.qmlファイルを含め、Time Zone Managerのソースファイルとヘッダーファイルをその QML モジュールにインポートします。
qt_add_qml_module(localizedClockIdBased
URI qtexamples.localizedclock
VERSION 1.0
QML_FILES
Main.qml
RESOURCES dialog.ui
SOURCES
timezonemanager.h timezonemanager.cpp
dialog.h dialog.cpp
)main.cpp
アプリケーションの開始点です。この部分は、ロケールの設定、必要な翻訳のインストール、および UI の読み込みを担当します。以下に、関連するコード部分の説明を示します:
ロケール引数を定義します。例:--locale en_US または--locale de_DE:
QCommandLineParser parser;
QCommandLineOption localeOption("locale"_L1, "Locale to be used in the user interface"_L1,
"locale"_L1);
parser.addOption(localeOption);
parser.addHelpOption();
parser.process(app);引数を解析し、指定されたロケールを取得して、入力ロケールをアプリケーションのデフォルトロケールとして設定します:
QLocale locale(parser.value(localeOption));
qInfo() << "Setting locale to" << locale.name();
QLocale::setDefault(locale);ロケールに関係なく英語翻訳をインストールし、他の言語の翻訳が不完全な場合でも対応できるようにします。QTranslator は、翻訳がインストールされた順序と逆の順序でテキストの翻訳を照会します:
QTranslator enPlurals;
const autoenPluralsPath= ":/i18n/clock_en.qm"_L1;
if(!enPlurals.load(enPluralsPath))
qFatal("Could not load %s!", qUtf8Printable(enPluralsPath));
app.installTranslator(&enPlurals);指定されたロケールに基づいて翻訳をインストールします:
QTranslator translation;
if(QLocale().language()!=QLocale::English) {
if(translation.load(QLocale(), "clock"_L1, "_"_L1, ":/i18n/"_L1)) {
qInfo("Loading translation %s",
qUtf8Printable(QDir::toNativeSeparators(translation.filePath())));
if(!app.installTranslator(&translation))
qWarning("Could not install %s!",
qUtf8Printable(QDir::toNativeSeparators(translation.filePath())));
}else{
qInfo("Could not load translation to %s. Using English.",
qUtf8Printable(QLocale().name()));
}
}前の手順で英語翻訳をインストールしたため、インストール済みの翻訳が2つ存在することになります。Qtでは、重複するキーについては、最も新しくインストールされた翻訳が使用されます。したがって、ロケール固有の翻訳が英語よりも優先され、翻訳が存在しない場合は、QTranslator が英語にフォールバックします。
タイムゾーンダイアログ
このクラスは、C++のQWidget ベースのダイアログ(QDialog )であり、タイムゾーンのリストを含むQComboBox を表示します。以下にコードの説明を示します:
UIフォーム(dialog.ui)でIDベースの翻訳を有効にします:
<ui version="4.0" idbasedtr="true">ID ベースの翻訳を使用してタイトルを設定します(dialog.ui)。ここで、「title」は翻訳の一意の ID です:
<property name="windowTitle">
<string id="title">Time Zone</string>
</property>ID ベースの翻訳(dialog.ui)を使用して、ID「timezonelabel」のラベルを追加します:
<widget class="QLabel" name="label">
...
<property name="text">
<string id="timezonelabel">Select time zone</string>
</property>
...
</widget>タイムゾーンマネージャー
C++ にある、タイムゾーンの変更を処理するQML_SINGLETON クラス。
ユーザーがタイムゾーンを選択すると、TimeZoneManager のインスタンスは選択されたタイムゾーンを記憶します:
connect(m_dialog.get(), &Dialog::timeZoneSelected, this, &TimeZoneManager::setTimeZone);タイムゾーンが更新されると、TimeZoneManager::timeZoneChanged シグナルが発信されます:
connect(m_dialog.get(), &Dialog::timeZoneSelected, this, &TimeZoneManager::setTimeZone);
}
m_dialog->show();
}TimeZoneManager::currentTimeZoneOffsetMs() Q_INVOKABLE でマークされており、選択されたタイムゾーンの時間オフセットを返します。 クラスはTimeZoneManager QML_ELEMENT およびQML_SINGLETONで宣言されているため、QMLからこのメソッドに直接アクセスして表示されている時刻を更新することができます。また、Main.qmlも参照してください。
qint64 TimeZoneManager::currentTimeZoneOffsetMs()
{
const QTimeZone tz(m_timeZone.toLatin1());
if (!tz.isValid())
return 0;
const QDateTime nowUtc = QDateTime::currentDateTimeUtc();
const int targetOffset = tz.offsetFromUtc(nowUtc);
const int systemOffset = QTimeZone::systemTimeZone().offsetFromUtc(nowUtc);
return (targetOffset - systemOffset) * 1000;
}Main.qml
メインのQMLファイルは、アプリケーションのユーザーインターフェースを定義しています。UIには、時刻、日付、現在のタイムゾーン、および秒単位のカウンターが表示されます。また、タイムゾーンを変更するための「タイムゾーンダイアログ」を開くボタンも用意されています。以下に、関連するコード部分の解説を示します。
qsTrId() を使用して、ID ベースの翻訳によりウィンドウを定義し、タイトルを設定します。ソース言語のテキストは、メタ文字列表記//% を使用して指定します(「テキストのIDベースの翻訳」を参照)。lupdateはメタ文字列を解析し、定義されたソーステキストをTSファイルに書き込みます。ソーステキストはメタ文字列を使用してコメント形式で指定されるため、実行時にはアプリケーションから認識されません。 したがって、アプリケーションが英語ロケールで読み込まれる場合、ソース言語が英語であっても、英語のテキストを表示するには英語の翻訳をインストールする必要があります。そうしないと、生のID「Main-Digital-Clock」が表示されます。これが、CMakeLists.txtの設定により、I18N_TRANSLATED_LANGUAGES で「en」を指定した理由でもあります。
//% "Digital Clock"
title: qsTrId("Main-Digital-Clock") qsTrId() を使用して、複数形に対応した秒数を表示します。ここでも、ソース言語のテキストは//% メタ文字列を使用して指定されます。複数形は、メタ文字列内のソーステキストで特別な表記「%n」を使用することで有効になります(「複数形の扱い」を参照)。 nの値に応じて、翻訳関数は対象言語の文法的に正しい数形を持つ異なる翻訳を返します。たとえば英語の場合、root.seconds の値が1より大きいと複数形が使用され、そうでない場合は単数形が使用されます。各言語の複数形に関する規則については、「複数形の翻訳規則」を参照してください。
//% "%n second(s)"
text: qsTrId("Main-n-second-s", root.seconds)ID ベースの翻訳を使用して、現在選択されているタイムゾーンを表示します。 //% "Time zone: " でソース言語のテキストを指定します:
//% "Time zone: "
text: qsTrId("timezone") + TimeZoneManager.timeZone;タイムゾーンダイアログを開くボタン。ボタンのテキストは、IDベースの翻訳においてqsTrId() を使用して指定されます。この場合、以前に dialog.ui ドキュメントで使用されていた ID「timezonelabel」を再利用しているため、ソーステキストはメタ文字列によって定義されなくなりました(「タイムゾーンダイアログ」を参照)。 ID ベースの翻訳では、プロジェクト内で ID ごとのソーステキストを 1 回だけ指定すれば十分です:
Button {
text: qsTrId("timezonelabel")
onClicked: TimeZoneManager.openDialog()
Layout.alignment: Qt.AlignHCenter
}タイムゾーンを変更し、TimeZoneManager::timeZoneChanged() シグナルを受信したら(「タイムゾーンマネージャー」を参照)、diff 変数に、選択されたタイムゾーンの時間オフセットを反映させて更新します:
Connections {
target: TimeZoneManager
function onTimeZoneChanged() {
root.diff = TimeZoneManager.currentTimeZoneOffsetMs();
}
}1秒ごとにトリガーされ、time、date、secondsプロパティを更新するTimerを宣言します。このタイマーは、現在の時刻に選択したタイムゾーンの時間オフセットを加算することで時刻を計算します:
Timer {
interval: 1000
running: true
repeat: true
triggeredOnStart: true
onTriggered: {
const now = new Date(new Date().getTime() + root.diff);
const locale = Qt.locale();
root.time = now.toLocaleTimeString(locale, Locale.ShortFormat);
root.date = now.toLocaleDateString(locale);
root.seconds = now.getSeconds();
}
}ロケールは、日付と時刻の表示方法に影響します。これらは、現在のロケールの国の慣習に従って書式設定されます。たとえば、ドイツのロケールでは24時間制の時刻と「DD.MM.YYYY」の日付形式が使用されますが、米国のロケールでは12時間制の時刻と「MM/DD/YYYY」の日付形式が使用されます。
© 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.