使用 Qt 国际化

应用程序的 国际化本地化 是使应用程序适应目标市场的不同语言, 区域差异和技术要求的过程. 国际化意味着设计一个软件应用程序, 使其能够适应各种语言和地区, 而无需进行工程更改. 本地化是指通过添加特定于区域设置的组件 (例如日期, 时间和数字格式) 并翻译文本, 使国际化软件适应特定区域或语言.

Qt 相关的类和 API

下列表格中的类支持 Qt 应用程序的国家化.

QTextCodec

文本编码之间的转换

QTextDecoder

基于状态的解码器

QTextEncoder

基于状态的编码器

QTranslator

支持文本输出的国际化

QCollator

根据本地化排序算法比较字符串

QCollatorSortKey

可用于加速字符串排序

QLocale

在数字及其各种语言的字符串表示形式之间进行转换

Languages and Writing Systems

在某些情况下, 国际化很简单, 例如, 使澳大利亚或英国用户可以访问美国应用程序可能只需要进行一些拼写更正即可. 但是, 要使日本用户可以使用美国应用程序, 或者德国用户可以使用韩国应用程序, 不仅需要软件以不同的语言运行, 而且还需要使用不同的输入技术, 字符编码和表示约定.

Qt 试图让开发人员尽可能轻松地实现国际化. Qt 中的所有输入控件和文本绘制方法都为所有受支持的语言提供内置支持. 内置字体引擎能够正确且美观地呈现同时包含来自各种不同书写系统的字符的文本.

Qt 支持当今使用的大多数语言, 特别是:

  • All East Asian languages (Chinese, Japanese and Korean)
  • All Western languages (using Latin script)
  • Arabic
  • Cyrillic languages (Russian, Ukrainian, etc.)
  • Greek
  • Hebrew
  • Thai and Lao
  • All scripts in Unicode 6.2 that do not require special processing
  • Bengali
  • Burmese (Myanmar)
  • Devanagari
  • Gujarati
  • Gurmukhi
  • Kannada
  • Khmer
  • Malayalam
  • Tamil
  • Telugu
  • Tibetan

上面列表的语言是受支持的, 并且只要系统具有渲染这些安装的书写系统的字体, 就可以在所有平台上工作.

在带有 FontConfig (客户端字体支持) 的 Windows, Linux 和 Unix 上, 还支持以下语言:

  • Dhivehi (Thaana)
  • Syriac
  • N'Ko

在 macOS 上, 还支持以下语言:

  • Oriya
  • Sinhala

许多书写系统都有独特之处:

  • 特殊的断线行为. 一些亚洲语言的书写方式是单词之间没有空格. 换行可以发生在每个字符之后 (如中文, 日文和韩文), 也可以发生在逻辑词边界之后(如泰文).
  • 双向写作. 阿拉伯语和希伯来语是从右到左书写的, 但数字和嵌入的英文文本是从左到右书写的. 确切的行为在 Unicode Technical Annex #9 中定义.
  • 无空格或变音符号 (欧洲语言中的重音或元音变音). 一些语言 (例如越南语) 广泛使用这些标记,并且某些字符可以同时使用多个标记来澄清发音.
  • 连字. 在特殊上下文中, 某些字符对会被形成连字的组合字形所取代. 常见的例子是美国和欧洲书籍排版中使用的 fl 和 fi ligatures.

Qt 尝试处理上面列出的所有特殊功能. 只要你使用 Qt 的输入控件 (如. QLineEdit, QTextEdit, 和派生类或 Quick TextInput 项) 和 Qt 的显示控件 (如. QLabel and Qt Quick 的 Text 项), 你通常不必担心这些功能.

对这些书写系统的支持对于程序员来说是透明的,并且完全封装在 Qt 的文本引擎 中. 这意味着你通常不需要了解特定语言中使用的书写系统的任何知识, 除非你想编写自己的文本输入控件. 在某些语言中, 例如阿拉伯语或印度次大陆的语言, 字形的宽度和形状根据周围的字符而变化. 要考虑到这一点, 请使用 QTextLayout. 编写输入控件还需要了解它们将在其中使用的脚本. 通常, 最简单的方法是子类化 QLineEdit 或 QTextEdit.

  • QPainter::drawText(int x, int y, const QString &str) will always draw the string with its left edge at the position specified with the x, y parameters. This will usually give you left aligned strings. Arabic and Hebrew application strings are usually right aligned, so for these languages use the version of drawText() that takes a QRect since this will align in accordance with the language.
  • When you write your own text input controls, use QTextLayout. In some languages (e.g. Arabic or languages from the Indian subcontinent), the width and shape of a glyph changes depending on the surrounding characters, which QTextLayout takes into account. Writing input controls usually requires a certain knowledge of the scripts it is going to be used in. Usually the easiest way is to subclass QLineEdit or QTextEdit.

有关如何国际化源代码的更多信息, 参见 Writing Source Code for TranslationInternationalization and Localization with Qt Quick.

Producing Translations

Qt 为将 Qt C++ 和 Qt Quick 应用程序翻译成本地语言提供了出色的支持. 发布人员, 翻译人员和开发人员可以使用 Qt 翻译工具来完成他们的任务.

Qt 翻译工具, Qt Linguist, lupdate, 和 lrelease 在 Qt 安装根目录的 bin 子目录中. 有关使用它们的更多信息, 参见 Qt Linguist Manual.

Qt 本身包含数千个字符串, 这些字符串也需要翻译成您的目标语言. 你将在 qttranslations 存储库中找到许多翻译文件. 在开始翻译 Qt 之前, 参见 wiki 页面 Translating Qt Into Other Languages.

Enabling Translation

通常, 应用程序的 main() 函数如下所示:


  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 myappTranslator;
      myappTranslator.load("myapp_" + QLocale::system().name());
      app.installTranslator(&myappTranslator);

      ...
      return app.exec();
  }

对于支持翻译的应用程序,将创建一个 QTranslator 对象,然后根据用户在运行时首选的 UI 显示区域设置加载翻译,最后将翻译器对象安装到应用程序中。

对于支持翻译的应用程序, 创建一个 QTranslator 对象, 然后根据用户在运行时首选的 UI 显示区域设置加载翻译, 最后将 QTranslator 对象安装到应用程序中.

注意: 你还可以使用 QLibraryInfo::location() 查找所使用的 Qt 模块的翻译. 你可以在运行时, 将翻译路径通过 QLibraryInfo::TranslationsPath 传入, 替代 QTDIR 环境变量.

Support for Encodings

对于用户数据, QTextCodecQTextStream 中的工具可以轻松支持许多过时的输入和输出编码. 当应用程序启动时, 机器的区域设置将确定处理外部 8 位数据时使用的 8 位编码. QTextCodec::codecForLocale() 返回一个可用于在此区域设置编码和 Unicode 之间进行转换的编解码器.

应用程序有时可能需要默认本地 8 位编码以外的编码. 例如, 西里尔语 KOI8-R 语言环境 (俄罗斯事实上的标准语言环境) 中的应用程序可能需要以 ISO 8859-5 编码输出西里尔语. 代码如下:


  QString string = ...; // some Unicode text

  QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5");
  QByteArray encodedString = codec->fromUnicode(string);

为了将 Unicode 转换为本地 8 位编码, 可以使用一个快捷方式: QString::toLocal8Bit() 函数返回这样的 8 位数据. 另一个有用的快捷方式是 QString::toUtf8(), 它以 8 位 UTF-8 编码返回文本: 这完美地保留了 Unicode 信息, 同时如果文本完全是 ASCII, 则看起来像纯 ASCII.

对于另一种方式的转换, Qt 提供 QString::fromUtf8() 和 QString::fromLocal8Bit() 便捷函数, 或通用代码, 通过从 ISO 8859-5 西里尔字母到 Unicode 转换的转换来演示:


  QByteArray encodedString = ...; // some ISO 8859-5 encoded text

  QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5");
  QString string = codec->toUnicode(encodedString);

应使用 Unicode I/O, 因为这可以最大限度地提高世界各地用户之间文档的可移植性. 然而, 在许多情况下, 仍然需要支持其他编码, 因为你的用户需要处理现有文档. 要支持的最重要的附加编码是 QTextCodec::codecForLocale() 返回的编码, 因为这是用户最有可能需要与其他人和应用程序通信的编码 (这是 local8Bit() 使用的编解码器).

Qt 本身支持大多数更常用的编码. 有关支持的编码的完整列表, 参见 QTextCodec.

在某些情况下, 对于不太常用的编码, 可能需要编写自己的 QTextCodec 子类. 联系 Qt 的技术支持团队或在 qt-interest 邮件列表上询问以查看其他人是否已经在支持该编码可能会很有用.

