Flask 擴展 國際化 本地化

pip install flask-babelhtml

先初始化一個Flask-Babel的實例python

from flask import Flask
from flask.ext.babel import Babel
 
app = Flask(__name__)
babel = Babel(app)

設置語言和時區

Flask-Babel提供了兩個Flask應用配置項: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()」方法清緩存:babel

from flask_babel import refresh
 
@app.route('/login')
def login():
    ... # Get new user locale and timezone
    refresh()
    ... # Render response

在視圖和模板中使用翻譯

Flask-Babel封裝了Python的」gettext()」方法,你能夠在視圖函數中使用它:app

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請求中,咱們來渲染此模板:spa

@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」的方法等

相關文章
相關標籤/搜索