Skip to content

Qt 工程实战:中文字符编码与国际化

在 Windows 平台使用 MSVC 编译器开发 Qt 项目时,界面中文乱码(如显示为“锟斤拷”或问号)以及多语言跨国支持是工程上线前最常遇到的问题。

本文从底层编码机制出发,提供一击必杀的乱码解决方案,并介绍规范的国际化(I18N)开发流程。


1. 中文字符乱码的本质原因

中文乱码通常是由于 源码文件编码编译器执行字符集Qt 内部编码 三者不一致导致的:

  1. 源码编码:编辑器(如 VSCode、Qt Creator)默认以 UTF-8 格式保存 .cpp 源码。
  2. 编译器解析字符集:Windows 下 MSVC 编译器默认以系统本地编码(中国地区默认为 GBK)去读取源码中的中文文本字面量。
  3. Qt 内部存储QString 内部统一采用 UTF-16 保存,接收字面量时默认以为是 UTF-8。MSVC 用 GBK 解析 UTF-8 源码编译出来的二进制字符本身就是错的,最终界面必然乱码。

2. 彻底解决中文乱码的三步法则

第一步:强制编译器采用 UTF-8 编译(关键)

必须在构建配置中显式加入 /utf-8 编译参数,强制 MSVC 编译器统一采用 UTF-8 解析和执行字符集。

  • 使用 CMake 时,在 CMakeLists.txt 中添加:
    cmake
    if(MSVC)
        add_compile_options(/utf-8)
    endif()
  • 使用 qmake 时,在 .pro 中添加:
    make
    msvc {
        QMAKE_CFLAGS += /utf-8
        QMAKE_CXXFLAGS += /utf-8
    }

第二步:源码中优先使用 QStringLiteral

不要直接写 QString("中文"),推荐使用 QStringLiteral 宏。

  • 原理QStringLiteral编译期直接生成存储在只读数据段的 QString 内部只读对象,彻底避开了运行期动态转换开销,且避免了字符集误判。
cpp
ui->label->setText(QStringLiteral("欢迎使用系统"));

第三步:读取本地外部非 UTF-8 文本

如果需要读取本地 GBK / ANSI 编码的文件或串口数据,使用 QString::fromLocal8Bit

cpp
QString localStr = QString::fromLocal8Bit(rawByteArray);

3. 规范的国际化 (I18N) 开发流程

为了支持多语言切换,不应将中文硬编码在界面控件中,而应通过 tr() 函数包裹:

3.1 编写可翻译代码

所有面向用户的文本均使用 tr() 包装:

cpp
ui->label->setText(tr("Welcome to System"));

3.2 提取与翻译流程

  1. 生成 .ts 翻译源文件:在 CMake / qmake 中配置 lupdate 工具提取代码中所有的 tr() 字符串;
  2. 翻译文件:使用 Qt 官方提供的 Qt Linguist 工具打开 .ts 文件完成各语言翻译;
  3. 编译 .qm 二进制包:使用 lrelease.ts 编译为体积小的 .qm 二进制文件;
  4. 运行时加载:使用 QTranslator 在程序启动或运行时动态加载目标语言包:
cpp
QTranslator translator;
if (translator.load("app_zh_CN.qm")) {
    qApp->installTranslator(&translator);
}

4. 总结

  1. 解决乱码根本:CMake 配置 /utf-8 参数解决 MSVC 编译字符集不一致,从源头消除乱码。
  2. 高性能字面量:代码内部中文字符优先使用 QStringLiteral 编译期构建字符串。
  3. 国际化标准:用户可见文本统一采用 tr() 包装,配合 QTranslator 与 Qt Linguist 完成多语言发布。

基于 VitePress 强力驱动 | 记录技术与生活