Localizing Numbers, Dates, Times and Currency

本地化是适应当地惯例的过程, 例如使用当地首选的格式呈现日期和时间. 对于本地化的数字, 日期, 时间和货币字符串, 使用 QLocale.

不建议本地化图像. 选择适合所有地区的清晰图标, 而不是依赖当地的双关语或延伸的隐喻. 左右指向箭头的图像除外, 对于阿拉伯语和希伯来语语言环境, 可能需要颠倒这些箭头.

Dynamic Translation

某些应用程序 (例如 Qt Linguist) 必须能够支持在运行时更改用户的语言设置. 要使 widget 知道已安装的 QTranslator 对象的更改, 重新实现 widget 的 changeEvent() 函数, 检查该事件是否是 LanguageChange 事件, 并以通常的方式使用 tr() 函数更新 widget 显示的文本. 例如:


  void MyWidget::changeEvent(QEvent *event)
  {
      if (event->type() == QEvent::LanguageChange) {
          titleLabel->setText(tr("Document Title"));
          ...
          okPushButton->setText(tr("&OK"));
      } else
          QWidget::changeEvent(event);
  }

所有其他更改事件都应通过调用该函数的默认实现来传递.

已安装的翻译器列表可能会因 LocaleChange 事件而发生变化, 或者应用程序可能会提供允许用户更改当前应用程序语言的用户界面.

QWidget 子类的默认事件处理程序响应 QEvent::LanguageChange 事件, 并在必要时调用该函数.

当使用 QCoreApplication::installTranslator() 函数安装新翻译时, 将发布 LanguageChange 事件. 此外, 其他应用程序组件也可以通过向 widget 发布 LanguageChange 事件, 强制 widget 自我更新.

System Support

Qt 运行的某些操作系统和窗口系统对 Unicode 的支持有限. 底层系统中可用的支持级别对 Qt 在这些平台上提供的支持有一定影响, 尽管一般来说 Qt 应用程序不需要太关心特定于平台的限制.

Unix/X11
  • 面向区域设置的字体和输入方法. Qt 隐藏了这些并提供 Unicode 输入和输出.
  • 如今, 大多数Unix系统都默认使用 UTF-8 等文件系统约定. 所有 Qt 文件函数都允许 Unicode, 但将文件名转换为本地 8 位编码, 因为这是 Unix 约定 (参见 QFile::setEncodingFunction() 以探索替代编码).
  • 文件 I/O 默认为本地 8 位编码, 在 QTextStream 中带有 Unicode 选项.
  • 一些较旧的 Unix 发行版仅包含对某些语言环境的部分支持. 例如, 如果你有 /usr/share/locale/ja_JP.EUC 目录, 这并不一定意味着你可以显示日语文本: 你还需要安装日语字体, 并且 /usr/share/locale/ja_JP.EUC 目录需要完整. 为了获得最佳结果, 使用系统供应商提供的完整区域设置.
Linux
  • Qt 提供完整的 Unicode 支持, 包括输入法, 字体, 剪贴板, 拖放.
  • 在所有现代 Linux 发行版上, 文件系统通常采用 UTF-8 编码, 因此不会造成问题. 文件 I/O 默认为 UTF-8.
Windows
  • Qt 提供完整的 Unicode 支持, 包括输入法, 字体, 剪贴板, 拖放和文件名.
  • 文件 I/O 默认为 Latin1, QTextStream 中带有 Unicode 选项. 注意, 某些 Windows 程序无法理解大端 Unicode 文本文件, 即使这是 Unicode 标准在缺乏更高级别协议的情况下规定的顺序.
macOS

有关 macOS 特定翻译的详细信息, 参见 Qt for macOS 问题.

相关页面

Translation Rules for Plurals

A summary of the translation rules for plurals produced by Qt's i18n tools.

Qt Linguist Examples

Using Qt Linguist to internationalize your Qt application

Overview of the Translation Process

Qt Linguist Manual

Qt Linguist Manual: Developers

Qt Linguist Manual: Release Manager

Qt Linguist Manual: TS File Format

Qt Linguist Manual: Text ID Based Translations

Text ID based internationalization provides support for large scale projects with many target locales and many texts to translate

Qt Linguist Manual: Translators

Writing Source Code for Translation

How to write source code in a way that makes it possible for user-visible text to be translated.