所谓的国际化,是指使用不同语言的用户在访问同一个网站页面时能够看到符合其自身语言的文本页面。
国际化的基本原理是:
Django对文本翻译、日期格式、时间格式、数字格式和时区具有很好的支持。这些内容是国际化的主要工作对象。
从本质上,Django做了这么两件事:
下面我们看一下Django是如何国际化的:
在视图中和HTML模板中都可以标识要翻译的文本。在视图中,通过_()
或ugettext()
函数,指定某个变量需要翻译,如下所示:
from django.utils.translation import ugettext as _ from django.http import HttpResponse def my_view(request): output = _("Welcome to my site.") return HttpResponse(output)
这等同于:
from django.utils.translation import ugettext from django.http import HttpResponse def my_view(request): output = ugettext("Welcome to my site.") return HttpResponse(output)
也等同于:
def my_view(request): sentence = 'Welcome to my site.' output = _(sentence) return HttpResponse(output)
还可以这么用:
def my_view(request, m, d): output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d} return HttpResponse(output)
如果你想给翻译人员一些提示,可以添加一个以Translators为前缀的注释,例如:
def my_view(request): # Translators: This message appears on the home page only output = ugettext("Welcome to my site.")
在模版文件中,要标识一个待翻译的文本,需要使用{% trans %}
模板标签,但首先你要在模版的顶部加载{% load i18n %}
。比如:
{% load i18n %} <title>{% trans "This is the title." %}</title> <title>{% trans myvar %}</title>
要注意的是trans标签内部不可以有内嵌的模板变量
如果你想提前翻译字符串但是不显示出来,可以使用下面的方法:
{% trans "This is the title" as the_title %} <title>{{ the_title }}</title> <meta name="description" content="{{ the_title }}">
上面的做法实际上相当于定义了几个模板变量,下面则是更加复杂的用法:
% trans "starting point" as start %} {% trans "end point" as end %} {% trans "La Grande Boucle" as race %} <h1> <a href="/" title="{% blocktrans %}Back to '{{ race }}' homepage{% endblocktrans %}">{{ race }}</a> </h1> <p> {% for stage in tour_stages %} {% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}<br />{% else %}, {% endif %} {% endfor %} </p>
与{% trans %}
模板标签不同,blocktrans标签允许你通过使用占位符来标记由文字和可变内容组成的复杂句子进行翻译,如下例所示:
{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
还可以像下面一样使用:
{% blocktrans with amount=article.price %} That will cost $ {{ amount }}. {% endblocktrans %} {% blocktrans with myvar=value|filter %} This will have {{ myvar }} inside. {% endblocktrans %}
甚至在一个blocktrans标签内内使用多个表达式:
{% blocktrans with book_t=book|title author_t=author|title %} This is {{ book_t }} by {{ author_t }} {% endblocktrans %}
一旦标记好需要翻译的文本(也就是国际化)后,就需要进行本地化,也就是创建翻译用的语言文件。
语言文件(Language File)是Django用于保存翻译关系的文件,你的网站应该为每种支持的语言建立一个语言文件。
建立语言文件是通过django-admin makemessages
命令完成的。
在项目的根目录下,也就是包含manage.py的目录下,运行下面的命令:
django-admin makemessages -l de
其中的de
表示你要本地化的国家,例如pt_BR
表示巴西葡萄牙语,奥地利德语为de_AT
,印尼语为id。
或者使用下面的方式:
python manage.py makemessages -l zh-cn //中文简体 python manage.py makemessages -l en //英文
执行命令后,Django会在根目录及其子目录下搜集所有需要翻译的字符串,默认情况下它会搜索.html、.txt和.py文件,然后在根目录的locale/LANG/LC_MESSAGES
目录下创建一个django.po
文件。对于上面的例子,目录就是locale/de/LC_MESSAGES/
,文件就是locale/de/LC_MESSAGES/django.po
。
否则会弹出下面的错误:
CommandError: Can't find msguniq. Make sure you have GNU gettext tools 0.15 or newer installed.
.po
文件的格式非常简单!
每个.po
文件首先包含一小部分元数据,例如翻译维护者的联系信息,但文件的大部分是翻译对照:被翻译字符串和特定语言的实际翻译文本之间的简单映射。
例如,有一个像下面这样的待翻译字符串:
_("Welcome to my site.")
在.po
文件中将包含一条下面样子的条目:
#: path/to/python/module.py:23 msgid "Welcome to my site." msgstr ""
这三行内容各自代表下面的意思:
这是一个文本文件,需要专业的翻译人员将所有的msgstr空白‘填写’齐全。如果你的项目比较大,这可能是个磨人的事。
当完成语言文件的创建和翻译工作后,或者对语言文件修改后,需要将其编译成对应的*.mo
文件,Django在运行时将使用*.mo
文件对网站进行国际化翻译。
进入项目根目录,运行下面的命令,进行语言文件编译:
django-admin compilemessages
Django将自动搜索所有的.po
文件,将它们都翻译成.mo
文件。
至此,国际化和本地化就完成了。你的网站页面将根据访问者使用语言的不同,展示为不同的语言版本,比如中文、英文、法文、德文之类。
下面列出了所有可用于各种系统设置的语言代码对照表: