【问题标题】:QQmlEngine retranslate not translating other StackView itemsQQmlEngine 重新翻译不翻译其他 StackView 项目
【发布时间】:2019-06-14 18:30:39
【问题描述】:

我有一个自定义类,我需要在其中保存新选择的语言并同时更改应用程序语言。基于 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

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

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

有人知道问题出在哪里吗?我怀疑引擎没有被正确获取。这是一个自定义类,我需要注册(qmlRegisterType)才能在 qml 中使用,我不确定如何正确获取引擎(因为引擎是在主函数中创建的)。

【问题讨论】:

  • 正如我所说,StackView 与此代码的组合。这还不够吗?我的意思是没有人在这里分享整个项目。它基于来自 Qt Creator 的堆栈移动应用程序模板。
  • 1) 还不够,2) 我没有告诉你分享你的项目,看来你没有看过链接的内容,一个MRE是一个项目不一定是你的项目而是一个极简版本(minimal),其任务只是重现问题(reproducible)。
  • 扩展了代码,希望现在可以了。展示了最重要的部分。
  • 展示你的 .pro....
  • 添加了我在那里所做的更改

标签: c++ qt qml qtquick2


【解决方案1】:

我遇到了同样的问题。我找到的解决方案是在创建 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 来进行一些内存管理。我还没有测试过这个示例代码,但是我在我的项目中使用了非常相似的代码并且它有效

【讨论】:

  • 在帖子作者中,翻译器对象在app.exec(); 执行期间将是活动的(这是阻塞的)——所以你的假设是不正确的。
【解决方案2】:

我使用了一个肮脏的技巧来实现整个应用程序的重新翻译,而无需在类中获取引擎。它不是完美的,但它有效。我在 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 值。这样,应用程序基本上会以新语言重新启动。

更新:虽然这可行,但最好将引擎和应用程序存储到使用问题中提到的方法处理翻译的单例类中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 2013-06-14
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    相关资源
    最近更新 更多