翻译应用程序#
Qt Linguist#
Qt Linguist及其相关工具可用于为应用程序提供翻译。
例子中的Qt Linguist示例展示了这一点。示例非常简单,它有一个菜单,显示一个具有多选功能的编程语言列表。
翻译通过传递消息字符串通过调用查找翻译的功能来实现。每个QObject
实例都提供了一个tr()
功能。还有一个QCoreApplication.translate()
用于将翻译文本添加到非QObject
类中。
Qt自带其自己的翻译,包含错误消息和标准对话框标题。
语言学家例子中有一些消息包含在self.tr()
中。选择更改时显示的状态栏消息使用一个基于计数的复数形式
count = len(self._list_widget.selectionModel().selectedRows())
message = self.tr("%n language(s) selected", "", count)
示例的翻译工作流程如下:使用lupdate
工具提取翻译的消息,生成基于XML的.ts
文件
pyside6-lupdate main.py -ts example_de.ts
如果example_de.ts
已经存在,它将以在代码间添加的新消息更新。
如果项目中包含表单文件(.ui
)和/或QML文件(.qml
),它们也应该传递给pyside6-lupdate
工具
pyside6-lupdate main.py main.qml form.ui -ts example_de.ts
由pyside6-uic
从表单文件生成的源文件不应传递。
PySide6-项目中的lupdate
模式也可以用于此。它会收集所有源文件,并在.pyproject
文件中提供了.ts
文件时运行pyside6-lupdate
。
pyside6-project lupdate .
.ts
文件使用Qt Linguist进行翻译。一旦完成,文件将转换为二进制形式(.qm
文件)。
pyside6-lrelease example_de.ts -qm example_de.qm
当在.pyproject
文件中提供.ts
文件时,pyside6-project
将自动构建.qm
文件。
pyside6-project build .
为了避免发送.qm
文件,建议将它们放入一个Qt资源文件中,与图标和其他应用资源一起(请参阅使用.qrc文件(pyside6-rcc))。资源文件linguist.qrc
提供了位于:/translations
下的example_de.qm
。
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="translations">
<file>example_de.qm</file>
</qresource>
</RCC>
在运行时,需要使用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)
代码首先加载Qt提供的翻译,然后加载资源中加载的应用程序的翻译。
然后可以通过示例以德语运行。
LANG=de python main.py
GNU gettext#
可以使用GNU gettext模块为应用程序提供翻译。
GNU gettext示例展示了这一点。这个例子非常简单,它有一个菜单,并显示一个多选的编程语言列表。
翻译是通过传递消息字符串通过查找翻译的功能调用来实现的。通常将主要的翻译功能别名到_
。对于一个包含基于计数的选择性单数形式的外部句子,有一个特殊的翻译函数。它通常别名为ngettext
。
这些函数在顶部定义
import gettext
# ...
_ = None
ngettext = None
然后按如下方式分配
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
这指定了我们的翻译文件具有基本名称example
,并将位于locales
源代码树中。代码将尝试加载与当前语言匹配的翻译。
要翻译的消息看起来像这样
file_menu = self.menuBar().addMenu(_("&File"))
响应于选择更改所显示的状态栏信息使用基于计数的复数形式
count = len(self._list_widget.selectionModel().selectedRows())
message = ngettext("{0} language selected",
"{0} languages selected", count).format(count)
ngettext()
函数接收单数形式、复数形式和计数。返回的字符串仍然包含格式化占位符,因此需要通过format()
传递。
为了将消息翻译成德语,首先创建了一个模板文件(.pot
)
mkdir -p locales/de_DE/LC_MESSAGES
xgettext -L Python -o locales/example.pot main.py
该文件有几个通用的占位符,可以被相应的值替换。然后将其复制到de_DE/LC_MESSAGES
目录。
cd locales/de_DE/LC_MESSAGES/
cp ../../example.pot .
还需要进行进一步的适应性改进,以应对德语的复数形式和编码
"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"
下面可以给出翻译后的信息
#: main.py:57
msgid "&File"
msgstr "&Datei"
最后,将.pot
转换为二进制形式(机器对象文件,.mo
),这需要部署
msgfmt -o example.mo example.pot
然后可以通过示例以德语运行。
LANG=de python main.py