最近在看Django的國際化,看了很多貼子,終於有了比較系統的認識,在這里做一下簡單總結。
先來看兩個概念:
- 國際化:是指為了該軟件在任何地區的潛在使用而進行程序設計的過程。 它包括了為將來翻譯而標記的文本(比如用戶界面要素和錯誤信息等)、日期和時間的抽象顯示以便保證不同地區的標准得到遵循、為不同時區提供支持,並且一般確保代碼中不會存在關於使用者所在地區的假設。 您會經常看到國際化被縮寫為“I18N”(18表示Internationlization這個單詞首字母I和結尾字母N之間的字母有18個)。
- 本地化: 是指使一個國際化的程序為了在某個特定地區使用而進行實際翻譯的過程。 有時,本地化縮寫為L10N 。
Django的國際化
Django本身是完全國際化了的,所有的字符串均因翻譯所需而被標記,並且設定了與地域無關的顯示控制值,如時間和日期。 Django是帶着50個不同的本地化文件發行的。 這些本地化文件所使用的國際化框架同樣也可以被用在自己的代碼和模板中。
只需要添加少量的掛接代碼到Python代碼和模板中。 這些掛接代碼被稱為* 翻譯字符串* 。它們告訴Django:如果這段文本的譯文可用的話,它應被翻譯為終端用戶指定的語言。Django會根據用戶的語言偏好,在線地運用這些掛接指令去翻譯Web應用程序。
本質上來說,Django做兩件事情:
- 它讓開發者和模板的作者指定他們的應用程序的哪些部分應該被翻譯。
- Django根據用戶的語言偏好來翻譯Web應用程序。
備注:Django的翻譯機制是使用 GNU gettext (http://www.gnu.org/software/gettext/),具體為Python自帶的標准模塊 gettext 。
如果不需要國際化:
Django的國際化掛接是默認開啟的,這可能會給Django的運行增加一點點開銷。 如果您不需要國際化支持,那么您可以在您的設置文件中設置 USE_I18N = False 。 如果 USE_I18N 被設為 False ,那么Django會進行一些優化,而不加載國際化支持機制。
也可以從您的 TEMPLATE_CONTEXT_PROCESSORS 設置中移除 'django.core.context_processors.i18n' 。
使用Django 國際化
- 第一步:在你的Python代碼和模板中嵌入待翻譯的字符串。
- 第二步:把那些字符串翻譯成你要支持的語言。
- 第三步:在你的Django settings文件中激活本地中間件。
1. 如何嵌入待翻譯的字符串
使用函數django.utils.translation.ugettext() 來指定一個翻譯字符串。 作為慣例,使用短別名 _ 來引入這個函數以節省鍵入時間.
from django.utils.translation import ugettext as _
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)
小注意:
- ugettext()函數的參數可以是變量,但檢測工具make_messages.py將找不到這些字符串。
- 占位符:特定語言的譯文可能對翻譯字符串重新排序,使用位置占位符可能達不到預期效果,建議使用命名字符串插入,如_('today is %(day)s'%{'day':'monday'})
- 使用 django.utils.translation.gettext_noop() 函數來標記一個不需要立即翻譯的字符串。 這個串會稍后從變量翻譯。使用這種方法的環境是,有字符串必須以原始語言的形式存儲(如儲存在數據庫中的字符串)而在最后需要被翻譯出來(如顯示給用戶時)。
- 使用 django.utils.translation.gettext_lazy() 函數,使得其中的值只有在訪問時才會被翻譯,而不是在gettext_lazy() 被調用時翻譯。
- 使用django.utils.translation.ungettext()來指定以復數形式表示的消息。
2. 模塊中嵌入翻譯字符串
Django模板使用兩種模板標簽,為了使得模板訪問到標簽,需要將{% load i18n %} 放在模板最前面。
這個{% trans %}模板標記翻譯一個常量字符串 或 可變內容:
{%load i18n%}
<title>{%trans 'this is a title' %}</title>
<title>{%trans strvar %}</title>
小注意:
在一個帶 {% trans %} 的字符串中,混進一個模板變量是不可能的。如果譯文要求字符串帶有變量,使用{%blocktrans%}、{%endblocktrans%}
3. 如何創建語言文件
當你標記了翻譯字符串,你就需要寫出(或獲取已有的)對應的語言翻譯信息。 這里就是它如何工作的。
a. 為一種語言創建消息文件.po
信息文件是包含了某一語言翻譯字符串和對這些字符串的翻譯的一個文本文件。
python django-admin.py makemessages ‐l zh_CN
這段腳本遍歷你的項目源樹或你的應用程序源樹並且提取出所有為翻譯而被標記的字符串。 它在locale/LANG/LC_MESSAGES 目錄下創建(或更新)了一個信息文件。針對上面的zh_CN,應該是locale/zh_CN/LC_MESSAGES/django.po。
'Welcome to my site'生成的.op示例如下:
#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""
b. 編譯信息文件.mo
python django-admin.py compilemessages
4. 本地化配置
讓每一個使用者各自指定語言偏好,就需要使用 LocaleMiddleware 。 LocaleMiddleware 使得Django基於請求的數據進行語言選擇,從而為每一位用戶定制內容。 它為每一個用戶定制內容。
偏好設置:
LANGUAGES = (
('cn', _('China')),
('en', _('English')),
)
使用 LocaleMiddleware 需要在 MIDDLEWARE_CLASSES 設置中增加'django.middleware.locale.LocaleMiddleware' 。
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
中間件的順序是有影響的,最好按照依照以下要求:
- 保證它是第一批安裝的中間件類。
- 因為 LocalMiddleware 要用到session數據,所以需要放在 SessionMiddleware 之后。
- 如果你使用CacheMiddleware,把LocaleMiddleware放在它后面。
LocaleMiddleware 按照如下算法確定用戶的語言:
- 首先,在當前用戶的 session 的中查找django_language鍵;
- 如未找到,它會找尋一個cookie
- 還找不到的話,它會在 HTTP 請求頭部里查找Accept‐Language, 該頭部是你的瀏覽器發送的,並且按優先順序告訴服務器你的語言偏好。 Django會嘗試頭部中的每一個語種直到它發現一個可用的翻譯。
- 以上都失敗了的話, 就使用全局的 LANGUAGE_CODE 設定值。
Django尋找項目中的翻譯
Django使用以下算法尋找翻譯:
- 首先,Django在該視圖所在的應用程序文件夾中尋找 locale 目錄。 若找到所選語言的翻譯,則加載該翻譯。
- 第二步,Django在項目目錄中尋找 locale 目錄。 若找到翻譯,則加載該翻譯。
- 最后,Django使用 django/conf/locale 目錄中的基本翻譯。