QT是支持多语言的,能够支持不同语言的动态切换,不同语言对应的编码格式转换,不同语言字体使用不同字库进行显示。

编码

QT对于字符串的处理使用了基本类型QString,它将所有传递给它的字符串或者字符使用UTF16格式存储起来。 那么问题来了,对于中文"你好"的编码格式可能是GBK或者UTF8或者UTF16等,对于英文则默认使用UTF8(ASCII兼容)。 因此需要将这些字符进行编码格式化转换。 格式转换大概会出现在下面几个地方:

1、代码编写时

QString message="你好".

在不同的编辑器中输入"你好",对应的编码可能不一样。使用QtCreator可以设置编辑器默认使用的编码格式,我喜欢使用UTF8格式(在项目的属性设置对话框中)。

代码中"你好"这时候实际上和"hello"没什么区别了,只是一个数组对应{0x11,0x12,0x13...};

2、char*和QString之间转换  QByteArray和QString之间转换

上面代码中,对QString进行赋值会调用到QString::operator(const QString&)函数,中间会将char[]转换成QString,调用QString(const char*)。 在这里它需要将char*中的字符串的编码格式进行转换了。现在问题来了,QString不知道char* 中字符串的编码格式。(编码格式那么多,不可能挨个去试)。 这时候使用

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

它就告诉我们怎么在QString和char*之间如何进行编码转换。

对于QByteArray和QString之间的转换也是一样的。

3、tr宏

对于多语言来说,需要使用到tr,这个函数的定义:

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

从定义上可以看出输入的是char*,输出的却是QString,这其中肯定涉及到编码格式转换的问题。不过QT使用了另外一个函数对这个行为进行控制:
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); 
下面可以看到,它实际上控制当翻译不成功时,如何将char*转换为QString。

4、业务流程需要编码转换

现在"你好"以及以UTF16的编码格式存储在message中了,若是需要将这个字符串写入一个记事本文件中并且希望用户打开文件后看到的不是乱码?

在这里,我们输出的字符串可能是中文,且国内大部分操作系统中编辑器默认使用的编码格式是GBK,所以:

QTextCodec::codecForName("GBK")->fromUnicode(message)

上面代码返回的就是"你好"的GBK编码数据,将它写入文件后,字符才能正常显示。

当然,若是使用"BIG5“编码格式的编辑器的话,那么上面的代码就需要改为:

QTextCodec::codecForName("GBK")->fromUnicode(message)

翻译

对于需要进行翻译的文字,需要使用tr("")进行包裹,例如QString c = tr("汉字"),在不同的语言设置中,返回不同的字符。这个函数的源码:

    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); }
