python 使用 xgettext 与 locale 做国家化与本土化的示例

简介

python 国家化与本土化的示例。起因是一款软件没有做语言的适配。

python的国际化gettext模块。mattkang 。2017-12-08 中对 i18n 和 l10n 说的特别到位的地方

国际化的软件具备这样一种能力,当软件被移植到不同的语言及地区时,软件本身不用做内部工程上的改变或修正。

相关词汇

Internationalization (i18n) - 国际化
Localization (l10n) - 本地化、本土化

怎么做

遇事不觉看文档 国际化 - Python docs,提到了 gettext 和 locale,又看了 gettext 的文档,emm 没有一个比较好的例子,整得我不会用。。

Bing 搜索了下发现几篇写的还很不错的,但是依然搞不懂怎么一步一步使用。。。

终于在 Bing 国际版找到了一篇循序渐进的文章。

最初 GNU gettext 仅支持 C 或 C++ ,但其扩展版本 xgettext 扫描以多种语言(包括 Python)编写的代码,以查找被标记为可翻译的字符串。Python 发行版包括一些称为 pygettext.py 和 msgfmt.py 的特定程序,它们仅识别 Python 源代码而不识别其他语言。

大纲

  • xgettext/pygettext 提取要翻译的文本
  • 翻译 po 文件
  • msgfmt 编译 po 文件为 mo 文件
  • gettext 翻译

案例

这里采用 Manjaro linux 发行版的 xgettext 和 msgfmt 作为例子。下面是一个很简单的 py3 的程序(main.py),运行结果也显而易见。

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-


print("Edit")
print("Cancel")
print("Confirm")

为了提取要翻译的词汇,这里加入引用,给要进行 i18n 的文本都放在 _() 中,此时运行程序的结果和上面一样。

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import gettext
_ = gettext.gettext

print(_("Edit"))
print(_("Cancel"))
print(_("Confirm"))

xgettext/pygettext 提取要翻译的文本

如下所示建立文件夹,locale 可以叫做别的名字,就保持默认吧

mkdir -p locale/zh_CN/LC_MESSAGES

生成 po 文件

xgettext -k_ -o locale/zh_CN/LC_MESSAGES/zh_CN.po main.py

文件结构树

├── locale
│   └── zh_CN
│       └── LC_MESSAGES
│           └── zh_CN.po
└── main.py

翻译 po 文件

刚才生成的文件(locale/zh_CN/LC_MESSAGES/zh_CN.po)如下所示

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-05 16:31+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: main.py:6
msgid "Edit"
msgstr ""

#: main.py:7
msgid "Cancel"
msgstr ""

#: main.py:8
msgid "Confirm"
msgstr ""

必须要需要修改的有两个地方,一个是 charset=CHARSET 要修改为 UTF-8(python3 默认这个编码),二是所有的 msgstr。上面的注释啥的看需求写哈

msgid 代表刚才提取出来的字符串,msgstr 代表其翻译,需要自己翻译。

改完之后是下面这个样子的

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# kearney <kearneyback@gmail.com>, 2021.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-05 16:31+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: kearney <kearneyback@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: main.py:6
msgid "Edit"
msgstr "编辑"

#: main.py:7
msgid "Cancel"
msgstr "取消"

#: main.py:8
msgid "Confirm"
msgstr "确认"

msgfmt 编译 po 文件为 mo 文件

翻译后生成mo最终文件

msgfmt -o locale/zh_CN/LC_MESSAGES/zh_CN.mo locale/zh_CN/LC_MESSAGES/zh_CN.po

文件结构树

├── locale
│   └── zh_CN
│       └── LC_MESSAGES
│           ├── zh_CN.mo
│           └── zh_CN.po
└── main.py

gettext 翻译

稍微修改一下代码,此时运行程序就会发现输出是刚才翻译后的中文,而不是程序中的英文

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import gettext
l10n = gettext.translation("zh_CN", localedir="locale", languages=["zh_CN"])
l10n.install()
_ = l10n.gettext

print(_("Edit"))
print(_("Cancel"))
print(_("Confirm"))

改进

上面写死了翻译为中文,理想状态下是根据用户的语言自动设定语言,没有对应的翻译包则默认显示英文。

这是一个通过 locale 获取本地语言和编码的案例

import locale
loc = locale.getlocale()
print(loc,loc[0],loc[1]) 
# 系统中文时输出: ('zh_CN', 'UTF-8') zh_CN UTF-8 
# 系统英文时输出: ('en_US', 'UTF-8') en_US UTF-8

可以用 locale 命令获取当前的系统语言设置,可以使用 export LANG=en_US.UTF-8 或者 export LANG=zh_CN.UTF-8 来临时修改环境变量中的语言设置。

下面这个程序实现了当系统语言不是 en_US 的时候,会尝试寻找对应语言翻译包,找到了就使用,没找到就使用默认 en_US 语言,需要注意的是,下面的代码存在没有鉴别编码、没有考虑其它英语地区等等问题。

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import gettext
import locale
_ = gettext.gettext


try:
  loc = locale.getlocale()
  if not loc[0]  =="en_US":
    l10n = gettext.translation(loc[0], localedir="locale", languages=[loc[0]])
    l10n.install()
    _ = l10n.gettext
except Exception as e:
  print(e,"\nUsing defalt language - English(en_US.UFT-8)")


print(_("Edit"))
print(_("Cancel"))
print(_("Confirm"))

总结

其实还可以做的更多,之前接触过一款开源软件,需要翻译,当时是进入一个网页,有不同的短语和对应谷歌翻译,志愿者可对其翻译进行修改、投票等。忘记是哪一个来着了,用互联网的思维去做软件本土化,毕竟不是每个软件都有翻译小组。

最后,不得晒一下我的博客啥的吗?

物语

参考

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值