这个错误是因为在较新版本的 Jinja2(3.0+)中,jinja2.ext.autoescape 和 jinja2.ext.with_ 这两个扩展已经被移除(它们的功能现在是默认开启的)。而你的 babel.cfg 配置文件中可能仍然按照旧教程写了:
[jinja2: **/templates/**.html] extensions=jinja2.ext.autoescape,jinja2.ext.with_
执行 pybabel extract 时,Babel 会尝试导入这些扩展,从而引发 AttributeError。
🔧 解决方案
方案一(推荐):移除 extensions 行
对于大多数 Flask 项目,Jinja2 模板中只需要识别 _() 函数即可,而 Babel 默认就能识别模板中的 _(),不需要额外扩展。最简单的做法是直接删除 extensions 这一行:
# babel.cfg [python: **.py] [jinja2: **/templates/**.html]
如果模板中使用了自定义过滤器或高级语法,Babel 仍然可以正常工作,因为 _() 是全局函数。
方案二:仅保留 i18n 扩展
如果你的模板中使用了 ngettext 或复杂的翻译逻辑,有时需要显式指定 jinja2.ext.i18n 扩展(但 Flask-Babel 已经自动注册了,通常不必)。不过,如果一定要写,只写这一个即可:
[jinja2: **/templates/**.html] extensions=jinja2.ext.i18n
不要 再包含 autoescape 和 with_。
📦 检查依赖版本
建议确认你使用的 Flask-Babel 和 Jinja2 版本是否兼容:
pip list | grep -E "Flask-Babel|Jinja2"
Flask-Babel 2.0.0+ 支持 Jinja2 3.0+
Jinja2 3.1+ 已移除
autoescape和with_扩展
如果版本过旧,可以考虑升级:
pip install --upgrade Flask-Babel Jinja2
🧪 验证修复
修改 babel.cfg 后,重新执行提取命令:
pybabel extract -F babel.cfg -o messages.pot .
如果不再报错,说明问题已解决。继续后续的 init、update 和 compile 步骤即可。
💡 补充说明
为什么旧教程会那样写? 因为 Jinja2 2.x 版本中,
autoescape和with_是可选扩展,需要显式启用,但现在它们已是内置行为。Flask-Babel 已自动处理:在 Flask 应用中,
Babel初始化时会自动将_函数注入模板上下文,所以 Babel 提取器无需额外扩展也能捕获模板中的翻译标记。
按照以上任意一种方案修改后,你的 Flask 多语言配置就能正常工作了