How can I get the application QmlEngine ?
-
@J-Hilk Nop, sorry. I have for the moment none QQmlEngines inside my project. To display my app, I have a class heriting from QQuickView which is using OpenGL to display my app via the function myView.SetSources("qrc:/main.qml"). After some googling, every example I found for dynamic translation are done in three steps : remove the actual QTranslator, install the new one and then retranslate the app. But in each of these examples, they are doing this line : engine->load(QUrl("qrc:/main.qml")) at first. If i do this line, my app is immediatly crashing because the qml file is already in use in the class which display the app. Let's say this class's name is "myView", I also tried to get the engine by doing : QQmlEngine* engine = QQmlEngine::contextForObject(&myView)->engine(); but my app is directly crashing.
@kmarconi ok I get it,
QQuickView has a getter for the internal QQmlEngine
https://doc.qt.io/qt-5/qquickview.html#enginecall that and simply call retranslate on that returned object, and you should be fine
-
@kmarconi ok I get it,
QQuickView has a getter for the internal QQmlEngine
https://doc.qt.io/qt-5/qquickview.html#enginecall that and simply call retranslate on that returned object, and you should be fine
wrote on 30 Nov 2020, 13:59 last edited by@J-Hilk Wow I think you saved my life here, thanks ^^ My app is finally not crashing anymore but I have now an error from my main.qml file : QML StackView: Binding loop detected for property "button". Any idea on why this could happen ?
Big thanks.
-
@J-Hilk Wow I think you saved my life here, thanks ^^ My app is finally not crashing anymore but I have now an error from my main.qml file : QML StackView: Binding loop detected for property "button". Any idea on why this could happen ?
Big thanks.
@kmarconi hard to tell without knowing your qml file content,
retranslate does not only reevaluate your text bindings, but all bindings
https://doc.qt.io/qt-5/qqmlengine.html#retranslateNote: Due to a limitation in the implementation, this function refreshes all the engine's bindings, not only those that use strings marked for translation. This may be optimized in a future release.
so, the bug is probably there from the binging :D
-
wrote on 30 Nov 2020, 14:08 last edited by kmarconi
Here is my main.qml file :
Item {
id:root
visible: true
width: 640
height: 480property var mainMenu: Menu{rootStack: root} StackView { anchors.fill: parent id: menuStack property var button: hmiclass.button initialItem: mainMenu onButtonChanged: { mainMenu.onButtonPushed(button) } }
}
EDIT: I need to find where that loop is coming from.. Or to find a patch to refresh only the bindings which are in the translation file.
-
Here is my main.qml file :
Item {
id:root
visible: true
width: 640
height: 480property var mainMenu: Menu{rootStack: root} StackView { anchors.fill: parent id: menuStack property var button: hmiclass.button initialItem: mainMenu onButtonChanged: { mainMenu.onButtonPushed(button) } }
}
EDIT: I need to find where that loop is coming from.. Or to find a patch to refresh only the bindings which are in the translation file.
wrote on 30 Nov 2020, 15:04 last edited by@kmarconi Last question : When I check the definition of the retranslate function, it says : Refreshes all binding expressions that use strings marked for translation. What is that "marked" thing and how to apply it ? Thanks
-
@kmarconi Last question : When I check the definition of the retranslate function, it says : Refreshes all binding expressions that use strings marked for translation. What is that "marked" thing and how to apply it ? Thanks
@kmarconi
take a look here:
https://doc.qt.io/qt-5/qtquick-internationalization.html -
@kmarconi
take a look here:
https://doc.qt.io/qt-5/qtquick-internationalization.htmlwrote on 30 Nov 2020, 15:29 last edited by@J-Hilk Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
-
@J-Hilk Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
@kmarconi said in How can I get the application QmlEngine ?:
Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
so, you answered your own question
Refreshes all binding expressions that use strings marked for translation. What is that "marked" thing and how to apply it ? Thanks
😉
-
@kmarconi said in How can I get the application QmlEngine ?:
Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
so, you answered your own question
Refreshes all binding expressions that use strings marked for translation. What is that "marked" thing and how to apply it ? Thanks
😉
wrote on 30 Nov 2020, 15:33 last edited by@J-Hilk Yeah but I thought that maybe there was another thing to do ... I'm stuck now so I'm trying everything I can Haha
-
@J-Hilk Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
wrote on 30 Nov 2020, 15:38 last edited by@kmarconi said in How can I get the application QmlEngine ?:
Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
My way to ensure translation is the define a global Object which handle language changes.
This object is exposed to QML withengine->rootContext()->setContextProperty("translation", &myLocalesHandler)
.This object has a property called
emptyString
:Q_PROPERTY(QString emptyString READ emptyString NOTIFY languageChanged) .... QString emptyString() const { return QString(); }
On language change signal
languageChanged()
is emitted and in QML I have something like this:Label { text: qsTr("This is a message") + translation.emptyString }
Works great for me, hope this could also helps you.
-
wrote on 30 Nov 2020, 15:39 last edited by
When I have objects that live in qml space such as a plain QObject, I will make it based upon QQuickItem in order to get the qml engine. I often do this for image providers that provide QImages to qml. I think any QQuick based object should be able to do this.
-
@kmarconi said in How can I get the application QmlEngine ?:
Yeah I already been there but every string which needs to be translated are already marked as qsTr so ...
My way to ensure translation is the define a global Object which handle language changes.
This object is exposed to QML withengine->rootContext()->setContextProperty("translation", &myLocalesHandler)
.This object has a property called
emptyString
:Q_PROPERTY(QString emptyString READ emptyString NOTIFY languageChanged) .... QString emptyString() const { return QString(); }
On language change signal
languageChanged()
is emitted and in QML I have something like this:Label { text: qsTr("This is a message") + translation.emptyString }
Works great for me, hope this could also helps you.
wrote on 1 Dec 2020, 08:18 last edited by@KroMignon Thanks for your help, will try it now. I just have question on your translation class. Where do you emit the signal languageChanged and how do you link it to your function which retranslate the app with the engine ? Thanks !
-
@KroMignon Thanks for your help, will try it now. I just have question on your translation class. Where do you emit the signal languageChanged and how do you link it to your function which retranslate the app with the engine ? Thanks !
@kmarconi what @KroMignon described was the way you had to go before Qt 5.10
you can take a look at this blog post, I think its rather good:
https://retifrav.github.io/blog/2017/01/04/translating-qml-app/
-
@kmarconi what @KroMignon described was the way you had to go before Qt 5.10
you can take a look at this blog post, I think its rather good:
https://retifrav.github.io/blog/2017/01/04/translating-qml-app/
wrote on 1 Dec 2020, 08:54 last edited by@J-Hilk Yeah I've seen this post but it's kinda dirty way to retranslate the whole app I think ... I still will try it but I hope to find a way to use the retranslate function properly.
-
@J-Hilk Yeah I've seen this post but it's kinda dirty way to retranslate the whole app I think ... I still will try it but I hope to find a way to use the retranslate function properly.
@kmarconi
what would you consider a proper retranslate functionality ?You can either,
- call retranslate() on the QQmlEngine,
- update the strings via the empty string property workaround
- reload the qml file entirely
there are not other ways, at least that I know of
-
@kmarconi
what would you consider a proper retranslate functionality ?You can either,
- call retranslate() on the QQmlEngine,
- update the strings via the empty string property workaround
- reload the qml file entirely
there are not other ways, at least that I know of
wrote on 1 Dec 2020, 09:18 last edited by kmarconi 12 Jan 2020, 09:21@J-Hilk Calling retranslate for me is the cleanest way. No need to add "+trans.emptyString" on each of my qsTr object and I have a lot. I need to figure out how to solve this infinite binding loop. Is reloading the whole qml a heavy task for the system ?
-
wrote on 1 Dec 2020, 09:20 last edited by KroMignon 12 Jan 2020, 09:20
@kmarconi said in How can I get the application QmlEngine ?:
I still will try it but I hope to find a way to use the retranslate function properly.
I can not figure out what your problem is.
@J-Hilk have give you all information you need to do it.If you are using Qt 5.10 and upper (which is not my case) simply follow documentation
That's not so complicated to follow, you could create a class which handle the locales, for example let it call LocalHandler, when you have install the new translator withQCoreApplication::installTranslator()
then emit a signal for example calledtranslationUpated()
.
Then in your main.cpp:LocalHandler loc; QObject::connect(&loc, &LocalHandler::translationUpated, engine, &QQmlEngine::retranslate);
Alternatively you can use a
app->installEventFilter()
to catchQEvent::LanguageChange
and then triggerQQmlEngine::retranslate()
.For prior version, you have to do more work ==> https://retifrav.github.io/blog/2017/01/04/translating-qml-app/
-
@kmarconi said in How can I get the application QmlEngine ?:
I still will try it but I hope to find a way to use the retranslate function properly.
I can not figure out what your problem is.
@J-Hilk have give you all information you need to do it.If you are using Qt 5.10 and upper (which is not my case) simply follow documentation
That's not so complicated to follow, you could create a class which handle the locales, for example let it call LocalHandler, when you have install the new translator withQCoreApplication::installTranslator()
then emit a signal for example calledtranslationUpated()
.
Then in your main.cpp:LocalHandler loc; QObject::connect(&loc, &LocalHandler::translationUpated, engine, &QQmlEngine::retranslate);
Alternatively you can use a
app->installEventFilter()
to catchQEvent::LanguageChange
and then triggerQQmlEngine::retranslate()
.For prior version, you have to do more work ==> https://retifrav.github.io/blog/2017/01/04/translating-qml-app/
wrote on 1 Dec 2020, 09:33 last edited by@KroMignon I already done everything you told me but thank you ;) I was just saying that if I could not use the emptyString trick it could be interesting for me. Why I'm saying this is because with the trick , I have the error " ListElement: cannot use script for property value" . Is is because I cannot use the trick in a ListElement object ?
-
@KroMignon I already done everything you told me but thank you ;) I was just saying that if I could not use the emptyString trick it could be interesting for me. Why I'm saying this is because with the trick , I have the error " ListElement: cannot use script for property value" . Is is because I cannot use the trick in a ListElement object ?
wrote on 1 Dec 2020, 09:47 last edited by KroMignon 12 Jan 2020, 09:53@kmarconi said in How can I get the application QmlEngine ?:
I have the error "ListElement: cannot use script for property value"
AFAIK, ListElement cannot be changed dynamically ==> cf QTBUG-16289
edit
You have to use
QT_TR_NOOP()
andqsTr()
on the delegate, like this (extract from QTBUG-16289):ListModel { id: myModel ListElement { desc: QT_TR_NOOP("Example") } } ListView { model: myModel delegate: Text { text: qsTr(desc) } }
-
@kmarconi said in How can I get the application QmlEngine ?:
I have the error "ListElement: cannot use script for property value"
AFAIK, ListElement cannot be changed dynamically ==> cf QTBUG-16289
edit
You have to use
QT_TR_NOOP()
andqsTr()
on the delegate, like this (extract from QTBUG-16289):ListModel { id: myModel ListElement { desc: QT_TR_NOOP("Example") } } ListView { model: myModel delegate: Text { text: qsTr(desc) } }
wrote on 1 Dec 2020, 09:51 last edited by kmarconi 12 Jan 2020, 09:51@KroMignon Yeah just seen it on a stackoverflow post (https://stackoverflow.com/questions/7659442/listelement-fields-as-properties) but I canno't change my qml part because the way it is designed is fixed so I need to find a way to use the retranslate function without having this binding loop.
15/38