惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 观无明

IE9 + django开发版WEB服务器 不响应或Socket报错 google chrome 下django用户登录失败的问题 不愁男女比例不协调 Word文件如源码一样也可比较和合并 python 的字符编码和中文处理 - 观无明 - 博客园 djang 测试心得 my django development environment (virtualenv+pip+django) nginx+fastcgi+django实践笔记 django 开发 - 小心模板文件的编码格式(utf-8) 汉王电子书D20使用笔记 使用south实现Django的数据库升级迁移 VIM 笔记 (for python ) 在Windows上使用Linux命令 cygwin 仍有人在真心关注这灾难 CruiseControl中应用NCover和NCoverExplore CruiseControl中使用NUnit中测试WEB服务 Resharper封装(Encapsulate)域Field为属性Property的命名问题 数据库开发的持续集成 - CruiseControl.Net的项目配置 数据库开发的持续集成 - Liquibase的简介和应用
django 开发多语言网站
观无明 · 2010-05-31 · via 博客园 - 观无明

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目录加到你系统路径中。

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