django 國際化支持 I18N


問題描述

最近做的網站需要中英雙語可以切換,內容大致相同,只是文字上需要做翻譯,而且可以讓用戶進行語言的選擇。

問題解決

其實頁面大部分內容是相同的,只是文字和部分圖片不同。django提供了i18n(internationalization)的解決方案。

i18n提供接口讓web開發者在制作網站時將需要翻譯的部分標記出來,然后生成翻譯文件,在翻譯文件中對標記的字符串進行翻譯,然后編譯生成供django使用的翻譯文件即可。下面按步驟記錄下過程。

1.添加url

在url文件中添加:

url(r'^i18n/', include('django.conf.urls.i18n')),

 

這樣,發送i18n/開頭的Post會送給django的i18n處理。

2. 在settings中更新國際化的相關設置

在settings.py中添加:

USE_I18N = True
ugettext = lambda s: s 

LANGUAGES = ( 
   ('en-us', ugettext('English')), 
   ('zh-CN', ugettext('Chinese')), 
) 

3.模板設置

在settings.py里面的TEMPLATES列表里面的OPTIONS里面的context_processors里面添加一條:

'django.template.context_processors.i18n',

 

4.添加django.middleware.locale.LocaleMiddleware中間件

需要放在
django.contrib.sessions.middleware.SessionMiddleware后面,
django.middleware.common.CommonMiddleware的前面,如下:

MIDDLEWARE = [
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.locale.LocaleMiddleware',
   'django.middleware.common.CommonMiddleware',
]

5.同步數據庫

i18n需要section數據庫表的支持,所以需要同步數據庫。

6.添加待翻譯標記

待翻譯部分可能位於模板中,也可能位於視圖函數中,兩者標記的方式不同。

試圖函數方法如下:

首先引入ugettext:

from django.utils.translation import ugettext as _

 

然后將待翻譯的字符串作為ugettext的參數,比如:

_('Please input correct verification code'))

 

這樣這個字符串在處理好i18n后就可能會被替換成其他語言。

在模板中方式如下:

首先要引入i18n:

{% load i18n %}

 

然后將待翻譯的字符串用{%trans ‘some strings’ %}包裹起來,比如:

{%trans 'please input password' %}

 

這樣在i18n中’please input password就會被替換成其他語言。

7.創建並更新語言文件

先在app中創建一個名為locale的路徑,然后執行:

$ django-admin makemessages -l zh_CN

 

這樣就會在locale目錄下生成一個zh_CN/LC_MESSAGES/這樣的路徑里面有個名為django.po的文件,這個文件將我們標記出來的字符串列了出來,我們可以在這里進行翻譯。

翻譯完成后執行:

$ django-admin compilemessages

生成一個名為django.mo的文件,就是django使用的翻譯文件。

做到這一步,就可以根據用戶的瀏覽器語言設置,使用相應的語言。但如果需要用戶自己選擇他的語言種類,還需要更進一步。

8.提供用戶選擇語言種類的接口

在模板中提供一個表單:

<form name="testform" id="testform" method='post'>{% csrf_token %}
    <select id="language" name="language" onchange="selectdb(this)">
        <option value="1">{% trans "Languages" %}</option>
        {% for lang in LANGUAGES %}
        <option value="{{ lang.0 }}" > {{ lang.1 }}</option>
        {% endfor %}
    </select>
</form>

<script>
function selectdb(obj) {
    str="/i18n/setlang/";
    myform = document.getElementById('testform');
    myform.method = "POST";
    myform.action = str;
    myform.submit();
}
</script>

 

這個表單可以將用戶選擇的語言種類傳給/i18n/setlang/,進行語言選擇。

另外,如果需要在試圖函數中獲得當前用戶使用的語言,可以使用如下值:

request.LANGUAGE_CODE

 

 

 

 

 

http://blog.csdn.net/pipisorry/article/details/45061579

如果你要實現多種語言版本的django網站,如英語和中文的兩個網站,lz將介紹一個最快捷的方法。

