您的位置:首页 > 运维架构 > 网站架构

django 开发多语言网站

2014-04-19 09:04 267 查看
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.zip 和 gettext-tools-X.zip

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

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

#Install gettext
#Download from http://ftp.gnu.org/gnu/gettext/ cd ~/Downloads
tar xzvf gettext-0.18.1.1.tar.gz
cd gettext-0.18.1.1
./configure
make
sudo make install


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'),

@Copyright, 251 zhangtao.it@gmail.com, http://itrust.cnblogs.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: