书接上回,上一篇我们讲解了 Tornado 模板基础配置、语法以及 XSS 安全相关知识点,本篇继续讲解国际化 与UI 模块。
二、国际化
当前用户的语言区域(无论用户是否登录),在 Handler 中通过self.locale访问;模板内直接使用locale。
locale.name可以拿到语言标识,例如en_US。调用Locale.translate()做文本翻译。模板内置全局翻译函数_()。
翻译函数两种用法
- 普通翻译 根据当前区域直接翻译字符串。
- 单复数翻译 第三个参数为数字;等于 1 取第一条字符串,大于 1 取第二条字符串。推荐使用命名占位符
%(num)d,翻译的时候占位符顺序可以调整。
国际化模板示例
bash
<html>
<head>
<title>FriendFeed - {{ _("Sign in") }}</title>
</head>
<body>
<form action="{{ request.path }}" method="post">
<div>{{ _("Username") }} <input type="text" name="username"/></div>
<div>{{ _("Password") }} <input type="password" name="password"/></div>
<div><input type="submit" value="{{ _("Sign in") }}"/></div>
{% module xsrf_form_html() %}
</form>
</body>
</html>
默认读取浏览器请求头Accept‑Language自动识别语言;匹配不到则回退en_US。
如果你希望用户可以手动选择语言,可以重写RequestHandler.get_user_locale()。
bash
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
user_id = self.get_signed_cookie("user")
if not user_id:
return None
return self.backend.get_user_by_id(user_id)
def get_user_locale(self):
if "locale" not in self.current_user.prefs:
# 使用浏览器Accept‑Language头
return None
return self.current_user.prefs["locale"]
如果get_user_locale返回None,系统回退读取Accept‑Language请求头。
tornado.locale模块支持两种翻译文件格式:gettext 标准.mo,以及简单的.csv。 程序启动时调用 tornado.locale.load_translations 或者 tornado.locale.load_gettext_translations加载翻译资源。
调用tornado.locale.get_supported_locales()获取程序支持的语言列表。系统会自动匹配最接近用户的语言。
举例:用户语言
es_GT,程序支持es,则最终使用es;完全匹配不到就回退en_US。
三、UI 模块
UI 模块用来封装可复用页面组件,跨页面复用 UI 小组件,组件可以附带自己的 CSS、JS。
场景举例:博客项目,博客条目组件需要在首页、详情页两处渲染。可以封装
EntryUI模块。新建uimodules.py。
1. 注册 UI 模块
在应用配置里面注册 UI 模块文件:
bash
from . import uimodules
class HomeHandler(tornado.web.RequestHandler):
def get(self):
entries = self.db.query("SELECT * FROM entries ORDER BY date DESC")
self.render("home.html", entries=entries)
class EntryHandler(tornado.web.RequestHandler):
def get(self, entry_id):
entry = self.db.get("SELECT * FROM entries WHERE id = %s", entry_id)
if not entry:
raise tornado.web.HTTPError(404)
self.render("entry.html", entry=entry)
settings = {
"ui_modules": uimodules,
}
application = tornado.web.Application([
(r"/", HomeHandler),
(r"/entry/([0-9]+)", EntryHandler),
],** settings)
2. 模板中调用模块
模板中使用{% module %}调用封装好的组件:
home.html
bash
{% for entry in entries %}
{% module Entry(entry) %}
{% end %}
entry.html
bash
{% module Entry(entry) %}
模块类可以重写下面方法来嵌入样式脚本: embedded_css、embedded_javascript、javascript_files、css_files
特性:不管页面中该模块被调用多少次,CSS、JS 只会输出一次。CSS 放在页面
<head>,JS 放在</body>结束标签之前。
纯 HTML 模板作为模块
如果不需要写 Python 逻辑,可以直接把 html 模板文件当做模块。
文件 module-entry.html
bash
<div class="entry">
<h2>{{ entry.title }}</h2>
<div>{{ entry.content }}</div>
</div>
调用方式:
bash
{% module Template("module-entry.html", entry=entry) %}
set_resources函数仅在{% module Template(...) %}模式下可用。
和 {% include %} 的区别
UI模块拥有独立命名空间,只能访问全局模板变量 + 传入的参数,无法继承父模板局部变量 ; 而{% include %}是直接把文件内容原地展开,可以直接使用父模板的局部变量。
系列文章:
- Tornado 如何增加网页操作(上)
- Tornado 如何增加网页操作(下)
参考文档: tornado 官方文档
博主持续分享量化、Python、Tornado 开发相关内容,欢迎点赞收藏关注。