Django国际化的详细文档: http://djangobook.py3k.cn/2.0/chapter19/ (中文) 英文好的可以看: https://docs.djangoproject.com/en/1.4/topics/i18n/
在这里写下Django实现国际化的基本步骤,详细内容见如上链接;
(只讲步骤,不谈原理;因为我讲不清,原理在上面链接中讲的很清楚;)
静态翻译html
一.)使用Django模板引擎的解析实现国际化,说白了就是 {% trans %}标签国际化
1.)将 {% load i18n %} 放在模板最前面;在html(默认的格式), txt, xml等Django模板支持的文件中将需要国际化的字段用 {% trans '****'%}表示;
2.)在Django项目根目录新建一个locale目录,然后在项目根目录下执行django-admin.py makemessages -l zh_CN (最后一个字段是语言代码;如果需要翻译的模板不是html,则需要通过参数-e 指明, 如: django-admin.py makemessages -l de -e txt),为每个要支持的语言执行一次; 该命令将生成对应语言的po文件,如locale/zh_CN/LC_MESSAGES/django.po。
3.)在每个po文件中,为所有需要翻译的字段填写对应语言的翻译内容; 每个msgstr对应上面的msgid;翻译完后将po文件保存为'UTF-8 无BOM'格式;
4.)执行django-admin.py compilemessages将所有的po文件转成便于编译模块处理的*.mo文件;
5.)在settings里面修改LANGUAGE_CODE查看效果;
静态翻译外部js
二.)外部javascript的国际化
1.)在js文件中将需要国际化的字段用 gettext('***')代替;
2.)在项目根目录下创建一个三级目录, 如: transjs/jsi18n/locale;在transjs和jsi18n下都放入__init__.py文件,保证改目录能够被导入;将要被国际化的js文件拷贝到jsi18n下;
3.)将transjs/jsi18n安装到INSTALL_APPS下;
4.)在html中,在导入需要翻译的js前,添加<script type='text/javascript' src='/jsi18n'></script>;
5.)在全局的urls.py中添加如下代码
js_info_dict = {
'packages': ('transjs.jsi18n',),
}
urlpatterns += patterns('',
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
)
6.)在trans/jsi18n下执行django-admin.py makemessages -d djangojs -l de,生成po文件,在po文件中填入相应语言的翻译内容;
7.)在trans/jsi18n下执行django-admin.py compilemessages编译po文件,生成mo文件;
8.)在settings里面修改LANGUAGE_CODE查看效果;
以上是静态翻译的基本步骤,是根据settings.py中的LANGUAGE_CODE翻译的,下面看看如何动态翻译
三.)动态翻译(提供语言列表让用户选择,根据用户选择的语言动态切换),以下步骤是在完成了上面一,二的基础上进行的;
1.)在settings.py中设置所支持的语言列表; 如支持中文和英文
LANGUAGES = (
('zh', '简体中文'),
('en', 'English'),
)
2.)添加中间件LocaleMiddleware, 在MIDDLEWARE_CLASSES设置中增加 'django.middleware.locale.LocaleMiddleware';必须放在 SessionMiddleware和CacheMiddleware的后面;
3.)重定向视图,Django自带了一个 django.views.i18n.set_language 视图,作用是设置用户语言偏好并重定向返回到指定的页面;
在URLconf中加入下面这行代码来激活这个视图:
(r'^i18n/', include('django.conf.urls.i18n')),
4.)提交切换语言的请求,下面是一个请求的表单例子;在next的value中指定切换语言后显示的页面;
<form action='/i18n/setlang/' method='post'>
<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>
四.)翻译的内容中含有参数的情况
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 %}
3.)js中使用参数;这个也许有更精妙的方法,但是目前我只知道下面的方法;
在需要翻译的字符串里放入一个占位符,然后在得到翻译的字串后,将占位符用实际的值取代;
如; gettext('Nice to meet you, %s');
这个地方用 %s 作为占位符;在得到翻译的字串后,将 %s 替换成实际的人名即可;
<完>
原理分析:
django.middleware.locale.LocaleMiddleware
LocaleMiddleware 按照如下算法确定用户的语言:
1. 首先,在当前用户的 session 的中查找django_language(LANGUAGE_SESSION_KEY = '_language')键;
2. 如未找到,它会找寻一个cookie,key为LANGUAGE_COOKIE_NAME = 'django_language'
3. 还找不到的话,它会在 HTTP 请求头部里查找Accept-Language, 该头部是你的浏览器发送的,并且按优先顺序告诉服务器你的语言偏好。 Django会尝试头部中的每一个语种直到它发现一个可用的翻译。
4. 以上都失败了的话, 就使用全局的 LANGUAGE_CODE 设定值。
-
只有在 LANGUAGES 设置中列出的语言才能被选用。 若希望将语言限制为所提供语言中的某些(因为应用程序并不提供所有语言的表示),则将 LANGUAGES 设置为所希望提供语言的列表,例如: 例如:
LANGUAGES = ( ('de', _('German')), ('en', _('English')), )
一旦LocaleMiddleware决定用户的偏好,它会让这个偏好作为request.LANGUAGE_CODE对每一个HttpRequest有效。请随意在你的视图代码中读一读这个值。 以下是一个简单的例子:
def hello_world(request):
if request.LANGUAGE_CODE == 'de-at':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")
注意,对于静态翻译(无中间件)而言,此语言在settings.LANGUAGE_CODE中,而对于动态翻译(中间件),它在request.LANGUAGE_CODE中。
来源:oschina
链接:https://my.oschina.net/u/914655/blog/614766