首页域名资讯 正文

Flask的Jinja2模板引擎 — 本地化(7th)

2025-01-10 1 0条评论

一个强大的工具一般都支持扩展或插件的开发功能,来允许第三方通过开发新扩展或插件,扩充工具本身功能,并可以贡献给社区。Jinja2也不例外,Jinja2本身提供了一部分扩展,你可以在程序中启用。同时,你还可以创建自己的扩展,来扩充模板引擎功能。本篇会先介绍Jinja2自带的扩展”jinja2.ext.i18n”的使用,自定义扩展的开发会放在下一篇阐述。

在Flask中启用Jinja2扩展

任何时候使用Jinja2时,都需要先创建Jinja2环境,所以启用扩展的方法就是在创建环境时指定:

1 2 from jinja2 import Environment jinja_env = Environment ( extensions = [ ‘jinja2.ext.i18n’ , ‘jinja2.ext.do’ ] )

但是你在使用Flask时,其已经有了一个Jinja2环境,你不能再创建一个,所以你需要想办法添加扩展。Flask对于扩展不像过滤器或测试器那样封装了添加方法和装饰器,这样你就只能直接访问Flask中的Jinja2环境变量来添加。

1 2 3 4 from flask import Flask app = Flask ( __name__ ) app . jinja_env . add_extension ( ‘jinja2.ext.i18n’ ) app . jinja_env . add_extension ( ‘jinja2.ext.do’ )

Jinja2内置扩展

我们已经介绍了四个Jinja2内置扩展的使用:”jinja2.ext.autoescape”, “jinja2.ext.with_”, “jinja2.ext.do”和”jinja2.ext.loopcontrols”。除了这几个以外,Jinja2还有一个非常重要的扩展,就是提供本地化功能的”jinja2.ext.i18n”。它可以与”gettext”或”babel”联合使用,接下来我们采用”gettext”来介绍怎么使用这个本地化扩展。

创建本地化翻译文件

建议大家先去了解下Python gettext相关知识,篇幅关系本文就不准备细讲。这里我们使用Python源代码(记住不是安装包)中”Tools/i18n”目录下的工具来创建翻译文件。

  1. 首先我们生成翻译文件模板,在”Tools/i18n”目录中找到”pygettext.py”并运行
1 $ python pygettext . py

上述命令会在当前目录下生成一个名为”message.pot”的翻译文件模板,内容如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid “” msgstr “” “Project-Id-Version: PACKAGE VERSION\n” “POT-Creation-Date: 2016-02-22 21:45+CST\n” “PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n” “Last-Translator: FULL NAME <EMAIL@ADDRESS>\n” “Language-Team: LANGUAGE <LL@trustauth.cn>\n” “MIME-Version: 1.0\n” “Content-Type: text/plain; charset=CHARSET\n” “Content-Transfer-Encoding: ENCODING\n” “Generated-By: pygettext.py 1.5\n”

2. 将”message.pot”中”CHARSET”和”ENCODING”替换成”UTF-8″。同时你可以更改注释信息

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # Jinja2 i18n Extention Sample # Copyright (C) 2016 trustauth.cn # Billy J. Hee <billy@trustauth.cn>, 2016. # msgid “” msgstr “” “Project-Id-Version: PACKAGE VERSION\n” “POT-Creation-Date: 2016-02-22 21:45+CST\n” “PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n” “Last-Translator: FULL NAME <EMAIL@ADDRESS>\n” “Language-Team: LANGUAGE <LL@trustauth.cn>\n” “MIME-Version: 1.0\n” “Content-Type: text/plain; charset=UTF-8\n” “Content-Transfer-Encoding: UTF-8\n” “Generated-By: pygettext.py 1.5\n”

修改完后,将其另存为翻译文件”lang.po”。

3.在”lang.po”中添加你要翻译的文字,比如

1 2 msgid “Hello World!” msgstr “世界,你好!

将其加在文件末尾。这里”msgid”指定了待翻译的文字,而”msgstr”就是翻译后的文字。

4. 生成”lang.mo”文件

我们依然使用”Tools/i18n”目录提供的工具,”msgfmt.py”:

1 $ python msgfmt . py lang . po

执行完后,当前目录生成了”lang.mo”文件。注意,只有这个”*.mo”文件才能被应用程序识别。另外,推荐一个工具Poedit,很强的图形化po编辑工具,也可以用来生成mo文件,非常好用,Mac和Windows下都能用。

5. 将po, mo文件加入应用

我们在当前Flask工程下创建子目录”locale/zh_CN/LC_MESSAGES/”,并将刚才生成的”lang.po”和”lang.mo”文件放到这个目录下。这里”locale”子目录的名字可以更改,其他的个人建议不要改。

