Qt Localization Guide: How to Translate Qt Applications for Multiple Languages

Qt is widely used for building cross-platform desktop, mobile, and embedded applications. When an application is intended for users in different regions, localization should be treated as part of the product architecture, not as a final cosmetic step. A well-localized Qt application adapts not only its text, but also dates, numbers, layout direction, and cultural expectations.

TLDR: Qt localization is typically handled with Qt Linguist, translation source files, and runtime loading of compiled translation files. Developers mark user-facing strings in code, generate translation files, send them for translation, compile them, and load the appropriate language at startup. For reliable results, plan localization early, avoid hard-coded text, and test every language in the actual interface.

Understanding Qt Localization

Localization in Qt usually consists of two related activities: internationalization and translation. Internationalization means preparing the application so it can support multiple languages and regional formats. Translation means converting the user-facing text into specific languages.

Qt provides a mature workflow for this through classes and tools such as QObject::tr(), QTranslator, lupdate, lrelease, and Qt Linguist. Together, these tools allow teams to extract text from source code, translate it, compile translations, and load them dynamically.

The standard Qt translation workflow uses three main file types:

  • Source code files, where translatable strings are marked.
  • TS files, which are XML-based translation source files used by translators.
  • QM files, which are compiled binary translation files loaded by the application.

Marking Strings for Translation

The first practical step is to mark all user-visible strings. In Qt Widgets and QObject-based classes, this is commonly done using tr(). For example:

setWindowTitle(tr("Settings"));
button->setText(tr("Save"));

The tr() function tells Qt’s translation tools that the string should be extracted. It also provides context, usually based on the class name, which helps differentiate identical words used in different places. For instance, the word “Open” may be a verb in one dialog and an adjective in another.

In QML, translations are usually marked with qsTr():

Text {
    text: qsTr("Welcome")
}

A serious localization process requires discipline. Avoid constructing sentences from fragments such as tr("File") + fileName + tr("saved"). Word order varies between languages, and translators need complete sentences. A better approach is to use placeholders:

tr("File %1 has been saved.").arg(fileName);

This gives translators control over grammar and word order while allowing the application to insert dynamic values safely.

Creating Translation Files

After strings are marked, translation files must be generated. In CMake-based Qt projects, translation files can be managed with Qt’s translation-related CMake functions. In qmake projects, the TRANSLATIONS variable is commonly used.

A typical set of language files might look like this:

  • app_en.ts for English
  • app_de.ts for German
  • app_fr.ts for French
  • app_ja.ts for Japanese

The lupdate tool scans the source code and updates TS files with newly found translatable strings. It also preserves existing translations where possible. This is important in long-term projects, where strings are added, changed, and removed continuously.

Once the TS files are updated, they can be opened in Qt Linguist. Translators use this tool to enter translations, review context, mark items as finished, and detect unfinished or problematic entries.

Using Qt Linguist Effectively

Qt Linguist is not just a text editor. It is designed to show translation context, source text, comments, and validation warnings. Developers can make translators’ work much easier by adding comments for ambiguous strings.

For example:

tr("Archive", "Verb, meaning to store old records");

This prevents misunderstandings and reduces costly correction cycles. In professional teams, translation quality depends heavily on context. A translator who sees only isolated words cannot reliably produce accurate results.

When using Qt Linguist, teams should establish clear rules:

  • Translate complete phrases rather than isolated fragments.
  • Review accelerator keys, such as &File, to avoid conflicts in menus.
  • Check placeholders, ensuring that %1, %2, and similar tokens are preserved.
  • Validate plural forms, because languages handle quantities differently.

Handling Plural Forms

Pluralization is one of the most common sources of localization errors. English generally has singular and plural forms, but many languages have more complex rules. Qt supports plural-aware translations with the n parameter.

tr("%n file(s) deleted", "", count);

