django 开发多语言网站

django的国际化支持非常好也很易用,支持代码、模板和JS的国际化整体解决方法。特别是到了1.2版本加入了对于模板本地的

日期和数字的本地格式化,其国际化支持已经完善。

 

应用方法

首先需要修改settings.py:

1. TEMPLATE_CONTEXT_PROCESSORS 加入django.core.context_processors.i18n

2. MIDDLEWARE_CLASSES中加入django.middleware.locale.LocaleMiddleware,注意:它要放在SessionMiddleware和CacheMiddleware的后面,其他中间件的前面

3. LANGUAGE_CODE 设置缺省的网站语言,如 en, zh-cn,it, de-at, es, pt-br

4. LANGUAGES设置网站所支持的所有语言,如(('en', u'English'),('zh-cn',u'中文'))

5. USE_I18N 设置为True

 

代码中的应用:

1. 所有需要国际化支持的源文件要引入函数gettext:  from django.utils.translation import ugettext_lazy as _

2.  需要多语言支持的字符串如此例写: name = models.CharField(_('Name')…)

 

模板中的应用:

1.  所有需要国际化支持的模板文件需要加载: {% load i18n %}

2.  需要多语言支持的字符串如此写:<title>{% trans "This is the title." %}</title>

3.  翻译中间带变量的句子:{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}

 

JS中的应用(这部分看django的文档没搞出来,自己看源码琢磨了一个方法。你也可参考这个文档):

1. 在url.py中加入: (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),

这句话告诉页面在加载这个脚本时由服务器上的javascript_catalog函数生成该脚本,具体的方法是通过packages找到locale,进而找到mo文件,然后将其中的所有翻译字符串放入生成脚本中的一个字典变量中,同时该脚本也定义了gettext函数,这样客户端脚本可使用gettext方法直接从字典中取出翻译字符串。

其中packages为你的项目名或者Application名的列表以加号隔开,格式为:  testproject+testproject.app1+testproject.app2。这些项目或Application应在INSTALLED_APPS中申明。

2. 引用jsi18n: <script type="text/javascript" src="/jsi18n/testproject+testproject.app1+testproject.app2”></script>

我的项目不大,只在项目目录下有locale目录因此这样写就可以了 <script type="text/javascript" src="/jsi18n/testproject”></script>

如果你的项目较大,可考虑在Application中放locale目录,如例写脚本链接,这样的话不用每次都生成和加载全站的JS翻译字符串,以加快速度。

3. 在JS中使用gettext函数翻译:document.write(gettext('this is to be translated'));

4. 翻译带变量的句子

fmts = ngettext('There is %s object. Remaining: %s', 'There are %s objects. Remaining: %s', 11); 

s = interpolate(fmts, [11, 20]); // s is 'There are 11 objects. Remaining: 20'


生成po文件和mo文件

这里先补补课,首先是locale目录, 请把locale创建在项目目录或Application目录中,其结构

locale
      en
           LC_MESSAGES (这个目录下放django.po/mo, djangojs.po/mo)
      zh-cn
           LC_MESSAGES(这个目录下放django.po/mo, djangojs.po/mo)

 

django.po/djangojs.po相当于资源文件,它被编译后形成django.mo/djangojs.mo文件,在运行时被读取。

po文件可以使用工具poedit编辑,我个人喜欢使用  mangage.py makemessages –a 让django自动分析源代码和模板文件

生成po,这里要注意两点:

1. 按我的实践,js中的字符串不能自动生成po,需手工生成

2. makemessages 需要调用工具xgettext, Windows没有,可下载晕版的gettext, 要下两个文件gettext-runtime-X.zipgettext-tools-X.zip 

   X为版本号,注意版本低了会报错“Django internationalization requires GNU gettext 0.15 or newer”)

   下来后放在解压在一个目录里,然后把下面的bin目录加到你系统路径中。

3. 通过mangage.py makemessages –a自动生成后,你需要做的是编辑po文件,如 zh-cn/LC_MESSAGES/djang.po,把你的

翻译逐个写上去。最后一步编译: mange.py compilemessages

 

让用户在页面上切换语言

把这个放到urls.py中:(r'^i18n/', include('django.conf.urls.i18n'))

搞个表单提交用户选择的语言,如例 

<form action="/i18n/setlang/" method="post"> {% csrf_token %} 
<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>

这里涉及一个问题,用户如此选择的语言是否能被记住,下次访问时无需再选?首先需要了解django如何确定用户需要的语言,其判断流程如此:

1. 首先判断Session里是否有键值为django_language的数据,如有则使用。(在用户选择语言时,如果网站支持Session,django把用户的语言偏好记录在Session中,否则记录在cookie里)

2. 检查cookie里是否有键值为settings.LANGUAGE_COOKIE_NAME的设置,如有则使用。

3. 检查浏览器提供的Accpet Language(各个浏览器都有的配置:语言首选项)是否被网站支持(是否有相应的翻译文件),如支持则使用

4. 以上方式都不能确定时,使用settings.LANGUAGE_CODE(网站缺省语言)

注意这样的方式能确保根据用户浏览器设置来为用户自动选定语言,也能保证用户选择语言后当次访问使用所选语言(用户的语言选择保存在Session和一次有效的cookie中)。如果用户浏览器的设置和其选择的语言不一致时,用户下次访问就无法使用本次选择的语言。要解决这个问题,可以接管"/i18n/setlang/"这个URL的处理,把用户选择直接保存在cookie里,而且其生命周期要搞得长一些。如例:

def set_language(request): 
from django.utils.translation import check_for_language

next = request.REQUEST.get('next', None)
if not next:
next = request.META.get('HTTP_REFERER', None)
if not next:
next = '/'
response = http.HttpResponseRedirect(next)
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['django_language'] = lang_code
max_age = 60*60*24*365
expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT")
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code, max_age, expires)
return response

最后,上述url配置改成这样: :(r'^i18n/setlang', 'yourproject.yourapp.views.set_language'),

 

posted @ 2010-05-31 16:48 观无明 阅读(...) 评论(...) 编辑 收藏