Flask 扩展 国际化 本地化
pip install flask-babel
先初始化一个Flask-Babel的实例
from flask import Flask
from flask.ext.babel import Babel app = Flask(__name__)
babel = Babel(app)
设置语言和时区
Flask-Babel提供了两个Flask应用配置项:
- BABEL_DEFAULT_LOCALE: 应用默认语言,不设置的话即为”en”
- BABEL_DEFAULT_TIMEZONE: 应用默认时区,不设置的话即为”UTC”
app.config.update(
DEBUG=True,
BABEL_DEFAULT_LOCALE='zh'
)
当程序里没指定时,就会采用这些默认设置。那么如何在程序里指定呢?Flask-Babel提供了两个装饰器”localeselector”和”timezoneselector”,分别用来设置语言和时区:
@babel.localeselector
def get_locale():
return 'zh' @babel.timezoneselector
def get_timezone():
return 'UTC'
这里的设置将会覆盖应用配置项中”BABEL_DEFAULT_LOCALE”和”BABEL_DEFAULT_TIMEZONE”。上面的程序不是个好例子,常见的情况是从当前用户会话中,或者从服务器环境中获取语言/时区设置。
装饰器”localeselector”和”timezoneselector”修饰的函数,被调用一次后就会被缓存,也就是不会被多次调用。但是有时候,当切换用户时,我们想从新用户会话中重新获取语言/时区设置,此时可以在登录请求中调用”refresh()”方法清缓存:
from flask_babel import refresh
@app.route('/login')
def login():
... # Get new user locale and timezone
refresh()
... # Render response
在视图和模板中使用翻译
Flask-Babel封装了Python的”gettext()”方法,你可以在视图函数中使用它:
from flask_babel import gettext, ngettext
@app.route('/trans')
@app.route('/trans/<int:num>')
def translate(num=None):
if num is None:
return gettext(u'No users')
return ngettext(u'%(num)d user', u'%(num)d users', num)
Flask-Babel还提供了”lazy_gettext()”方法,它的作用同”gettext()”类似,区别是它在文字被使用时才会被翻译,所以可以用来在上下文环境外定义要翻译的文字,比如:
from flask_babel import lazy_gettext
hello = lazy_gettext(u'Hello World') @app.route('/lazy')
def lazy():
return unicode(hello)
同样在模板中,我们也可以使用”gettext()”方法,更简单的我们可以用”_()”方法代替:
<!doctype html>
<title>{{ _('Test Sample') }}</title>
<h1>{{ _('Hello World!') }}</h1>
在Flask请求中,我们来渲染此模板:
@app.route('/')
def index():
return render_template('hello.html')
启动应用,访问上面的视图,验证下程序是否正常运行。大家应该可以看到”gettext()”方法里的文字被显示出来了,目前还没有被翻译。
创建本地化翻译文件
Babel中的”pybabel”命令来创建翻译文件
- 首先让我们创建一个Babel的配置文件,文件名任意,这里我们取名为”babel.cfg”
[python: **.py]
[jinja2: **/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_这个文件告诉”pybabel”要从当前目录及其子目录下所有的”*.py”文件,和templates目录及其子目录下所有的”*.html”文件里面搜寻可翻译的文字,即所有调用”gettext()”,”ngettext()”和”_()”方法时传入的字符串。同时它告诉”pybabel”,当前Jinja2模板启用了autoescape和with扩展。
- 接下来,在当前目录下,生成一个名为”messages.pot”的翻译文件模板
pybabel extract -F babel.cfg -o messages.pot . 打开”messages.pot”,你会发现,上例中”No users”, “Test Sample”等文字都出现在”msgid”项中了,很强大吧。参数”-F”指定了Babel配置文件;”-o”指定了输出文件名。
- 如果你在程序中用到了”lazy_gettext()”方法,那么你需要加上参数”-k lazy_gettext”来提醒pybabel要搜索该方法的调用: pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot .
- 修改翻译文件模板
首先记得将”messages.pot”中的”#, fuzzy”注释去掉,有这个注释在,将无法编译po文件。然后修改里面的项目信息内容如作者,版本等
- 创建”.po”翻译文件
pybabel init -i messages.pot -d translations -l zh
- 上面的命令就可以创建一个中文的po翻译文件了,文件会保存在当前目录下的”translations/zh/LC_MESSAGES”下,文件名为”messages.po”。参数”-i”指定了翻译文件模板;”-d”指定了翻译文件存放的子目录,上例中我们放在”translations”子目录下;”-l”指定了翻译的语言,同样也是第二级子目录的名称”zh”。
- 编辑”.po”翻译文件
打开刚才生成的中文po翻译文件,将我们要翻译的内容写入”msgstr”项中,并保存:
#: flask-ext3.py:31
msgid "No users"
msgstr "没有用户" #: flask-ext3.py:32
msgid "%(num)d user"
msgid_plural "%(num)d users"
msgstr[0] "%(num)d个用户" #: templates/hello.html:2
msgid "Test Sample"
msgstr "测试范例" #: templates/hello.html:3
msgid "Hello World!"
msgstr "世界,你好!"- 最后一步,编译po文件,并生成”*.mo”文件
pybabel compile -d translations
- “-d”指定了翻译文件存放的子目录。该命令执行后,”translations”目录下的所有po文件都会被编译成mo文件。
- 如果我们当前的语言”locale”已经设置为”zh”了,再次启动应用,访问根视图或者”/trans”视图,你会看到我们的文字都已经是中文的了。
- 之后,如果代码中的待翻译的文字被更改过,我们需要重新生成”messages.pot”翻译文件模板。此时,要是再通过”pybabel init”命令来创建po文件的话,会丢失之前已翻译好的内容,这个损失是很大的,其实我们可以通过下面的方法来更新po文件:
pybabel update -i messages.pot -d translations
- “-i”和”-d”参数就不用再解释了。执行”pybabel update”后,原先的翻译会被保留。不过要注意,因为有些字条pybabel无法确定,会将其标为”fuzzy”,你要将”fuzzy”注释去掉才能使其起效。
- 最后的最后,提醒下大家,translations目录必须是跟你Flask的app应用对象在同一目录下,如果你的app对象是放在某个包里,那translations目录也必须放在那个包下。
格式化日期
Flask-Babel不仅可以翻译文字,还可以自动翻译日期格式,运行下面的例子:
from flask_babel import format_datetime
from datetime import datetime @app.route('/now')
def current_time():
return format_datetime(datetime.now())
假设当前系统时间是”2016-3-20 11:38:32″,在locale是en的情况下,会显示”Mar 20, 2016, 11:39:59 AM”;而在locale是zh的情况下,会显示”2016年3月20日 上午11:38:32″。
“format_datetime()”方法还可以带第二个参数指定输出格式,如”full”, “short”, “yyyy-MM-dd”等
格式化数字
Flask-Babel提供了”format_number”和”format_decimal”方法来格式化数字,使用方法同上例中的”format_datetime”非常类似,只需传入待格式化的数字即可:
from flask.ext.babel import format_decimal
@app.route('/num')
def get_num():
return format_decimal(1234567.89)
上面的数字,在locale是en的情况下,会显示”1,234,567.90″;而在locale是de的情况下,会显示”1.234.567,89″。
格式化货币
既然可以格式化数字,自然也少不了货币格式化显示的功能了。我们可以使用”format_currency”方法,它同”format_decimal”的区别是它必须传入两个参数,第二个参数指定了货币类型:
from flask_babel import format_currency
@app.route('/currency')
def currency():
return format_currency(1234.5, 'CNY')
上面的数字”1234.5″,在类型(即第二个参数)是”CNY”的情况下,会显示”¥1,234.50″;而在类型是”USD”的情况下,会显示”US$1,234.50″。
Flask-Babel还提供了格式化百分数”format_percent”,和格式化科学计数”format_scientific”的方法等
Flask 扩展 国际化 本地化的更多相关文章
- JS魔法堂:不完全国际化&本地化手册 之 理論篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- JS魔法堂:不完全国际化&本地化手册 之 实战篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- JS魔法堂:不完全国际化&本地化手册 之 拓展篇
前言 最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求--国际化&本地化.熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已. ...
- Inside Flask - flask 扩展加载过程
Inside Flask - flask 扩展加载过程 flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask. ...
- 08-IOSCore - App Store、国际化/本地化
App Store 1. 帐号身份 0. 有Xcode 写程序,在虚拟机上运行 1. 成为苹果使用者 appleid 验证邮箱 权限: 能下载应用程序 2. 成为苹果开发者 https://devel ...
- Flask從入門到入土(二)——請求响应與Flask扩展
———————————————————————————————————————————————————————————— 一.程序和請求上下文 Flask從客戶端收到請求時,要讓視圖函數能訪問一些對象 ...
- Flask 扩展 自定义扩展
创建一个为视图访问加日志的扩展Flask-Logging,并从中了解到写Flask扩展的规范. 创建工程 先创建一个工程,目录结构如下: flask-logging/ ├ LICENSE # 授权说明 ...
- Flask从入门到精通之flask扩展
Flask被设计成可扩展形式,因此并没有提供一些重要的功能,比如数据库和用户认证,所以开发者可以自由选择最适合程序的包,或者按需求自行开发.社区成员开发了大量不同用途的扩展,如果这还不能满足需求,你还 ...
- Flask扩展实现HTTP令牌token认证HTTPTokenAuth
Token认证 在restful设计中,用户认证模式通常使用json web token,而不会使用传统的HTTP Basic认证(传入账号密码) token认证模式如下:在请求header中加入to ...
随机推荐
- html基础加强2
1.表单元素 表单元素一定要提交在form标签里面 2.id和name 所有元素都有ID,但只有表单元素才有name ID不可以重复,name可以重复 name属性的目的时可以将数据提交到服务器.id ...
- poj3268(置换矩阵思想)
题意:一群牛分别从1~n号农场赶往x号农场参加聚会,农场与农场之间的路时单向的,在n个农场之间有m条路,给出 a ,b , t表示从a号农场到b号农场需要t时间. 每头牛都会选择最短的路,问来回路上( ...
- tomcat查看端口被占用
1. tomcat有安装版和压缩版 安装版的没有关闭命令 压缩版的命令如下: tomcat关闭:catalina stop/shutdown 开启:catalina start 2. 在tomca ...
- java 多态 ---父类调用子类方法
package test1;//多态的体现import javax.print.attribute.standard.RequestingUserName;import java.util.Scann ...
- k60引脚图
/*! 枚举管脚编号 */ typedef enum { /* PTA端口 */ //0~31 PTA0, PTA1, PTA2, PTA3, PTA4, PTA5, PTA6, PTA7, PTA8 ...
- 云计算之路-阿里云上:docker swarm 问题最新进展
今天中午我们在 docker swarm 集群上发布应用时遇到了一个奇怪的 docker swarm 内置负载均衡的问题,该应用的 2 个新容器成功启动后,在容器内访问正常,但通过服务名访问时一会正常 ...
- JDK的安装和Java环境变量配置
所需工具:JDK 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html
- C# 中的关键字整理
C#中的所有关键字大致可以分为保留关键字和上下文关键字两部分 快来看一下有没有不认识的吧 欢迎补充 保留关键字 abstract as base bool break byte case ...
- python笔记之函数
函数 >>> def funTest(param1): ... 'this is function document string.' #正文需要有缩进 ... return par ...
- vue简单的自由拖拽
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...