Qt Quick实践系列-多语言切换

2023-03-17 13:34:10 浏览数 (3)

❝简单的QML小例子,展示如何在QML中多语言动态切换。❞

0x01 加载语言文件操作

代码语言:javascript复制
/* 加载中文语言(默认) */
QTranslator translator;
if (! translator.load(":/Resources/zh_CN.qm")) {
    qDebug() << "Failed to load translation file!";
}
qApp->installTranslator(&translator);

0x02 切换语言

  这里涉及到C 与QML的数据操作与交互。

  1. 创建一个C 自定义类型,用于导入到QML中使用。其中SettingModel中的language属性为切换语言的状态。
代码语言:javascript复制
class SettingModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged)
public:
    SettingModel(QObject *parent = NULL) : QObject(parent)
    {
        m_language = "zh_CN";
    }

    QString language()
    {
        return m_language;
    }

    void setLanguage(const QString &language)
    {
        QTranslator translator;
        if (! translator.load(QString(":/Resources/%1.qm").arg(language))) {
            qDebug()<<"Failed to load translation file!";
            return;
        }

        /* 切换语言 */
        qApp->installTranslator(&translator);

        m_language = language;
        emit languageChanged();
    }

signals:
    void languageChanged();

private:
    QString m_language;
};
  1. QML切换语言操作,通过操作SettingModel类中的language属性后,会即刻切换语言(文件)。
代码语言:javascript复制
Text {
    anchors.horizontalCenter: parent.horizontalCenter
    text: tr("Hello World")
    font.pixelSize: 30
}

Row {
    spacing: 10

    Button {
        id: chinese
        text: "中文"
        /* 切换为中文,逻辑在SettingModel的setLanguage函数中。 */
        onClicked: settingModel.language = "zh_CN"
    }

    Button {
        id: english
        text: "English"
        /* 切换为英文,逻辑在SettingModel的setLanguage函数中。 */
        onClicked: settingModel.language = "en"
    }
}

SettingModel { id: settingModel }

0x03 这就完成了吗?

  上面一顿操作猛如虎,一看效果二百五。怎么没反应的,没变化呀。似乎有细心的人发现了一些奇怪的地方就是:

代码语言:javascript复制
text: tr("Hello World")

  不应该是下面这个吗?

代码语言:javascript复制
text: qsTr("Hello World")

  别急,还没写完嘛!tr函数如下咯。

代码语言:javascript复制
function tr(string) {
    /**
     * tmp变量这里没有使用,原因是利用QML语言绑定机制,
     * 当settingModel.language有变化时,
     * QML立即自动调用tr函数,对所有绑定该函数的表达式都会重新调用一次。
     */
    var tmp = settingModel.language;
    /* 设置"Window"字段上下文,在对应ts中需要添加<name>Window</name> */
    return qsTranslate("Window", string)
}

  这tr函数太奇怪了吧!没错要使QML的翻译动态更新,就需要额外绑定一个变量,当变量变化时就会触发对应tr函数的绑定,从而重新调用一次text: tr("Hello World")后刷新翻译了。

0x04 翻译误区

  这里需要注意的是,君君特别地使用qsTranslate这个接口而不是使用qsTr,如果单纯使用qsTr会导致翻译不到的情况,因为大多数翻译字段都设置了上下文。

qsTranslate("Window", string)中的第一个参数是翻译的「上下文」,第二个参数是需要翻译的字段。

  关于翻译字段「上下文」理解,选取zh_CN.ts文件内容为例:

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="zh_CN">
<context>
    <name>QObject</name>
    <message>
        <source>QtHub.com</source>
        <translation>@Qt君</translation>
    </message>
    <message>
        <source>Hello World</source>
        <translation>你好,世界</translation>
    </message>
    <message>
        <source>open</source>
        <translation>打开</translation>
    </message>
    <message>
        <source>close</source>
        <translation>关闭</translation>
    </message>
</context>
<context>
    <name>Window</name>
    <message>
        <source>QtHub.com</source>
        <translation>@Qt君</translation>
    </message>
    <message>
        <source>Hello World</source>
        <translation>你好,世界</translation>
    </message>
    <message>
        <source>open</source>
        <translation>打开</translation>
    </message>
    <message>
        <source>close</source>
        <translation>关闭</translation>
    </message>
</context>
</TS>

  从上面可以看出,有两个上下文字段QObjectWindow,如果在QML中使用了qsTr是不能直接翻译成功的,必须加上上下文。

代码语言:javascript复制
<name>QObject</name>
<name>Window</name>

  做翻译字段时,建议大多数情况下都添加上下文。

0x05 更多

  • 2019-01-31 推文 《Qt多语言翻译示例》,介绍Qt多语言翻译。
  • 2020-05-02 推文《Qt Quick实践系列-函数绑定》,介绍数据绑定机制。

关于Qt&QML的多语言翻译有什么想法在留言区和大家讨论吧。

1 人点赞