How to use translation in Qt? - c++

I'm trying to use Qt's tr() function for translation.
In .pro file I have:
TRANSLATIONS += languages/myapp_en.ts \
languages/myapp_es.ts
and in main.cpp:
QTranslator translator;
translator.load("myapp_es"); //espanol
app.installTranslator(&translator);
I run lupdate and the files myapp_en.ts, myapp_es.ts are generated.
I edit the file myapp_es.ts, for example:
<context>
<name>Example</name>
<message>
<location filename="../example.cpp" line="24"/>
<source>Good night</source>
<translation>Buenas noches</translation> <!-- THIS IS MY EDIT -->
</message>
</context>
Then I run lrelease so the files myapp_en.qm, myapp_es.qm are generated.
Then I use tr() in code like this:
button->setText(tr("Good night"));
inside the constructor of a Q_OBJECT class.
But the text is still showing in English ("Good night"), and not in Spanish.
What am I doing wrong?
Edit:
Putting the *.qm files in the correct directory solved the problem. Just had to make sure it's in the Release directory and not the Debug.

You need to include the extension .qm and correct path when calling translator.load:
QTranslator translator;
translator.load("languages/myapp_es.qm"); //espanol
app.installTranslator(&translator);

after installing translator you have to call retranslate of ui generated class if applied or call tr again

From the other answers I can see that you're now getting true for load, so it's finding the translation file. What it could then be is that you're installing the translation after the system has already initialised the UI, so you can do one of two things:
Install the translator before you create your UI, for me it would go:
translator.load(someTranslation)
a.installTranslator(&translator)
MainWindow w;
Install the translator after you create the UI, which if you're providing multiple language support is most likely where you'll want it. Qt provides a retranslateUi() function, which when called will update the user interface. There's a question here which shows this in more depth: How to translate language in Qt on the fly. There's a bit more code required for handling the language change event, but it does allow for dynamic language updates.

Related

How to use QML_ELEMENT with cmake

