MaixPy MaixCAM i18n(国际化) 多语言实现

i18n (国际化)简介

i18n 是国际化单词(internationalization)的简称,目的在与根据用户的地域或者喜好切换语言。

我们常用的 中文 和 英文 这个就是语言,语言有对应的地域编码( LCID),比如中文的地域编码为zh,英文为en,日文为ja,另外还有二级地域编码,比如简体中文对应zh-cn,一般我们实现zh即可。

地域编号可以参考Windows的地域编码表 或者看 wikipedia

MaixPy MaixCAM 中使用 i18n

用户使用大致流程如下:

  • 首先用户使用时,在系统设置中可以选择系统语言,比如出厂默认是en即英文。
  • 然后程序通过maix.i18n.get_locale()可以获得当前系统设置的地域。
  • 程序根据系统设置的地域显示对应语言的字符串。

对于应用程序来说,比较麻烦的地方就在这里的第三步,即根据地域设置查表获取对应的字符串,下面提供两种方法,根据自己的需求选择:

不使用翻译文件,直接使用字典

如果你的程序只有几个字符串,可以直接手动指定翻译字典:

from maix import i18n

trans_dict = {
    "zh": {
        "hello": "你好"
    },
    "en": {
    }
}

trans = i18n.Trans(trans_dict)
tr = trans.tr

trans.set_locale("zh")
print(tr("hello"))
print(tr("my friend"))

这里用trans.set_locale("zh")临时设置语言为中文了, 运行就会打印你好my friend 了, 因为没给my friend填加翻译,所以原封不动地返回了。

自动扫描生成字典,并且从翻译文件加载

这种方法比较适合有大量需要翻译的字符串的场景。

前面的方法我们手动指定了字符串翻译,在简单场景很方便,但是如果字符串太多了,手动改字典很容易漏掉,所以我们需要程序自动帮我们找到需要翻译的字符串并生成翻译文件,我们只需要翻译一下文件就好了。

在 MaixPy 中,提供了maix.i18n.Trans 这个类,可以用来加载多种语言的翻译文件,调用其成员函数tr(),传入想要翻译的文字即可获得翻译,举例:

from maix import i18n, err
trans = i18n.Trans()
tr = trans.tr

e = trans.load("locales")
err.check_raise(e, "load translation yamls failed")

print(tr("hello"))

这里从当前目录下的locales文件夹加载了翻译文件,然后根据系统的语言设置打印hello,比如中文就会打印你好

翻译文件: 既然这里加载用到了翻译文件,这些翻译文件怎么制作呢?
首先我们需要知道我们需要翻译那些文字,显而易见,就是上面我们用函数tr调用的字符串,所以我们只需要搜索源码中所有用到了tr函数的字符串即可认为是我们需要翻译的所有字符串了。
所以使用流程如下:

  • 建立一个项目文件夹,里面存放代码入口main.py,可以使用 `MaixVision`` 打开这个项目文件夹方便运行。
  • 编写main.py,让需要翻译的字符串都用上述的tr函数调用。
  • MaixPy 提供了一个扫描工具,首先确保安装了maixtool(电脑通过系统终端 pip install maixtool -U 命令来安装升级)。
  • 然后在目录下仍然使用电脑终端执行maixtool i18n -d . r来扫描需要翻译的字符串,并且生成一个locales目录,里面包含了中英文两种语言的翻译文件,如果要更多语言,执行maixtool i18n -h查看帮助。
  • 生成的文件是键值对组成的,比如zh.yaml中的hello: hello 的意思就是字符串hello中文翻译是hello,这显然不对,需要我们手动翻译一下,改成hello: 你好即可。注意编辑文件一定要用支持 UTF-8 编码的编辑器,特别是在Windows下不要将文件改为GBK编码了,不然会出错,可以用 MaixVision 或者 VsCode 编辑。
  • 然后运行项目,或者打包项目为安装包都可以,记得把 locales 目录也一起打包进去。
  • 如果后面又更新了源码,需要再次执行maixtool命令更新文件,更新会对之前已经翻译了的文件更新,如果你担心程序不小心将之前的错误覆盖,可以先自行备份一份,确认无误后再删除备份。

这样你的程序就会根据系统语言设置更改语言了,如果你调试程序也可以手动调用trans.set_locale("zh")来手动临时切换语言。

显示翻译到界面

前面的例子都是在调用print函数打印,如果想显示到界面上,还有一步要做,就是需要字库支持,对于英文来说默认都支持了,可是对于中文这种字库庞大的语言,默认是不支持的。
比如:

from maix import i18n, image, display, app, time

trans_dict = {
    "zh": {
        "hello": "你好"
    },
    "en": {
    }
}

trans = i18n.Trans(trans_dict)
tr = trans.tr
trans.set_locale("zh")

disp = display.Display()
img = image.Image(disp.width(), disp.height())

img.draw_string(10, 10, tr("hello"), image.COLOR_WHITE, scale=2)
disp.show(img)

while not app.need_exit():
    time.sleep_ms(100)

运行会发现显示了一堆?,因为没有中文字库,对于image模块,可以加载字库,系统内置了一个中文字库,你也可以用你自己的字库:

from maix import i18n, image, display, app, time

trans_dict = {
    "zh": {
        "hello": "你好"
    },
    "en": {
    }
}

trans = i18n.Trans(trans_dict)
tr = trans.tr
trans.set_locale("zh")

disp = display.Display()


image.load_font("sourcehansans", "/maixapp/share/font/SourceHanSansCN-Regular.otf", size = 24)
image.set_default_font("sourcehansans")

img = image.Image(disp.width(), disp.height())
img.draw_string(10, 10, tr("hello"), image.COLOR_WHITE, scale=2)
disp.show(img)

while not app.need_exit():
    time.sleep_ms(100)