Note:lz建議不會經常變動的字符如網頁表頭、title什么的用資源.po文件實現翻譯。而admin后台管理員填寫的內容在model中設置多個語種的字段,再在views中判斷當前請求的語言,來返回相應語種的字段。


Django 國際化簡介

國際化 -- Internationalization,i 和 n 之間有 18 個字母,簡稱 I18N,。本地化 -- localization, l 和 n 之間有 10 個字母,簡稱 L10N。國際化意味着 Web 產品有適用於任何地方的潛力,針對程序開發人員;本地化則是指使一個國際化的程序為了在某個特定地區使用而進行實際翻譯的過程,針對翻譯人員而言。

Django 的開發和維護者對 Django 框架本身進行了完全國際化,我們可以在 ./Python2.5/site-packages/django/conf/locale/ 找到相關的語言文件。目前 Django-1.2.1 帶着 52 個不同的本地化語言文件發行的,使用戶能夠方便的使用它現有的管理界面。

Django 國際化的本質就是開發者對需要翻譯的字符串進行標記,並對字符串進行相應的翻譯。當用戶訪問該 Web 時,Django 內部框架根據用戶使用偏好進行 Web 呈現。

Django 國際化使用的翻譯模塊是使用 Python 自帶的 gettext 標准模塊。通過一個到 GNU gettext 消息目錄庫的接口,這個模塊為 Python 程序提供了國際化 (I18N) 和本地化 (L10N)。

開發人員和翻譯人員需要完成一下 3 個步驟:

1. 第一步:在 Python 代碼和模板中嵌入待翻譯的字符串,

2. 第二步:把那些字符串翻譯成需要支持的語言,並進行相應的編譯

3. 第三步:在 Django settings 文件中激活本地中間件

http://blog.csdn.net/pipisorry/article/details/45061579



安裝配置gettext

Django框架具有很好的I18N和L10N的支持,其實現是基於GNU的gettext,所以要想在Django中使用I18N還需要先安裝配置gettext。

Windows下的gettext(linux下可能不用安裝)

對於那些要提取消息或編譯消息文件的人們來說,需要的只有這么多。翻譯工作本身僅僅包含編輯這個類型的現存文件,但如果你要創建你自己的消息文件,或想要測試或編譯一個更改過的消息文件,你將需要這個gettext公用程序。

1. 從http://sourceforge.net/projects/gettext下載以下zip文件

gettext-runtime-0.17.zip

gettext-tools-0.17.zip

  • 同一文件夾下(e.g.D:\Downloads\Programming\gettext)展開這2個壓縮文件中的bin\。(注意目錄合並了)

  • 更新系統路徑

    • 控制面板>系統>高級>環境變量系統變量列表中,點擊Path,點擊Edit;D:\Downloads\Programming\gettext\bin加到變量值字段的末尾。

Note:安裝時一定要注意版本對應,如django1.7對應版本0.15+;安裝可能需要 libiconv-1.9.1.tar.gz
在CMD中驗證下我們的配置是否正確 xgettext --version或者gettext --version。

Note:
1. 可能先要用命令CHCP 65001修改cmd編碼為utf-8,否則執行gettext --version會出現亂碼和死循環打印奇怪字符。(lz也是醉了- -!)[windows命令行cmd設置和快捷鍵]
2. 只要xgettext--version命令正常工作,你亦可使用從別處獲得的gettext的二進制代碼。有些版本的0.14.4二進制代碼被發現不支持這個命令。 不要試圖與Django公用程序一起使用一個gettext。在一個windows命令提示窗口輸入命令 `` xgettext —version``將導致出現一個錯誤彈出窗口–“xgettext.exe產生錯誤並且將被windows關閉”。
3. gettext-tools-X.binzip中的readme提到This package contains Win32 binaries of GNU gettext-tools 0.17.Together with these binaries, you also need the Win32 binaries of GNU gettext-runtime (0.17.1) and of GNU libiconv (1.9.1 or newer).Unpack them in the same directory as this package.7
4. If you don’t have the gettext utilities installed,makemessages will create empty files.



配置

settings.py 里面有一個屬性LANGUAGE_CODE = 'en',這里設置了網站默認的語言。

啟用i18n

由於settings.py里面的屬性支持重寫,首先在project的setting.py 文件中啟用i18n和l10n,及設置USE_I18N =TRUE和USE_L10N=TRUE,一般情況下這兩個值默認是開啟狀態

如果您不需要國際化支持,那么您可以在您的設置文件中設置 USE_I18N=False 。 如果USE_I18N 被設為 False ,那么Django會進行一些優化,而不加載國際化支持機制。您也可以從您的TEMPLATE_CONTEXT_PROCESSORS 設置中移除'django.core.context_processors.i18n'

[Django的官方文檔上的i18n]

http://blog.csdn.net/pipisorry/article/details/47185795



聲明需要進行國際化的字符串

這又分為.py文件的國際化和html模板文件的國際化。
py文件的國際化
在.py文件中指定翻譯字符串的 4 個主要函數及其用途:

django.utils.translation.ugettext()        指定一個翻譯字符串,一般都用於 views.py

No-op翻譯django.utils.translation.gettext_noop()

標記一個不需要立即翻譯的字符串。 這個串會稍后從變量翻譯。使用這種方法的環境是,有字符串必須以原始語言的形式存儲(如儲存在數據庫中的字符串)而在最后需要被 翻譯出來(如顯示給用戶時)。

惰性翻譯django.utils.translation.gettext_lazy()

ugettext_lazy() 將字符串作為惰性參照存儲,而不是實際翻譯 , 一般會用於 models.py。 翻譯工作將在字符串在字符串上下文中被用到時進行,比如在 Django 管理頁面提交模板時。在 Django 模型中總是無一例外的使用惰性翻譯。lazy 是一種延遲計算,使用它表示一種對結果的承諾,但只有當真正需要時才會去計算。只要你不是真是需要,你得到的並不是真正的結果。

django.utils.translation.ungettext()    函數包括三個參數: 單數形式的翻譯字符串,復數形式的翻譯字符串,和對象的個數(將以 count 變量傳遞給需要翻譯的語言)。

這里強烈要求使用惰性翻譯,這樣能夠有效節省django的性能開支。以下我們以惰性翻譯為例舉個例子:
from django.utils.translation import gettext_lazy as _
transText = _("please login")

模板文件中的國際化
標簽修改有兩種{% trans "string" %}和{% blocktrans%},{%endblocktrans %},這兩個標簽都需要在模板的最開始地方加入{% load i18n %}

Note:模板中的 {% load %} 標簽用於加載已有的模板。在 /usr/local/lib/Python2.5/site-packages/django/templatetags/i18n.py 文件中定義了指定模版中翻譯字符串的模板標簽。在 django 的模板前加入 {% load i18n %},在 i18n.py 源文件中的定義標簽就可以在有 load 語句的模板中使用了。

{% trans "string" %}
{% load i18n %}
<!DOCTYPE html>
<html lang="en">
<head>
<title> Learning Center {% trans "Welcome You" %}--Learn Center</title>
這樣,我們就指定了要進行國際化的字符串welcome you,在適當的時機Django就能夠將其翻譯成相對應的文字。
Note:一般情況下這兩個標簽沒有什么區別,翻譯工作都准備就緒了,接下來就是體現到模板上去了,首先加載i18n,在模板文件的頭部加入{% load i18n%},下來對於需要i18n支持的字段使用{% trans 'Key' %},這里的Key就是某個msgid。
只有需要翻譯的字符串包含了django的變量,我們才不得不使用blocktrans來標識。
翻譯的內容中含有參數的情況{% blocktrans%},{%endblocktrans %}
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 %}
[模板標簽的實現原理]

