Translating Applications¶
翻译应用程序¶
Qt Linguist¶ Qt 语言学家¶
Qt Linguist and
its related tools can be used to provide translations for applications.
Qt Linguist 及其相关工具可用于为应用程序提供翻译。
The Qt Linguist Example example illustrates this. The example is
very simple, it has a menu and shows a list of programming languages with
multiselection.
Qt Linguist 示例示例说明了这一点。这个例子非常简单,它有一个菜单,并显示了一个带有多选的编程语言列表。
Translation works by passing the message strings through function calls that
look up the translation. Each QObject instance provides a tr()
function for that purpose. There is also QCoreApplication.translate()
for adding translated texts to non-QObject classes.
翻译的工作原理是通过查找翻译的函数调用传递消息字符串。每个 QObject 实例都提供了一个 tr()
函数。还有 QCoreApplication.translate()
用于将翻译的文本添加到非 QObject 类中。
Qt ships its own translations containing the error messages and standard
dialog captions.
Qt 提供自己的翻译,其中包含错误消息和标准对话框标题。
The linguist example has a number of messages enclosed in self.tr().
The status bar message shown in response to a selection change uses
a plural form depending on a count:
linguist 示例在 self.tr() 中包含了许多消息。响应选择更改时显示的状态栏消息使用复数形式,具体取决于计数:
count = len(self._list_widget.selectionModel().selectedRows())
message = self.tr("%n language(s) selected", "", count)
The translation workflow for the example is as follows:
The translated messages are extracted using the lupdate tool,
producing XML-based .ts files:
该示例的翻译工作流程如下:使用 lupdate 工具提取已翻译的消息,生成基于 XML 的 .ts 文件:
pyside6-lupdate main.py -ts example_de.ts
If example_de.ts already exists, it will be updated with the new
messages added to the code in-between.
如果 example_de.ts 已存在,则将使用添加到中间代码的新消息对其进行更新。
If there are form files (.ui) and/or QML files (.qml) in the project,
they should be passed to the pyside6-lupdate tool as well:
如果项目中存在格式文件 (.ui) 和/或 QML 文件 (.qml),则还应将它们传递给 pyside6-lupdate 工具:
pyside6-lupdate main.py main.qml form.ui -ts example_de.ts
The source files generated by pyside6-uic from the form files
should not be passed.
不应传递 pyside6-uic 从表单文件生成的源文件。
The lupdate mode of pyside6-project can also be used for this. It
collects all source files and runs pyside6-lupdate when .ts file(s)
are given in the .pyproject file:pyside6-project 的 lupdate 模式也可以用于此目的。它收集所有源文件,并在 .pyproject 文件中给出 .ts 文件时运行 pyside6-lupdate:
pyside6-project lupdate .
.ts files are translated using Qt Linguist. Once this is complete,
the files are converted to a binary form (.qm files):.ts 文件都使用 Qt Linguist 进行翻译。完成此作后,文件将转换为二进制形式(.qm 文件):
pyside6-lrelease example_de.ts -qm example_de.qm
pyside6-project will build the .qm file automatically when
.ts file(s) are given in the .pyproject file:pyside6-project 将在
.ts 文件在 .pyproject 文件中给出:
pyside6-project build .
To avoid having to ship the .qm files, it is recommend
to put them into a Qt resource file along with icons and other
applications resources (see Using .qrc Files (pyside6-rcc)).
The resource file linguist.qrc provides the example_de.qm
under :/translations:
为避免必须提供 .qm 文件,建议将它们与图标和其他应用程序资源一起放入 Qt 资源文件中(请参阅使用 .qrc 文件 (pyside6-rcc))。资源文件 linguist.qrc 提供 example_de.qm
在 :/translations:
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="translations">
<file>example_de.qm</file>
</qresource>
</RCC>
At runtime, the translations need to be loaded using the QTranslator class:
在运行时,需要使用 QTranslator 类加载翻译:
path = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
translator = QTranslator(app)
if translator.load(QLocale.system(), 'qtbase', '_', path):
app.installTranslator(translator)
translator = QTranslator(app)
path = ':/translations'
if translator.load(QLocale.system(), 'example', '_', path):
app.installTranslator(translator)
The code first loads the translations shipped for Qt and then
the translations of the applications loaded from resources.
该代码首先加载为 Qt 提供的翻译,然后加载从资源加载的应用程序的翻译。
The example can then be run in German:
然后,可以用德语运行该示例:
LANG=de python main.py
GNU gettext¶
The GNU gettext module
can be used to provide translations for applications.
GNU gettext 模块可用于为应用程序提供翻译。
The GNU gettext Example example illustrates this. The example is
very simple, it has a menu and shows a list of programming languages with
multiselection.
GNU gettext 示例示例说明了这一点。这个例子非常简单,它有一个菜单,并显示了一个带有多选的编程语言列表。
Translation works by passing the message strings through function calls that
look up the translation. It is common to alias the main translation function
to _. There is a special translation function for sentences that contain
a plural form depending on a count (“{0} items(s) selected”). It is commonly
aliased to ngettext.
翻译的工作原理是通过查找翻译的函数调用传递消息字符串。将主转换函数的别名设置为 _ 是很常见的。对于包含复数形式的句子,有一个特殊的翻译功能,具体取决于计数(“{0} 项选择”)。它通常别名为 ngettext。
Those functions are defined at the top:
这些函数在顶部定义:
import gettext
# ...
_ = None
ngettext = None
and later assigned as follows:
后来分配如下:
src_dir = Path(__file__).resolve().parent
try:
translation = gettext.translation('example', localedir=src_dir / 'locales')
if translation:
translation.install()
_ = translation.gettext
ngettext = translation.ngettext
except FileNotFoundError:
pass
if not _:
_ = gettext.gettext
ngettext = gettext.ngettext
This specifies that our translation file has the base name example and
will be found in the source tree under locales. The code will try
to load a translation matching the current language.
这指定了我们的翻译文件具有基本名称示例 ,并且将在源代码树的 locales 下找到。该代码将尝试加载与当前语言匹配的翻译。
Messages to be translated look like:
要翻译的消息如下所示:
file_menu = self.menuBar().addMenu(_("&File"))
The status bar message shown in response to a selection change uses
a plural form depending on a count:
响应选择更改而显示的状态栏消息使用复数形式,具体取决于计数:
count = len(self._list_widget.selectionModel().selectedRows())
message = ngettext("{0} language selected",
"{0} languages selected", count).format(count)
The ngettext() function takes the singular form, plural form and the count.
The returned string still contains the formatting placeholder, so it needs
to be passed through format().ngettext() 函数采用单数形式、复数形式和计数。返回的字符串仍然包含格式化占位符,因此需要通过 format() 传递。
In order to translate the messages to say German, a template file (.pot)
is first created:
为了将消息翻译成德语,首先创建一个模板文件 (.pot):
mkdir -p locales/de_DE/LC_MESSAGES
xgettext -L Python -o locales/example.pot main.py
This file has a few generic placeholders which can be replaced by the
appropriate values. It is then copied to the de_DE/LC_MESSAGES directory.
此文件有一些通用占位符,可以替换为适当的值。然后将其复制到 de_DE/LC_MESSAGES 目录。
cd locales/de_DE/LC_MESSAGES/
cp ../../example.pot .
Further adaptions need to be made to account for the German plural
form and encoding:
需要进一步调整以考虑德语复数形式和编码:
"Project-Id-Version: PySide6 gettext example\n"
"POT-Creation-Date: 2021-07-05 14:16+0200\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
Below, the translated messages can be given:
下面,可以给出翻译后的信息:
#: main.py:57
msgid "&File"
msgstr "&Datei"
Finally, the .pot is converted to its binary form (machine object file,
.mo), which needs to be deployed:
最后, 将 .pot 转换为其二进制形式(机器目标文件、
.mo),需要部署:
msgfmt -o example.mo example.pot
The example can then be run in German:
然后,可以用德语运行该示例:
LANG=de python main.py