属性的 QML 翻译

QML Translation of Properties

我知道 QML 中字符串的翻译过程。但是有没有办法用 QML 函数完全转换 QML 属性?我正在使用 PySide2,我需要翻译 Python 和 QML 端定义的属性。作为一个还没有翻译功能的简约示例:

主要。 py

class example_model(QObject):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self._model = QStandardItemModel()

    @Property(str, constant=True)
    def python_property(self):
        return "Example String"

def main():
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    context = engine.rootContext()
    model = example_model( parent=context)
    context.setContextProperty("exampleModel", model)
    engine.load(QUrl(QUrl.fromLocalFile(os.path.join(os.path.dirname(inspect.getfile(lambda: None)), "main.qml"))))

    return app.exec_()
    
if __name__ == '__main__':
    sys.exit(main())

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    id: root
    width: 200
    height: 400
    visible: true
    property string qmlProperty: "exampleString"

    Text{
        text: QT_TR_NOOP(exampleModel.python_property)
    }
    Text{
        text: QT_TR_NOOP(root.qmlProperty)
    }
}

我如何实现这两个属性(python_propertyqmlProperty)分别被 Qt 的 lupdate 函数或任何其他函数正确检测到。我需要动态翻译,所以要用到engine.retranslate()函数。

翻译与 QML 类似,只是要使用 python 翻译,您必须使用 qsTranslate,您必须在其中传递上下文(python class 的名称),因为它不同于 qml 的上下文(.qml 文件的名称)。

另一方面,OP 似乎不理解 QT_TR_NOOP 的操作,因此建议查看文档。

使用下面的例子我将展示翻译过程:

import os
import sys
from pathlib import Path

from PySide2.QtCore import (
    Property,
    QCoreApplication,
    QObject,
    Qt,
    QTimer,
    QTranslator,
    QUrl,
)
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine

CURRENT_DIRECTORY = Path(__file__).resolve().parent
QML_DIRECTORY = CURRENT_DIRECTORY / "qml"
TRANSLATIONS_DIR = CURRENT_DIRECTORY / "translations"


class PythonModel(QObject):
    def python_property(self):
        return self.tr("Python Example String")

    pythonProperty = Property(str, fget=python_property, constant=True)


def main():
    app = QGuiApplication(sys.argv)

    py_tranlator = QTranslator()
    res = py_tranlator.load(os.fspath(TRANSLATIONS_DIR / "py.qm"))
    assert res

    qml_tranlator = QTranslator()
    res = qml_tranlator.load(os.fspath(TRANSLATIONS_DIR / "qml.qm"))
    assert res

    python_model = PythonModel(app)

    engine = QQmlApplicationEngine()
    engine.rootContext().setContextProperty("pythonModel", python_model)

    filename = os.fspath(QML_DIRECTORY / "main.qml")
    url = QUrl.fromLocalFile(filename)

    def handle_object_created(obj, obj_url):
        if obj is None and url == obj_url:
            QCoreApplication.exit(-1)

    engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
    engine.load(url)

    ok = False

    def handle_timeout():
        nonlocal ok
        if ok:
            QCoreApplication.installTranslator(py_tranlator)
            QCoreApplication.installTranslator(qml_tranlator)
        else:
            QCoreApplication.removeTranslator(py_tranlator)
            QCoreApplication.removeTranslator(qml_tranlator)

        engine.retranslate()

        ok = not ok

    timer = QTimer(interval=1000, timeout=handle_timeout)
    timer.start()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    id: root

    property string qmlProperty: qsTr("QML Example String")

    width: 200
    height: 400
    visible: true

    Column {
        Text {
            text: qsTranslate("pythonModel", pythonModel.pythonProperty)
        }

        Text {
            text: root.qmlProperty
        }

    }

}
├── main.py
├── qml
│   └── main.qml
└── translations
    ├── py.qm
    ├── py.ts
    ├── qml.qm
    └── qml.ts
  1. 使用 pyside2-lupdate 和 lupdate 生成 .ts:

    pyside2-lupdate main.py -ts translations/py.ts
    lupdate qml/main.qml -ts translations/qml.ts 
    
  2. 使用 Qt Linguist 工具添加翻译。

  3. 使用 lrelease 生成 .qm:

    lrelease translations/py.ts translations/py.qm
    lrelease translations/qml.ts translations/qml.qm
    
  4. 然后你必须加载两个翻译。

如果您不想拥有多个 .ts 或 .qm,那么您可以使用 lconvert 来合并文件。

您可以找到完整的示例 here