Django i18n国际化

最近在看Django的国际化,看了很多贴子,终于有了比较系统的认识,在这里做一下简单总结。

先来看两个概念:

  • 国际化:是指为了该软件在任何地区的潜在使用而进行程序设计的过程。 它包括了为将来翻译而标记的文本(比如用户界面要素和错误信息等)、日期和时间的抽象显示以便保证不同地区的标准得到遵循、为不同时区提供支持,并且一般确保代码中不会存在关于使用者所在地区的假设。 您会经常看到国际化被缩写为“I18N”(18表示Internationlization这个单词首字母I和结尾字母N之间的字母有18个)。
  • 本地化: 是指使一个国际化的程序为了在某个特定地区使用而进行实际翻译的过程。 有时,本地化缩写为L10N 。

 

Django的国际化

Django本身是完全国际化了的,所有的字符串均因翻译所需而被标记,并且设定了与地域无关的显示控制值,如时间和日期。 Django是带着50个不同的本地化文件发行的。 这些本地化文件所使用的国际化框架同样也可以被用在自己的代码和模板中。

只需要添加少量的挂接代码到Python代码和模板中。 这些挂接代码被称为* 翻译字符串* 。它们告诉Django:如果这段文本的译文可用的话,它应被翻译为终端用户指定的语言。Django会根据用户的语言偏好,在线地运用这些挂接指令去翻译Web应用程序。

本质上来说,Django做两件事情:

  1. 它让开发者和模板的作者指定他们的应用程序的哪些部分应该被翻译。
  2. Django根据用户的语言偏好来翻译Web应用程序。

备注:Django的翻译机制是使用 GNU gettext (http://www.gnu.org/software/gettext/),具体为Python自带的标准模块 gettext 。

 

如果不需要国际化:
Django的国际化挂接是默认开启的,这可能会给Django的运行增加一点点开销。 如果您不需要国际化支持,那么您可以在您的设置文件中设置 USE_I18N = False 。 如果 USE_I18N 被设为 False ,那么Django会进行一些优化,而不加载国际化支持机制。

也可以从您的 TEMPLATE_CONTEXT_PROCESSORS 设置中移除 'django.core.context_processors.i18n' 。

 

使用Django 国际化

  1. 第一步:在你的Python代码和模板中嵌入待翻译的字符串。
  2. 第二步:把那些字符串翻译成你要支持的语言。
  3. 第三步:在你的Django settings文件中激活本地中间件。

1. 如何嵌入待翻译的字符串

使用函数django.utils.translation.ugettext() 来指定一个翻译字符串。 作为惯例,使用短别名 _ 来引入这个函数以节省键入时间.

from django.utils.translation import ugettext as _
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)

小注意:

  1. ugettext()函数的参数可以是变量,但检测工具make_messages.py将找不到这些字符串。
  2. 占位符:特定语言的译文可能对翻译字符串重新排序,使用位置占位符可能达不到预期效果,建议使用命名字符串插入,如_('today is %(day)s'%{'day':'monday'})
扩展知识:
  1. 使用 django.utils.translation.gettext_noop() 函数来标记一个不需要立即翻译的字符串。 这个串会稍后从变量翻译。使用这种方法的环境是,有字符串必须以原始语言的形式存储(如储存在数据库中的字符串)而在最后需要被翻译出来(如显示给用户时)。
  2. 使用 django.utils.translation.gettext_lazy() 函数,使得其中的值只有在访问时才会被翻译,而不是在gettext_lazy() 被调用时翻译。
  3. 使用django.utils.translation.ungettext()来指定以复数形式表示的消息。


2. 模块中嵌入翻译字符串

Django模板使用两种模板标签,为了使得模板访问到标签,需要将{% load i18n %} 放在模板最前面。
这个{% trans %}模板标记翻译一个常量字符串 或 可变内容:

{%load i18n%}
<title>{%trans 'this is a title' %}</title>
<title>{%trans strvar %}</title>

小注意:

在一个带 {% trans %} 的字符串中,混进一个模板变量是不可能的。如果译文要求字符串带有变量,使用{%blocktrans%}、{%endblocktrans%}

3. 如何创建语言文件

当你标记了翻译字符串,你就需要写出(或获取已有的)对应的语言翻译信息。 这里就是它如何工作的。

a. 为一种语言创建消息文件.po

信息文件是包含了某一语言翻译字符串和对这些字符串的翻译的一个文本文件。

python django-admin.py makemessages ‐l zh_CN

这段脚本遍历你的项目源树或你的应用程序源树并且提取出所有为翻译而被标记的字符串。 它在locale/LANG/LC_MESSAGES 目录下创建(或更新)了一个信息文件。针对上面的zh_CN,应该是locale/zh_CN/LC_MESSAGES/django.po。

'Welcome to my site'生成的.op示例如下:

#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""

b. 编译信息文件.mo

python django-admin.py compilemessages

 

4. 本地化配置

让每一个使用者各自指定语言偏好,就需要使用 LocaleMiddleware 。 LocaleMiddleware 使得Django基于请求的数据进行语言选择,从而为每一位用户定制内容。 它为每一个用户定制内容。

偏好设置:

LANGUAGES = (
('cn', _('China')),
('en', _('English')),
)

使用 LocaleMiddleware 需要在 MIDDLEWARE_CLASSES 设置中增加'django.middleware.locale.LocaleMiddleware' 。

MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)

中间件的顺序是有影响的,最好按照依照以下要求:

  1. 保证它是第一批安装的中间件类。
  2. 因为 LocalMiddleware 要用到session数据,所以需要放在 SessionMiddleware 之后。
  3. 如果你使用CacheMiddleware,把LocaleMiddleware放在它后面。

LocaleMiddleware 按照如下算法确定用户的语言:

  1. 首先,在当前用户的 session 的中查找django_language键;
  2. 如未找到,它会找寻一个cookie
  3. 还找不到的话,它会在 HTTP 请求头部里查找Accept‐Language, 该头部是你的浏览器发送的,并且按优先顺序告诉服务器你的语言偏好。 Django会尝试头部中的每一个语种直到它发现一个可用的翻译。
  4. 以上都失败了的话, 就使用全局的 LANGUAGE_CODE 设定值。

 

Django寻找项目中的翻译

Django使用以下算法寻找翻译:

  1. 首先,Django在该视图所在的应用程序文件夹中寻找 locale 目录。 若找到所选语言的翻译,则加载该翻译。
  2. 第二步,Django在项目目录中寻找 locale 目录。 若找到翻译,则加载该翻译。
  3. 最后,Django使用 django/conf/locale 目录中的基本翻译。

 

 

posted @ 2012-04-05 20:51  残夜  阅读(8693)  评论(1编辑  收藏  举报