Translation values returned from C++ models
-
Hi, I'm facing some problems with translation in a specific case of C++/qml combination. I have a C++ model derived from QAbstractTableModel. The data() function there returns QVariant. In the ui I need to see a translation of returned value. How do I achieve that?
I followed the steps (described here: https://www.qt.io/blog/qt-quick-multilingual-app-creation), and could translate the application otherwise, it works fine. The problem concerns this specific case when C++ model returns a string from its data() function.
Here is a snippet:import QtQuick import QtQuick.VirtualKeyboard import QtQuick.Controls import tableTest Window { id: window width: 250 height: 250 visible: true title: qsTr("Hello World") Button { width: 70 height: 40 anchors.centerIn:parent text: qsTr("translate") onClicked: { Qt.uiLanguage = Qt.uiLanguage === "en" ? "sv" : "en" } } TableView { anchors.fill: parent columnSpacing: 1 rowSpacing: 1 clip: true model: MyModel {} delegate: Rectangle { implicitWidth: 100 implicitHeight: 50 Text { text: qsTr(display) // not translated } } } }
#include <qqml.h> #include <QAbstractTableModel> class MyModel : public QAbstractTableModel { Q_OBJECT QML_ELEMENT public: int rowCount(const QModelIndex & = QModelIndex()) const override { return 2; } int columnCount(const QModelIndex & = QModelIndex()) const override { return 2; } QVariant data(const QModelIndex &index, int role) const override { switch (role) { case Qt::DisplayRole: //return QString("%1, %2").arg(index.column()).arg(index.row()); return m_data[index.row()][index.column()]; default: break; } return QVariant(); } QHash<int, QByteArray> roleNames() const override { return { {Qt::DisplayRole, "display"} }; } private: QVector<QVector<QString>> m_data {{tr("One"), tr("Two")}, {tr("Three"), tr("Four")}}; // the ts file has the translation for "One", "Two", "Three" and "Four" };
-
Seems to work with qsTranslate in qml and QT_TRANSLATE_NOOP in the vector (inspired by http://imaginativethinking.ca/how-the-heck-can-i-use-qstr-with-variables/). Thank you all.
-
yes using the tr() function where you define that string is the way to achieve this. The vector declaration is the right place to do this.
There's no problem in returning a QString in the data function, the string will be implicitly converted to QVariant.
tr returns a QString, and when you return that string in data, it will be converted to QVariant.You can also
return QVariant (m_data[index.row()][index.column()]) ;
if you estimate that explicitly converting is more understandable or readable to you.Edit: ok I didn't see the call to qsTr in your delegate. Remove it. You are trying to retranslate a string that is already translated. Do translate strings when you define them between quotes. Don't translate use tr() or qsTr() on variables.
-
The vector declaration is not the right place to call
tr()
. You want to delay that until you display the text in Qt Quick, where it would be reevaluated on language change.Use
QT_TR_NOOP
inside the vector instead oftr
and useqsTr
like you did in QML.More info also here : Use QT_TR_NOOP() for Translatable Data Text Strings
-
Thank you for your answers. Unfortunately, even QT_TR_NOOP didn't help.
Unrelated, but I also forgot "z: -1" for table view.
Here is the setup that doesn't work either (i.e. "Hello World" and "translate" get translated, but delegates' texts still not...). Basically, none of the combinations of QT_TR_NOOP, tr, qsTr work....import QtQuick import QtQuick.VirtualKeyboard import QtQuick.Controls import tableTest Window { id: window width: 250 height: 250 visible: true title: qsTr("Hello World") Button { width: 70 height: 40 anchors.centerIn:parent text: qsTr("translate") onClicked: { Qt.uiLanguage = Qt.uiLanguage === "en" ? "sv" : "en"; } } TableView { anchors.fill: parent columnSpacing: 1 rowSpacing: 1 z: -1 clip: true model: MyModel {} delegate: Rectangle { implicitWidth: 100 implicitHeight: 50 Text { text: qsTr(display) } } } }
#include <qqml.h> #include <QAbstractTableModel> class MyModel : public QAbstractTableModel { Q_OBJECT QML_ELEMENT public: int rowCount(const QModelIndex & = QModelIndex()) const override { return 2; } int columnCount(const QModelIndex & = QModelIndex()) const override { return 2; } QVariant data(const QModelIndex &index, int role) const override { switch (role) { case Qt::DisplayRole: //return QString("%1, %2").arg(index.column()).arg(index.row()); return m_data[index.row()][index.column()]; default: break; } return QVariant(); } QHash<int, QByteArray> roleNames() const override { return { {Qt::DisplayRole, "display"} }; } private: // NONE of these work in combination with <qsTr(display)> , <QT_TR_NOOP(display)> or <display> in the qml file. //QVector<QVector<QString>> m_data {{QT_TR_NOOP("One"), QT_TR_NOOP("Two")}, {QT_TR_NOOP("Three"), QT_TR_NOOP("Four")}}; //QVector<QVector<QString>> m_data {{tr("One"), tr("Two")}, {tr("Three"), tr("Four")}}; QVector<QVector<QString>> m_data {{"One", "Two"}, {"Three", "Four"}}; };
-
The vector declaration is not the right place to call
tr()
. You want to delay that until you display the text in Qt Quick, where it would be reevaluated on language change.Use
QT_TR_NOOP
inside the vector instead oftr
and useqsTr
like you did in QML.More info also here : Use QT_TR_NOOP() for Translatable Data Text Strings
-
Seems to work with qsTranslate in qml and QT_TRANSLATE_NOOP in the vector (inspired by http://imaginativethinking.ca/how-the-heck-can-i-use-qstr-with-variables/). Thank you all.
-