Qt Commercial Support Weekly #24 - Dynamic translation of application strings

Being able to provide translations for your application with the help of Qt Linguist is one of the big advantages to using Qt as it makes it easy to translate your application into another language and have your application support this translation with either no or little changes. For the basic case of loading the translator at the start of the application and then installing it, everything is easy to set up, you just put tr() around your strings and then away you go.

 

However, what if you decided later on, or even when you start the design of your application, that the application should be able to switch into different languages at runtime. A fair number of applications already make this possible, however they tend to indicate that you need to restart the application in order to get it to use the new translation. With Qt, it is possible to avoid the restart and I will show you how to do this.

 

The main thing that needs to be done is that whenever the language has been changed then all the translatable strings that are used for visible widgets need to be reset, for example, the text on a pushbutton needs to be reset via setText(). This is assuming that the string is marked for translation with tr() when it is used in the setText() call so something like pushButton->setText(tr("Push me"));. Although this may mean some readjustment as to how the application is designed the easiest way to go about setting this up ready for dynamic translation is to move these string setting calls into a separate function. It can be one that is for the whole application, or one that is added to a subclass of a widget. In this case we will add it as member of a QMainWindow subclass.

 

	void MainWindow::retranslateUi()
{
setWindowTitle(tr("My Application in English"));
fileLabel->setText(tr("Filename:"));
openButton->setText(tr("Open"));
}

 

In order to ensure that this is still working in the default case, we just need to call this function at the end of our mainwindow constructor. All that is now left for us to do is to ensure that this function is called whenever the language changes. Luckily for us there is an event that is sent whenever a new translation is installed which is called QEvent::LanguageChange so all we need to do is listen for this event which is initially sent to the application object and then passed on to all the widgets in the application. So all that is left to be done is to reimplement event() in the class where we have our retranslateUi() function and listen for that event.

 

	bool MainWindow::event(QEvent *e)
{
if (e->type() == QEvent::LanguageChange)
retranslateUi();
return QMainWindow::event(e);
}

 

And there you have it, whenever a new translation is installed on the QApplication, or when one is removed then it will ensure that the user visible strings are translated again and set again on the appropriate widgets without having to restart the application.

 

Before I sign off for this week, I have a tip that a customer sent in to us that solves a problem that some people have reported to us in the past with regards to font spacing when printing to a PDF file on Windows. So if you are experiencing or run into this then you can do the following to workaround the issue:

 

    font.setHintingPreference(QFont::PreferNoHinting);

 

And this will ensure the text is rendered correctly. Until next time, happy coding! :)


Comments