另一種實現-使用template filter[http://simple-is-better.com/news/407]




消息文件 - 翻譯文件

制作消息文件

就是為一種語言創建一個信息文件。 信息文件是包含了某一語言翻譯字符串和對這些字符串的翻譯的一個文本文件。 信息文件以 .po 為后綴名。

這一步的前提是gettext配置好了,然后我們進入到project的根目錄創建一個locale的文件夾(如果沒有這個文件夾命令會出錯)

Note:Changed in Django 1.7:When you runmakemessages from the root directory of your project, theextracted strings will be automatically distributed to the proper messagefiles. That is, a string extracted from a file of an app containing alocale directory will go in a message file under that directory.A string extracted from a file of an app without anylocale directorywill either go in a message file under the directory listed first inLOCALE_PATHS or will generate an error if LOCALE_PATHSis empty.Django中帶有一個工具,bin/make-messages.py ,它完成了這些文件的創建和維護工作。

下面兩處處之一運行以下命令:Django項目根目錄(包含manage.py的目錄。e.g. E:\mine\python_workspace\WebSite\labsite\labsite);您Django應用的根目錄。The script should be run from one of two places:The root directory of your Django project (the one that contains manage.py).The root directory of one of your Django apps.

創建或更新一個信息文件

django-admin.py makemessages -l zh


Note:

1. linux/migw使用命令django-admin.py makemessages -l en,如果是在windows環境下需要特別注意,因為這兩個命令(+compilemessages)使用了一個windows下默認沒有安裝的組件,gettext。為在windows下運行,需要下載安裝gettext。確保已經安裝了gettext,否則出錯:

2. windows命令行cmd中要指明路徑使用命令pythonD:\python3.4.2/Lib/site-packages/django/bin/django-admin.py makemessages -l en來生成翻譯的.po文件

3. zh_CN是所創建的信息文件的語言代碼。 在這里,語言代碼是以本地格式給出的。 例如,巴西地區的葡萄牙語為pt_BR ,德語de, 澳大利亞地區的德語為de_AT 。lz建議在windows下實現時將zh_CN改成zh,原因見《在settings.py中設置所支持的語言列表》部分Note2

4. 這段腳本遍歷你的項目源樹或你的應用程序源樹並且提取出所有為翻譯而被標記的字符串。 它在 locale/LANG/LC_MESSAGES 目錄下創建(或更新)了一個信息文件。針對上面的de,應該是locale/de/LC_MESSAGES/django.po

5. 作為默認, django-admin.py makemessages 檢測每一個有.html 擴展名的文件。  以備你要重載缺省值,使用--extension-e 選項指定文件擴展名來檢測。
django-admin.py makemessages -l de -e txt

用逗號和(或)使用-e--extension來分隔多項擴展名:django-admin.py makemessages -l de -e html,txt -e xml

6. locale下子目錄的樣式有固定格式,如:locale/<language>/LC_MESSAGES/。如果是中文,對應的目錄就是locale/zh_CN/LC_MESSAGES/。如果是英文,則應該是locale/en/LC_MESSAGES/

7. 為了在django里面使用i18n,po文件名必須為django.po,編譯過后必須為django.mo,那么翻譯的內容就固定在po文件里了。
8. 也可以自己創建目錄在目錄中使用python D:/python3.4.2/Tools/i18n/pygettext.py生成翻譯文件模版messages.pot,改之,charset=gb2312 Content-Transfer-Encoding: utf8,保存之,文件名改為lang.po.

再參考[python國際化(i18n)和中英文切換]

消息文件錯誤處理

makemessages時解碼錯誤UnicodeDecodeError:skipped file

windows下,如果html文件(包括注釋,不僅僅是trans中的)中存在中文或者奇怪空字符&nbsp&nbsp,就會出現的錯誤:UnicodeDecodeError:skipped file

commanderror: errors happened while running msgmerge msgmetge:無法識別的選項“--previous"

解決

1. 如果trans中含有中文,建議將html文檔編碼改成gbk編碼[windows小工具 - 轉換文件編碼]

2. 如果只是html中有中文(trans中沒有),建議將D:\python3.4.2\Lib\site-packages\django\core\management\commands\makemessages.py中91/95行語句改成

with open(orig_file, 'r' if six.PY3 else 'rU', encoding='utf-8') as fp:
with open(os.path.join(self.dirpath, thefile), "w", encoding='utf-8') as fp:
原因及解釋

html文件編碼與django的解碼器不對應,官方文檔中提到html必須是utf-8編碼的,但還是出現編碼錯誤

lz通過分析django源碼,發現UnicodeDecodeError錯誤來源於 makemessages(D:\python3.4.2\Lib\site-packages\django\core\management\commands\makemessages.py),

從第91行語句可見文件是以系統默認編碼打開文件的 with open(orig_file, 'r' if six.PY3 else 'rU') as fp:

在文件D:\python3.4.2\Lib\site-packages\django\utils\encoding.py中print編碼值,得到cp936而不是utf-8


"Content-Transfer-Encoding: 8bit\n"

msgid "Home"
msgstr "主頁"

msgid "News"
msgstr "新聞"
Note:

 

1. 格式相對比較簡單,也是鍵值對的形式。如果是多行的話,需要使用msgstr""的形式,首行不寫東西,在后續的幾行寫文本,翻譯出來的結果會由程序自動把文字組合到一起。
2. 編寫完的po文件需要編輯成二進制的mo文件才可以被django使用,django使用了gettext來實現翻譯,所以mo格式也是gettext要求的。
3. 在linux下使用msgfmt -o django.modjango.po即可完成轉換過程,相當方便,windows下需要下載poEdit這個軟件。


[一詞多譯:Same string with different translation]


編譯信息文件

創建信息文件之后,每次對其做了修改,都需要將它重新編譯成一種更有效率的形式,供 gettext 使用。可以使用django-admin.pycompilemessages完成。


這個工具作用於所有有效的 .po 文件,創建優化過的二進制.mo 文件供gettext 使用。在你可以運行django-admin.pymakemessages的目錄下,運行
django-admin.py compilemessages


Note:執行django-admin.pycompilemessages會將所有的po文件轉成便於編譯模塊處理的*.mo文件;
知道了需要翻譯的語言,Django就會相應的去查找mo文件
首先,Django查看setting.py中是否指定了LOCALE_PATHS,如果有,則使用此值。
如果setting中沒有指定,則使用project的各個app目錄下的locale文件。
如果project的各個app目錄下沒有locale,Django就會查找project的根目錄,這也是為什么我們第三步在根目錄下創建的原因。
如果根目錄底下也沒有,Django就會自動加載定義在django\conf\locale中的mo文件。

http://blog.csdn.net/pipisorry/article/details/45061579


Django處理語言偏好

一旦你准備好了翻譯,如果希望在Django中使用,那么只需要激活這些翻譯即可。在這些功能背后,Django擁有一個靈活的模型來確定在安裝和使用應用程序的過程中選擇使用的語言。


要設定一個安裝階段的語種偏好,請設定LANGUAGE_CODE。如果其他翻譯器沒有找到一個譯文,Django將使用這個語種作為缺省的翻譯最終嘗試。

如果你只是想要用本地語言來運行Django,並且該語言的語言文件存在,只需要簡單地設置LANGUAGE_CODE 即可。

如果要讓每一個使用者各自指定語言偏好,就需要使用 LocaleMiddlewareLocaleMiddleware 使得Django基於請求的數據進行語言選擇,從而為每一位用戶定制內容。 它為每一個用戶定制內容。

加入一些middleware來支持動態切換語言

使用 LocaleMiddleware需要在MIDDLEWARE_CLASSES中增加django.middleware.locale.LocalMiddleware(此選項用於支持動態國際化)

MIDDLEWARE_CLASSES = (
   'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', ) 

Note:

1. 中間件的順序是有影響的,最好按照依照以下要求:保證它是第一批安裝的中間件類。因為 LocalMiddleware 要用到session數據,所以需要放在SessionMiddleware 之后,因為需要從Session里面獲取一個語言類型。如果你使用CacheMiddleware,把LocaleMiddleware放在它后面。[中間件]

2. 這里需要注意,需要用數據庫保存 session。在本實例中用到了 mysql test2 數據庫中的 django_session 數據表。我們在 /home/jerry/testsite 目錄下運行 Python manage.py syncdb 就能產生 django_session 了。

LocaleMiddleware 按照如下算法確定用戶的語言:

  • 首先,在當前用戶的 session 的中查找django_language鍵;

  • 如未找到,它會找尋一個cookie

  • 還找不到的話,它會在 HTTP 請求頭部里查找Accept-Language, 該頭部是你的瀏覽器發送的,並且按優先順序告訴服務器你的語言偏好。 Django會嘗試頭部中的每一個語種直到它發現一個可用的翻譯。

  • 以上都失敗了的話, 就使用全局的 LANGUAGE_CODE 設定值。

Note

1. 在上述每一處,語種偏好應作為字符串,以標准的語種格式出現。 例如,巴西葡萄牙語是pt-br。如果一個基本語種存在而亞語種沒有指定,Django將使用基本語種。 比如,如果用戶指定了de-at (澳式德語)但Django只有針對de 的翻譯,那么 de 會被選用。

在settings.py中設置所支持的語言列表

只有在 LANGUAGES 設置中列出的語言才能被選用。 若希望將語言限制為所提供語言中的某些(因為應用程序並不提供所有語言的表示),則將LANGUAGES 設置為所希望提供語言的列表

測試你返回的是哪個語言的html

一旦LocaleMiddleware決定用戶的偏好,它會讓這個偏好作為request.LANGUAGE_CODE對每一個HttpRequest有效。請隨意在你的視圖代碼中讀一讀這個值,如在view.py的某個view函數中寫入語言測試代碼:

def index(request):  '''  首頁  '''  if request.LANGUAGE_CODE == 'en':  return HttpResponse("You prefer to read english.") else:  return HttpResponse("You prefer to read another language.") # return render(request, 'bigdata/index.html', locals())
Note:
1. 盡管settings.py中設置了LANGUAGE_CODE = 'zh-CN',但是request.LANGUAGE_CODE卻是en,可能是lz用的瀏覽器是英文版的,創建的session或者request中的lang設置成了en。
2. 對於靜態翻譯(無中間件)而言,此語言在settings.LANGUAGE_CODE中,而對於動態翻譯(中間件),它在request.LANGUAGE_CODE中。
3. 如果你選擇的是用兩個不同的html來實現多語種就可以通過上面這個來選擇顯示的語言。至於request.LANGUAGE_CODE怎么設置下面可以通過html模板上的一個form實現語言選擇和設置。
在view中返回response?對象時可以用兩種形式
return render(request, 'bigdata/index_e.html', locals()) return render_to_response('bigdata/index_e.html', locals(), RequestContext(request)) # return render_to_response('bigdata/index_e.html', locals(), context_instance=RequestContext(request))



在你自己的項目中使用翻譯

Django使用以下算法尋找翻譯:

  • 首先,Django在該視圖所在的應用程序文件夾中尋找locale 目錄。 若找到所選語言的翻譯,則加載該翻譯。

  • 第二步,Django在項目目錄中尋找 locale 目錄。 若找到翻譯,則加載該翻譯。

  • 最后,Django使用 django/conf/locale 目錄中的基本翻譯。

以這種方式,你可以創建包含獨立翻譯的應用程序,可以覆蓋項目中的基本翻譯。 或者,你可以創建一個包含幾個應用程序的大項目,並將所有需要的翻譯放在一個大的項目信息文件中。 決定權在你手中。

 所有的信息文件庫都是以同樣方式組織的: 它們是:
  • $APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

  • $PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

  • 所有在settings文件中 LOCALE_PATHS 中列出的路徑以其列出的順序搜索<language>/LC_MESSAGES/django.(po|mo)

  • $PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)

