I am looking for a relatively minimal example how to dynamically translation. I am creating a tutorial on using the Qt resource system along with UI and TS files. For this purpose I've created a basic UI form:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>widget_form</class>
<widget name="widget_form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>860</width>
<height>527</height>
</rect>
</property>
<property name="windowTitle">
<string>Get Started</string>
</property>
<layout name="verticalLayout_2">
<item>
<layout name="horizontalLayout_2">
<item>
<widget name="btn_import_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/import);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_check_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/check);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_delete_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/delete);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_add_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/add);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="cb_change_lang">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout name="horizontalLayout">
<item>
<widget name="pte_file_view">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget name="vline_right">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout name="verticalLayout">
<item>
<widget name="btn_csv">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/csv);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_code">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/code);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_json">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/json);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_xml">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/xml);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections/>
</ui>
which I add to a QRC file along with a bunch of images that I use as icons:
<RCC>
<qresource prefix="icons/files">
<file alias="xml">icons/file-formats/icons8-xml-96.png</file>
<file alias="json">icons/file-formats/icons8-json-96.png</file>
<file alias="csv">icons/file-formats/icons8-csv-96.png</file>
<file alias="code">icons/file-formats/icons8-code-96.png</file>
</qresource>
<qresource prefix="icons/files">
<file alias="import">icons/file-ops/icons8-import-96.png</file>
<file alias="delete">icons/file-ops/icons8-delete-file-96.png</file>
<file alias="check">icons/file-ops/icons8-check-file-96.png</file>
<file alias="add">icons/file-ops/icons8-add-file-96.png</file>
</qresource>
<qresource prefix="icons/flags">
<file alias="fr">icons/flags/icons8-france-80.png</file>
<file alias="de">icons/flags/icons8-germany-80.png</file>
<file alias="gb">icons/flags/icons8-great-britain-80.png</file>
<file alias="ru">icons/flags/icons8-russian-federation-80.png</file>
</qresource>
<qresource prefix="forms">
<file alias="main">ui/widget.ui</file>
</qresource>
</RCC>
I manage my project with the following CMakeLists.txt
:
cmake_minimum_required(VERSION 3.13)
project(ExampleGetStarted LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
find_package(Qt5
COMPONENTS
Widgets
Xml
XmlPatterns
Concurrent
UiTools
LinguistTools
REQUIRED
)
#find_package(Qt5XmlPatterns REQUIRED)
# TODO https://stackoverflow.com/questions/51217734/how-to-add-qt-translations-to-cmake
set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources/resources.qrc)
set(TS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/resources/translations)
qt5_create_translation(TS_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_DIR}/en.ts ${TS_DIR}/de.ts)
#qt5_add_translation(TS_FILES_FINISHED ${TS_DIR}/en.ts ${TS_DIR}/de.ts)
# TODO Convert configure_file to custom post-build action. QM files are initially not available
#configure_file(${QM_FILES} ${CMAKE_BINARY_DIR} COPYONLY)
#qt5_add_translation(QM_FILES ${TS_FILES})
add_executable(example_get_started
example_get_started.cpp
${RESOURCES}
${TS_FILES}
)
target_link_libraries(example_get_started
Qt5::Widgets
Qt5::Xml Qt5::XmlPatterns
Qt5::Concurrent
Qt5::UiTools
#Qt5::LinguistTools
)
# Copy translations to binary directory where executable can access thoses
foreach(TS_FILE ${TS_FILES})
add_custom_command(
TARGET example_get_started POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${TS_FILE}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMENT "Copied ${TS_FILE} to binary directory"
)
endforeach(TS_FILE)
The UI form is loaded with the following code (work in progress):
#include <vector>
#include <utility>
#include <iostream>
#include <QApplication>
#include <QtWidgets>
#include <QtUiTools>
#include <QFile>
#include <QTranslator>
QScopedPointer<QTranslator> translator(new QTranslator());
static QWidget *loadUiFile(QWidget *parent)
{
QFile file(":/forms/main");
file.open(QIODevice::ReadOnly);
QUiLoader loader;
return loader.load(&file, parent);
}
static void retranslate(QString lang_code)
{
std::cout << "Translating to " << lang_code.toStdString() << std::endl;
std::cout << "Looking into directory \"" << QApplication::applicationDirPath().toStdString() << "\"" << std::endl;
if (lang_code == QString("fr"))
{
if (translator->load("fr", QApplication::applicationDirPath()))
{
QApplication::instance()->installTranslator(translator.data());
std::cout << "Switched to " << lang_code.toStdString() << std::endl;
}
else
std::cout << "Unable to load translation for " << lang_code.toStdString() << std::endl;
}
else if (lang_code == QString("de"))
{
if (translator->load("de", QApplication::applicationDirPath()))
{
QApplication::instance()->installTranslator(translator.data());
std::cout << "Switched to " << lang_code.toStdString() << std::endl;
}
else
std::cout << "Unable to load translation for " << lang_code.toStdString() << std::endl;
}
else if (lang_code == QString("ru"))
{
if (translator->load("ru", QApplication::applicationDirPath()))
{
QApplication::instance()->installTranslator(translator.data());
std::cout << "Switched to " << lang_code.toStdString() << std::endl;
}
else
std::cout << "Unable to load translation for " << lang_code.toStdString() << std::endl;
}
else
{
QApplication::instance()->removeTranslator(translator.data());
}
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Translations need to be created before widgets they affect
/*
if (!translator->load("en_GB.qm"))
std::cout << "Unable to load translation file \"en_GB\"" << std::endl;
app.installTranslator(translator.data());
if (!translator->load("de_DE.qm"))
std::cout << "Unable to load translation file \"de_DE\"" << std::endl;
app.installTranslator(translator.data());
std::cout << translator->language().toStdString() << std::endl;
*/
QWidget *widget = loadUiFile(nullptr);
widget->findChild<QPushButton *>("btn_add_file")->setToolTip(QObject::tr("Create a new file"));
widget->findChild<QPushButton *>("btn_check_file")->setToolTip(QObject::tr("Check the opened file's contents for errors"));
widget->findChild<QPushButton *>("btn_delete_file")->setToolTip(QObject::tr("Deletes the opened file's contents"));
widget->findChild<QPushButton *>("btn_import_file")->setToolTip(QObject::tr("Import existing file"));
QComboBox *cb_change_lang = widget->findChild<QComboBox *>("cb_change_lang");
std::vector<std::pair<QString, QIcon>> langs = {
std::pair<QString, QIcon>(QObject::tr("English (en)"), QIcon(":/icons/flags/gb")),
std::pair<QString, QIcon>(QObject::tr("Deutsch (de)"), QIcon(":/icons/flags/de")),
std::pair<QString, QIcon>(QObject::tr("Français (fr)"), QIcon(":/icons/flags/fr")),
std::pair<QString, QIcon>(QObject::tr("Руский (ru)"), QIcon(":/icons/flags/ru"))};
auto lang_idx = 0;
for (auto lang : langs)
{
cb_change_lang->insertItem(lang_idx, lang.first);
cb_change_lang->setItemIcon(lang_idx, lang.second);
lang_idx ;
}
QRegularExpression regex("\\(([^()] )\\)");
QObject::connect(cb_change_lang,
qOverload<int>(&QComboBox::currentIndexChanged),
[=](int idx)
{
retranslate(regex.match(langs.at(cb_change_lang->currentIndex()).first).captured(1));
});
std::cout << regex.match(langs.at(cb_change_lang->currentIndex()).first).captured(1).toStdString() << std::endl;
widget->show();
return app.exec();
}
The widget looks like this:
I would like to keep the creation of my widget as it is (UI file loaded in C and some extra functionality added to it). The reason why my QTranslator
is a global is because of that plus the fact that a translator needs to live as long as QApplication
's instance is alive.
The way it's supposed to work (but currently is not) is for the tooltips of each button to be translated whenever the currently selected item inside the QComboBox
(top right corner in the screenshot) is changed. I am very new to the translation facilities of Qt and the documentation is not really stellar in this regard (personal opinion here).
Before I started working on the dynamic translation, I loaded one of the QM files inside my main()
and it worked - the tooltips were in the language the QM file was made for. Only after adding the new functionality I don't see any change.
CodePudding user response:
I searched around and also asked in the official Qt forum. Some of the tips I was given made me rework my code:
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(ExampleGetStarted LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt5
COMPONENTS
Core
Widgets
Xml
XmlPatterns
Concurrent
UiTools
LinguistTools
REQUIRED
)
set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources/resources.qrc)
set(TS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/resources/translations)
qt5_create_translation(TS_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_DIR}/en.ts ${TS_DIR}/de.ts ${TS_DIR}/fr.ts ${TS_DIR}/ru.ts)
add_executable(example_get_started
example_get_started.cpp
${RESOURCES}
${TS_FILES}
)
target_link_libraries(example_get_started
Qt5::Core
Qt5::Widgets
Qt5::Xml Qt5::XmlPatterns
Qt5::Concurrent
Qt5::UiTools
)
# Copy translations to binary directory where executable can access these
foreach(TS_FILE ${TS_FILES})
add_custom_command(
TARGET example_get_started POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${TS_FILE}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMENT "Copied ${TS_FILE} to binary directory"
)
endforeach(TS_FILE)
CPP file
#include <vector>
#include <utility>
#include <QApplication>
#include <QtWidgets>
#include <QtUiTools>
#include <QFile>
#include <QTranslator>
#include <QDebug>
// Needs to be included so that the header file is generated. Note that if the UI file is in a subdirectory, that also needs to be specified here
#include "resources/ui/ui_widget.h"
QScopedPointer<QTranslator> translator(new QTranslator());
class MainWidget : public QWidget
{
Q_OBJECT
Ui::widget_form *ui;
QString lang_curr = "en";
public:
MainWidget(QWidget* parent=nullptr)
: QWidget(parent),
ui(new Ui::widget_form)
{
ui->setupUi(this);
QRegularExpression regex("\\(([^()] )\\)");
QObject::connect(ui->cb_change_lang,
qOverload<int>(&QComboBox::currentIndexChanged),
[=](int idx)
{
retranslate(regex.match(ui->cb_change_lang->currentText()).captured(1));
});
}
~MainWidget()
{
delete ui;
}
protected:
void changeEvent(QEvent *event) override
{
if (event->type() == QEvent::LanguageChange)
{
ui->retranslateUi(this);
}
return QWidget::changeEvent(event);
}
private:
void retranslate(QString lang_code)
{
if (lang_code == QString("fr"))
{
if (translator->load("fr", QApplication::applicationDirPath()))
{
QApplication::instance()->removeTranslator(translator.data());
QApplication::instance()->installTranslator(translator.data());
lang_curr = lang_code;
}
else
qDebug() << "Unable to load translation for " << lang_code;
}
else if (lang_code == QString("de"))
{
if (translator->load("de", QApplication::applicationDirPath()))
{
QApplication::instance()->removeTranslator(translator.data());
QApplication::instance()->installTranslator(translator.data());
lang_curr = lang_code;
}
else
qDebug() << "Unable to load translation for " << lang_code;
}
else if (lang_code == QString("ru"))
{
if (translator->load("ru", QApplication::applicationDirPath()))
{
QApplication::instance()->removeTranslator(translator.data());
QApplication::instance()->installTranslator(translator.data());
lang_curr = lang_code;
}
else
qDebug() << "Unable to load translation for " << lang_code;
}
else
{
if (translator->load("en", QApplication::applicationDirPath()))
{
QApplication::instance()->removeTranslator(translator.data());
QApplication::instance()->installTranslator(translator.data());
lang_curr = lang_code;
}
else
qDebug() << "Unable to load translation for " << lang_code;
}
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWidget mw;
mw.show();
return app.exec();
}
#include "example_get_started.moc"
XML UI form file
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>widget_form</class>
<widget name="widget_form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>860</width>
<height>527</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Get Started</string>
</property>
<layout name="verticalLayout_2">
<item>
<layout name="horizontalLayout_2">
<item>
<widget name="btn_create_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Create a new file</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/create);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_import_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Import existing file</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/import);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_delete_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Delete the opened file's contents</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/delete);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_check_file">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Check the opened file's contents for errors</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/check);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="cb_change_lang">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<item>
<property name="text">
<string>English (en)</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/flags/gb</normaloff>:/icons/flags/gb</iconset>
</property>
</item>
<item>
<property name="text">
<string>Deutsch (de)</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/flags/de</normaloff>:/icons/flags/de</iconset>
</property>
</item>
<item>
<property name="text">
<string>Français (fr)</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/flags/fr</normaloff>:/icons/flags/fr</iconset>
</property>
</item>
<item>
<property name="text">
<string>Руский (ru)</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/flags/ru</normaloff>:/icons/flags/ru</iconset>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout name="horizontalLayout">
<item>
<widget name="pte_file_view">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget name="vline_right">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout name="verticalLayout">
<item>
<widget name="btn_csv">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Create CSV file</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/csv);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_code">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Create script file</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/code);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_json">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Create JSON file</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/json);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget name="btn_xml">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Create XML file</string>
</property>
<property name="styleSheet">
<string notr="true">image: url(:/icons/files/xml);</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections/>
</ui>
What I did is:
Replace the
QUiLoader
with the standard way of loading the UI form file, which I have more experience with (I have very little experience with UI forms in general :D)Moved all the tooltips I was setting in the source code to the UI form file - more or that in the next point
Added
changeEvent()
to the widget in the source coded that use the UI form file - by handling theQEvent::LanguageChanged
and using this way of loading the UI one gets access to theretranslateUi()
function. This function is automatically generated when the header (hereui_widget.h
) that represents the UI form file is generated. The function makes it possible to automatically retranslate all strings marked as translatable (in Qt Designer this is thetranslateable
checkbox). Initially (before previous point) I saw thatretranslateUi()
does not include any of my tooltips. Apparently mixing strings in source code with UI form strings doesn't work as I thought it will. By moving the tooltips to the UI form file I got from the initialvoid retranslateUi(QWidget *widget_form) { btn_create_file->setText(QString()); btn_import_file->setText(QString()); btn_delete_file->setText(QString()); btn_check_file->setText(QString()); cb_change_lang->setItemText(0, QCoreApplication::translate("widget_form", "English (en)", nullptr)); cb_change_lang->setItemText(1, QCoreApplication::translate("widget_form", "Deutsch (de)", nullptr)); cb_change_lang->setItemText(2, QCoreApplication::translate("widget_form", "Fran\303\247ais (fr)", nullptr)); cb_change_lang->setItemText(3, QCoreApplication::translate("widget_form", "\320\240\321\203\321\201\320\272\320\270\320\271 (ru)", nullptr)); btn_csv->setText(QString()); btn_code->setText(QString()); btn_json->setText(QString()); btn_xml->setText(QString()); (void)widget_form; } // retranslateUi
to
void retranslateUi(QWidget *widget_form) { #if QT_CONFIG(tooltip) btn_create_file->setToolTip(QCoreApplication::translate("widget_form", "Create a new file", nullptr)); #endif // QT_CONFIG(tooltip) btn_create_file->setText(QString()); #if QT_CONFIG(tooltip) btn_import_file->setToolTip(QCoreApplication::translate("widget_form", "Import existing file", nullptr)); #endif // QT_CONFIG(tooltip) btn_import_file->setText(QString()); #if QT_CONFIG(tooltip) btn_delete_file->setToolTip(QCoreApplication::translate("widget_form", "Delete the opened file's contents", nullptr)); #endif // QT_CONFIG(tooltip) btn_delete_file->setText(QString()); #if QT_CONFIG(tooltip) btn_check_file->setToolTip(QCoreApplication::translate("widget_form", "Check the opened file's contents for errors", nullptr)); #endif // QT_CONFIG(tooltip) btn_check_file->setText(QString()); cb_change_lang->setItemText(0, QCoreApplication::translate("widget_form", "English (en)", nullptr)); cb_change_lang->setItemText(1, QCoreApplication::translate("widget_form", "Deutsch (de)", nullptr)); cb_change_lang->setItemText(2, QCoreApplication::translate("widget_form", "Fran\303\247ais (fr)", nullptr)); cb_change_lang->setItemText(3, QCoreApplication::translate("widget_form", "\320\240\321\203\321\201\320\272\320\270\320\271 (ru)", nullptr)); #if QT_CONFIG(tooltip) btn_csv->setToolTip(QCoreApplication::translate("widget_form", "Create CSV file", nullptr)); #endif // QT_CONFIG(tooltip) btn_csv->setText(QString()); #if QT_CONFIG(tooltip) btn_code->setToolTip(QCoreApplication::translate("widget_form", "Create script file", nullptr)); #endif // QT_CONFIG(tooltip) btn_code->setText(QString()); #if QT_CONFIG(tooltip) btn_json->setToolTip(QCoreApplication::translate("widget_form", "Create JSON file", nullptr)); #endif // QT_CONFIG(tooltip) btn_json->setText(QString()); #if QT_CONFIG(tooltip) btn_xml->setToolTip(QCoreApplication::translate("widget_form", "Create XML file", nullptr)); #endif // QT_CONFIG(tooltip) btn_xml->setText(QString()); (void)widget_form; } // retranslateUi
Note: I forgot to mark the combobox items as not translatable so that's why those are present here. It's considered generally a good practice to put the language names in their original language and for those to remain invariant to the change in the locale since otherwise users will be confused (not knowing English but wanting to switch to Chinese with the language name written in English is a guarantee for poor UX).
So the final results is (used Google Translate for French and Russian :P)