Qt/C++ - Lesson 049. QTranslator - dynamic translation of multilingual application to Qt

Qt, Linguist, QTranslator

Sooner or later, the developer of Qt applications meets the need multilanguage support of  his application. Then you can to use QTranslator class and Qt Linguist for creating of translations.

QTranslator object class is used to load translation from a special file with the extension .qm, which is a hexadecimal file of translations. This file is compiled from the translation file in XML format, which has the extension .ts and it is prescribed in the project profile. This file contains all of the application line, which were concluded in the tr() function. I recommend describe the entire interface of the application in English, which will be the default language, and translations have to load the desired language from the translation files. If the required translation file is not found, it will automatically be downloaded in English translation. Although you can certainly use another language as the default language.

Translation download Example

The structure of the file name of the translation has an important role in working with QTranslator . Let us see the minimum example.

#include "mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>

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

    QTranslator qtLanguageTranslator;
    qtLanguageTranslator.load(QString("QtLanguage_") + QString("ru_RU"));
    qApp->installTranslator(&qtLanguageTranslator);

    MainWindow w;
    w.show();

    return a.exec();
}

In this example creates a class object QTranslator, in which we will download the file , which is interested for us, indicating the language. In this case, the full name of the file translation following QtLanguage_ru.qm. That is, given the general name for the file transfer QtLanguage, as well as language translation prefix _ru. But you may have noticed that as an argument for using load generated QtLanguage_ru_RU line. This is done in order to determine the proper dialect, such as the US (en_US) or British (en_GB) English. But if in the translation file name is not specified dialect, then the file will be selected without specifying a dialect, for example, QtLanguage_ru.qm.

After the translations file is downloaded, it must be installed in the application. In this case, it uses a global pointer to the application qApp->installTranslator (&qtLanguageTranslator).

Creating a translation file

Once we figured out a way to transfer the minimum settings in the application, let's understand, how do you can create a translation. To create a translation is necessary to use the following functions: tr(), trUtf8 (), translate () in the application, etc. That is, all the text that will require translation is necessary to frame it in those functions, then to create a translation file. Look it might read:

label->setText(QApplication::translate("MainWindow", "Select Language", 0));
label_2->setText(tr("Hello"));
label_3->setText(trUtf8("Hello world"));

Once in the application marked all the necessary lines, you will need to create a translation file, do the translation itself directly and compile the final translation file. To do this, use the following programs:

  1. lupdate - program for the formation of the field of translation TRANSLATIONS pro file in the file and update information on all new lines in applications that require translation.
  2. lrelease - program for the compile of the final translation file to be used in the application.
  3. Qt Linguist - directly the package itself to create translations.

The first step that needs to be done after the application has registered a string requiring translation is to add the file to be translated into pro project file. You may also want to specify the encoding information that is used for the translation.

TRANSLATIONS += QtLanguage_ru.ts

CODECFORSRC     = UTF-8

Next, you need to use a utility to create lupdate QtLanguage_ru.ts file. In Qt Creator, look here: Tools -> External -> Linguist -> lupdate.

lupdate reported the results of the search strings to translate.

Runs an external tool «D:\Qt\5.6\mingw49_32\bin\lupdate.exe» D:/AndroidQT/QTProjects/QtLanguage/QtLanguage.pro
Updating 'QtLanguage_ru.ts'...
    Found 4 source text(s) (0 new and 4 already existing)

«D:\Qt\5.6\mingw49_32\bin\lupdate.exe» completed

Next, open the Qt Linguist make translations all rows, marking, which are translated (This is purely a service information for the translator himself)

After you created the translation, save the file and compile the hex file transfer using the utility lrelease. It can be found in Qt Creator in the same place and lupdate, or run out of Qt Linguist: File -> Release.

For use file will need to place it in a directory with the application's executable file.

Dynamic translation of Application

Loading translation app - it's good, but what if you need to change the dynamic translation? Let's look at a simple example where there QComboBox indicating two languages: English and Russian.

Structure of project

  • QtLanguage.pro -project profile;
  • main.cpp - project file with the main function;
  • mainwindow.h - header file of apllication main window;
  • mainwindow.cpp - source file of main window;
  • mainwindow.ui - form of main window.

mainwindow.ui

I prefer to use a graphic designer to create a GUI application, as it accelerates the development, unless you want something complicated in the appearance of the application, so create a window with the following appearance.

In this window, there are:

  • label
  • label_2
  • comboBox

With the transfer of which we will work. Ease of graphic designer is also the fact that it automatically generates retranslateUi () method, which is used to change the translation of all the signatures that are used in the application, although you can own to register manually a similar method, but personally I do not want to waste time on it, which it may very well be created automatically. For example, in this lesson, it looks as follows:

void retranslateUi(QMainWindow *MainWindow)
{
    MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
    label_2->setText(QApplication::translate("MainWindow", "The QTranslator class provides internationalization support for text output.An object of this class contains a set of translations from a source language to a target language. QTranslator provides functions to look up translations in a translation file. Translation files are created using Qt Linguist.", 0));
    label->setText(QApplication::translate("MainWindow", "Select Language", 0));
} // retranslateUi

QtLanguage.pro

As mentioned above, indicate the name of the translation file in the project profile.

#-------------------------------------------------
#
# Project created by QtCreator 2016-05-22T14:34:42
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = QtLanguage
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

TRANSLATIONS = QtLanguage_ru.ts

CODECFORSRC     = UTF-8

main.cpp

And here in this file will not change anything.

#include "mainwindow.h"
#include <QApplication>

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

    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

In the header of the main window of the application must be declared QTranslator object class and override the method changeEvent (QEvent * event) , which will be determined by the application of language change event.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTranslator>
#include <QEvent>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    // The method of obtaining the events in the main application window
    // In it will be checked events change transfer applications
    void changeEvent(QEvent * event) override;

private:
    Ui::MainWindow *ui;
    QTranslator qtLanguageTranslator;   // Select the translation in a separate field, otherwise it will not work
};

#endif // MAINWINDOW_H

mainwindow.cpp

The logic of the application is as follows: when you change the item in the combo box will change the translation of the application.

Note. Do not forget to put the translation file with the extension qm next to the application's executable file and collect the required dll , otherwise it not will work.

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
#include <QTranslator>
#include <QLibraryInfo>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Set two points with the text of the locales in the combo box
    ui->comboBox->addItems(QStringList() << "ru_RU" << "en_US");

    // connect to the signal change of combo box item 
    // to lambda function that will change application translation 
    // where there is an interesting point. 
    // Since QComboBox has an overload signal signatures, 
    // then we need to cast to the desired signal signature. 
    // In this case, we use the name of the item at its change
    connect(ui->comboBox, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
            [=](const QString &str){
        qtLanguageTranslator.load("QtLanguage_" + str, ".");   // load translation
        qApp->installTranslator(&qtLanguageTranslator);        // Set the translation in the application
    });

    // Make an initial transfer to the initialization of the application window
    qtLanguageTranslator.load(QString("QtLanguage_") + QString("ru_RU"));
    qApp->installTranslator(&qtLanguageTranslator);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *event)
{
    // In the case of events changing the application language
    if (event->type() == QEvent::LanguageChange) {
        ui->retranslateUi(this);    // translate the window again
    }
}

Result

As a result, you will receive an application with support for two languages in its graphical user interface.

Download example of Application with QTranslator

Video lesson

Virtual hosting with 10 percent discount
Virtual hosting with 10 percent discount
EVILEG offers reliable hosting with a 10% discount for virtual hosting and 5% for VPS
Support the author Donate
w

Не работает....

Очень содержательный комментарий. По моему опыту, не работает всегда потому, что кто-то что-то не правильно делает. А в видео показано, что все отлично работает.

АК

