• 9181阅读
  • 3回复

[建议]Qt C++源码中使用中文所需了解的细节 [复制链接]

上一主题 下一主题
离线dbzhang800
 

只看楼主 倒序阅读 楼主  发表于: 2013-05-20
— 本帖被 dbzhang800 执行取消置顶操作(2013-08-07) —
网络上Qt的中文相关的内容非常多,与之相应,错误也相当多。为了使大家少走弯路,本文准备简单整理一下相关内容,但具体还没想好怎么写 ^_^

问题: 为何不建议使用中文?
                    


如果你有追求简单或追求完美的癖好,源码内避免中文几乎是唯一选择。

由于C++标准本身的对源文件的编码没有任何规定,使得各个编译器对此可以随意发挥。故尔一旦使用了非ASCII的字符,可能会出现各种稀奇古怪的现象。尤其以MSVC对非ASCII编码的支持最为奇葩,完全一样的代码在不同语言的操作系统中可以得到完全不同的结果。

源码内使用ASCII代码,同时使用Qt提供的i18n方案,可以使得你的程序在不同环境下的行为都是正确的。

但如果你坚持使用中文,那么...

问题: UTF-8  还是 GBK ?
                  


为了简化问题,我们此处不去区分C、C++中和中文密切相关的input-charset 和 exec-charset 这两个概念,暂且认为二者一致(如果你想彻底理清问题,区分二者却是必不可少的)

  1. 如果你在使用VS2003,你应该使用 GBK ,且使用简体中文操作系统(你的代码在其他语言的系统下编译是有问题的)。

  2. 如果你在使用VS2005或VS2008,你只能使用 GBK,且使用简体中文操作系统

  3. 如果你在使用VS2010,尽管你仍可以使用GBK和简体中文操作系统,但最好选择 UTF-8(可跨各个语言)

  4. 如果你在使用GCC或Intel C++ 编译器或其他,首选 UTF-8


尽管从VS2010起,开始支持UTF-8,但是需要2个操作。
  1. 源码保存为 带 BOM 的UTF-8 (用以保证input-charset是UTF8)
  2. 源码开头添加如下代码  (用以保证exec-charset是UTF8)

  1. #if _MSC_VER >= 1600
  2. #pragma execution_character_set("utf-8")
  3. #endif

在Qt4下,我们可以告诉Qt我们使用的是何种字符集。可是,


问题: Qt5下如何选择?
                  


从 Qt5.0开始,问题得到极大的简化, 你只能选择UTF-8作为执行字符集。同时,根据前面的分析,由于VS2005和VS2008无法使用UTF8作为执行字符集,故尔它们将无法用于这种场合!!

Qt4中的GBK那些用法不再有效,如果你仍要用GBK,请自行进行GBK编码的char* 到 Unicode的QString的转化。


选择了编码并不是问题的结束,恰恰相反,它只是问题的开始

问题: setCodecForXxxxxx() 如何使用?
                  


在Qt4时代,网络中充斥大量的setCodecForXxxxx的语句,但绝大多数的用法都是不规范的(或者说碰巧可以得到正确的结果)。

建议如下:
代码 Qt4 Qt5
QTextCodec::setCodecForCStrings(); 正确用法 不复存在
QTextCodec::setCodecForTr(); 不要使用 不复存在
QTextCodec::setCodecForLocale(); 不要使用 不要使用


注意:
  1. tr() 是被滥用最多的函数之一,请不要纯粹为了中文乱码而使用它!

  2. 在Qt4中,请根据你所使用的是GBK还是UTF-8调用setCodecForCStrings()即可

  3. 在Qt5中,请确保你所使用的编码是UTF-8

  4. 不要使用codecForName("System")!!


比如,不少网友在简体中文Windows下使用GBK时,会混用下面几个语句:
  1. QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
  2. QTextCodec::setCodecForCStrings(QTextCodec::codecForName("System"));
  3. QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());

后者的问题是,在非简体中文系统下,程序乱码!所以,不要使用后两个语句

问题:为什么开发机上正常,发布时乱码?
                  


如果同一个字符串中的字符,部分正常,部分显示为方框或不显示。一般来说是字体问题,请安装相应字体。