要創建信息文件,也是使用 django-admin.py makemessages.py 工具,和Django信息文件一樣。 需要做的就是進入正確的目錄——conf/locale (在源碼樹的情況下)或者locale/ (在應用程序信息或項目信息的情況下)所在的目錄下。 同樣地,使用compile-messages.py 生成gettext 需要使用的二進制django.mo 文件。

您亦可運行django-admin.py compilemessages--settings=path.to.settings 來使編譯器處理所有存在於您LOCALE_PATHS 設置中的目錄。

應用程序信息文件稍微難以發現——因為它們需要 LocaleMiddle 。如果不使用中間件,Django只會處理Django的信息文件和項目的信息文件。

最后,需要考慮一下翻譯文件的結構。 若應用程序要發放給其他用戶,應用到其它項目中,可能需要使用應用程序相關的翻譯。 但是,使用應用程序相關的翻譯和項目翻譯在使用make-messages 時會產生古怪的問題。它會遍歷當前路徑下所有的文件夾,這樣可能會把應用消息文件里存在的消息ID重復放入項目消息文件中。

 最容易的解決方法就是將不屬於項目的應用程序(因此附帶着本身的翻譯)存儲在項目樹之外。 這樣做的話,項目級的make-messages 將只會翻譯與項目精確相關的,而不包括那些獨立發布的應用程序中的字符串。
