背景
代码均为开源代码
基于yoga版本,需要对openstack某服务做翻译,了解到oslo_i18n有翻译功能,配置oslo_i18n来给组件进行翻译
用法
用法
每个服务自己会带一个i18n.py的文件,如果要对日志进行翻译,从i18n导入_,代码如下
from oslo_log import log
from ceilometer.i18n import _
text = "hello, world"
LOG = log.getLogger(__name__)
# not translate
LOG.info(text)
# translate
LOG.info(_(text))
官网oslo.i18n – Oslo Internationalization Utilities — oslo.i18n 3.12.1.dev4 documentation (openstack.org)
从pike版本后就不支持log翻译了,这个文档是ocata版本
定制修改
直接改po文件即可,改完po文件生成mo文件即可
配置
pike版本以后不支持log翻译了,使用翻译前需要配置
环境变量
参考如下官网配置How to Use oslo.i18n in Your Application or Library — oslo.i18n 3.12.1.dev4 documentation (openstack.org)
总的来说大概需要配两个环境变量,一个是你要翻译的目标语言类型,值可以是zh_CN, en_US等;一个是localedir,这个目录下存放的是mo和po文件,目录结构如下
po与mo文件配置
代码仓默认在各个语言的路径下只存在.po文件,如果要翻译需要先根据po文件生成mo文件,有了mo文件,才能翻译,通过命令msgfmt ceilometer.po -o ceilometer.mo生成.mo文件,mo文件需要在刚配置的环境变量localedir目录下,不然翻译的时候找不到mo文件就翻译不了
msgfmt ceilometer.po -o ceilometer.mo
msgfmt在debian需要先安装gettext:apt install gettext,不然msgfmt命令找不到报错
其他配置
rootwrap
生成mo目标文件的目录权限不够的话可以考虑配rootwrap
代码流程
oslo_i18n.TranslatorFactory
从服务.i18n导入_并使用,_实际是_translators.primary函数,_translator实际是oslo_i18n.TranslatorFactory的实例
_translator初始化需要传入domain参数,domain就是服务的名字,比如nova, neutron等,最后寻找.mo翻译文件的文件名就是domain.mo,可选参数localedir,即用来在localedir下寻找mo文件,不传入localedir参数的话会从环境变量寻找名为DOMAIN_LOCALEDIR变量的值,如果没配这个变量则为None,后续会处理这个None
oslo_i18n.TranslatorFactory.primary
primary流程如下,实际调用了gettext模块去翻译
注意到这个oslo_i18n._lazy.USE_LAZY,为全局bool类型,如果代码里用了oslo_i18n.enable_lazy()这样的函数会设置USE_LAZY为True,就会走到oslo_i18n._message.Message(msg, domain=domain)里,这个在yoga版本不会翻译成你的目标语言,即使配置了环境变量和mo文件
gettext.translation
先寻找mo文件,如果没找到则根据fallback返回,fallback若为False,则没找到mo时抛异常,fallback为True,则没找到mo文件时返回一个空NullTranslations,会对语言的翻译什么也不做
找到mo文件的话,会根据mo文件内容生成一个GNUTranslations对象返回
gettext.find
find作用是寻找mo文件,find会根据domain,localedir,language寻找mo文件
domain:mo文件的名字,即目标文件名为domain.mo
localedir:在localedir下寻找domain.mo,如果之前没配DOMAIN_LOCALEDIR会导致这里localedir为空,此时会用_default_localedir,值为/usr/share/locale
language:目标语言,即会在localedir的哪个language目录下寻找domain.mo,也需要配置环境变量指定用哪个语言,如果没配默认是英文,最后可能返回一个空列表,配置的话,可以参考下图的四个环境变量选一个进行配置
报错与问题
配置了mo仍不翻译
发现primary会判断是否USE_LAZY,如果是会走到oslo_i18n._message.Message,这个东西新版本看着不会翻译,可以通过禁用oslo_i18n.enable_lazy跳过此处