Localized Clock with Runtime Language Switch

The example demonstrates best practices for using Qt's translation and localization features in CMake and Qt Quick, in particular changing the language of an application during runtime. It extends the simpler Localized Clock Example.

See the Qt Linguist Manual for more information about translating Qt applications.

User Interface

The example shows the current time and date in your system's locale and language. The UI texts are also localized for the following languages: English, German, French, Spanish, Italian, Japanese, Korean, Portuguese, Arabic, and Chinese. Users can also use a menu button to select different languages and locales.

The English version of the application:

The German version after changing the language at runtime:

Implementation

The application has four parts:

CMakeLists.txt

The CMake integration is the same as the CMake integration of the Localized Clock example. Please refer to that page for more details.

main.cpp

The starting point of the application, responsible for loading the QML module.

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    QObject::connect(
            &engine, &QQmlApplicationEngine::objectCreationFailed, &app,
            [](const QUrl &) { QCoreApplication::exit(-1); }, Qt::QueuedConnection);
    engine.loadFromModule("qtexamples.localizedclockswitchlocale", "Main");
    return app.exec();
}
Translator Manager (translator.h, translator.cpp)

TranslatorManager is a QML singleton class that manages language and locale switching at runtime. The central method of the class is TranslatorManager::switchLanguage(), which accepts a string representing a language code.

While the method is marked with Q_INVOKABLE, the TranslatorManager class is declared with QML_ELEMENT and QML_SINGLETON. This allows the method to be directly accessed from QML; also, see Main.qml.

void TranslatorManager::switchLanguage(const QString &lang)
{
    QLocale locale(lang);
    QLocale::setDefault(locale);
    qApp->removeTranslator(&m_translator); // not necessary from Qt 6.10
    if (m_translator.load(locale, "clock"_L1, "_"_L1, ":/i18n/"_L1)
        && qApp->installTranslator(&m_translator)) {
        m_engine.retranslate();
    } else {
        qWarning("Could not load translation to %s!", qPrintable(locale.name()));
    }
}
Updating Translations at Runtime

Upon switching language, the previous translation is removed (QCoreApplication::removeTranslator()) and a new translation for the selected language is loaded (QTranslator::load()) and installed (QCoreApplication::installTranslator()). QQmlEngine::retranslate() then triggers the retranslation of the strings in the QML document.

Updating Date and Time Formats

Changing language could also affect how dates and times are displayed. For instance, if QLocale on your system prefers locale "en_US" for "en", and "de_DE" for "de":

  • The application is initially loaded with "US" as the country code.
  • Due to the US locale conventions, the date is presented in MM/DD/YYYY format, and the time uses a 12-hour clock.
  • After changing the language to German, "de_DE" is the first preferred locale for the German language, so the country changes to Germany.
  • The German conventions bring the date in DD.MM.YYYY format and use a 24-hour clock.

Upon switching the language, the application updates its QLocale according to the selected language using QLocale::setDefault(). When representing time, the function Date.toLocaleTimeString() takes care of localizing the time and date according to the locale of the application (see Main.qml).

Main.qml

The main QML file defines the application's user interface. The UI presents time, date, and a counter for seconds. For the basic translation (window title) and plural handling (number of seconds), please refer to the Localized Clock example.

Upon selecting an item from the Menu TranslatorManager.switchLanguage() is called with the respective language code. This call also takes care of retranslating the translatable texts (see Translator Manager). However, we still need to invoke updateClock() to update the time representation in the new localization format when the language is changed.

        ListModel {
            id: languageModel
            ListElement { name: "English"; code: "en" }
            ListElement { name: "Deutsch"; code: "de" }
            ListElement { name: "العربية"; code: "ar" }
            ListElement { name: "한국어"; code: "ko" }
            ListElement { name: "中文"; code: "zh" }
            ListElement { name: "日本語"; code: "ja" }
            ListElement { name: "Français"; code: "fr" }
            ListElement { name: "Italiano"; code: "it" }
            ListElement { name: "Español"; code: "es" }
            ListElement { name: "Português"; code: "pt" }
        }
        Menu {
            id: languageMenu
            width: languageButton.width
            Repeater {
                model: languageModel
                delegate: MenuItem {
                    required property string name
                    required property string code
                    text: name
                    onTriggered: {
                        TranslatorManager.switchLanguage(code)
                        root.selectedLanguage = name
                        root.updateClock()
                    }
                }
            }
        }

Example project @ code.qt.io

© 2025 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.