tr() with binding: how to get the calling classname to a function,
-
Hey guys,
I want to be able to switch my application-language on runtime to another language.
The QML part works out of the box via retranslate() but I have several c++ data-models which are not updating.To keep things clean, I would like to create a method like tr() which takes 3 parameters, which I could call like this:
trExt("myText", &targetObject, &TargetClass::setName);
So internally something like this should happen (Attention this is NOT a working function it is just a draft of an idea):
template <typename Func> void trExt(const QString &text, typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func slot) { QMetaObject::invokeMethod(receiver, slot, Q_ARG(QString, text); connect(&languageChanger(), &LanguageChanger::languageChanged, [&]() { QString newText = QCoreApplication::translate(char* NAME OF CALLING CLASS, text); QMetaObject::invokeMethod(receiver, slot, Q_ARG(QString, newText); } }
To be able to use QCoreApplication::translate() correctly I have to forward the calling classname somehow as a context.
I have no idea how this can be done. Somehow the default tr() function is able to do it but I don't know how (magic ? ).
I would also like to avoid passing the calling context-name as an additional parameter.Any idea?
THX -
It's not QObject::tr() but <YourObjectWithQ_OBJECT_macro>::tr() and therefor the class name is known and can be passed to QCoreApplication::translate()
-
It's not QObject::tr() but <YourObjectWithQ_OBJECT_macro>::tr() and therefor the class name is known and can be passed to QCoreApplication::translate()
@Christian-Ehrlicher ahhh, ok. That makes sense.
So the best approach would be to put it in a macro. -
Hi,
Out of curiosity, why do you want to translate a class name ?
-
I don’t want to translate the classname.
I want to connect a translation to a slot.
Normally I have situations like:
object.setName(tr(„super english text“))Problem is that in this situations a retranslate wouldn’t trigger a new „setName“.
So my idea is to have a function
trExt("super english text", &object, &Class::setName);That way it would call setName and create a connection to a languageChanged event which resets the parameter to the new translation every time
-
@SGaist said in tr() with binding: how to get the calling classname to a function,:
why do you want to translate a class name ?
No, he wants not translate the class name but mimic tr() which in fact calls QCoreApplication::translate() where the context is the class name.
-
one additional question:
how do I invoke a methode without the name? Or how do I get the nameI have this:
#define N_TRANSLATE\ template <typename Func>\ void trExt(const QString &text, typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func slot) {\ QMetaObject::invokeMethod(receiver, "HERE I NEED A NAME", Q_ARG(QString, text));\
To use "invokeMethod" I need the slotname.
I would like to pass the slot as shown. Can I get the name somehow? Or is there another way of invoking this slot? -
@themts said in tr() with binding: how to get the calling classname to a function,:
how do I invoke a methode without the name?
I don't understand what you mean - when you want to call a function you should know it's name, or?
-
That is my function:
template <typename Func> void trExt(const char *text, typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func slot) { const char* className = metaObject()->className(); //A) CALL "Func slot" HERE AND PASS tr(text) as parameter to "Func slot" connect(&_langLoader(), &NLanguageLoader::languageChanged, [className, text, slot]() { QString newText = QCoreApplication::translate(className, text); //B) INVOKE METHOD "Func slot" HERE AND PASS newText as parameter to "Func slot" like QMetaObject::invokeMethod to be sure it is threadsafe }); }
I' missing two things now:
A) how do i call the slot (parameter 3) of the receiver? I would have exptected to use only slot(tr(text)) but compiler tells me "there is no function that takes 1 argument". Just from c++ side I would have expected that it works.B) as the thread-context might be different I would like to use the QMetaObject::invokeMethod function as it will send it to the event loop if the target is in another context.
-
-
ok, I will give up...
I will do it like this.
Instead of callingtrExt("super english text", &object, &Class::setName);"
I will call
trExt("super english text", &object, "setName");
I would have prefered the first way but I'm not that deep in the Qt internals.
void trExt(const char *text, QObject *receiver, const char *member) { QMetaObject::invokeMethod(receiver, member, Q_ARG(QString, tr(text))); const char* className = metaObject()->className(); connect(&_langLoader(), &NLanguageLoader::languageChanged, [className, text, receiver, member]() { QString newText = QCoreApplication::translate(className, text); QMetaObject::invokeMethod(receiver, member, Q_ARG(QString, newText)); }); }
-
What about implementing the changeEvent method to handle your object's translatable strings like shown in the dynamic translation part of the internationalization documentation ?