国际化(i18n)

Python中的i18n可以实现程序的多语言支持。下面通过vnpy包在Windows系统上进行演示。

标记字符

在源码中标记需要翻译的字符,如以下代码所示:

from .locale import _

output(_("参数优化空间:{}").format(len(settings)))

请注意:

  • 不要忘记加载_函数

  • 需要用format写法代替f-string

创建pot文件

在命令行中,调用python环境下Tools\i18n文件夹中的pygettext.py对模块所有python文件进行扫描,把所有标记过的字符都写入指定的pot模板文件,如以下代码所示:

python "你的python环境路径"\Tools\i18n\pygettext.py -o vnpy\trader\locale\vnpy.pot vnpy\trader\*.py vnpy\trader\ui\*.py

其中-o后面是要生成的pot文件的路径,“vnpy\trader*.py”是扫描指定文件夹下所有Python文件的示例。

创建po文件

以英文版为例,在locale文件夹下创建/en/LC_MESSAGES文件夹,复制生成的pot文件到该文件夹下并修改后缀为po。

修改po文件顶部的charset为UTF-8,再对模板内的msgid进行翻译,如下代码所示:

修改前:

#: vnpy/trader/optimize.py:62
msgid "范围参数添加成功,数量{}"
msgstr ""

修改后:

#: vnpy/trader/optimize.py:62
msgid "范围参数添加成功,数量{}"
msgstr "Range parameter added successfully, quantity {}"

请注意标点符号的语言转换。

生成mo文件

在命令行中,调用python环境下Tools\i18n文件夹中的msgfmt.py将po文件转成二进制mo文件,如以下代码所示:

python "你的python环境路径"\Tools\i18n\msgfmt.py -o vnpy\trader\locale\en\LC_MESSAGES\vnpy.mo vnpy\trader\locale\en\LC_MESSAGES\vnpy

其中-o后面是生成mo文件的路径,最后的是po文件的路径(无需后缀名)

打包

打包过程中请在MANIFEST.in文件中添加*.mo,这样安装时才不会忽略mo文件

使用

配置好系统语言,正常使用软件即可。运行时程序会读取配置的系统语言并尝试寻找对应语言翻译包。

Internationalization (i18n)

This document outlines the i18n process. Using the steps in this guide, multi-language support can be incorporated into VeighNa using standard Python conventions

References:

  • https://docs.python.org/3.10/library/i18n.html

  • https://simpleit.rocks/python/how-to-translate-a-python-project-with-gettext-the-easy-way/

  • https://www.mattlayman.com/blog/2015/i18n/

prerequisites

  • gettext

    • Linux/Mac: brew install gettext

    • Windows: https://mlocati.github.io/articles/gettext-iconv-windows.html (or similar)

mark messages

The first step is to mark message strings for translation. We do this by wrapping the string with a special function. Example:

output("优化参数组合为空,请检查")

becomes

from .locale import _

output(_("优化参数组合为空,请检查"))

or, a parameterised message

output("参数优化空间:{}".format(len(settings)))

becomes

from .locale import _

output(_("参数优化空间:{}").format(len(settings)))

as unfortunately f-strings are not supported. One way to search for Chinese characters is to use the regex \p{InCJK_UNIFIED_IDEOGRAPHS}

template files

Once all the messages are marked, we run xgettext to extract the translatable strings into a message template file

xgettext -o vnpy/trader/locale/base.pot `find ./vnpy -name "*.py"`

individual language files

We then create individual language files, by copying the template. So for English and Spanish

mkdir -p vnpy/trader/locale/{en, es}/LC_MESSAGES
cp vnpy/trader/locale/vnpy.pot vnpy/trader/locale/en/LC_MESSAGES/vnpy.po
cp vnpy/trader/locale/vnpy.pot vnpy/trader/locale/es/LC_MESSAGES/vnpy.po

Then edit the .po files to add the translated text, updating the msgstr attributes. So for English (vnpy/trader/locale/en/LC_MESSAGES/vnpy.po):

#: vnpy/trader/optimize.py:45
msgid "固定参数添加成功"
msgstr ""

#: vnpy/trader/optimize.py:48
msgid "参数优化起始点必须小于终止点"
msgstr ""

becomes

#: vnpy/trader/optimize.py:45
msgid "固定参数添加成功"
msgstr "Fixed parameters added successfully"

#: vnpy/trader/optimize.py:62
msgid "范围参数添加成功,数量{}"
msgstr "Range parameter added successfully, quantity {}"

See these projects for automation of the translation step:

  • https://www.deepl.com/translator

  • https://poeditor.com/

  • https://www.transifex.com/

Quality of the automatic translation services is variable, and not always free. But they do at least provide a starting point. Sometimes a string will require a manual edit.

binary files

The plain text languages files (*.po) must be converted into the binary format (.mo) used at runtime. This would be normally done at the build stage. But to do it manually during development or testing:

msgfmt -o vnpy/trader/locale/en/LC_MESSAGES/vnpy.mo vnpy/trader/locale/en/LC_MESSAGES/vnpy

install

pip install . 

execution

Now run the application, with your chosen language specified

LANG=en python vnpy/examples/veighna_trader/run.py 

or, set the environment variable LANG first, then run as normal. The names ‘LANGUAGE’, ‘LC_ALL’, ‘LC_MESSAGES’ also work

distribution

TBD