http://blog.csdn.net/pipisorry/article/details/45061579



在html模板中設置語言選項設置顯示語言

set_language 重定向視圖

方便起見,Django自帶了一個 django.views.i18n.set_language 視圖,作用是設置用戶語言偏好並重定向返回到前一頁面。

Make sure that the following item is in your TEMPLATE_CONTEXT_PROCESSORS list in your settings file:

TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.i18n', 'django.contrib.auth.context_processors.auth', )

在URLconf中加入下面這行代碼來激活這個視圖(在urls.py里面配置一個i18n的輔助應用):

(r'^i18n/', include('django.conf.urls.i18n')),

Note:

1. 注意這使得這個視圖在 /i18n/setlang/ 中有效

2. 這個視圖是通過 GET 方法調用的,在請求中包含了language 參數。 如果session已啟用(默認已啟用'django.contrib.sessions.middleware.SessionMiddleware',),這個視圖會將語言選擇保存在用戶的session中。 否則,它會以缺省名django_language在cookie中保存這個語言選擇。(這個名字可以通過LANGUAGE_COOKIE_NAME設置來改變)

html模板中設置語言選項表格

實現1(推薦,lz親試)

<form action="{% url 'set_language' %}" method="post"> {% csrf_token %} <input name="next" type="hidden" value="{{ redirect_to }}"/> <select name="language"> {% for language in LANGUAGES %} <option value="{{ language.0 }}"{% if language.0 == LANGUAGE_CODE %} selected="selected"{% endif %}> {{ language.1 }} ({{ language.0 }}) {% endfor %} </select> <input type="submit" value="Go"/> </form>

