关闭

Qt 数据库操作与多语言支持的解决途径探讨

标签: 数据库uiqt国际化多语言
1084人阅读 评论(3) 收藏 举报
分类:

最近帮朋友使用Qt开发了一个毕业设计,自动化成绩系统的PC端。其实,对与消费用户发生交互的应用来说,使用Web APP是最合适的了。无奈,题目要求如此,也只能照办。由于需要做繁体、简体转换,考虑到使用Qt內建的国际化支持。对UI的元素进行国际化,大致牵扯到以下几个部分。
UI元素:如按钮、各种控件。
代码中的字符串:比如一些弹出消息等。
数据库内容:包括字段名、字段值。
这三个部分由易到难。

翻译之前的准备

Qt国际化的原理是通过加载字典文件(qm文件),并对上下文(Context) 中的对应原文进行替换。这个字典文件是由翻译脚本(ts文件)发布生成的,执行这个工作的工具是Qt语言家。
翻译前的第一步,是为项目加入ts文件。打开 .pro 工程,加入如下两行:

TRANSLATIONS += XXXX_zh_CN.ts \
        XXXX_zh_HK.ts
OTHER_FILES +=  XXXX_zh_CN.ts \
        XXXX_zh_HK.ts 

其中,XXXX代表工程的TARGET,如果直接用向导生成,这个名字也是工程文件的名字。TRANSLATIONS 入口告诉Qt,这两个文件是翻译脚本文件。一旦有这个入口,lupdate 工具即可根据该设置,自动扫描工程包含的所有元素,并更新ts文件。
翻译前的第二步,即执行lupdate.exe,自动扫描生成ts 文件。该入口在
“工具”–>“外部”–>“Qt语言家”–>“更新翻译”。

UI元素的国际化

首先得到解决的是UI元素。因为UI元素在设计师中默认开启了翻译的功能。所有没有额外关闭该属性的界面元素,都会出现在ts文件中。
右键单击工程树的翻译脚本,选择用Qt语言家打开,即可开始翻译工作。

语言家便捷入口 在语言家中对UI进行翻译
Qt语言家打开 开始翻译

代码中的字符串

在代码中的提示信息,如 QMessageBox中的提示,可直接使用tr()宏进行包含,以告诉Qt语言家,这个提示是需要翻译的。如动态插入三列名称:

    m_pLayerDispMod = new QStandardItemModel(this);
    m_pLayerDispMod->setColumnCount(3);
    m_pLayerDispMod->setHeaderData(0,Qt::Horizontal,QString(tr("name")));
    m_pLayerDispMod->setHeaderData(1,Qt::Horizontal,QString(tr("active")));
    m_pLayerDispMod->setHeaderData(2,Qt::Horizontal,QString(tr("visible")));
    ui->tableView_QTV_layers->setModel(m_pLayerDispMod);

在ts文件中,把他们翻译为名称、活动、可见即可。
比较奇怪的一点是,QMessageBox::information\ warning等静态方法,尽管弹出的内容可以使用tr()包裹,但标准按钮却一直是“Ok”\”Yes”。这个问题笔者一直没有找到很好的方法,最终只能自己写了一个类似功能的类完成了按钮的汉化。

数据库字段名

为了使数据库中选择的列名是跟随语言变化而变化的,有很多截然不同的方法。

方法1,准备多个视图

这个方法根据语言环境的后缀,准备多个视图,使用

create view view_stu_zh_CN as
select 
    stu_name as '学生姓名',
    stu_age  as '学生年龄',
    ...;
create view view_stu_zh_HK as
select 
    stu_name as '學生姓名',
    stu_age  as '學生年齡',
    ...

而后,在数据库接口代码中,根据不同的语境,选择不同的视图。
缺点:在代码中的条件查询,也要跟上语境。如果想从视图中选择年龄>20岁的条件,则需要区分语境,使用不同的字段名。

方法2,在接口文件中使用tr()

这个方法,思路是在接口文件中,统一进行显式tr包裹。如:

QSqlQuery queryStudentByAge(const int ageMin, const int ageMax)
{
    ...
    try{
        ...
        QString sql_main =
                    "select "
                    " stu_name as " + tr("StudentName") +
                    ",stu_age as " + tr("StudentAge") +
                    " from student where stu_age >= ? and stu_age <=?; ";
        ...
    }
    ...
}

此时,只要保证所有引用学生名称的位置全部都用tr(“StudentName”)包裹,界面元素全用StudentName作为Text,就能达到适应语言的效果。

数据库中的数据记录

翻译中,最难的就是数据库中的数据记录。数据记录里,学生的姓名是动态录入的,在程序完成编译后,这些信息会不断变更。

方法1 冗余字段/翻译表

这个方法就是直接添加两个姓名字段,分别存储繁体、简体。或者稍微高明一些,建立一个字典表,而后根据语言做联合键,left join 过去。
这种方法,每次需要录入两个姓名,而且,需要一个视图,来统一接口。目前的工程,采用的就是这个方法。

方法2 PostgreSQL json /hstore 字段

SELECT stuname->'zh_CN' FROM student ;

这个方法是比较灵活的方法,把stuname定义为json字段,则可以使用键选择不同的语言了。不过缺点与方法一类似,就是仍然需要录入好几种字符。详见 PostgreSQL Json字段
PostgreSQL还有一个类似的字段类型是 HStore,存储了单层键-值序列,有异曲同工之妙。有兴趣的可以看看这里

方法3 动态显示转换

可以重载QSqlQueryModel,对它的 data()方法进行重载,动态切换显示语言。此外,为显示控件提供一个自定义代理,即QItemDelegate 的派生类,在其中实现繁简体转换也是可以的。繁简体转换其实就是逐个字符查表。

