zoukankan      html  css  js  c++  java
  • flask-babel

    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”命令来创建翻译文件

    1. 首先让我们创建一个Babel的配置文件,文件名任意,这里我们取名为”babel.cfg”
    2. [python: **.py]
      [jinja2: **/templates/**.html]
      extensions=jinja2.ext.autoescape,jinja2.ext.with_

      这个文件告诉”pybabel”要从当前目录及其子目录下所有的”*.py”文件,和templates目录及其子目录下所有的”*.html”文件里面搜寻可翻译的文字,即所有调用”gettext()”,”ngettext()”和”_()”方法时传入的字符串。同时它告诉”pybabel”,当前Jinja2模板启用了autoescape和with扩展。

    3. 接下来,在当前目录下,生成一个名为”messages.pot”的翻译文件模板   
      pybabel extract -F babel.cfg -o messages.pot .   打开”messages.pot”,你会发现,上例中”No users”, “Test Sample”等文字都出现在”msgid”项中了,很强大吧。参数”-F”指定了Babel配置文件;”-o”指定了输出文件名。
    4. 如果你在程序中用到了”lazy_gettext()”方法,那么你需要加上参数”-k lazy_gettext”来提醒pybabel要搜索该方法的调用: pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot .
    5. 修改翻译文件模板
    6. 首先记得将”messages.pot”中的”#, fuzzy”注释去掉,有这个注释在,将无法编译po文件。然后修改里面的项目信息内容如作者,版本等

    7. 创建”.po”翻译文件
    8. pybabel init -i messages.pot -d translations -l zh
    9. 上面的命令就可以创建一个中文的po翻译文件了,文件会保存在当前目录下的”translations/zh/LC_MESSAGES”下,文件名为”messages.po”。参数”-i”指定了翻译文件模板;”-d”指定了翻译文件存放的子目录,上例中我们放在”translations”子目录下;”-l”指定了翻译的语言,同样也是第二级子目录的名称”zh”。
    10. 编辑”.po”翻译文件
    11. 打开刚才生成的中文po翻译文件,将我们要翻译的内容写入”msgstr”项中,并保存:

    12. 复制代码
      #: 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 "世界,你好!"
      复制代码
    13. 最后一步,编译po文件,并生成”*.mo”文件
    14. pybabel compile -d translations
    15. “-d”指定了翻译文件存放的子目录。该命令执行后,”translations”目录下的所有po文件都会被编译成mo文件。
    16. 如果我们当前的语言”locale”已经设置为”zh”了,再次启动应用,访问根视图或者”/trans”视图,你会看到我们的文字都已经是中文的了。
    17. 之后,如果代码中的待翻译的文字被更改过,我们需要重新生成”messages.pot”翻译文件模板。此时,要是再通过”pybabel init”命令来创建po文件的话,会丢失之前已翻译好的内容,这个损失是很大的,其实我们可以通过下面的方法来更新po文件:
    18. pybabel update -i messages.pot -d translations
    19. “-i”和”-d”参数就不用再解释了。执行”pybabel update”后,原先的翻译会被保留。不过要注意,因为有些字条pybabel无法确定,会将其标为”fuzzy”,你要将”fuzzy”注释去掉才能使其起效。
    20. 最后的最后,提醒下大家,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”的方法等

  • 相关阅读:
    LeetCode 109 Convert Sorted List to Binary Search Tree
    LeetCode 108 Convert Sorted Array to Binary Search Tree
    LeetCode 107. Binary Tree Level Order Traversal II
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 103 Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 104. Maximum Depth of Binary Tree
    接口和多态性
    C# 编码规范
  • 原文地址:https://www.cnblogs.com/miaoweiye/p/12525167.html
Copyright © 2011-2022 走看看