Note:

1. 點擊"Submit" 按鈕, form-data 數據(就是input中的value和select選中的option中的value)就會被送到服務器上的url 'set_language'對應的頁面(也可以使用下面實現2中的"/i18n/setlang/".)action啟用了django.views.i18n.set_language 視圖,它的作用是設置用戶語言偏好並重定向返回到前一頁面。[html_form_submit]

2. 如果出現錯誤Forbidden (403)CSRF verification failed. Request aborted.要在<form action="/i18n/setlang/" method="post">下一行加上 {% csrf_token %}[CSRF verification failed. Request aborted. ]

3.name="next"和name="language"不能改成其它,因為在下面原理中的set_language函數會用到。

4. 第一個input是看不到的,直接向set_language參數request提供next屬性,在next的value中指定切換語言后顯示的頁面,為空時set_language會處理為當前頁面的HTTP_REFERER(這個就先當作是原來頁面吧)

5.LANGUAGES是在settings.py中設置的全局函數,前面有講到

6. option中的if應該是選擇option中的對應於setting.py的LANGUAGE_CODE語種作為默

實現2

<form action="i18n/setlang/" method="post"> {% csrf_token %} <input name="next" type="hidden" value="{{ redirect_to }}"/> <select name="language"> {% for lang in LANGUAGES %} <option value="{{ lang.0 }}">{{ lang.1 }}</option> {% endfor %} </select> <input type="submit" value="Go"/> </form> 
這樣,在html頁面中選擇某個語言,就會返回翻譯過后的那個html頁面,完成了多語種支持。

/i18n/setlang/中的處理函數分析(文件路徑D:\python3.4.2\Lib\site-packages\django\views\i18n.py)

def set_language(request):
    """
    Redirect to a given url while setting the chosen language in the session or cookie. The url and the language code need to be specified in the request parameters.
    Since this view changes how the user will see the rest of the site, it must only be accessed as a POST request. If called as a GET request, it will redirect to the page in the request (the 'next' parameter) without changing any state.

    當在 session 或 cookie 中設置所選擇的語言時,會重定向到指定的網址。URL 和語言代碼需要在 request 的參數中被指定。由於這個視圖改變用戶如何看到網站的其他部分,它必須只能通過 POST request. 如果調用 GET request, 它將重定向到 request 的那頁,但沒有任何狀態改變。

    """
    next = request.POST.get('next', request.GET.get('next'))
    if not is_safe_url(url=next, host=request.get_host()):
        next = request.META.get('HTTP_REFERER')#using http://127.0.0.1:8000/
        if not is_safe_url(url=next, host=request.get_host()):
            next = '/'
    response = http.HttpResponseRedirect(next)#next is http://127.0.0.1:8000/
    if request.method == 'POST':
        lang_code = request.POST.get('language', None)
        if lang_code and check_for_language(lang_code):
            if hasattr(request, 'session'):
                request.session[LANGUAGE_SESSION_KEY] = lang_code;print(lang_code, 'session')#using this
            else:
                response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code,
                                    max_age=settings.LANGUAGE_COOKIE_AGE,
                                    path=settings.LANGUAGE_COOKIE_PATH,
                                    domain=settings.LANGUAGE_COOKIE_DOMAIN);print(lang_code, 'cookie')
    return response

從上面的代碼,可以了解到保存了語言選擇后,Django 根據以下算法來重定向頁面:

(1)Django 在 POST 數據中尋找 next 參數。

(2)如果 next 參數不存在或為空,Django 嘗試重定向頁面為 HTML 頭部信息中 Referer 的值。

(3)如果 Referer 也是空的,即該用戶的瀏覽器並不發送 Referer 頭信息,則頁面將重定向到 / (頁面根目錄)。

這個視圖是通過 POST 方法調用的,在請求中包含了 language 參數。所以在前面的模版的 select 的 name 和 id 必須為” language”。

如果 session 已啟用(上面提到過默認已啟用),這個視圖會將語言選擇保存在用戶的 session 中。 否則,它會以缺省名 django_language 在 cookie 中保存這個語言選擇。( 這個名字可以通過 LANGUAGE_COOKIE_NAME 設置來改變 )。



在瀏覽器中測試

Firefox 語言順序的選擇

工具 - 〉選項 - 〉內容,語言欄這一項選着,將漢語 / 中國 [zh-cn] 移到最上面。這樣頁面將會根據瀏覽器的配置,優先中文顯示。



其它解決方案

1. Django多語言翻譯輕量解決方案:使用localeurl和mothertongue來實現多語言支持,通過localurl實現URL的語言前綴,通過mothertougue來翻譯相應的字段。可以對數據庫中的內容進行翻譯等等,還可以嘗試調用google的翻譯接口,對一些簡單的單詞進行翻譯,在填入英文時自動翻譯成中文。

[Django多語言翻譯輕量解決方案]

2. 采用自定義tag的方式定義一個語言選擇的下拉框

[django多語言支持]

 from:http://blog.csdn.net/pipisorry/article/details/45061579
ref:Internationalization: in template code
Django實現國際化的步驟
Django 國際化實例及原理分析
基於gettext的Django國際化or多國語言支持(Internationlization)
django 實現多語功能
網站需要支持中英文切換的功能-CSDN論壇



免責聲明!

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



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