用 Python t-string
翻译完整的消息¶
gettext-tstrings 把 Python 3.14+ 的 t-string 接到标准 gettext 目录和 Babel
工具链上。值和格式留在应用程序代码里;翻译者拿到的是完整消息和简单的
{name} 占位符:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales"))
name = "Ada"
print(_(t"Hello {name}")) # with a Japanese catalog: こんにちは Ada
目录里放的是 Hello {name}。译文可以移动或重复 {name}。如果它删掉、改名或
重新格式化这个占位符,目录验证会报出错误。万一有无效的条目还是进了生产环境,
本库会记录一条警告并渲染源消息,而不是崩溃。
Alpha · Python 3.14+ · 标准 PO/MO 目录 · 无第三方运行时依赖
本站身体力行自己所记录的内容:每一个语言版本——导航、标签和支持复数规则的
构建报告——都由
gettext-tstrings 自身
从 PO 目录渲染。
它适合你吗?¶
现在就合适:你的应用运行在 Python 3.14 或更高版本上;你已经在用 gettext 和 Babel,或者打算采用它们的 PO/MO 工作流;并且你想要带命名占位符、且在渲染之前 就被检查过的 t-string 语法。
暂时还不合适:你需要 Python 3.13 或更早的版本;你要求一个稳定的 Python API——这是 alpha 版本,其中已经定型的部分是规范;或者你几乎所有可翻译 文本都在某种 template 语言里,而不在 Python source 中。
已经有目录了?它们继续有效。_("Hello {name}").format(name=name) 与
tr(t"Hello {name}") 产出同一个 msgid,因此现有翻译能挺过这次切换——
迁移完整讲了整个过程。
目录可以说什么¶
一份译文无法改变它所翻译的那条消息的结构。 这就是全部的承诺,本站其余内容
都由它推导而来。翻译可以调整或重复 {name},也可以改写它周围的每一个词。但它
不能删掉这个占位符、凭空造一个新的、借它伸手去碰你的对象,也不能自行附加格式。
本库在入口处检查这一点——目录编译的时候——渲染时再检查一次;这正是“在评审中发现 的错误”与“被用户发现的错误”之间的区别。
初次接触 gettext?四句话讲完整个工作流
gettext 是软件获得翻译的标准方式,在 Python 内外皆然。你的代码标记可翻译
字符串;提取器把它们收集进模板文件(.pot);翻译者——通常不是程序员——为
每种语言填写一份目录文件(.po),再编译成二进制 .mo,由应用程序在运行时
加载。翻译函数的约定名称是 _,因此 _(t"Hello {name}") 读作“翻译这句话”。
教程用大约五分钟走完整条路径——标记、提取、翻译、编译、
运行。
它解决的问题¶
在任何库看到 f-string 之前,插值已经完成——f"Hello {name}" 已经变成
"Hello Ada",而围绕一个值去翻译前后的片段会破坏大多数语言的语法。t-string
(PEP 750)分别保留静态文本、已求值的值、源表达式、转换和格式说明——这恰好是
消息目录所需要的分离方式。
参阅它带来了哪些变化,了解它与 %(name)s、.format() 和
$-string 的区别。
不过,gettext 和 Babel 都没有规定如何将 t-string 变成一条消息。本库做出了这一 选择,将其写成带版本的规范,并提供一致性测试套件 来验证实现。
设计原则¶
- 始终翻译完整消息,而不是句子片段。
- 只接受
{name}这样的简单变量名。 !r和:.2f由应用程序控制,不进入目录。- 允许翻译调整和重复已知占位符,同时阻止它们访问属性或增加格式。
- 继续使用普通的 POT、PO、MO 文件以及现有工具。
与之对应的,是它刻意不碰的那份清单:它不本地化数字、货币或日期——请先 用 Babel 把它们格式化好;它不为 HTML、shell 或 terminal 转义渲染结果;它也无法判断一份译文是否正确,只能判断其中的占位符是否 完好。
安装¶
需要 Python 3.14 或更高版本。渲染不需要任何依赖项——只使用标准库的
gettext。
提取和目录验证通过 Babel 运行。请在执行 pybabel 的环境中安装相应 extra;
通常这是开发或 CI 环境,而不是生产镜像:
接下来¶
入门 — 不要求任何 gettext 经验:
- 教程 — 从空目录到运行日语翻译只需五步,每条命令都附带 其输出。
- 为什么选择 t-string — 用四种方式编写同一条消息,并比较
%(name)s、.format()和$-string 分别把什么交给目录。
正式使用 — 日常工作的参考:
深入理解 — 从历史到实现:
参考 — 各项契约:
状态¶
| 包版本 | 0.1.0a8 |
| API 稳定性 | alpha —— Python API 仍有可能调整 |
| 规范 | v1,附带一致性测试套件 |
| Python | 3.14 及更高版本;已在 3.14、3.14t(自由线程)和 3.15 上测试 |
| Babel | 2.18 或更高版本,且仅在运行 pybabel 的场合需要 |
| 运行时依赖 | 无 —— 只用标准库的 gettext |
| 目录格式 | 普通的 POT、PO 和 MO |
| 变更 | CHANGELOG |
目前是 alpha 版本。契约刻意保持精简,其中稳定的部分是规范;Python API 仍有可能调整。稳定发布之前,还需要更广泛的语言 fixture、持续性能跟踪、真正使用 gettext 和 Babel 的用户参与 API 评审,以及覆盖所有受支持 Python 与 Babel 版本的 兼容性测试。
欢迎提交 Issue 和 Pull Request。 alpha 阶段正是讨论接口最有价值的时候。
加入社区¶
- 从范围明确的 good first issue 开始贡献。
- 在 Q&A Discussions 中询问使用问题。
- 在 Ideas Discussions 中分享生产 gettext 工作流和 API 想法。
- 提交 Pull Request 前,请阅读 贡献指南。