А к чему относится такая проблема? Есть QPlainTextEdit. У него есть горячие клавиши. Но они работает только на английском языке : Когда на клавиатуре нажимается ctrl + 'x', горячая клавиша "вырезать" срабатывает. Но при нажатии ctrl + 'ч' не срабатывает. Стоит создать тему на форуме или это что-то само собой разумеющиеся?
Данный код в main.cpp не помог :

    QString translatorFileName = QLatin1String("qt_");
    translatorFileName += QLocale::system().name();
    QTranslator *translator = new QTranslator(&a);
    if (translator->load(translatorFileName, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        a.installTranslator(translator);

А вы случаем не переводили эти сочетания клавиш там, где они устанавливаются? Если где-то есть этот перевод, то есть там подставлена tr() b trUtf8() функция, то могут быть проблемы, лучше те куски кода не оборачивать в функции перевода и не делать перевода, тем более, что это и не нужно. Скорее всего коды клавиш неправильно определяются.

Скачал пример, увы, не работает. Комбобокс исправно пашет, переключения языков нет.

Ещё подскажите, как без шаманства кастования переключать язык? Например, как это обычно бывает, после перезагрузки приложения.

Странно. Должен был бы работать... проверю на досуге.

Вообще сохраняют инфоромацию о языке в QSettings, который нужно установить. Закрывают приложение и после запуска из QSettings подтягивается инофрмация о локализации приложения, после чего загружается требуемый язык.

Если использовать QComboBox для выбора языка, то с новым синтаксисом сигналов и слотов без каста не получится, но можно использовать шаблонный функционал Qt для упрощения работы с сигналами и слотам. Подробнее в этой статье про QOverload

  • #
  • July 13, 2018, 11:55 a.m.
Хорошая статья. Только один вопрос как это сделать для CMake?

Интересует именно запись в CMakeList

  1. TRANSLATIONS += QtLanguage_ru.ts
  2. CODECFORSRC = UTF-8
Пытался так, но не работает и хотя в документации написано так.

file(GLOB TRANSLATION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.ts)

qt5_add_translation(TRANSLATION_QM ${TRANSLATION_FILES})
add_custom_target(translations DEPENDS ${TRANSLATION_QM})
Ругается на
qt5_add_translation
пишет - неизвестная команда.

qt5_create_translation понимает, но ничего не происходит.

У меня на руках есть один проект, где какие-то потуги с переводами и подключением этого добра в CMAKE делались.

Но там файл перевода добавляется прямо в ресурсы проекта. То есть бинарных qm файл переводов добавлялся в qrc файл. То есть при компилировании перевод сохранялся как ресурс, а потом уже из ресурсов забирался.
 
qt5_add_resources(RCC_RESOURCES
        resources/translations.qrc
        )

add_executable({RCC_RESOURCES})
Как понимаю,
qt5_add_translation или qt5_create_translation
Должны ещё создать этот самый бинарный qm файл переводов

Спасибо,  попробую.

Работает так:

find_package (Qt5LinguistTools)
file (GLOB TS_FILES ${SOURCE_DIR}/translations/*.ts)
qt5_add_translation (QM_FILES ${TS_FILES})
add_custom_target (translations ALL DEPENDS ${QM_FILES})
......
add_executable (${PROJECT_NAME} ${SOURCE_FILES} ${HEADER_FILES} ${UI_FILES} ${RESOURCES} ${QM_FILES})

Comments

Only authorized users can post comments.
Please, Log in or Sign up
N
June 25, 2019, 2:41 p.m.
Nico03

C++ - Test 001. The first program and data types

  • Result:40points,
  • Rating points-8
S
June 25, 2019, 9:16 a.m.
SabaNtuy

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:40points,
  • Rating points-8
SZ
June 24, 2019, 5:49 p.m.
Serg Zhi

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
Last comments
June 24, 2019, 10:23 a.m.
Евгений Легоцкой

Хорошо, ну будут проблемы помимо того, что касается статей, то не стесняйтесь задавать вопросы на форуме.
МБ
June 24, 2019, 10:21 a.m.
Михаил Булатов

Извиняюсь, все работает(из-за невнимательности).
June 24, 2019, 9:52 a.m.
Евгений Легоцкой

Придётся делать ещё сигнал в дочернем qml и пробрасывать через коннекты и обработчики. А вообще нужно смотреть конкретный код и что вы пытаетесь сделать. Так что лучше будет, если вы зад...
June 21, 2019, 8:31 a.m.
Ruslan Polupan

Вот моя строка по которой все отлично сработало %cqtdeployer% -bin c:/CentralMposKeys/CentalMposKeys.exe -qmake c:/Qt/5.12.2/mingw73_64/bin/qmake.exe
June 21, 2019, 8:24 a.m.
Андрей Янкович

Возможно кому то пригодится сqtdeployer для windows работает точно так же как и для Linux разница лишь в команде запуска Linux: cqtdeployer Windows: %cqtdeployer...
Now discuss on the forum
June 25, 2019, 6:16 p.m.
Алексей Внуков

только через webengine, прямого апи у Яндекса нет, вроде что-то есть у гугла, сам только начал интересоваться этим вопросом
June 25, 2019, 5:05 p.m.
Михаиллл

Само заработало. Странно.
June 25, 2019, 2:32 p.m.
Михаиллл

Похоже глюк вебсокета. К другим вебсокетам подключаюсь.
June 25, 2019, 1:55 p.m.
Андрей Янкович

падало потому что boolStatus был на стеке метода, после завершения метода переменная убивалась, и на обращении к ней было падение.просто сделай вот так: connect(&t, &QTimer::timeou...
June 25, 2019, 10:55 a.m.
IscanderChe

По пункту 3 попытался переписать метод setData. В итоге комбобокс перестал работать. bool MySqlTableModel::setData(const QModelIndex& index, const QVariant& value, int /* role */){...
Looking for a Job?
10,000.00 руб. - 15,000.00 руб.
Нужен помощник для создания API.
Moscow, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB