Python3实现i18n国际化
Python3实现i18n国际化
主要涉及Python基础类库gettext。详细步骤如下:
1. 编写公共方法的python文件(_i18n.py)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time:2022/9/21 10:39
# @Software:PyCharm
__author__ = "JentZhang"
import os, gettext, sys
_ = None
def get_user_language():
"""
获取用户语言
:return:
"""
language = "zh-CN"
# language = "en-US"
if len(sys.argv) > 1:
language = sys.argv[1]
return language
def get_local_strings(domain):
"""
获取翻译后的内容
我们把把所有需要本地化的字符串放到_()里面,注意domain是资源文件的名字,例如:'resource.mo'。
"en-US"作为备份,如果找不到对应语言的资源文件,就使用"en-US"。
:param domain: 翻译文件名
:return:
"""
current_dir = os.path.dirname(os.path.realpath(__file__))
return gettext.translation(domain, current_dir, [get_user_language(), 'en-US']).gettext
_ = get_local_strings("guess")
2. 生成pot文件
python [pathto]pygettext.py -o guess.pot main.py
pygettext.py在python安装目录下 Toolsi18n 文件夹里面。 使用pygettext.py从py文件中提取所有被标记成需要本地化的字符串,也就是在_()里面的字符串。
生成guess.pot。其中pathto是pygettext.py文件所在的路径。一般在Python安装目录的Toolsi18n目录下,一般生成的内容如下:
guess.pot
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2022-10-10 13:50+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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=cp936\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: main.py:13
msgid "Hello! What's your name?"
msgstr ""
#: main.py:17
msgid "Well, {}, I am thinking of a number between 1 and 20."
msgstr ""
#: main.py:21
msgid "Take a guess."
msgstr ""
#: main.py:26
msgid "You should give me a number."
msgstr ""
#: main.py:30
msgid "Your guess is too low."
msgstr ""
#: main.py:33
msgid "You guess is too high."
msgstr ""
#: main.py:39
msgid "Good job, {}! You guessed my number in {} guesses!"
msgstr ""
#: main.py:43
msgid "Nope. The number I was thinking of was {}."
msgstr ""
3. 创建zh-CNLC_MESSAGES、en-USLC_MESSAGES两个目录:
我们在main.py同级目录下创建zh-CNLC_MESSAGES,en-USLC_MESSAGES两个目录,把guess.pot改名为guess.po,为每种语言拷贝一份guess.po放到对应的目录下;
将每种语言的po文件编译为gettext可读写的二进制mo文件,这里有两种方式,一种是使用python提供的工具,运行如下命令;
python [pathto]msgfmt.py -o guess.mo guess.po
运行命令时候进入每种语言的目录LC_MESSAGES目录下。
另一种就是使用poEdit软件编辑保存([poEdit官网](Poedit Translation Editor — Poedit)),它会自动生成一份mo文件,并且同po文件同名(推荐这种方式)。
卷 Windows 的文件夹 PATH 列表
卷序列号为 AC74-7099
C:.
│ guess.pot
│ main.py
│ readme.md
│ _i18n.py
│ __init__.py
│
├─en-US
│ └─LC_MESSAGES
│ guess.mo
│ guess.po
│
├─zh-CN
│ └─LC_MESSAGES
│ guess.mo
│ guess.po
│
└─__pycache__
_i18n.cpython-39.pyc
__init__.cpython-39.pyc
4. 部分代码展示
main.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time:2022/9/21 10:44
# @Software:PyCharm
__author__ = "JentZhang"
import random
from i18n_demo._i18n import _
guessesTaken = 0
print(_("Hello! What's your name?"))
myName = input()
number = random.randint(1, 20)
print(_("Well, {}, I am thinking of a number between 1 and 20.").format(myName))
while guessesTaken < 6:
guessesTaken += 1
print(_("Take a guess."))
guess = input()
try:
guess = int(guess)
except ValueError:
print(_("You should give me a number."))
continue
if guess < number:
print(_("Your guess is too low."))
if guess > number:
print(_("You guess is too high."))
if guess == number:
break
if guess == number:
print(_("Good job, {}! You guessed my number in {} guesses!").format(
myName, guessesTaken))
if guess != number:
print(_("Nope. The number I was thinking of was {}.").format(number))
zh-CN\LC_MESSAGES\guess.po
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2022-10-10 13:50+0800\n"
"PO-Revision-Date: 2022-10-10 13:59+0800\n"
"Last-Translator: ZhangTao <zhangtao@zz.tech>\n"
"Language-Team: \n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.1.1\n"
#: main.py:13
msgid "Hello! What's your name?"
msgstr "你好!你叫什么名字?"
#: main.py:17
msgid "Well, {}, I am thinking of a number between 1 and 20."
msgstr "嗯,{},我想到的是1到20之间的数字。"
#: main.py:21
msgid "Take a guess."
msgstr "猜一猜。"
#: main.py:26
msgid "You should give me a number."
msgstr "你应该给我一个号码。"
#: main.py:30
msgid "Your guess is too low."
msgstr "你的猜测太低了。"
#: main.py:33
msgid "You guess is too high."
msgstr "你的猜测太高了。"
#: main.py:39
msgid "Good job, {}! You guessed my number in {} guesses!"
msgstr "好样的,{}!你在{}次的猜测中猜到了我的号码!"
#: main.py:43
msgid "Nope. The number I was thinking of was {}."
msgstr "不对。我所想的数字是{}。"
5. 运行效果
zh-CN
你好!你叫什么名字?
zt
嗯,zt,我想到的是1到20之间的数字。
猜一猜。
10
你的猜测太高了。
猜一猜。
5
好样的,zt!你在2次的猜测中猜到了我的号码!
Process finished with exit code 0
en-US
Hello! What's your name?
tt
Well, tt, I am thinking of a number between 1 and 20.
Take a guess.
10
You guess is too high.
Take a guess.
5
You guess is too high.
Take a guess.
3
You guess is too high.
Take a guess.
2
You guess is too high.
Take a guess.
1
Good job, tt! You guessed my number in 5 guesses!
Process finished with exit code 0
Note:
- 使用的Python版本是Python3.9;
- 没有使用到其他第三方包。
好记性不如烂笔头!