QString QMetaObject::tr(const char *s, const char *c) const
{return QCoreApplication::translate(d.stringdata, s, c, <span style="color:#ff0000;">QCoreApplication::CodecForTr</span>);
}
QString QCoreApplication::translate(const char *context, const char *sourceText,const char *disambiguation, Encoding encoding)
{return translate(context, sourceText, disambiguation, encoding, -1);
}
QString QCoreApplication::translate(const char *context, const char *sourceText,const char *disambiguation, Encoding encoding, int n)
{QString result;if (!sourceText)return result;if (self && !self->d_func()->translators.isEmpty()) {QList<QTranslator*>::ConstIterator it;QTranslator *translationFile;for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {translationFile = *it;result = <span style="color:#ff0000;">translationFile->translate(context, sourceText, disambiguation, n);</span>if (!result.isEmpty())break;}}if (result.isEmpty()) {
#ifdef QT_NO_TEXTCODECQ_UNUSED(encoding)
#elseif (encoding == UnicodeUTF8)result = QString::fromUtf8(sourceText);else if (QTextCodec::codecForTr() != 0)result = QTextCodec::codecForTr()->toUnicode(sourceText);else
#endifresult = QString::fromLatin1(sourceText);}replacePercentN(&result, n);return result;
}

注意上面调用translate时会传入QCoreApplication::CodecForTr,它实际上控制着翻译不成功时如何将char*转为QString。

从上面可以看到,最终调用的是QTranslator::translate,它实际上调用的函数是:

QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText,const char *comment, int n) const
{if (context == 0)context = "";if (sourceText == 0)sourceText = "";if (comment == 0)comment = "";if (!offsetLength)return QString();/*Check if the context belongs to this QTranslator. If manytranslators are installed, this step is necessary.*/if (contextLength) {quint16 hTableSize = read16(contextArray);uint g = elfHash(context) % hTableSize;const uchar *c = contextArray + 2 + (g << 1);quint16 off = read16(c);c += 2;if (off == 0)return QString();c = contextArray + (2 + (hTableSize << 1) + (off << 1));for (;;) {quint8 len = read8(c++);if (len == 0)return QString();if (match(c, context, len))break;c += len;}}size_t numItems = offsetLength / (2 * sizeof(quint32));if (!numItems)return QString();int numerus = 0;if (n >= 0)numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);for (;;) {quint32 h = elfHash(QByteArray(sourceText) + comment);const uchar *start = offsetArray;const uchar *end = start + ((numItems-1) << 3);while (start <= end) {const uchar *middle = start + (((end - start) >> 4) << 3);uint hash = read32(middle);if (h == hash) {start = middle;break;} else if (hash < h) {start = middle + 8;} else {end = middle - 8;}}if (start <= end) {// go back on equal keywhile (start != offsetArray && read32(start) == read32(start-8))start -= 8;while (start < offsetArray + offsetLength) {quint32 rh = read32(start);start += 4;if (rh != h)break;quint32 ro = read32(start);start += 4;QString tn = getMessage(messageArray + ro, messageArray + messageLength, context,sourceText, comment, numerus);if (!tn.isNull())return tn;}}if (!comment[0])break;comment = "";}return QString();
}

do_translate将从offsetArray指向的中查找对应的翻译字符串,中间涉及的存储结构以及如何查找和Hash表相关。

使用时步骤:

1、将所有需要翻译的字符使用tr("")包裹起来

2、在项目文件中定义TRANSLATIONS,指定翻译文件生成路径

3、使用lupdate生成ts文件

4、使用Linguist对ts文件进行翻译

5、使用lrelease将ts文件转换为qm文件

6、将qm文件部署到设备上

7、代码中添加对qm文件的加载,根据不同的业务加载不同的文件:

                translatorpass = new QTranslator();//removeTranslator(translatorpass); 如果之前添加过,需要先删除translatorpass->load("en.ts","/usr/local/translation");

字库

除了编码和翻译问题,还需要解决字库部署问题。例如,在支持中文的基础上,需要添加对阿拉伯语的支持,除了涉及翻译和编码外,还需要部署支持阿拉伯的字库文件。
不然当切换到阿拉伯下,整个界面对于阿拉伯语的显示就有问题。

对于中文,我们可以使用文泉译这种开源字库(wqy-zenhei.ttf), 对于阿拉伯语则找到了名为DroidSansArabic.ttf的字库。将这两个字库放入QT安装路径下的font文件夹下,QT就能找到他们。

当然,也可以使用其他方式进行部署,例如指定fontdir的路径,然后在fontdir中定义字库名字。

业务逻辑实现时,需要动态切换字库,则需要调用

void QApplication::setFont(const QFont &font, const char *className)

它会指定整个应用的默认字库

对于整个系统支持的字库文件可以使用下面程序进行查询:

QFontDatabase database;
QStringList families=database.families();

文字输入/显示方向

上面提到的阿拉伯语在显示文字是从右往左,这个实现比较简单。

程序中声明

QApplication::tr("QT_LAYOUT_DIRECTION");

然后在ts文件中将它翻译成"RTL",即可。

因为在文字显示过程中,有这样一句代码:

static bool qt_detectRTLLanguage()
{return force_reverse ^(QApplication::tr("QT_LAYOUT_DIRECTION","Translate this string to the string 'LTR' in left-to-right"" languages or to 'RTL' in right-to-left languages (such as Hebrew"" and Arabic) to get proper widget layout.") == QLatin1String("RTL"));
}

QT 多语言 字库 编码 文字方向相关问题相关推荐

  1. drawtext函数用法设置字体 qt,解决QPainter::drawText修改文字方向

    今天在绘制双坐标曲线的时候需要修改y轴文字提示 QPainter的drawText()函数提供了绘制文本的功能. 它有几种重载形式,我们使用了其中的一种,即制定文本的坐标然后绘制 正常我们的文字书写方 ...

  2. 引用 字库编码Unicode相关知识

    引用 weifeng.shen 的 字库编码Unicode相关知识 1.      各地编码 首先说明一下现在常用的一些编码方案: 1.         在中国,大陆最常用的就是GBK18030编码, ...

  3. [Messy Note 1] 有关文本编辑语言及编码的一些概念

    1.纯文本与富文本 纯文本--只有文字和基本的标点,如记事本.(纯文本格式:Plain Text Format) 富文本--可以有图以及各种特殊标点,分段等格式,如 Word.(富文本格式:Rich ...

  4. 学习c语言未来的就业方向_语言学习的未来

    学习c语言未来的就业方向 Making quality language learning content is hard. Duolingo, which is perhaps the most p ...

  5. 使用Python基于VGG/CTPN/CRNN的自然场景文字方向检测/区域检测/不定长OCR识别

    GitHub:https://github.com/pengcao/chinese_ocr https://github.com/xiaofengShi/CHINESE-OCR |-angle 基于V ...

  6. Qt中的字符编码转换:UTF8、Unicode、GBK、ASCII、16进制字符、16进制数值

    文章目录 前言 简述 ASCII GBK Unicode UTF-8 应用场景 开发环境 编码转换 16进制数值转换为16进制字符 16进制数值转化为字符串 16进制字符串转换为Unicode字符串 ...

  7. c语言程序设计A课程试,自学考试有关论文范文,与C语言程序设计A课程辅导相关硕士毕业论文范文...

    自学考试有关论文范文,与C语言程序设计A课程辅导相关硕士毕业论文范文 关于自学考试及高等教育自学考试及控件方面的免费优秀学术论文范文,自学考试有关毕业论文开题报告,关于C语言程序设计A课程辅导相关论文 ...

  8. QT乱码总结8.编码测试和总结三

    QT乱码总结0.Qt乱码产生因素 https://blog.csdn.net/liujiayu2/article/details/103167953 QT乱码总结1.Unicode 和 UTF-8 h ...

  9. QT乱码总结6.编码测试和总结一

    QT乱码总结0.Qt乱码产生因素 https://blog.csdn.net/liujiayu2/article/details/103167953 QT乱码总结1.Unicode 和 UTF-8 h ...

最新文章

  1. 3 css 奖品出现弹出动画_【技术】nuxt中引入wow和animate.css 页面随滚动条出现动画...
  2. Jmeter Md5加密操作之-------BeanShell PreProcessor
  3. 5训练需要更改参数吗_这就是需要的瘦肚子训练,5个杠铃片腹肌训练动作暴汗燃脂瘦腰腹...
  4. zookeeper启动占用8080端口
  5. 在控制台中录入学生成绩,计算总分,最高分,最低分(Python)
  6. sysdig案例分析 - 哪些文件正在被进程访问
  7. 利用最新Apache解析漏洞(CVE-2017-15715)绕过上传黑名单
  8. 执行ssh-add时出现Could not open a connection to your authentication agent
  9. 阿里第二代微服务强势崛起,你还敢往简历上写“精通”吗?
  10. linux rename
  11. Java程序猿从笨鸟到菜鸟之(九十二)深入java虚拟机(一)——java虚拟机底层结构具体解释...
  12. clickhouse 分布式表
  13. 【跃迁之路】【507天】程序员高效学习方法论探索系列(实验阶段264-2018.06.27)...
  14. BZOJ3687 简单题
  15. 如何登录新浪微博html5,新浪微博怎么用登录名登录
  16. 如何朴实无华的双开微信?
  17. Assembler - Debug
  18. 2005-10-22 风波
  19. IEMS_11_课程信息相关的初始数据导入
  20. java解析JT808协议-netty

热门文章

  1. CDOJ 1347柱爷的矩阵(二维dp)
  2. 大学四年因为知道了这32个网站,我成了别人眼中的大神!
  3. itext 合并 pdf 并插入页码
  4. 炒股的10个境界,你在第几级?
  5. Kettle5.2 couldn't convert string [...] to a date using format [yyyy/MM/dd HH:mm:ss.SSS]
  6. 现代程序员 VS. 古典程序员,你属于哪一类?
  7. 用ultraiso安装linux系统教程,U盘安装Ubuntu 10.04 Beta 1 (利用UltraISO制作LiveCD)
  8. 解决Waiting for incoming connection with ide key xdebug错误
  9. [luogu] P4735 最大异或和
  10. 2019北航考研机试题解