Babel

安装依赖

1
2
uv add Babel
# pip install Babel

语言

提取源字符串

定义 babel.cfg 配置

1
2
[python: **.py]
encoding = utf-8

定义函数

  • cast用于覆盖函数定义消除IDE警告
  • 注释 # Translator: 用于生成 .pot 文件时带入注释,可自定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from typing import Callable, cast

import gettext
import os

LOCALES_DIR = os.path.join(os.path.dirname(__file__), 'translations')


def get_translator(lang):
# 如果找不到语言,回退到默认 gettext.NullTranslations()
try:
t = gettext.translation('messages', localedir=LOCALES_DIR, languages=[lang])
except FileNotFoundError:
t = gettext.NullTranslations()
_gettext = cast(Callable[[str], str], t.gettext)
_ngettext = cast(Callable[[str, str, int], str], t.ngettext)
return _gettext, _ngettext


def show_messages(lang, counts=(0, 1, 2, 5)):
_, ngettext = get_translator(lang)
print(f'--- language: {lang} ---')
# 简单消息
print(_('Hello, world!'))
# 带占位符
for n in counts:
# Translator: 使用 ngettext 处理单复数
msg = ngettext('There is %(num)d apple', 'There are %(num)d apples', n) % {'num': n}
print(msg)
print()


if __name__ == '__main__':
print()
# 演示英文和中文
show_messages('en')
show_messages('zh_CN')

提取源字符串命令

1
uv run pybabel extract --add-comments=Translator -F babel.cfg -o messages.pot .

初始化新语言

1
2
uv run pybabel init -l zh_CN -d locales -i messages.pot
uv run pybabel init -l en_US -d locales -i messages.pot

更新现有翻译

1
uv run pybabel update -d locales -i messages.pot

po文件编译成mo

1
uv run pybabel compile -d locales

数字/货币

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from babel.numbers import (
format_decimal, parse_decimal,
format_percent,
format_currency,
NumberFormatError,
)

print()
# 小数
print(format_decimal(12345.678, locale="zh_CN")) # 12,345.678
print(format_decimal(12345.678, locale="en_US")) # 12,345.678
print(format_decimal(12345.678, locale="sv_SE")) # 12 345,678
print(format_decimal(12345.678, locale="de_DE")) # 12.345,678
try:
print(parse_decimal('1,099.98', locale='en_US')) # 1099.98
print(parse_decimal('1.099,98', locale='de')) # 1099.98
print(parse_decimal('2,109,998', locale='de')) # raise NumberFormatError
except NumberFormatError as ex:
print(ex)

# 百分比
print(format_percent(0.2567, locale="zh_CN")) # 25.67%
print(format_percent(0.2567, locale="en_US")) # 25.67%
print(format_percent(25.1234, locale='sv_SE')) # 25.67%

# 货币
print(format_currency(12345.67, 'CNY', locale='zh_CN')) # ¥12,345.67
print(format_currency(12345.67, 'USD', locale='en_US')) # $12,345.67

日期、时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from babel.dates import format_datetime
from datetime import datetime
from zoneinfo import ZoneInfo

print()
# 数据库时间(+8 时区,北京时间)
db_time = datetime(
2025, 11, 8, 21, 0, 0,
tzinfo=ZoneInfo("Asia/Shanghai")
)
# 假设用户在美国东部(UTC-5)
tz_ny = ZoneInfo("America/New_York")

# 转换到用户时区
user_time = db_time.astimezone(tz_ny)

# 格式化显示
print(format_datetime(user_time, locale="en_US")) # 美国用户看到本地时间
print(format_datetime(db_time, locale="zh_CN")) # 中国用户看到北京时间


夏令时

1
2
3
4
5
6
7
8
9
10
from datetime import datetime
from zoneinfo import ZoneInfo

print()
tz_NY = ZoneInfo("America/New_York")
dt_NY = datetime(2024, 7, 15, 12, 0, 0, tzinfo=tz_NY)
print(f"夏令时间:{dt_NY}") # 2024-07-15 12:00:00-04:00
dt_NY = datetime(2024, 1, 15, 12, 0, 0, tzinfo=tz_NY)
print(f"冬令时间:{dt_NY}") # 2024-01-15 12:00:00-05:00


Babel
https://itxiaopang.github.io/p/5113b7c6c2424c74887d4e9791de6cae/
作者
挨踢小胖
发布于
2025年11月8日
许可协议