关于qt中的tr()函数

在论坛中漂,经常遇到有人遇到tr相关的问题。用tr的有两类人:

  1. 因为发现中文老出问题,然后搜索,发现很多人用tr,于是他也开始用tr
  2. 另一类人,确实是出于国际化的需要,将需要在界面上显示的文件都用tr包起来,这有分两种:
    2a) 用tr包住英文(最最推荐的用法,源码英文,然后提供英文到其他语言的翻译包)
    2b) 用tr包住中文(源码用中文,然后提供中文到其他语言的翻译包)

注意哦,如果你正在用tr包裹中文字符,却不属于(2b),那么,这是个信号:

你在误用tr,你需要的是QString,而不是tr,如果你确实属于(2b),请做好心理准备,你可能还会遇到很多困难,请考虑Qt国际化(源码含中文时)的点滴分析

tr 是做什么的?下面二者的区别是什么?

QString text1 = QObject::tr("hello");
QString text2 = QString("hello");

tr是用来实现国际化,如果你为这个程序提供了中文翻译包(其中hello被翻译成中文"你好"),那么text1的内容将是中文"你好";如果你为程序提供且使用日文翻译包,那么text1的内容将是日文。

tr是经过多级函数调用才实现了翻译操作,是有代价的,所以不该用的时候最好不要用。

关注的对象
本文关注的是trtranslate中包含中文字符串的情况:

QObject::tr()

QCoreApplication::translate()

QTextCodec::setCodecForTr

这个问题本多少可说的。因为涉及到的编码问题和QString 与中文问题中是完全一样的,只不过一个是用的setCodecForCStrings一个用的是setCodecForTr

简单回顾QString的中文问题
QString 采用的unicode,在中文支持上不存在任何问题
“我是中文” 这是传统的 const char * 的窄字符串

当将窄字符串赋值到QString时,我们需要告诉它我们的窄串采用的何种编码(gbk?、utf-8?)
究竟何种编码主要取决于我们的源代码文件的编码(windows上一般是gbk,其他平台一般utf-8)
例子:

QString s1 = "我是中文";
QString s2("我是中文");
QString s3;
s3 = "我是中文";

s1、s2 用的是QString的构造函数QString ( const char * str )

s3 用的是QString的赋值操作符 QString & operator= ( const char * str)

如果不指定编码,s1,s2,s3将全部都是(国内大多数人所称的)乱码。因为QString将这些const char *按照latin1来解释的,而不是用户期待的gbk或utf8。

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"))

这两条语句中的一条可以解决问题,至于如何选择,此处不再重复。

QObject::tr
说实话,在tr中使用中文不是个好主意。不过既然总有人用(无论是(1)还是(2b)),而且总有人遇到问题,所以还是简单整理一下吧。

相比QCoreApplication::translate,大家用tr应该用的很多了,尽管不少人不清楚tr究竟是做什么的

tr(“我是中文”);
这调用的是下面这个函数(至少我们可这么认为是)。

QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 )

与QString(“我是中文”)完全一样,你必须告诉tr这个窄字符串是何种编码?你不告诉它,它就用latin1。于是所谓的乱码问题就出来了。

如何告诉tr你写的这几个汉字在磁盘中保存的是何种编码呢?这正是

QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

所做的。这两个选择的原则,由于和前文完全一样,此处也不再重复。

如果你的编码采用的utf8,可以直接使用trUtf8而不必设置setCodecForTr。

如果你只关心乱码问题,到此为止就可以了(下面不再关注编码)。如果想对tr进一步了解,不妨。。继续。。

QCoreApplication::translate
我们知道tr是用于实现程序的国际化(或者说多语言翻译),看Qt相关资料的话,我们知道实现该功能的还有下面这个函数:

QString QCoreApplication::translate ( const char * context, const char * sourceText, const char * disambiguation, Encoding encoding, int n )

其实,这个才是真正进行翻译操作的函数,前面我们提到的tr最终是通过调用该函数来实现翻译功能的(稍后我们会看tr是如何调用translate的)。