The doc shows I can use QML_ELEMENT macro to create QML types from C++ by adding some variables in qmake's .pro file. But I'm using cmake
Update (Qt 6.2+)
As of Qt 6.2, qt_add_qml_module is a single command for building qml modules that should take care of virtually everything, replacing amongst others the old qt6_qml_type_registration command.
Old answer (Qt 6.0/6.1)
Now that Qt 6.0 is out this is supported, albeit poorly documented. What you need now is:
set_target_properties(foo PROPERTIES
QT_QML_MODULE_VERSION 1.0
QT_QML_MODULE_URI Foo
)
qt6_qml_type_registration(foo)
you can then do in qml:
import Foo
and you'll have access to types that have QML_ELEMENT and friends. Notes:
Two files are created in the build output folder, <project>_qmltyperegistrations.cpp and <project>.qmltypes, if your imports are failing you can look at those to see which types are missing. I found that I needed to do full recompiles sometimes after adding/removing registered types.
Qt examples have been migrated to cmake, so take a look at e.g. Examples/Qt-6.0.0/quick/tableview/gameoflife to see it in action
There are now pro2cmake.py and run_pro2cmake.py files in the Qt sources at Qt/6.0.0/Src/qtbase/util/cmake. They are mentioned on this Readme page, you can find them here, haven't tried it myself.
Edit (Qt 6.x)
This answer was originally posted for Qt 5.15. Now that Qt 6 is available, and if you are using Qt 6, refer to the answer from #Adversus.
Original answer (Qt 5.x)
From what I can see, CONFIG += qmltypes, which is required to use QML_ELEMENT, is not yet supported in CMake by looking at the documentation, even for the master branch.
And the efforts to provide a python .pro to cmake converter are for Qt6, not merged, and not functional as far as I can tell, by testing them from util on the wip/cmake branch (the CMakeLists.txt didn't have relevant information).
You can see that the actual conversion script does test for qmltypes presence in CONFIG, but it doesn't seem to map to anything usable for CMake.
Solution
Instead of using QML_ELEMENT and CONFIG += qmltypes, which is brand new from Qt 5.15 (latest when writing this), and not supported at this time with CMake, use the good old qmlRegisterType from C++:
#include "YouCustomCppClass.h"
int main(int argc, char** argv) {
// Let you import it with "import ModuleName 1.0" on the QML side
qmlRegisterType<YouCustomCppClass>("ModuleName", 1, 0, "YourQmlComponent");
//Create your QML view or engine
}
This won't require anything specific on the project file side, as long as your code/plugin executes qmlRegisterType statement.
You can refer to Qt's documentation, same page as yours, but for Qt 5.14 instead of latest, which describes exactly that: Writting QML extensions for C++ | Qt 5.14

Adding multi-language option to a Qt app with hard-coded text

I'm a beginner in Qt. I have an app designed using Qt which has multiple windows with each consisting of several labels with hard coded text. What would be the easiest way to add multi language support for this app? Which built in Qt objects/functions I should use?
My current idea is to maybe create a separate xml file including the text for all labels for a language. Then once the user selects a language icon from the menu, load the relevant xml file. But I have no idea how to do this. Any help would be highly appreciated!
UPDATE:
I have tried to implement the example given here. But it throws the following error and I can't fix it. 'class Ui::MainWindow' has no member named 'menuLanguage'
QActionGroup* langGroup = new QActionGroup(ui->menuLanguage);
Try Qt Linguist:
I made you a simple example:
.pro
TRANSLATIONS += translation_fa.ts
.h
#include <QTranslator>
QTranslator translator;
.cpp
if(translator.load("E:/Qt/Linguist/linguist/translation_fa.qm"))
qDebug()<<"successfully load qm file.";
else
qDebug()<<"problem in load qm file.";
// change language to second language
qApp->installTranslator(&translator);
// change language to default language
qApp->removeTranslator(&translator);
Don't forget to use Qt Linguist Tools.
This is a sample project for your question on github download here.
Qt has translation support. Look into Qt Linguist
Basically, you mark all you hard coded texts with a call to QObject::tr, e.g.
lbl->setText(tr("My text to translate"));
Qt Linguist parses all source files and UI forms for such calls (using lupdate.exe) and builds a ts file. With the Qt Linguist GUI application, you can translate them. With lrelease you create a qm file that will be loaded at runtime, and automatically translate the texts
Qt has built in functions for managing multiple languages:
see: https://wiki.qt.io/How_to_create_a_multi_language_application
Research lupdate lrelease and linguist

How do I create multipul Forms / .ui in qt?

I'm new to qt so this may be a basic question. I want to create multipul ui pages but I don't really know how to do it. I've gone Add New -> C++ Class -> include QWidget. Although this creates new source and header files, it does not create and additional .ui file. I've tried building and running QMake but that hasn't helped. I've also tried adding temperature.ui to the forms section of the .pro files but that just gives me the
":-1: error: No rule to make target 'temperature.ui', needed by 'ui_temperature.h'. Stop." error. Any suggestions? Many thanks
One thing is a C++ Class and another thing is a Qt class. The first one has a *.cpp and a *.h and the second one has, in addition, a *.ui file which contains the ui made with Qt designer.
So that, you need to Add a Designer Form Class instead of a C++ class

wxTextEntryDialog translation of OK and Cancel

I have my application with all the translations working perfectly except the 'OK' and 'Cancel' contained in the wxTextEntryDialog dialog. How can I get these to translate properly? Even the wxMessageBox is working fine when using OK and Cancel but wxTextEntryDialog doesn't just seem to translate to any other language.
I have used the following snippets for the languages assignment within my code:
wxLocale m_locale; // locale we'll be using (this is defined in the header file of my app)
// Within the source
lang = wxLANGUAGE_CHINESE_SIMPLIFIED; // for e.g. could be any language
m_locale.Init(lang);
// normally this wouldn't be necessary as the catalog files would be found in the default locations, but when the program is not installed the
// catalogs are in the build directory where we wouldn't find them by default
wxLocale::AddCatalogLookupPathPrefix(wxT(LanguagePath));// add path of install
// Initialize the catalogs we'll be using
m_locale.AddCatalog(_("messages")); // .mo file generated by my application language specific .mo file
Thanks in advance for any help.
Does your call to Init() succeed? You should really check for its return value, it's possible that it doesn't find wxstd.mo, which contains translations for all the messages used inside wxWidgets, because you call it before setting the lookup path. You need to
Ensure that wxstd.mo is available in your catalog path.
Call Init() after setting this path.
Check its return value.
Thanks #VZ. for the insight. Your approach helped me debug my application better i.e. I was able to see that the Init() did not succeed by checking the return value. With this I was able to investigate further. Also, the wxstd.mois just the default .po generated .mo (not translated so why would I require this?)
Solution: I had to add the wxWidgets translation files i.e. the .mo generated catalog files from the .po files contained in the <wxdir>/locale/. I had to copy them to the same directories as my messages.mo. Hence, the working code looks like this for Simplified chinese.
wxLocale m_locale; // locale we'll be using (this is defined in the header file of my app)
// Within the source
lang = wxLANGUAGE_CHINESE_SIMPLIFIED; // for e.g. could be any language
wxLocale::AddCatalogLookupPathPrefix(wxT(LanguagePath));// add path of install
m_locale.Init(lang, wxLOCALE_CONV_ENCODING);
m_locale.AddCatalog(wxT("zh_CN")); // This is the .mo file I generated from the wxWidgets .po files
// Initialize the catalogs we'll be using
m_locale.AddCatalog(_("messages")); // .mo file generated by my application language specific .mo file
I did not include the checks for a purpose because I want the application to run in english even if the language is not supported but I did use it for debugging

Qt Resource Files don't update without compiling

I am making a C++ application, and I created a function that will apply a stylesheet from a css file. This is the method:
void MainWindow::load_css_file() {
QFile styleFile(":/light_style_css");
styleFile.open(QFile::ReadOnly);
QString styleSheet = styleFile.readAll();
setStyleSheet(styleSheet);
};
This works fine, except for the fact that I need to run "make" every time I make a change to "light_style_css" (which is an alias for a css file in my project resource file).
But, when I change the method to something like this:
void MainWindow::load_css_file() {
QFile styleFile("../stylesheets/light_style.css");
styleFile.open(QFile::ReadOnly);
QString styleSheet = styleFile.readAll();
setStyleSheet(styleSheet);
};
I can make changes to the file, and the program updates without having to run "make" for the changes to take place.
Is there a way, that I can use the resource system, without having to run "make" for the changes to take place?
This is my resource file:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="light_style_css">stylesheets/light_style.css</file>
</qresource>
</RCC>
Simply said: no, you can't.
Resources are built into your executable. If you want to change them, you need to rebuild the executable.
Your second method reads the file from disk, so it doesn't have that behavior.
If this is a real problem for you, give the possibility to pass in the stylesheet as an argument on the command line, and default to the resource. That way you can debug the stylesheet as much as you want without recompiling every time. Rebuild once it's satisfactory (and before you ship!).
We do the following solution in our project (I can't provide code because of company policies):
First, we build all resources to separate binary .rcc file. It is not necessary, but helpful.
Second, In release builds we always load resources from the Qt resource system.
Third, only in debug builds:
We check the resource folder for a main.qss file.
If it exists: we open it and replace all :/ with ./resource/ string, then apply it
If it doesn't exist: we load resources as in the release version.