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”命令來創建翻譯文件

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM