为了使django项目具有可翻译性,必须向Python代码和模板添加最少数量的钩子。这些钩子称为翻译字符串(tanslation strings)。他们告诉Django:“如果可以使用该语言翻译该文本,则应将文本翻译为最终用户的语言。”因此,标记可翻译字符串是您的责任,系统只能翻译它知道的字符串。
Django提供了将tanslation strings提取到一个message文件中的功能。此文件为翻译人员提供了一种将tanslation strings与目标语言一一对应的简便方法。一旦翻译人员填写了message文件,就必须对其进行编译。这个过程依赖于 GNU gettext工具集。
准备软件进行本地化。通常由开发人员完成。
编写翻译和本地格式。通常由翻译人员完成。更多的细节可以查看 W3C Web Internationalization FAQ, the Wikipedia article or the GNU gettext documentation.
区域设置名称,可以是表单ll的语言规范,也可以是表单ll_cc的组合语言和国家规范。示例:it、de_AT、es、pt_BR。语言部分总是小写,国家部分总是大写。分隔符是下划线。
表示语言的名称。浏览器与HTTP头均接受该语言名称形成。示例:it、de-at、es、pt-br。语言代码通常用小写表示,但HTTP Accept语言头不区分大小写。分隔符是破折号。
消息文件是一个纯文本文件,表示一种语言,它包含所有可用的translation string以及它们在给定语言中的表示方式。消息文件具有.po文件扩展名。
能够被翻译的字符串
格式文件是一个定义给定区域设置数据格式的python模块。
指定一个translation string 使用gettext()函数,通过inport并做为别名_是常见的形式,如下:
from django.http import HttpResponse
from django.utils.translation import gettext as _
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)
注意:在gettext之前加u前缀是为了与python2区别,但是Django2.1支持python3,以后的版本将会取消这种用法。django-admin makemessages可以用于生成message文件,compilemessage可以进行编译。
_()或gettext()可以使用占位符,如下:
def my_view(request, m, d):
output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
return HttpResponse(output)
如果要向翻译人员提供有关可翻译字符串的提示,可以在字符串前一行添加前缀为translators关键字的注释。生成的.po文件中也会包含这个注释,例如:
def my_view(request):
# Translators: This message appears on the home page only
output = gettext("Welcome to my site.")
#-----.po文件中-------------#
#. Translators: This message appears on the home page only
# path/to/python/file.py:123
msgid "Welcome to my site."
msgstr ""
在模板语言中,也可以使用commet进行多行标记,如下
{% comment %}Translators: View verb{% endcomment %}
{% trans "View" %}
{% comment %}Translators: Short intro blurb{% endcomment %}
{% blocktrans %}A multiline translatable literal.{% endblocktrans %}
或者使用{#...#}进行单行标记
{# Translators: Label of a button that triggers search #}
{# Translators: This is a text of the base template #}
{% blocktrans %}Ambiguous translatable block of text{% endblocktrans %}
使用函数 django.utils.translation.ngettext()
对信息复数化,例如object是单数,objects是复数,而ngettext函数有三个参数,分别是单数形式的translation string, 复数形式的translation string和对象的个数,如下例子:
from django.http import HttpResponse
from django.utils.translation import ngettext
def hello_world(request, count):
page = ngettext(
'there is %(count)d object',
'there are %(count)d objects',
count) % {
'count': count,
}
return HttpResponse(page)
上下文标记,是因为有些单词有多个意思,例如英语中“May”,可以是月份的名字也可以是一个动词。 django.utils.translation.pgettext()函数可以实现这个功能,并在.po的文件中增加一个msgctxt来标记,例如:
from django.utils.translation import pgettext
month = pgettext("month name", "May")
或者也可以使用
from django.db import models
from django.utils.translation import pgettext_lazy
class MyThing(models.Model):
name = models.CharField(help_text=pgettext_lazy(
'help text for MyThing model', 'This is the help text'))
则在 .po的文件中表示为:
msgctxt "month name"
msgid "May"
msgstr ""
Lazy是python设计模式中的一个概念,可以让实际对象的生成在使用时才生成,这样做的好处是可以节约内存。 django.utils.translation中有lazy前缀的函数是其lazy版本,这个函数存储了字符串的惰性相关,而不是实际的翻译。当字符串被使用时,例如模板被渲染时,翻译的行为才执行。当被调用的这些函数需要在模块加载时执行,这些函数的使用是非常重要的。
这是在定义模型、窗体和模型窗体时很容易发生的事情,因为Django实现了这些,使得它们的字段实际上是类级属性。因此,请确保在以下情况下使用惰性翻译:
1)在Model fileds、关系(如
ForeignKey
, ManyToManyField
和 OneToOneField
)中出现
verbose_name
和 help_text等选项值时:
from django.db import models
from django.utils.translation import gettext_lazy as _
class MyThing(models.Model):
name = models.CharField(help_text=_('This is the help text'))
在关系中使用verbose_name(可读性名称)选项时的例子:
class MyThing(models.Model):
kind = models.ForeignKey(
ThingKind,
on_delete=models.CASCADE,
related_name='kinds',
verbose_name=_('kind'),
)
2)Model verbose names values
from django.db import models
from django.utils.translation import gettext_lazy as _
class MyThing(models.Model):
name = models.CharField(_('name'), help_text=_('This is the help text'))
class Meta:
verbose_name = _('my thing')
verbose_name_plural = _('my things')
其中Meta是Django的内部类,它用于定义一些Django模型类的行为特性,详细可参见https://www.cnblogs.com/flash55/p/6265405.html
3)模型中的short_description属性值
对于模型方法,可以向django和具有short_description属性的管理站点提供翻译:
from django.db import models
from django.utils.translation import gettext_lazy as _
class MyThing(models.Model):
kind = models.ForeignKey(
ThingKind,
on_delete=models.CASCADE,
related_name='kinds',
verbose_name=_('kind'),
)
def is_mouse(self):
return self.kind.type == MOUSE_TYPE
is_mouse.short_description = _('Is it a mouse?')
注意:
gettext_lazy()调用的结果可以在其他任何位置的django代码中使用字符串(str对象),但它可能不适用于任意的python代码。例如,由于requests库不处理gettext_lazy对象,因此以下内容无法工作:
body = gettext_lazy("I \u2764 Django") # (unicode :heart:)
requests.post('https://example.com/send', data={'body': body})
通过将gettext_lazy()对象强制转换为文本字符串,然后将其传递给非django代码,可以避免此类问题:
requests.post('https://example.com/send', data={'body': str(body)})