tr和这个函数,manual中都有比较详尽的解释。我们这儿简单看一下它的这几个参数:

context 上下文,一般就是需要翻译的字符串所在的类的名字
sourceText 需要翻译的字符串。(我们关注的编码其实就是它的编码)
disambiguation 消除歧义用的。(比如我们的类内出现两处"close",一处含义是关闭,另一处含义是亲密的。显然需要让翻译人员知道这点区别)
encoding 指定编码。它有两个值
CodecForTr 使用setCodecForTr()设置的编码来解释 sourceText

UnicodeUTF8 使用utf8编码来解释 sourceText
其实这两个分别对应tr和trUtf8
n 处理单复数(对中文来说,不存在这个问题)
tr与translate
这两个函数的说明,一个在QObject的manual,另一个在QCoreApplication的manual中。

介绍一下tr与translate的关系。前面提到了,tr调用的是translate。如果仅仅这样一说,没有证据,还真难以让大家相信。好吧,继续

tr 在何处定义
你可能说:这不废话吗,manual中写得明白的,它是QObject的静态成员函数。而且还有源码为证:

//来自 src/corelib/kernel/qobject.h
#ifdef qdoc
static QString `tr`(const char *sourceText, const char *comment = 0, int n = -1);
static QString trUtf8(const char *sourceText, const char *comment = 0, int n = -1);
#endif

嘿嘿,差点就被骗了,发现没:它们被预处理语句包住了。

这说明了什么呢?说明了这段代码仅仅是用来生成Qt那漂亮的文档的(qdoc3从代码中抽取信息,生成一系列的html格式的manual)。

啊,也就是说,这是假的。那么真正的定义呢??在一个大家都很熟悉的地方,猜猜看?

这就是

Q_OBJECT
该宏的定义在src/corelib/kernel/qobjectdefs.h中

#define Q_OBJECT \public: \Q_OBJECT_CHECK \static const QMetaObject staticMetaObject; \Q_OBJECT_GETSTATICMETAOBJECT \virtual const QMetaObject *metaObject() const; \virtual void *qt_metacast(const char *); \QT_TR_FUNCTIONS \virtual int qt_metacall(QMetaObject::Call, int, void **); \private:

其中的宏QT_TR_FUNCTIONS

\# define QT_TR_FUNCTIONS \static inline QString tr(const char *s, const char *c = 0) \{ return staticMetaObject.tr(s, c); } \static inline QString trUtf8(const char *s, const char *c = 0) \{ return staticMetaObject.trUtf8(s, c); } \static inline QString tr(const char *s, const char *c, int n) \{ return staticMetaObject.tr(s, c, n); } \static inline QString trUtf8(const char *s, const char *c, int n) \{ return staticMetaObject.trUtf8(s, c, n); }

现在看到:tr调用的是 staticMetaObject对象的tr函数,staticMetaObject 的定义在moc生成的 xxx.moc 或 moc_xxx.cpp 文件内(你随时可以验证的)。

staticMetaObject 是一个 QMetaObject 类的实例,我们继续看一下该类的源码:

/*!\internal
*/QString QMetaObject::tr(const char *s, const char *c) const{return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr);}/*!\internal
*/
QString QMetaObject::trUtf8(const char *s, const char *c) const
{
return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8);
}