在模板中使用本地化

让我们在Flask应用代码中启用”jinja2.ext.i18n”,并加载刚创建的翻译文件。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 #coding:utf8 import gettext from flask import Flask , render_template app = Flask ( __name__ ) # 加载扩展 app . jinja_env . add_extension ( ‘jinja2.ext.i18n’ ) # ‘lang’表示翻译文件名为”lang.mo”,’locale’表示所有翻译文件都在”locale”子目录下, # ‘zh_CN’表示二级子目录,含义上讲就是加载中文翻译。所以下面的代码会加载文件: # “locale/zh_CN/LC_MESSAGES/lang.mo” gettext . install ( ‘lang’ , ‘locale’ , unicode = True ) translations = gettext . translation ( ‘lang’ , ‘locale’ , languages = [ ‘zh_CN’ ] ) translations . install ( True ) app . jinja_env . install_gettext_translations ( translations )

这个”install_gettext_translations()”方法就是Jinja2提供来加载”gettext”翻译文件对象的。加载完后,你就可以在模板中使用本地化功能了。方法有两种:”{% trans %}”语句或”gettext()”方法。我们先来试下”{% trans %}”语句,在模板文件中,我们加上:

1 < h1 > { % trans    % } Hello World ! { % endtrans % } < / h1 >

运行下,有没有看到页面上打印了”世界,你好!”,恭喜你,成功了!使用”gettext()”方法如下,效果同”{% trans %}”语句一样。

1 < h1 > { { gettext ( ‘Hello World!’ ) } } < / h1 >

Jinja2还提供了”_( )”方法来替代”gettext( )”,代码看起来很简洁,个人推荐使用这个方法。

1 < h1 > { { _ ( ‘Hello World!’ ) } } < / h1 >

上面的例子是在程序中指定本地化语言,你也可以在请求上下文中判断请求头”Accept-Language”的内容,来动态的设置本地化语言。

翻译内容带参数

有时候,待翻译的文字内有一个变量必须在运行时才能确定,怎么办?我可以在翻译文字上加参数。首先,你要在po文件中定义带参数的翻译文字,并生成mo文件:

1 2 msgid “Hello %(user)s!” msgstr “%(user)s,你好!”

然后,你就可以在模板中,使用”{% trans %}”语句或”gettext()”方法来显示它:

1 2 < h1 > { % trans user = name % } Hello { { user } } ! { % endtrans % } < / h1 >      < h1 > { { _ ( ‘Hello %(user)s!’ ) | format ( user = name ) } } < / h1 >

上例中,我们把模板中的变量”name”赋给了翻译文字中的变量”user”。翻译文字上可以有多个变量。

新样式 (Newstyle)

Jinja2从2.5版本开始,支持新的gettext样式,使得带参数的本地化更简洁,上面的例子在新样式中可以写成:

1 < h1 > { { _ ( ‘Hello %(user)s!’ , user = name ) } } < / h1 >

不过使用新样式前,你必须先启用它。还记得我们介绍过Jinja2加载翻译文件的方法吗?对,就是”install_gettext_translations()”。调用它时,加上”newstyle=True”参数即可。

1 app . jinja_env . install_gettext_translations ( translations , newstyle = True )

单/复数支持

英文有个特点就是名词有单/复数形式,一般复数都是单数后面加s,而中文就不区分了,哎,老外就是麻烦。所谓外国人创造的Python gettext,自然也对单/复数提供了特殊的支持。让我们现在po文件中,加上下面的内容,并生成mo文件:

1 2 3 4 msgid “%(num)d item” msgid _plural “%(num)d items” msgstr [ 0 ] “%(num)d个物品” msgstr [ 1 ] “%(num)d个物品集”

什么意思呢,这个”msgid_plural”就是指定了它上面”msgid”文字的复数形式。而”msgstr”的[0], [1]分别对应了单/复数形式翻译后的内容。为什么这么写?你别管了,照着写就是了。

在模板中,我们加上下面的代码:

1 2 3 { % set items = [ 1 , 2 , 3 , 4 , 5 ] % }    { { ngettext ( ‘%(num)d item’ , ‘%(num)d items’ , items | count ) } } < br / >    { { ngettext ( ‘%(num)d item’ , ‘%(num)d items’ , items | first ) } }

 

文章转载来自:trustauth.cn

文章版权及转载声明

本文作者:亿网 网址:https://edns.com/ask/post/150798.html 发布于 2025-01-10
文章转载或复制请以超链接形式并注明出处。