QQmlEngine重新翻译而不翻译其他StackView项

时间:2019-06-14 18:30:39

标签: c++ qt qml qtquick2

我有一个自定义类,需要在其中保存新选择的语言并同时更改应用程序语言。一个基于QtCreator中StackView示例项目的示例:

//main.cpp
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);

    qmlRegisterType<CustomClass>("io.qt.CustomClass", 1, 0, "CustomClass");

    QTranslator translator;
    translator.load(":/EN.qm");
    app.installTranslator(&translator);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}



//customclass.h
class CustomClass : public QObject
{
    Q_OBJECT
public:
    explicit CustomClass(QObject *parent = nullptr) : QObject(parent) {}
    Q_INVOKABLE void change(){
        QTranslator translator;
        QApplication::removeTranslator(&translator);
        translator.load(":/CZ.qm");
        QApplication::installTranslator(&translator);
        //QQmlApplicationEngine * engine = qobject_cast<QQmlApplicationEngine *>(qmlEngine(this));
        QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
        engine->retranslate();
    }
};



//main.qml
...
CustomClass{id:test}
...
 ItemDelegate {
                text: qsTr("Page 1")
                width: parent.width
                onClicked: {
                    test.change()
                    drawer.close()
                }
            }...



//.pro file
QT += quick gui core
...
TRANSLATIONS = EN.ts CZ.ts
...
HEADERS += \
    customclass.h

在此示例中,单击Page 1按钮应更改语言。

我的应用程序基于StackView,当我使用此代码调用该函数时,一切似乎都可以正常工作。字符串已翻译。但是,当我将一个新项目推入堆栈时(例如从菜单中打开一个新部分),那里的字符串以更改之前的原始语言返回。就像重新翻译只更改当前可见的字符串一样。

有人知道问题出在哪里吗?我怀疑引擎无法正确获得。这是一个自定义类,我需要先注册(qmlRegisterType)才能在qml中使用,但我不确定如何正确地将引擎添加到那里(因为在主函数中创建了引擎)。

2 个答案:

答案 0 :(得分:2)

我遇到了同样的问题。我发现的解决方案是在创建QTranslator对象时使用new运算符。这将导致在堆内存而不是堆栈中创建对象。如果它在堆栈存储器中,则在函数完成后,QTranslator将被删除(至少,这就是我的理解。我相信具有更多C ++经验的人可能会更好地解释它)。

因此,您的自定义类代码将如下所示:

//customclass.h
class CustomClass : public QObject
{
    Q_OBJECT
public:
    explicit CustomClass(QObject *parent = nullptr) : QObject(parent) {}
    Q_INVOKABLE void change(){
        QTranslator *translator = new QTranslator(qApp);
        if (m_previousTranslator) {
            QApplication::removeTranslator(m_previousTranslator);
            m_previousTranslator->deleteLater();
            m_previousTranslator = nullptr;
        }
        translator->load(":/CZ.qm");
        m_previousTranslator = translator;
        QApplication::installTranslator(translator);
        QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
        engine->retranslate();
    }
private:
    QTranslator *m_previousTranslator = nullptr;
};

请注意,我添加了一个私有变量m_previousTranslator来进行一些内存管理。我尚未测试此示例代码,但我在项目中使用了非常相似的代码,并且可以正常工作

答案 1 :(得分:0)

我使用了一个肮脏的把戏来实现整个应用程序的重新翻译,而无需在类中使用引擎。这不是完美的,但可以。我在main中添加了一个循环,如下所示:

    int returnValue = 0;
    do
    {
        QApplication app(argc, argv);
        QTranslator translator;
        translator.load(":/translation/"+langString+".qm"); //langString might be the "CZ" as in the question example
        app.installTranslator(&translator);

        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/src/qml/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;

        returnValue = app.exec();

        langString = settings.value("language").toString();
    }
    while(returnValue == TRANSLATION_RESTART);


    return returnValue;

因此在我的自定义类中,我只需使用以下命令退出应用程序:

    qApp->exit(TRANSLATION_RESTART);

我还保存了langString值。这样,应用程序基本上会以新语言重新启动。