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

推荐订阅源

S
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Know Your Adversary
Know Your Adversary
G
GRAHAM CLULEY
V
Vulnerabilities – Threatpost
P
Palo Alto Networks Blog
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
Simon Willison's Weblog
Simon Willison's Weblog
A
Arctic Wolf
T
Tor Project blog
T
Threatpost
NISL@THU
NISL@THU
I
InfoQ
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Apple Machine Learning Research
Apple Machine Learning Research
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
aimingoo的专栏
aimingoo的专栏
Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
K
Kaspersky official blog
W
WeLiveSecurity
L
LINUX DO - 热门话题
小众软件
小众软件
Recorded Future
Recorded Future
B
Blog RSS Feed
H
Help Net Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
L
Lohrmann on Cybersecurity
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
雷峰网
雷峰网
爱范儿
爱范儿
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
H
Hacker News: Front Page
博客园 - 三生石上(FineUI控件)
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
有赞技术团队
有赞技术团队
N
News and Events Feed by Topic
云风的 BLOG
云风的 BLOG
Scott Helme
Scott Helme
V2EX - 技术
V2EX - 技术

博客园 - 观无明

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