Django2.1 translation详解

一、translation机制简介

    为了使django项目具有可翻译性,必须向Python代码和模板添加最少数量的钩子。这些钩子称为翻译字符串(tanslation strings)。他们告诉Django:“如果可以使用该语言翻译该文本,则应将文本翻译为最终用户的语言。”因此,标记可翻译字符串是您的责任,系统只能翻译它知道的字符串。

    Django提供了将tanslation strings提取到一个message文件中的功能。此文件为翻译人员提供了一种将tanslation strings与目标语言一一对应的简便方法。一旦翻译人员填写了message文件,就必须对其进行编译。这个过程依赖于 GNU gettext工具集。

 

二、translation相关的定义

internationalization

准备软件进行本地化。通常由开发人员完成。

localization

编写翻译和本地格式。通常由翻译人员完成。更多的细节可以查看 W3C Web Internationalization FAQ, the Wikipedia article or the GNU gettext documentation.

locale name

区域设置名称,可以是表单ll的语言规范,也可以是表单ll_cc的组合语言和国家规范。示例:it、de_AT、es、pt_BR。语言部分总是小写,国家部分总是大写。分隔符是下划线

language code

表示语言的名称。浏览器与HTTP头均接受该语言名称形成。示例:it、de-at、es、pt-br。语言代码通常用小写表示,但HTTP Accept语言头不区分大小写。分隔符是破折号

message file

消息文件是一个纯文本文件,表示一种语言,它包含所有可用的translation string以及它们在给定语言中的表示方式。消息文件具有.po文件扩展名。

translation string

能够被翻译的字符串

format file

格式文件是一个定义给定区域设置数据格式的python模块。

 

三、Internationalization

Standard translation

指定一个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)

Comments for translators

如果要向翻译人员提供有关可翻译字符串的提示,可以在字符串前一行添加前缀为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 %}

Pluralization

使用函数 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)

Contextual markers

上下文标记,是因为有些单词有多个意思,例如英语中“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 translation

    Lazy是python设计模式中的一个概念,可以让实际对象的生成在使用时才生成,这样做的好处是可以节约内存。 django.utils.translation中有lazy前缀的函数是其lazy版本,这个函数存储了字符串的惰性相关,而不是实际的翻译。当字符串被使用时,例如模板被渲染时,翻译的行为才执行。当被调用的这些函数需要在模块加载时执行,这些函数的使用是非常重要的。

 这是在定义模型、窗体和模型窗体时很容易发生的事情,因为Django实现了这些,使得它们的字段实际上是类级属性。因此,请确保在以下情况下使用惰性翻译:

1)在Model fileds、关系(如 ForeignKeyManyToManyField 和 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)})

 

 

你可能感兴趣的:(Django)