用 Jinja 的 Babel 支持来提取 Bottle STPL 模板里的待翻译文本

Bottle 的 SimpleTemplate (STPL) 模板引擎虽然颇为简单, 但是从我们长期的使用看来还是十分方便的. 然而美中不足的是, Bottle 并没有像 Jinja 那样对 Babel 的待翻译文本提取工具进行集成支持. 因此, 当我们需要提取模板中的待翻译文本的时候, 便只好把主意打到语法有些接近的 Jinja 上面了.

安装 jinja2 模块, 然后直接使用 Jinja 处理全部模板文件:

[jinja2: **.html]

(如果你仍在使用 Bottle STPL 的默认后缀 .tpl, 可以按照需要进行修改.)

这时我们会发现, 大部分的文本被提取出来了, 但是仍然可能会缺一些, 这是为什么呢?

阅读 Jinja 关于 Babel 集成部分的文档, 我们看到:

Until 2.7 template syntax errors were always ignored. This was done since many people are dropping non template html files into the templates folder and it would randomly fail.

也就是说, 如果遇到含有语法错误的模板, 这个模板会在提取时被忽略, 于是里面所有的待翻译文本都不会被成功提取出来.

在命令行里简单使用 jinja2.Template 测试了一下, 我发现问题主要出在 STPL 的 {{!variable}} 语法上面. STPL 使用 {{!variable}} 来表示禁用 XSS 过滤, 然而这个语法在 Jinja 中是非法的. 稍微研究了一下相关的代码, 我并没有找到通过配置就能解决的方案 (包括试图添加一个可选的 variable_start_string 以求 {{! 和 {{ 都能被识别, 但是这也被认为是不可能的).

于是, 我只好在 pybabel 的 wrapper 中用 monkey-patch 的方法来简单 hack 一下这个问题了:

#!/usr/bin/env python
import sys
from pkg_resources import load_entry_point

# Hack jinja2 to recognize bottle STPL's {{!variable}} syntax
try:
    from jinja2 import ext
    from StringIO import StringIO

    _babel_extract = ext.babel_extract
    def babel_extract_with_stpl_support(fileobj, *args, **kwargs):
        new_fileobj = StringIO(fileobj.read().replace("{{!", "{{"))
        return _babel_extract(new_fileobj, *args, **kwargs)

    ext.babel_extract = babel_extract_with_stpl_support
except ImportError:
    print("jinja2 not present, ignoring monkey-patching...")

if __name__ == '__main__':
    sys.exit(
        load_entry_point('Babel', 'console_scripts', 'pybabel')()
    )

这样, 所有的 {{! 会在尝试提取时被替换为 {{. 经过测试, 这个修改过的 babel_extract_with_stpl_support 成功地提取出了我们所有模板里的所有待翻译文本.

3 thoughts on “用 Jinja 的 Babel 支持来提取 Bottle STPL 模板里的待翻译文本”

Leave a Reply

Your email address will not be published. Required fields are marked *

QR Code Business Card