Django國際化的詳細文檔: http://djangobook.py3k.cn/2.0/chapter19/ (中文) 英文好的能夠看: https://docs.djangoproject.com/en/1.4/topics/i18n/javascript
在這裏寫下Django實現國際化的基本步驟,詳細內容見如上連接;html
(只講步驟,不談原理;由於我講不清,原理在上面連接中講的很清楚;)java
靜態翻譯html算法
一.)使用Django模板引擎的解析實現國際化,說白了就是 {% trans %}標籤國際化django
1.)將 {% load i18n %} 放在模板最前面;在html(默認的格式), txt, xml等Django模板支持的文件中將須要國際化的字段用 {% trans '****'%}表示;瀏覽器
2.)在Django項目根目錄新建一個locale目錄,而後在項目根目錄下執行django-admin.py makemessages -l zh_CN (最後一個字段是語言代碼;若是須要翻譯的模板不是html,則須要經過參數-e 指明, 如: django-admin.py makemessages -l de -e txt),爲每一個要支持的語言執行一次; 該命令將生成對應語言的po文件,如locale/zh_CN/LC_MESSAGES/django.po。服務器
3.)在每一個po文件中,爲全部須要翻譯的字段填寫對應語言的翻譯內容; 每一個msgstr對應上面的msgid;翻譯完後將po文件保存爲'UTF-8 無BOM'格式;cookie
4.)執行django-admin.py compilemessages將全部的po文件轉成便於編譯模塊處理的*.mo文件;session
5.)在settings裏面修改LANGUAGE_CODE查看效果;ide
靜態翻譯外部js
二.)外部javascript的國際化
1.)在js文件中將須要國際化的字段用 gettext('***')代替;
2.)在項目根目錄下建立一個三級目錄, 如: transjs/jsi18n/locale;在transjs和jsi18n下都放入__init__.py文件,保證改目錄可以被導入;將要被國際化的js文件拷貝到jsi18n下;
3.)將transjs/jsi18n安裝到INSTALL_APPS下;
4.)在html中,在導入須要翻譯的js前,添加<script type='text/javascript' src='/jsi18n'></script>;
5.)在全局的urls.py中添加以下代碼
js_info_dict = {
'packages': ('transjs.jsi18n',),
}
urlpatterns += patterns('',
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
)
6.)在trans/jsi18n下執行django-admin.py makemessages -d djangojs -l de,生成po文件,在po文件中填入相應語言的翻譯內容;
7.)在trans/jsi18n下執行django-admin.py compilemessages編譯po文件,生成mo文件;
8.)在settings裏面修改LANGUAGE_CODE查看效果;
以上是靜態翻譯的基本步驟,是根據settings.py中的LANGUAGE_CODE翻譯的,下面看看如何動態翻譯
三.)動態翻譯(提供語言列表讓用戶選擇,根據用戶選擇的語言動態切換),如下步驟是在完成了上面一,二的基礎上進行的;
1.)在settings.py中設置所支持的語言列表; 如支持中文和英文
LANGUAGES = (
('zh', '簡體中文'),
('en', 'English'),
)
2.)添加中間件LocaleMiddleware, 在MIDDLEWARE_CLASSES設置中增長 'django.middleware.locale.LocaleMiddleware';必須放在 SessionMiddleware和CacheMiddleware的後面;
3.)重定向視圖,Django自帶了一個 django.views.i18n.set_language 視圖,做用是設置用戶語言偏好並重定向返回到指定的頁面;
在URLconf中加入下面這行代碼來激活這個視圖:
(r'^i18n/', include('django.conf.urls.i18n')),
4.)提交切換語言的請求,下面是一個請求的表單例子;在next的value中指定切換語言後顯示的頁面;
<form action='/i18n/setlang/' method='post'>
<input name='next' type='hidden' value='/next/page/' />
<select name='language'>
{% for lang in LANGUAGES %}
<option value='{{ lang.0 }}'>{{ lang.1 }}</option>
{% endfor %}
</select>
<input type='submit' value='Go' />
</form>
四.)翻譯的內容中含有參數的狀況
1.)在html中使用模板參數,此時必須使用{% blocktrans %}代替{% trans %},例如:
{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
其中{{ value }}是一個django模板變量,由django在將模板轉換成具體的html時傳入;
2.)若是要使用模板過濾器來翻譯一個模板表達式,須要在翻譯的這段文本中將表達式綁定到一個本地變量中:
{% blocktrans with value|filter as myvar %} This will have {{ myvar }} inside. {% endblocktrans %}
myvar就是用來綁定表達式本地變量;filter是django所支持的全部過濾器,下面是個使用length的例子;
例如:有一個模板變量{{ funcname }},在翻譯串內須要用到該變量的字符長度:
{% blocktrans with funcname|length as len %}
There is {{ len }} letter in {{ funcname }}.
{% endblocktrans %}
len :本地變量,用來綁定(或者說保存){{funcname}}的長度,而後在做爲參數出如今翻譯字符串內;
{{ funcname }}: 就是1.)裏面所講的模板變量;
這裏又引出了另外一個問題,就是若是len大於1怎麼辦? Good question,its answer is using {% plural %} tag. 簡單的說就是把單複數形式的句子都寫一遍,用{% plural %}區分開,先寫單數形式,再寫複數形式,實際翻譯時,會自動根據len的值來選擇句子,具體以下:
{% blocktrans with funcname|length as len %}
There is only one letter in {{funcname}}.
{% plural %}
There are {{ len }} letters in {{ funcname }}.
{% endblocktrans %}
3.)js中使用參數;這個也許有更精妙的方法,可是目前我只知道下面的方法;
在須要翻譯的字符串裏放入一個佔位符,而後在獲得翻譯的字串後,將佔位符用實際的值取代;
如; gettext('Nice to meet you, %s');
這個地方用 %s 做爲佔位符;在獲得翻譯的字串後,將 %s 替換成實際的人名便可;
<完>
原理分析:
django.middleware.locale.LocaleMiddleware
LocaleMiddleware 按照以下算法肯定用戶的語言:
1. 首先,在當前用戶的 session 的中查找django_language(LANGUAGE_SESSION_KEY = '_language')鍵;
2. 如未找到,它會找尋一個cookie,key爲LANGUAGE_COOKIE_NAME = 'django_language'
3. 還找不到的話,它會在 HTTP 請求頭部裏查找Accept-Language, 該頭部是你的瀏覽器發送的,而且按優先順序告訴服務器你的語言偏好。 Django會嘗試頭部中的每個語種直到它發現一個可用的翻譯。
4. 以上都失敗了的話, 就使用全局的 LANGUAGE_CODE 設定值。
只有在 LANGUAGES 設置中列出的語言才能被選用。 若但願將語言限制爲所提供語言中的某些(由於應用程序並不提供全部語言的表示),則將 LANGUAGES 設置爲所但願提供語言的列表,例如: 例如:
LANGUAGES = ( ('de', _('German')), ('en', _('English')), )
一旦LocaleMiddleware決定用戶的偏好,它會讓這個偏好做爲request.LANGUAGE_CODE對每個HttpRequest有效。請隨意在你的視圖代碼中讀一讀這個值。 如下是一個簡單的例子:
def hello_world(request): if request.LANGUAGE_CODE == 'de-at': return HttpResponse("You prefer to read Austrian German.") else: return HttpResponse("You prefer to read another language.")
注意,對於靜態翻譯(無中間件)而言,此語言在settings.LANGUAGE_CODE中,而對於動態翻譯(中間件),它在request.LANGUAGE_CODE中。