Qt is a great toolkit, with fine support for translations in general. You can take a Qt application and, assuming that the guidelines have been followed, it will adjust really well to starting in different languages. Changing languages on-the-fly is a different matter; even though there are guidelines to get you to 98%, I’m going to write about the 2% sadness that remains. OK? 确定? OK? ठीक है?

I’m going to gloss over the technology here; the documentation is much more in-depth, and QTranslator does most of the work-work. Read those things, then gripe about my gloss.

Happy Translations

Qt comes with translations for many things; applications can organize their translations into catalogs. To display a text, Qt applications will typically use the tr() function to look up a source-text and return a translation in the current language. For instance, tr("OK") will return the translation of “OK”.

Translations have a context, which in the case of a naive call to tr() is generally the class name performing the call. This gives the translations at least the opportunity to change the way “OK” is translated in the context of classes MyFancyWidget or MyAwkwardDialog.

So a catalog will basically be a table, helping to look up string in context to produce a translation.

Using the QTranslator class, it’s easy to load a new catalog; if the catalog is installed on the application, then subsequent calls to tr() will find the string in context in that new catalog. And by golly it works pretty well. Calamares is a Qt-based installer for Linux distributions, and it ships with translations into 81 languages (although some of them are very rudimentary). The application starts up in whatever language the system is configured in, but the first thing it does is ask the user what language to use for the application – you can start it in an English environment, and tell it to continue in Russian (or vice-versa).

Here are two screenshots of Calamares; one started in English, one started in Russion.

Calamares in English, welcome page
Calamares in English, welcome page
Calamares in Russian, welcome page
Calamares in Russian, welcome page

For strings under the control of the application, the catalog is easy to identify, and the application source-code contains all of the contexts and strings. So dealing with the translation of “Welcome” (a string that occurs in Calamares) is straightforward.

Qt itself ships catalogs, too. For instance a catalog qtbase that contains strings used in user-visible messages from the qtbase repository. Loading a different qtbase catalog works exactly the same way as any other catalog, assuming your distribution puts the catalogs in the expected location (mine doesn’t).

This concludes the 98% happiness talk.

2% Sadness

There are a couple of corner cases:

  • languages where qtbase has no translation,
  • places where you don’t know what the context is for a string.

Qt has community-contributed translations, with 28 languages participating in qtbase. Calamares has a Thai translation, which Qt as a whole does not. That means that the application displays OK on buttons where the text comes from Qt, and ตกลง if Calamares sets the text explicitly using translations from Calamares. Similar things apply to Yes and No and Cancel.

Here are three screenshots of Calamares, one started in English, one started in Russian, and one started in English and then switched to Simplified Chinese.

Calamares in English, about dialog
Calamares in English, about dialog
Calamares in Russian, about dialog
Calamares in Russian, about dialog
Calamares in Simplified Chinese, about dialog
Calamares in Simplified Chinese, about dialog

Notice that all three use a user-visible string OK, even though the qtbase catalog contains a translation (for Simplified Chinese, anyway). This shows that the context of the string matters, and that the OK button in this dialog, gets its user-visible string from a different context, but with the same source string, as other OK buttons.

The relevant difference in context is QStandardButton. The not-translated OK buttons are added to the dialog as standard buttons; I chased the code for some distance, and found that the string comes from the platform integration module, which in turn probably means the theme that is applied to the application. In other words, some source of strings provides the user-visible string here, but I don’t know what, or even if it is Qt-based.

It is, quite simply, futile to try to change translations for the OK text on a standard button by loading catalogs or applying Qt translation techniques, because it’s impossible to know where the text comes from.

In the end, I wrote a helper function that applies a Calamares-translated text to a Qt standard button, using the context StandardButton. That moves translations into a different catalog, applies the standard Calamares translation workflow to it, and gets me the last 2% of the way:

Calamares in Simplified Chinese, fixed!
Calamares in Simplified Chinese, fixed!

Tamam!

My remaining sadness is that Qt is almost there, and documentation says that it should all work, and that in the end I need to pull off some stupid hack to provide the right display of a 2-character string (2 glyphs in Simplified Chinese, 5 in Turkish). At least it’s documented, and the next time someone files an issue that there’s a missing translation I have a handle on what kind of code to add.