Reputation: 1585
Lets suppose we add some TabButton
using the qml
javascript, with the line tabBar.addItem
and as argument tabButton.createObject
.
Now what i want to do is if i change the language i want the text of the TabButton
to change too.
How can this be done?
I know i can have on components (and i already have it working on a real app) a conection (that reacts to a signal) from a c++ class where we load the translations like this
Connections {
target: qmlTranslator
onLanguageChanged: {
doSomething()
}
}
I'm not finding a way to have it work with this tabbuttons. I provide a simple code to illustrate what i have:
import QtQuick 2.7
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Tabbars")
function assertCDataTabs () {
var tabs = ["Config", "Devices", "IOs", "Sounders", "Zones"]
for (var t in tabs) {
tabBar.addItem(tabButton.createObject(tabBar, { text: QT_TRANSLATE_NOOP("main",t), "font.pixelSize": 14 }))
}
backgroundHome.visible=false;
}
header: TabBar {
id: tabBar
opacity:0.8
}
Component {
id: tabButton
TabButton {
font.pixelSize: 14
}
}
StackLayout {
id: content
currentIndex: tabBar.currentIndex
anchors.fill: parent
}
Component.onCompleted: {
assertCDataTabs()
}
}
EDIT: Why does this not work?
Connections {
target: qmlTranslator
onLanguageChanged: {
var _contentData = tabBar.contentData
if(_contentData.length > 0){
for(var i=0;i<_contentData.length;i++){
var textTrans = _contentData[i]['contentItem']['text']
tabBar.itemAt(i).text = qsTr(textTrans)
}
}
}
}
qmltranslator.cpp
#include "qmltranslator.h"
#include <QApplication>
#include <QDebug>
#include <QDir>
QmlTranslator::QmlTranslator(QQmlEngine *engine)
{
_translator = new QTranslator(this);
_engine = engine;
}
void QmlTranslator::selectLanguage(QString language)
{
// working folder
QDir dir = QDir(qApp->applicationDirPath()).absolutePath();
// #ifdef Q_OS_MACOS // crutch for Mac OS
// dir.cdUp();
// dir.cdUp();
// dir.cdUp();
// #endif
// qDebug() << dir.path();
QString languagesArray[] = { "en", "pt", "es", "br", "de", "dk", "fi", "fr", "it", "lt", "no", "ro", "tr", "hu" };
for(int i=0;i<languagesArray->length();i++){
if(languagesArray[i] != language){
_translator->load(":/translations/" + QString("Lang-%1").arg(languagesArray[i]));
qApp->removeTranslator(_translator);
}
}
if (!_translator->load(":/translations/" + QString("Lang-%1").arg(language)))
{
qDebug() << "Failed to load translation file, falling back to English";
}
qApp->installTranslator(_translator);
_engine->retranslate();
emit languageChanged();
}
qmltranslator.h
#ifndef QMLTRANSLATOR_H
#define QMLTRANSLATOR_H
#include <QObject>
#include <QTranslator>
#include <QQmlEngine>
class QmlTranslator : public QObject
{
Q_OBJECT
public:
QmlTranslator(QQmlEngine *engine);
Q_INVOKABLE void selectLanguage(QString language);
signals:
void languageChanged();
private:
QTranslator *_translator;
QQmlEngine *_engine;
};
#endif // QMLTRANSLATOR_H
on the main to have it acessible through qml
QQmlApplicationEngine engine;
QmlTranslator qmlTranslator(&engine);
// and register it as a context in Qml layer
engine.rootContext()->setContextProperty("qmlTranslator", &qmlTranslator);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
Upvotes: 3
Views: 1154
Reputation: 244003
In these cases you must use a model (for example, ListModel) with QT_TR_NOOP as indicated by the docs, and to add the TabButton to the TabBar a Repeater is used.
In this example I use 3 translations:
translations
├── Lang-de.qm
├── Lang-en.qm
└── Lang-es.qm
Considering the above, the solution is the following:
translator.cpp
#include "translator.h"
#include <QGuiApplication>
#include <QDirIterator>
#include <QSettings>
Translator::Translator(QQmlEngine *engine, QObject *parent) :
QObject(parent),
m_engine(engine)
{
m_translator = new QTranslator(this);
m_dir = QDir(":translations");
m_languages.clear();
for(QString entry : m_dir.entryList()){
entry.remove(0, QString("Lang-").length());
entry.chop(extension.length());
m_languages.append(entry);
}
emit languagesChanged();
QSettings settings;
QString lang =settings.value("Language/current", QLocale::system().bcp47Name()).toString();
selectLanguage(lang);
}
QStringList Translator::languages() const
{
return m_languages;
}
QString Translator::currentLanguage() const
{
return m_currentLanguage;
}
QString Translator::languageByCode(const QString &code)
{
QLocale lo(code);
return QLocale::languageToString(lo.language());
}
void Translator::selectLanguage(const QString &language)
{
qApp->removeTranslator(m_translator);
if(m_languages.contains(language)){
QString file = QString("Lang-%1%2").arg(language).arg(extension);
if(m_translator->load(m_dir.absoluteFilePath(file))){
m_currentLanguage = language;
QSettings settings;
settings.setValue("Language/current", language);
emit currentLanguageChanged();
}
}
qApp->installTranslator(m_translator);
m_engine->retranslate();
emit languageChanged();
}
main.qml
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: "tabBars"
ListModel{
id: tabmodel
}
function assertCDataTabs(){
var tabs = [QT_TR_NOOP("Configuration"),
QT_TR_NOOP("Devices"),
QT_TR_NOOP("Sounders"),
QT_TR_NOOP("Zones")]
for (var i in tabs)
tabmodel.append({"text": tabs[i] })
}
header: TabBar{
id: tabBar
opacity:0.8
Repeater{
model: tabmodel
TabButton{
text: qsTr(tabmodel.get(index).text)
font.pixelSize: 14
}
}
}
Column {
width: parent.width * 0.95
spacing: 15
padding: 15
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
Repeater{
model: trans.languages
Button{
id: btn
property string code: modelData
text: trans.languageByCode(code)
onClicked: trans.selectLanguage(btn.code)
Layout.preferredWidth: 100
Layout.preferredHeight: 50
highlighted: code == trans.currentLanguage
}
}
}
}
Component.onCompleted: assertCDataTabs()
}
The complete example you find here.
Upvotes: 3