In Qt Linguist, translators can provide the correct forms for their language. This is far better than writing conditional English logic in the code. For a serious multilingual application, plural handling should be tested with values such as 0, 1, 2, 5, and larger numbers, depending on the target language.

Compiling and Loading Translations

After translation work is complete, TS files must be compiled into QM files using lrelease. The resulting QM files are what the Qt application loads at runtime.

A basic C++ example looks like this:

QTranslator translator;
if (translator.load("app_de.qm", ":/translations")) {
    qApp->installTranslator(&translator);
}

In production, the language is usually selected based on the system locale, a user preference, or a configuration file. Qt provides QLocale to help identify the user’s language and region:

QString locale = QLocale::system().name();

This might return values such as de_DE, fr_FR, or es_MX. Applications often attempt to load the most specific translation first and then fall back to a more general language if needed.

It is also common to include translation files in Qt resources using a .qrc file. This ensures translation files are deployed with the application and are not accidentally omitted during packaging.

Supporting Runtime Language Switching

Some applications allow users to change the language without restarting. Qt supports this, but it requires careful implementation. When a new translator is installed, widgets must update their displayed text. In Qt Widgets applications, this is often handled by responding to QEvent::LanguageChange and calling a function such as retranslateUi().

If the interface was created with Qt Designer, generated UI classes usually include retranslateUi(). This function reapplies translated text to labels, buttons, menus, and other interface elements.

Runtime language switching should be tested thoroughly. Some strings may be set manually after initialization, some dialogs may be created lazily, and some cached text may not update automatically. A restart requirement is sometimes acceptable for enterprise or embedded software, but it should be clearly communicated to users.

Adapting Formats, Layouts, and Direction

True localization goes beyond translated strings. Dates, times, currencies, decimal separators, and measurements may differ by region. Qt’s QLocale helps format these values appropriately:

QLocale locale;
QString price = locale.toCurrencyString(49.99);
QString date = locale.toString(QDate::currentDate(), QLocale::LongFormat);

Applications targeting Arabic, Hebrew, Persian, or Urdu may also need right-to-left layout support. Qt provides layout direction handling, but developers should avoid assumptions such as placing important information only on the left side or embedding directional symbols incorrectly.

Testing Localized Qt Applications

Localization testing should be part of the release process. Translated text is often longer than the original English, which can break layouts, truncate labels, or overflow buttons. German, Finnish, and Russian strings may require more space; Japanese or Chinese may require different font considerations.

A practical test plan should include:

  • Visual inspection of dialogs, menus, toolbars, and error messages.
  • Functional testing to ensure translated actions still trigger correct behavior.
  • Placeholder testing for dynamic values in translated strings.
  • Locale testing for dates, numbers, currency, and sorting.
  • Fallback testing when a translation is missing or incomplete.

It is also useful to test with a pseudo-translation, where text is intentionally expanded or decorated. This helps identify strings that were not marked for translation and UI elements that cannot handle longer text.

Best Practices for Long-Term Maintainability

For professional Qt projects, localization should be integrated into the development workflow. Run lupdate regularly, keep TS files under version control, and avoid changing source strings unnecessarily. Even minor wording changes may invalidate existing translations and create extra work.

Use consistent terminology throughout the application. If “Settings” is used in one place and “Preferences” in another, translators may produce inconsistent results. Maintaining a glossary is especially valuable for technical, medical, financial, or industrial applications.

Finally, collaborate with native-speaking reviewers whenever possible. Automated translation can be useful for drafts, but user-facing software requires accuracy, tone, and cultural appropriateness. Poor localization damages trust, while careful localization makes an application feel reliable and professionally maintained.

Conclusion

Qt provides a strong and proven localization system, but the quality of the final result depends on how carefully it is used. By marking strings correctly, using Qt Linguist, supporting plural forms, loading translations properly, and testing localized interfaces, developers can deliver applications that serve users across languages and regions. Treat localization as an engineering concern from the beginning, and your Qt application will be far better prepared for international adoption.