缺点:如果需要从程序中动态获取条件,如姓名=张三,则要搞清楚,数据库中究竟存储的是繁体还是简体,否则,字符串比较肯定不对。

这三个方法都不好,操作起来不是数据库端要费尽,就是末端显示要大把的代码。不知道各位高手有木有傻瓜化的解决方案,好指导指导楼猪,不胜感激。

发布翻译

最后一步,是在主函数中加入翻译功能的代码,直接拷贝Qt文档即可。

#include "XXXX.h"
#include <QApplication>
#include <QLibraryInfo>
#include <QTranslator>
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTranslator qtTranslator;
    qtTranslator.load("qt_" + QLocale::system().name(),
                      QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    app.installTranslator(&qtTranslator);

    QTranslator appTranslator;
    QString strTransLocalFile =
            QCoreApplication::applicationDirPath()+"/" +
            QCoreApplication::applicationName()+"_"+
            QLocale::system().name()+".qm";
    appTranslator.load(strTransLocalFile );
    app.installTranslator(&appTranslator);

    XXXX w;
    w.show();
    return app.exec();
}

当然,这段代码会根据当前操作系统的语言环境自动选择 zh_CN或者 zh_HK,或者 zh_TW等。如果想让用户动态切换,需要额外添加手工切换、刷新(调用 retranslateUi(this))的代码。

用Qt预言家发布翻译为.QM文件,拷贝到可执行文件所在文件夹即可。

1
0
查看评论

技术路线的可行性和解决关键技术的途径

三层应用构架是一种成熟的开发模式,可以应用到本系统中。 Java技术是一种成熟的技术,已经得到广泛的应用,J2EE技术规范已经得到大的中间件生成厂商如BEA公司、IBM公司的产品化支持。中间件技术是软件产品的发展方向,现在市场上已有大量的产品可供选择,因此在结合本系统需求开发数据中间件是可行的,在数...
  • wuyq11
  • wuyq11
  • 2008-03-16 09:14
  • 5448

QT的多语言实现

基本流程是:先生成ts文件,然后生成qm文件,最后通过QTranslator类来加载qm文件,实现多语言包的切换在Qt Creator中生成多国语言包1生成ts文件在QT的项目文件(.pro)中添加:TRANSLATIONS = XXX.ts YYY.ts(如果是多行,则用 \ 分割)//.pro文...
  • mlyjqx
  • mlyjqx
  • 2017-12-11 16:42
  • 110

字符串的多国语言支持解决方案 Qt篇

最近比较懒,公司的事情忙完后,在家也就是看看《Game Engine Architecture》,好久没有写博客了,总算遭到报应了,昨晚腹泻,发烧,冷汗,今天一天班都没上,于是,闲话少说,还是写篇博客吧.......    在不久以前,软件还是由一帮根本不知道世界上存在...
  • vagrxie
  • vagrxie
  • 2011-08-11 01:45
  • 8490

【大话QT之十四】QT实现多语言切换

QT制作多语言包,实现多语言切换。
  • houqingdong2012
  • houqingdong2012
  • 2014-07-18 20:10
  • 8766

QT学习笔记19数据库操作

1 数据库操作 Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作。这里我们所说的"平台独立",既包括操作系统平台,有包括各个数据库平台。另外,我们强调了"基于 SQL",因为 NoSQL 数据库至今没有一个通用查询方法,所以不可能提供一...
  • lzjsqn
  • lzjsqn
  • 2017-02-09 23:33
  • 745

QT国际化与多语言实现

1.Unicode编码         Unicode是一种支持世界上绝大多数文字系统的字符编码标准。QT中的QString类用于将字符串存储为Unicode。 2.应用程序如何翻译QT文件       如果想让应用程序能使...
  • VIPCCJ
  • VIPCCJ
  • 2015-11-16 13:25
  • 779

Qt入门-界面多语言国际化的实现

Qt为国际化的实现提供了简便的方法。下面使用Qt Linguist示例一个中文语言界面的生成。    我使用以前的实例:http://blog.csdn.net/xgbing/article/details/7778856    它是一个英文界面:...
  • imxiangzi
  • imxiangzi
  • 2016-03-21 15:10
  • 566

Qt多语言支持

试用QT中的多语言翻译 基本原理: 为了在使用多语言,必须做两件事情: 1,把想要翻译的字符串放入tr()中,如 QString str=tr("Legal"); 2, 在开始的时候载入预先制作好的翻译文件(.qm)。 以下利用Qt提供的工具,把翻译文件制作出来,并在程
  • lusugu
  • lusugu
  • 2011-08-23 11:30
  • 302

大学生实习就业调研报告之二 - 共性问题与企业技术&管理者探讨

针对学生反响强烈的有代表性和针对性的8类问题,CSDN高校俱乐部邀请BAT技术管理者、互联网企业CEO、创始人、人力资源管理者等人士对全部问题进行逐一答复,希望对即将毕业和迷茫中在读的大学生,提供借鉴帮助和指导裨益。
  • csdnstudent
  • csdnstudent
  • 2014-11-11 14:35
  • 9425

设计模式探讨

1、模式的定义:什么是模式?应该没有一个很精确的定义,但我们可以通俗的来说。模式是特定的‘语境’中重复出现的设计‘问题’的‘解决方案’。模式是人们经验的积累,人们利用经验来指导新的软件的设计。2、模式的分类:由模式用于解决问题的规模和它的抽象程度高低来划分,由高至低可分为体系结构模式(archite...
  • d9g_bj
  • d9g_bj
  • 2007-03-29 22:27
  • 557
    个人资料
    • 访问:352016次
    • 积分:4822
    • 等级:
    • 排名:第7056名
    • 原创:98篇
    • 转载:3篇
    • 译文:0篇
    • 评论:338条
    最新评论