Qt Translation text not loading
-
Hello, i've a qt project in which i'm trying to load a qm translation file, i've specified around 150 translation in it, but only few widgets are getting translated, is there something i'm missing, Currently using Qt 5.15.2 with Mingw 32 bit toolkit, ts file was generated using linguist 5.15.2 mingw32 bit,
Code Snippet for loading
static int prevIndex = ENGLISH; static QTranslator langObj; static QCoreApplication *appObj = QCoreApplication::instance(); if(prevIndex != index){ if(index == ENGLISH){ }else if(index == ARMENIAN){ // QString armenianLangPath = appObj->applicationDirPath()+"/languages/armenia.qm"; langObj.load(":/languages/armenia.qm"); appObj->installTranslator(&langObj); qDebug()<<appObj->applicationDirPath(); } } prevIndex = index;
And in ChangeEvent following code
if (event->type() == QEvent::LanguageChange){ QList<QPushButton*> btnList = this->findChildren<QPushButton*>(); for (int i = 0; i < btnList.count(); ++i) { qDebug()<<btnList.at(i)->objectName()<<btnList.at(i)->text()<<tr(btnList.at(i)->text().toStdString().c_str()); } }else{ QWidget::changeEvent(event); }
Am i missing something while loading the translation??
-
Hello, i've a qt project in which i'm trying to load a qm translation file, i've specified around 150 translation in it, but only few widgets are getting translated, is there something i'm missing, Currently using Qt 5.15.2 with Mingw 32 bit toolkit, ts file was generated using linguist 5.15.2 mingw32 bit,
Code Snippet for loading
static int prevIndex = ENGLISH; static QTranslator langObj; static QCoreApplication *appObj = QCoreApplication::instance(); if(prevIndex != index){ if(index == ENGLISH){ }else if(index == ARMENIAN){ // QString armenianLangPath = appObj->applicationDirPath()+"/languages/armenia.qm"; langObj.load(":/languages/armenia.qm"); appObj->installTranslator(&langObj); qDebug()<<appObj->applicationDirPath(); } } prevIndex = index;
And in ChangeEvent following code
if (event->type() == QEvent::LanguageChange){ QList<QPushButton*> btnList = this->findChildren<QPushButton*>(); for (int i = 0; i < btnList.count(); ++i) { qDebug()<<btnList.at(i)->objectName()<<btnList.at(i)->text()<<tr(btnList.at(i)->text().toStdString().c_str()); } }else{ QWidget::changeEvent(event); }
Am i missing something while loading the translation??
Hi and welcome to devnet,
You are missing re-applying the texts of your controls.
-
@SGaist Hello , thanks,
I tried that, but still some text are not translating, thats why i was trying to check the data using qDebug, but in qDebug also same result is seen.if (event->type() == QEvent::LanguageChange){ QList<QPushButton*> btnList = this->findChildren<QPushButton*>(); for (int i = 0; i < btnList.count(); ++i) { QString currText = btnList.at(i)->text(); btnList.at(i)->setText(tr(currText.toStdString().c_str())); qDebug()<<btnList.at(i)->objectName()<<btnList.at(i)->text()<<tr(btnList.at(i)->text().toStdString().c_str()); } }else{ QWidget::changeEvent(event); }
-
@SGaist Hello , thanks,
I tried that, but still some text are not translating, thats why i was trying to check the data using qDebug, but in qDebug also same result is seen.if (event->type() == QEvent::LanguageChange){ QList<QPushButton*> btnList = this->findChildren<QPushButton*>(); for (int i = 0; i < btnList.count(); ++i) { QString currText = btnList.at(i)->text(); btnList.at(i)->setText(tr(currText.toStdString().c_str())); qDebug()<<btnList.at(i)->objectName()<<btnList.at(i)->text()<<tr(btnList.at(i)->text().toStdString().c_str()); } }else{ QWidget::changeEvent(event); }
Write a single function that sets the texts on your widget's controls.
Call it from your constructor and from the changeEvent method.
What you are retrieving here is the already translated text and that's not what you want.
-
Hi @AkashPatel28,
I'm not sure exactly where the issue lies, but here's a few observations... (and suspect #2 is the key?).
- As @SGaist said, you don't seem to be actually assigning the newly-translated text/s. You should have something like:
btnList.at(i).setText(tr(...));
- The contents of your
tr()
call within thechangeEvent
handler will not be translated, because that line will not exist in your translations file. Let me explain...
Let's say one of you buttons was created like (I'm adding preceding line numbers):
27: auto btn = new QPushButton(tr("MyButton))";
Then your
changeEvent
does:90: // if, for, etc { 91: btnList.at(i).setText(tr(btnList.at(i)->text().toStdString().c_str())); 92: }
The, your translations
*.ts
file will include:- one entry for line 27, listing the translation for "MyButton"; and
- most likely nothing for line 91. But if (unlikely) it has any entry for line 91, it will be a translation for "btnList.at(i)->text().toStdString().c_str()" - which wouldn't make sense.
So, when your application first initialises the button, if there's a translation for (line 27) "MyButton", then it will be used. When the
changeEvent
occurs, it will try to translate frombtnList.at(i)->text().toStdString().c_str()
- which makes no sense, so I dare say thelupdate
tool never put that line into your*.ts
file - it skips lots of stuff like this.(Hint, have a look into the
*.ts
file - its just XML)Also, if
tr()
was acting on the content of the button's text (which it isn't) then if the language is change more than once, then you'd need translations from every language to every language, instead of just from one "source" language to all others.The correct way to do this, would be to the initialisation, and re-setting into a common place. eg
MyWidget::MyWidget(...) { myButton = new QPushButton(this); setButtonText(); } MyWidget::setButtonText() { myButton.setText(tr("MyButton")); } MyWidget::changeEvent(...) { ... setButtonText(); }
That way all the translations for that button appear in one line, which
lupdate
will process correctly.-
You shouldn't need to iterate all of the children in
changeEvent
. QWidget is already doing that internally - propagating that particular event to all children. So you just need to handle the current widget, and let the super implementation do the rest. -
All of the
QCoreApplication
functions you are calling (at least in the code shown) are static. So don't save a pointer toQCoreApplication::instance()
, just use the static calls, likeQCoreApplication::applicationDirPath()
andQCoreApplication::installTranslator()
. Also, you should check thatQTranslation::load()
actually returnstrue
. -
You don't need to keep re-installing the same
QTranslator
object.QCoreApplication::installTranslator()
is actually prepending the same pointer to a list every time you call it. A more typical pattern would be to simply load all translations as different translator objects, and this is usually done before the application is shown. However, you might not want to do that if you have tight memory constraints, or don't know in advance which translations are available?
I would say #1 and #2 are the ones to focus on to begin with. #3 might taking a little exploring. #4 is just clean-up, but probably not your immediate concern. And #5 might take a little more info to understand your use case better, but look into the first three first :)
Cheers.
-
Hi @AkashPatel28,
I'm not sure exactly where the issue lies, but here's a few observations... (and suspect #2 is the key?).
- As @SGaist said, you don't seem to be actually assigning the newly-translated text/s. You should have something like:
btnList.at(i).setText(tr(...));
- The contents of your
tr()
call within thechangeEvent
handler will not be translated, because that line will not exist in your translations file. Let me explain...
Let's say one of you buttons was created like (I'm adding preceding line numbers):
27: auto btn = new QPushButton(tr("MyButton))";
Then your
changeEvent
does:90: // if, for, etc { 91: btnList.at(i).setText(tr(btnList.at(i)->text().toStdString().c_str())); 92: }
The, your translations
*.ts
file will include:- one entry for line 27, listing the translation for "MyButton"; and
- most likely nothing for line 91. But if (unlikely) it has any entry for line 91, it will be a translation for "btnList.at(i)->text().toStdString().c_str()" - which wouldn't make sense.
So, when your application first initialises the button, if there's a translation for (line 27) "MyButton", then it will be used. When the
changeEvent
occurs, it will try to translate frombtnList.at(i)->text().toStdString().c_str()
- which makes no sense, so I dare say thelupdate
tool never put that line into your*.ts
file - it skips lots of stuff like this.(Hint, have a look into the
*.ts
file - its just XML)Also, if
tr()
was acting on the content of the button's text (which it isn't) then if the language is change more than once, then you'd need translations from every language to every language, instead of just from one "source" language to all others.The correct way to do this, would be to the initialisation, and re-setting into a common place. eg
MyWidget::MyWidget(...) { myButton = new QPushButton(this); setButtonText(); } MyWidget::setButtonText() { myButton.setText(tr("MyButton")); } MyWidget::changeEvent(...) { ... setButtonText(); }
That way all the translations for that button appear in one line, which
lupdate
will process correctly.-
You shouldn't need to iterate all of the children in
changeEvent
. QWidget is already doing that internally - propagating that particular event to all children. So you just need to handle the current widget, and let the super implementation do the rest. -
All of the
QCoreApplication
functions you are calling (at least in the code shown) are static. So don't save a pointer toQCoreApplication::instance()
, just use the static calls, likeQCoreApplication::applicationDirPath()
andQCoreApplication::installTranslator()
. Also, you should check thatQTranslation::load()
actually returnstrue
. -
You don't need to keep re-installing the same
QTranslator
object.QCoreApplication::installTranslator()
is actually prepending the same pointer to a list every time you call it. A more typical pattern would be to simply load all translations as different translator objects, and this is usually done before the application is shown. However, you might not want to do that if you have tight memory constraints, or don't know in advance which translations are available?
I would say #1 and #2 are the ones to focus on to begin with. #3 might taking a little exploring. #4 is just clean-up, but probably not your immediate concern. And #5 might take a little more info to understand your use case better, but look into the first three first :)
Cheers.
Hi @Paul-Colby , point #1 wasnt working, so i tried printing the text in change event to see if i'm seeing translation result, in there i only saw few translation.
point #2 buttons are created in UI file, and text is set via there only, text is not changed during runtime, when i opened ts file, i saw translation string for the button , but when i'm trying to load its not loading. i've attached a small snippet from ts file, but when i'm printing in point #1, i'm not seeing translation for it.
point #3 i'll try this and report back.
point #4 Thanks i'll correct that , when i check return value of load its returning true.
point #5 I'll update this as wellThanks for details explaination
-
Hi @Paul-Colby , point #1 wasnt working, so i tried printing the text in change event to see if i'm seeing translation result, in there i only saw few translation.
point #2 buttons are created in UI file, and text is set via there only, text is not changed during runtime, when i opened ts file, i saw translation string for the button , but when i'm trying to load its not loading. i've attached a small snippet from ts file, but when i'm printing in point #1, i'm not seeing translation for it.
point #3 i'll try this and report back.
point #4 Thanks i'll correct that , when i check return value of load its returning true.
point #5 I'll update this as wellThanks for details explaination
@AkashPatel28 said in Qt Translation text not loading:
2 buttons are created in UI file, and text is set via there only.
Then you should call ui->retranslateUi() as stated in the documentation.
-
@AkashPatel28 said in Qt Translation text not loading:
2 buttons are created in UI file, and text is set via there only.
Then you should call ui->retranslateUi() as stated in the documentation.
@Christian-Ehrlicher Thanks that did the trick, not sure how did i missed that in documentation.
-
@Christian-Ehrlicher Thanks that did the trick, not sure how did i missed that in documentation.
@AkashPatel28 Then please mark this topic as solved, thx.
-