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:

  1. 使用的Python版本是Python3.9;
  2. 没有使用到其他第三方包。
posted on 2022-10-10 14:59  JentZhang  阅读(1659)  评论(0)    收藏  举报