Qt中tr()函数的使用相关推荐

  1. QT中main函数中加载外部字体:OTF

    QT中main函数中加载外部字体:OTF 我们开发的程序中,如果想使用外部下载的开源字体,同时保证在软件发布时,程序字体能保证和开发者环境下一致,且不想通过安装字体方式实现字体跟随软件时,我们需要在代 ...

  2. QTimer计时速度不断加快问题和QT中show函数失效问题的思考和处理

    使用QT所遇问题之QTimer和show 一. QTimer计时速度不断加快问题 1. 问题的发现 2.问题解决的思路 (1)梳理整个功能实现的逻辑 (2)监控进入定时器中断的次数 (3)跟踪参数lo ...

  3. QT中connect函数的几种用法详解总结

    前言 信号与槽机制是QT非常核心的东西,通过信号与槽我们可以将不同的部分有机的结合起来,使得各个组件之间的交互简单高效,信号与曹槽像是设计模式中的观察者模式(我自己觉得是这样),只关心信号何时发来,以 ...

  4. QT 中 connet 函数

    定义:connect,是QT中的连接函数,将信号发送者sender对象中的信号signal与接受者receiver中的member槽函数联系起来. 源码: static bool connect(co ...

  5. Qt中exec函数的作用

    Qt中的exec()方法到处可见,例如: QCoreApplicaton::exec()  QApplication::exec() QDialog::exec() QThread::exec() Q ...

  6. Qt中槽函数触发两次的两种场景分析

    在Qt开发中,有两种情况能够触发槽函数被触发两次,第一种情况是必现的,属于错误的写法,是指信号和槽关联两次:第二种情况是偶然出现的,是指对信号没有正确理解导致的. 1.信号与槽关联两次     通常这 ...

  7. qt中append函数_Qt 加载cern-root库 并调用root类

    cern-root是欧洲核子研究中心CERN开发的基于C++,可与python,R,Fortran等语言进行绑定的数据处理框架.cern-root最初基于Qt开发,在root5之前可通过Qt来开发ro ...

  8. qt中drawline函数的参数_在Qt GraphicsView中创建长线(或十字线)光标的最佳方法...

    如果我理解正确,您想绘制水平线和垂直线,在光标位置交叉,并且与视口一样大. 问题是,场景不知道鼠标的位置.这意味着视图必须跟踪它并在鼠标位置发生变化时通知场景. 要做到这一点,您必须创建自己的Grap ...

  9. Qt中sender()函数的用法

    你在一个槽里面,调用这个函数,返回的就是你信号来源的对象: QPushButton *aaaa = new QPushButton(this); 比如 connect(aaaaa, SIGNAL(Cl ...

最新文章

  1. 电液伺服系统_电液伺服系统的误差/偏差以及开环增益
  2. oracle 序列的使用
  3. “百亿补贴”真的能拯救一切吗?
  4. Windows 系统管理
  5. java俄文xml解析错误,XML解析出错处理
  6. php cli 编程,php-cli下编程如何分层架构、面向对象、统一入口文件?
  7. 线程也不是越多越好,多少是好?
  8. 180405之循环嵌套
  9. cs6给画笔分组_画笔工具,PS cs6笔刷入门介绍
  10. 【app爬虫】某宝详情页《问大家》数据采集分析
  11. java控制发送邮箱(qq邮箱、网易邮箱、新浪邮箱)
  12. php for iis express,iis10.0完整安装包
  13. [Irving]字符串相似度-字符编辑距离算法(c#实现)
  14. 扒一扒迅雷的代码结构
  15. 洛谷刷题C语言:CRNE、CETIRI、PRASE
  16. 数据结构:查找与排序
  17. python饼图添加颜色_Python中的五颜六色的饼状图!(二)
  18. 9.2.3 将警告视为错误
  19. vuex报错Computed property “xxx“ was assigned to but it has no setter.
  20. 计算机反复几次才能启动,电脑连续开机几次才能启动怎么办?

热门文章

  1. okhttp post提交参数完成登录功能 保存返回的token
  2. 美图的概念- M8美图
  3. 使用微信开放标签wx-open-launch-app实现从h5跳转至app
  4. access数据库窗体设计实验报告_ACCESS 查询和窗体实验报告
  5. win平板 安装linux系统下载,【年轻人的第一款4G Win8平板:七彩虹i108w 4G】安装Ubuntu 14.10 系统...
  6. 项目glossary
  7. jvm与Tomcat调优【详解】——有这一篇就够了
  8. oracle结果相减_oracle 两个时间相减得秒
  9. usb接口供电不足_Win7系统下电脑USB供电不足的解决方法
  10. python如何开发游戏脚本_python能开发游戏吗