# 国际化（i18n）

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


## 标记字符

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

```python
from .locale import _

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

请注意：
 - 不要忘记加载_函数
 - 需要用format写法代替f-string


## 创建pot文件

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

```python
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 "你的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](https://www.gnu.org/software/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:

```python
output("优化参数组合为空，请检查")
```

becomes 

```python
from .locale import _

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

or, a parameterised message 

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

becomes

```python
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 

```shell
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

```shell
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:

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

## install

```shell
pip install . 
```

## execution

Now run the application, with your chosen language specified

```shell
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
