acrobat xi pro 简体中文语言支持包_Qml组件化编程12-多国语言动态翻译

目录

  • 简介
  • 发行说明
  • 效果预览
  • Qt本身的国际化
  • 存在翻译不全的问题
  • 新的方案
  • 关于批量翻译
  • 总结

简介

本文是《Qml组件化编程》系列文章的第十二篇,主要讨论多国语言动态翻译。

2019年,分享过使用Qt自带翻译的方案,但是效果不太好。这次分享一个非官方的多国语言方案。

发行说明

文章主要发布在涛哥的博客

涛哥的博客-gitee镜像

涛哥知乎专栏-Qt进阶之路。

效果预览

看一下最终效果

bf38f2eb33430c7590f4b145ef29f423.png

(原始字符串全部为英文,中文为人工翻译。

其它语言使用的百度翻译api批量翻译,不太准确,暂时先这样)

Qt本身的国际化

先来回顾一下,Qt的国际化方案:

  1. C++代码中的字符串使用QObject::tr()包起来,类本身是QObject的子类时可以省略作用域“QObject::”,直接写tr
  2. qml代码中使用qsTr把字符串包起来
  3. pro文件中添加一句TRANSLATIONS += trans_zh.qs ,这个名字起什么无所谓,关键是‘_zh’要有。
  4. 调用lrelease工具,扫描项目并生成trans_zh.qs 文件。这个文件是xml格式的,未经过翻译的,需要为这个文件做一些翻译工作。
  5. 翻译做好后,调用lupdate工具,生成trans_zh.qm文件。这个文件就是把xml压缩成了二进制。
  6. 将qm文件放在运行路径,或者资源文件里。
  7. 切换语言时, Qt/C++代码中使用QTranslater加载qm文件,QCoreApplication卸载旧的QTranslater,并安装新的QTranslater。调用
    QmlEngine::retranslate函数

在5.10以前的版本,Qt是不能直接动态切换语言的,要么重新启动程序,要么把所有的text都set一遍,retranslate是5.10才有的接口。

存在翻译不全的问题

上面的方案,在TaoQuick中使用了。

明显的问题是,只能翻译静态的内容,动态加载的ListModel,动态切换语言时不能自动刷新。

按照Qt文档所说,Array或者其它数据结构中的内容,也不能自动刷新。

新的方案

这里抛弃Qt的翻译机制,使用自己实现的方案。

1、约定要用到的字符串,全部用英文。

2、翻译文件使用json文件,一个文件翻译一种语言。

文件命名格式language_xx.json, json内容格式如下;

{
    

其中lang字段表示当前语言,trans字段是所有的翻译项。

3、实现核心翻译器Trans

自己实现一个Trans类,用来加载翻译包、提供翻译数据,类声明如下:

//Trans.h

其中languages是加载过后支持的所有语言,currentLang是当前语言。

trans函数是用来做翻译的,传入要翻译的字符串,根据当前语言,返回翻译后的字符串。

因为软件到处都要翻译,所以trans函数会被频繁调用,使用QHash<QString, QHash<QString, QString>>这样的

嵌套Hash数据结构,保证查询的平均复杂度为O(1).

transString是一个特殊的属性,其值始终为空,在语言被切换时,会触发transStringChange信号。

这样有什么用呢?先知道这个设定,后面qml部分会详细解释。

cpp 实现如下:

//Trans.cpp

4、Qml中使用新的翻译语法

qml中的语法如下:

Text {
    text: trans.trans("Welcome")  + trans.transString
}

这是一个很常规的’Qml属性绑定’,或者叫’绑定表达式’, 这样写了以后,text的值依赖于trans.trans()函数返回值和 transString。

当text依赖的属性发出change信号时,qml引擎会重新对这个表达式求值,并把结果赋值给text。

一般情况下,text的值就是trans的返回值,后面的空值不会影响到结果。

当前语言被改变时,函数没有change信号,而transString属性的change信号会被触发,导致qml引擎会重新对这个表达式求值,

此时会重新调用trans函数,按照新的语言返回翻译结果。

Text组件的text属性变化时,会自己刷新UI。

于是,就实现了动态翻译多国语言。

对于ListModel,就把静态字符串换成动态的变量即可:

ListView {
    ...
    delegate: Text {
        text: trans.trans(modelData)  + trans.transString
    }
}

复杂一些的格式化字符串,也是没有问题的:

Text {
    text: trans.trans("Today is %1, i feel %2").arg(trans.trans("Sunday")).arg(trans.trans("happy"))  + trans.transString
}

对应的翻译文件:

{
    

关于批量翻译

翻译效果不太理想,不过还是可以分享一下方法。

首先是提取出了所有要翻译的字符串:

//key.json

其次是写了一个PowerShell脚本,逐个调用百度翻译API,并把结果按照前面的json输出。

# trans.ps1

结果如下,生成了一堆json文件

4a838b46cc579cbdb2af7297fffe0ead.png

总结

Qml中带个尾巴的写法,虽然有些别扭,但是够用、能达到动态翻译的目标。

如果你有更好的思路,欢迎留言交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值