如果中文显示的乱码,而且你是在Qt4下使用的GBK编码,那么应该是你没有发布相应的GBK编解码插件。

* application.exe
* codecs\qcncodecs4.dll

注意:一定要有那个codecs目录!!

问题:编译运行时,Qt自带对话框或控件为何显示英文?
                  


Qt源码中的字符串都是英文,其国际化是通过程序加载相应的翻译文件来实现的。 翻译文件位于translations目录中

Qt4 Qt5
qt_zh_CN.qm qt_zh_CN.qm
qt_help_zh_CN.qm qt_help_zh_CN.qm
assistant_zh_CN.qm assistant_zh_CN.qm
... qtquick1_zh_CN.qm
... qtscript_zh_CN.qm
... ...


要让Qt内部的字符串正确显示中文,你必须安装Qt提供的你所需要的qm文件。代码片段如下:

  1. int main(int argc, char *argv[])
  2. {
  3.     QApplication a(argc, argv);
  4.     QTranslator *translator = new QTranslator(QCoreApplication::instance());
  5.     if (translator->load("qt_zh_CN", YourDirPath)) {
  6.         QCoreApplication::installTranslator(translator);
  7. ...


其中,YourDirPath可以用 QLibraryInfo::location(QLibraryInfo::TranslationsPath),也可以使用你自己喜欢的包含.qm文件的目录。

如果想让它根据locale加载不同语言的翻译文件,你也可以直接使用下列代码(该代码来自Qt Assistant的源码):

  1. void setupTranslation(const QString &fileName, const QString &dir)
  2. {
  3.     QTranslator *translator = new QTranslator(QCoreApplication::instance());
  4.     if (translator->load(fileName, dir)) {
  5.         QCoreApplication::installTranslator(translator);
  6.     } else if (!fileName.endsWith(QLatin1String("en_US"))  && !fileName.endsWith(QLatin1String("_C"))) {
  7.         qWarning("Could not load translation file %s in directory %s.",  qPrintable(fileName), qPrintable(dir));
  8.     }
  9. }
  10. void setupTranslations()
  11. {
  12.     const QString& locale = QLocale::system().name();
  13.     const QString &resourceDir  = QLibraryInfo::location(QLibraryInfo::TranslationsPath); //假定所有翻译文件在Qt的标准翻译目录下
  14.     setupTranslation(QLatin1String("yourself_") + locale, resourceDir);
  15.     setupTranslation(QLatin1String("qt_") + locale, resourceDir);
  16.     setupTranslation(QLatin1String("qt_help_") + locale, resourceDir);
  17. }
  18. int main(int argc, char *argv[])
  19. {
  20.     QApplication a(argc, argv);
  21.     setupTranslations();
  22. ...


问题:发布时,Qt自带的对话框或Assistant等工具为何是英文?
                  


仅仅代码中有相应的加载代码还是不够的,程序发布时,你需要发布你所需要的所有 .qm 文件,并且需要让你的程序能够找到他们。

情况一:代码中使用完全自定义目录,比如说,放置于可执行程序所在目录 QCoreApplication::applicationDirPath() 下的某个文件夹。这个没什么好说的。

情况二:使用标准目录 QLibraryInfo::location(QLibraryInfo::TranslationsPath)。在开发程序的机器上,它就是Qt下面的translations目录。可是发布程序是,这些 .qm 该放置于何处呢??

答案:我们可以随意放置,只需要通过创建一个 qt.conf 文件,在该文件内指定一下目录即可。比如

  1. [Paths]
  2.     Prefix=.
  3.     Translations = translations


问题: ?

问题: ?

问题: ?

问题: ?


推荐相关文章
            

关于Qt4程序支持中文方法的总结

QString 乱谈(2)-C++中的中文







离线neil-wen

只看该作者 1楼 发表于: 2013-08-08
多谢楼主的详细分析,收益了
离线ppdayz

只看该作者 2楼 发表于: 2013-08-08
MSVC是个奇葩,现在代码为了能跨平台,所有的编码都是UTF-8 不带bom,遇到中文注释msvc就会waring,受不了了。
离线jdwx

只看该作者 3楼 发表于: 2013-08-08
非常有用!顶起来!
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
快速回复
限100 字节
 
上一个 下一个