The Qt framework supports internationalization (I18N) and you can easily use it to your applications with a little effort. So, in this article I’ll show you how you can make it happen in a simple Qt application. The first thing you should do is making the GUI of the application translation-aware. That means setting all the texts you want of your widgets to be translatable. From the Qt Designer you can make translation-aware all your widgets. Here is an image that shows you how you can make the text of a QPushButton instance to be translation-aware :

After you make all the texts from your GUI widgets translatable you can go and make also translatable all your strings that are not accessible from the Qt Designer. To achieve this you should pass each string as a parameter to the Qt tr() method.

Here is some examples :

QString example1 = tr ("Example");

QString example2 = tr ("Cannot load image: '%1'").arg (fileName);

QString example3 = tr ("Var 1: '%1', Var 2: '%2'").arg (var1, var2);

QLabel * labelName = new QLabel (tr ("Name:"));

In this step you can extract all your GUI texts and application strings in translation files and give these to your translator to do his job. The tool lupdate is used to extract all the GUI texts from the forms and any other strings used with the tr() method, in readable translation XML files. This tool also synchronizes the translation files with any other changes that happen during the development. After the translation is finished by the translator you can use the tool lrelease to output the machine object translation files which can be loaded by the application in runtime. The translation most of the times is performed with Qt Linquist.

For lupdate to work successfully, it must know which translation files to produce. The files are simply listed in the application’s .pro Qt project file. Also, if your sources contain genuine non-Latin1 strings, lupdate needs to be told about it in the .pro file.

Here is how you do it :

TARGET = ApplicationName
TRANSLATIONS = $${TARGET}_el_GR.ts $${TARGET}_fr.ts
CODECFORSRC = UTF-8

Please take account that lupdate and lrelease can be called directly from the Qt Creator menu :

Tools -> External -> Linquist -> a) lupdate
                                 b) lrelease

After you call  lrelease and outputs the machine object translation files, add these in the correct path :

.
├── ApplicationName
└── Resources
    └── Translations
        ├── ApplicationName_el_GR.qm
        └── ApplicationName_fr.qm

Next step is to load the appropriate translation file programmatically. I have created the I18N class that loads from your translations resources the appropriate machine object translation file according to the current locale of the operating system.

You have just to use it to do your job 🙂

Here is an example of a Qt application that uses it :

#include <QApplication>

#include "GlobalDeclarations.h"
#include "MainWindow.h"
#include "I18N.h"

int main (int argc, char * argv[])
{
    QApplication application (argc, argv);

    application.setApplicationName (APPLICATION_NAME);
    application.setApplicationVersion (APPLICATION_VERSION);
    application.setOrganizationName (ORGANIZATION_NAME);

    I18N i18n (TRANSLATIONS_PATH, APPLICATION_ENCODING);

    i18n.translate ();

    MainWindow window;

    window.show ();

    return application.exec ();
}

Here is the “GlobalDeclarations.h” file:

#ifndef _GLOBAL_DECLARATIONS_H
#define _GLOBAL_DECLARATIONS_H

#include <QString>

const QString APPLICATION_NAME = "ApplicationName";
const QString APPLICATION_VERSION = "1.0";
const QString APPLICATION_ENCODING = "UTF-8";
const QString ORGANIZATION_NAME = "OrganizationName";
const QString TRANSLATIONS_PATH = "Resources/Translations";

#endif // _GLOBAL_DECLARATIONS_H

Follows the interface of the I18N class :

#ifndef _I18N_H
#define _I18N_H

#include <QTranslator>

class I18N
{
    public:
        I18N ();

        ~I18N ();

        I18N (const QString & path, const QString & encoding);

        void setPath (const QString & path);
        void setEncoding (const QString & encoding);

        QString getPath ();
        QString getEncoding ();

        void translate ();

    private:
        QString _path, _encoding;

        QTranslator _apTranslator, _qtTranslator;
};

#endif // _I18N_H

Here is the implementation of I18N class :

#include <QCoreApplication>
#include <QLibraryInfo>
#include <QTextCodec>
#include <QLocale>

#include "I18N.h"

I18N::~I18N ()
{
}

I18N::I18N ()
{
}

I18N::I18N (const QString & path, const QString & encoding)
{
    _path = path;
    _encoding = encoding;
}

void I18N::setEncoding (const QString & encoding)
{
    _encoding = encoding;
}

void I18N::setPath (const QString & path)
{
    _path = path;
}

QString I18N::getEncoding ()
{
    return _encoding;
}

QString I18N::getPath ()
{
    return _path;
}

void I18N::translate ()
{
    QTextCodec::setCodecForCStrings (
      QTextCodec::codecForName (_encoding.toAscii ())
    );

    QTextCodec::setCodecForTr (
      QTextCodec::codecForName (_encoding.toAscii ())
    );

    _apTranslator.load (
      QCoreApplication::applicationName () + "_" + QLocale::system ().name (),
      QCoreApplication::applicationDirPath () + "/" + _path
    );

    _qtTranslator.load (
      "qt_" + QLocale::system ().name (),
      QLibraryInfo::location (QLibraryInfo::TranslationsPath)
    );

    QCoreApplication::installTranslator (&_apTranslator);
    QCoreApplication::installTranslator (&_qtTranslator);
}

Please take account that I18N class tries to install also a translator for Qt text messages as well.