第十八章 国际化文档格式.docx
- 文档编号:17899577
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:15
- 大小:27.84KB
第十八章 国际化文档格式.docx
《第十八章 国际化文档格式.docx》由会员分享,可在线阅读,更多相关《第十八章 国际化文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
如果USE_I18N被设为False,那么Django会进行一些优化,而不加载国际化支持机制。
您也可以从您的TEMPLATE_CONTEXT_PROCESSORS设置中移除'
django.core.context_processors.i18n'
。
在Python代码中指定翻译字符串
翻译字符串指定这段文本需要被翻译。
这些字符串出现在您的Python代码和模板中。
您需要做的是标记出这些翻译字符串;
而系统只会翻译出它所知道的东西。
标准的翻译函数
Django通过使用函数_()来指定翻译字符串(是的,函数名是一个下划线字符)。
这个函数是全局有效的(也就是说,相当于它是一个内置函数);
您不需要import任何东西。
在下面这个例子中,这段文本"
Welcometomysite"
被标记为翻译字符串:
defmy_view(request):
output=_("
Welcometomysite."
)
returnHttpResponse(output)
函数django.utils.translation.gettext()与_()是相同的。
下面这个例子与前一个例子没有区别:
fromdjango.utils.translationimportgettext
output=gettext("
大多数开发者喜欢使用_(),因为它比较短小.
翻译字符串对于语句同样有效。
下面这个例子和前面两个例子相同:
words=['
Welcome'
'
to'
my'
site.'
]
output=_('
'
.join(words))
翻译也可以对变量进行。
同样的例子:
sentence='
Welcometomysite.'
output=_(sentence)
(如以上两个例子所示地使用变量或语句,需要注意的一点是Django的翻译字符串检测工具,make-messages.py,不能找到这些字符串。
在后面的内容中会继续讨论这个问题。
传递给_()或gettext()的字符串可以接受由Python标准字典型对象的格式化字符串表达式指定的占位符,比如:
defmy_view(request,n):
%(name)sismyname.'
)%{'
name'
:
n}
这项技术使得特定语言的译文可以对这段文本进行重新排序。
比如,一段文本的英语翻译为"
Adrianismyname."
,而西班牙语翻译为"
MellamoAdrian."
,此时,占位符(即name)实在被翻译的文本之前而不是之后。
正因为如此,您应该使用字典型对象的格式化字符串(比如,%(name)s),而不是针对位置的格式化字符串(比如,%s或%d)。
如果您使用针对位置的格式化字符串,翻译机制将无法重新安排包含占位符的文本。
标记字符串为不操作
使用django.utils.translation.gettext_noop()函数来标记一个不需要立即翻译的字符串。
而被标记的字符串只在最终显示出来时才被翻译。
使用这种方法的环境是,有字符串必须以原始语言的形式存储(如储存在数据库中的字符串)而在最后需要被翻译出来,如当其在用户前显示出来时。
惰性翻译
使用django.utils.translation.gettext_lazy()函数,使得其中的值只有在访问时才会被翻译,而不是在gettext_lazy()被调用时翻译。
比如,要标记help_text列是需要翻译的,可以这么做:
fromdjango.utils.translationimportgettext_lazy
classMyThing(models.Model):
name=models.CharField(help_text=gettext_lazy('
Thisisthehelptext'
))
在这个例子中,gettext_lazy()将字符串作为惰性翻译字符串存储,此时并没有进行翻译。
翻译工作将在字符串在字符串上下文中被用到时进行,比如在Django管理页面提交模板时。
如果觉得gettext_lazy太过冗长,可以用_(下划线)作为别名,就像这样:
fromdjango.utils.translationimportgettext_lazyas_
name=models.CharField(help_text=_('
在Django模型中最好一直使用惰性翻译(除非这样翻译的结果无法正确地显示)。
同时,对于列名和表名最好也能进行翻译。
这需要在Meta中明确verbose_name和verbose_name_plural的值:
name=models.CharField(_('
),help_text=_('
classMeta:
verbose_name=_('
mything'
verbose_name_plural=_('
mythings'
复数的处理
使用django.utils.translation.ngettext()函数来指定有单数和复数形式之分的信息,比如:
fromdjango.utils.translationimportngettext
defhello_world(request,count):
page=ngettext(
thereis%(count)dobject'
thereare%(count)dobjects'
count
)%{'
count'
count}
returnHttpResponse(page)
ngettext函数包括三个参数:
单数形式的翻译字符串,复数形式的翻译字符串,和对象的个数(将以count变量传递给需要翻译的语言)。
在模板中指定翻译字符串
Django模板使用两种模板标签,且语法格式与Python代码有些许不同。
为了使得模板访问到标签,需要将{%loadi18n%}放在模板最前面。
{%trans%}模板标签标记需要翻译的字符串:
<
title>
{%trans"
Thisisthetitle."
%}<
/title>
如果只需要标记字符串而以后再翻译,可以使用noop选项:
value"
noop%}<
在{%trans%}中不允许使用模板中的变量,只能使用单引号或双引号中的字符串。
如果翻译时需要用到变量(占位符),可以使用{%blocktrans%},比如:
{%blocktrans%}Thiswillhave{{value}}inside.{%endblocktrans%}
使用模板过滤器来翻译一个模板表达式,需要在翻译的这段文本中将表达式绑定到一个本地变量中:
{%blocktranswithvalue|filterasmyvar%}
Thiswillhave{{myvar}}inside.
{%endblocktrans%}
如果需要在blocktrans标签内绑定多个表达式,可以用and来分隔:
{%blocktranswithbook|titleasbook_tandauthor|titleasauthor_t%}
Thisis{{book_t}}by{{author_t}}
为了表示单复数相关的内容,需要在{%blocktrans%}和{%endblocktrans%}之间使用{%plural%}标签来指定单复数形式,例如:
{%blocktranscountlist|lengthascounter%}
Thereisonlyone{{name}}object.
{%plural%}
Thereare{{counter}}{{name}}objects.
其内在机制是,所有的块和内嵌翻译调用相应的gettext或ngettext。
使用RequestContext(见第10章)时,模板可以访问三个针对翻译的变量:
{{LANGUAGES}}是一系列元组组成的列表,每个元组的第一个元素是语言代码,第二个元素是用该语言表示的语言名称。
{{LANGUAGE_CODE}}是以字符串表示的当前用户偏好语言(例如,en-us)。
(详见Django如何确定语言偏好。
{{LANGUAGE_BIDI}}是当前语言的书写方式。
若设为True,则该语言书写方向为从右到左(如希伯来语和阿拉伯语);
若设为False,则该语言书写方向为从左到右(如英语、法语和德语)。
你也可以通过使用模板标签来加载这些变量:
{%loadi18n%}
{%get_current_languageasLANGUAGE_CODE%}
{%get_available_languagesasLANGUAGES%}
{%get_current_language_bidiasLANGUAGE_BIDI%}
翻译的hook在任何接受常量字符串的模板块标签内也是可以使用的。
此时,使用_()表达式来指定翻译字符串,例如:
{%some_special_tag_("
Pagenotfound"
)value|yesno:
_("
yes,no"
)%}
这种情况下,标签和过滤器都将看到已翻译的字符串(也就是说,字符串是在传递给标签处理函数之前翻译的),所以它们(标签和过滤器)不必处理相关的东西。
创建语言文件
当你标记了翻译字符串,你就需要写出(或获取已有的)对应的语言翻译信息。
在这一节中我们将解释如何使它起作用。
创建信息文件
第一步,就是为一种语言创建一个信息文件。
一个信息文件是包含了某一语言翻译字符串和对这些字符串的翻译的一个文本文件。
信息文件以.po为后缀名。
Django中带有一个工具,bin/make-messages.py,它完成了这些文件的创建和维护工作。
运行以下命令来创建或更新一个信息文件:
bin/make-messages.py-lde
其中de是所创建的信息文件的语言代码。
在这里,语言代码是以本地格式给出的。
例如,巴西地区的葡萄牙语为pt_BR,澳大利亚地区的德语为de_AT。
可查看django/conf/locale目录获取Django所支持的语言代码。
这段脚本应该在三处之一运行:
django根目录(不是Subversion检出目录,而是通过$PYTHONPATH链接或位于该路径的某处)
Django项目根目录
Django应用程序根目录
该脚本作用于所在的整个目录树,并且抽取所有被标记的字符串以进行翻译。
它在conf/locale目录下创建(或更新)了一个信息文件。
在上面这个例子中,这个信息文件是conf/locale/de/LC_MESSAGES/django.po。
运行于项目源码树或应用程序源码树下时,该脚本完成同样的功能,但是此时locale目录的位置为locale/LANG/LC_MESSAGES(注意没有``conf``前缀)。
在第一次运行时需要创建locale目录。
没有gettext?
如果没有安装gettext组件,make-messages.py将会创建空白文件。
这种情况下,安装gettext组件或只是复制英语信息文件(conf/locale/en/LC_MESSAGES/django.po)来作为一个起点;
只是一个空白的翻译信息文件而已。
.po文件格式很直观。
每个.po文件包含一小部分的元数据,比如翻译维护人员的联系信息,而文件的大部分内容是简单的翻译字符串和对应语言翻译结果的映射关系的列表。
举个例子,如果Django应用程序包括一个"
的翻译字符串,像这样:
make-message.py将创建一个包含以下片段的.po文件:
#:
path/to/python/module.py:
23
msgid"
msgstr"
"
按顺序简单解释一下:
msgid是在源文件中出现的翻译字符串。
不要做改动。
msgstr是相应语言的翻译结果。
刚创建时它只是空字符串,此时就需要你来完成它。
注意不要丢掉语句前后的引号。
方便起见,每一条信息包含了翻译字符串所在文件的文件名和行数。
对于比较长的信息也有其处理方法。
msgstr(或msgid)后紧跟着的字符串为一个空字符串。
然后真正的内容在其下面的几行。
这些字符串会被直接连在一起。
同时,不要忘了字符串末尾的空格,因为它们会不加空格地连到一起。
比如,以下是一个多行翻译(取自随Django发行的西班牙本地化文件):
There'
sbeenanerror.It'
sbeenreportedtothesiteadministratorsviae-"
mailandshouldbefixedshortly.Thanksforyourpatience."
Haocurridounerror.Sehainformadoalosadministradoresdelsitio"
mediantecorreoelectrnicoydeberaarreglarseenbreve.Graciasporsu"
paciencia."
注意每一行结尾的空格。
注意字符集
当你使用喜爱的文本编辑器创建.po文件时,首先请编辑字符集行(搜索"
CHARSET"
),并将其设为你将使用的字符集。
一般说来,UTF-8对绝大多数语言有效,不过gettext会处理任何你所使用的字符集。
若要对新创建的翻译字符串校验所有的源代码和模板中,并且更新所有语言的信息文件,可以运行以下命令:
make-messages.py-a
编译信息文件
创建信息文件之后,每次对其做了修改,都需要将它重新编译成一种更有效率的形式,供gettext使用。
使用``bin/compile-messages.py``来完成这项工作。
这个工具作用于所有有效的.po文件,创建优化过的二进制.mo文件供gettext使用。
在运行make-messages.py的同一目录下,运行compile-messages.py:
bin/compile-messages.py
就是这样了。
你的翻译成果已经可以使用了。
Django如何处理语言偏好
一旦你准备好了翻译,如果希望在Django中使用,那么只需要激活这些翻译即可。
在这些功能背后,Django拥有一个灵活的模型来确定在安装和使用应用程序的过程中选择使用的语言。
若要在整个安装和使用过程中确定语言偏好,就要在设置文件中设置LANGUAGE_CODE。
Django将用指定的语言来进行翻译,如果没有其它的翻译器发现要进行翻译的语句,这就是最后一步了。
如果你只是想要用本地语言来运行Django,并且该语言的语言文件存在,只需要简单地设置LANGUAGE_CODE即可。
如果要让每一个使用者各自指定语言偏好,就需要使用LocaleMiddleware。
LocaleMiddleware使得Django基于请求的数据进行语言选择,从而为每一位用户定制内容。
使用LocaleMiddleware需要在MIDDLEWARE_CLASSES设置中增加'
django.middleware.locale.LocaleMiddleware'
中间件的顺序是有影响的,最好按照依照以下要求:
保证它是第一批安装的中间件类。
因为LocalMiddleware要用到session数据,所以需要放在SessionMiddleware之后。
如果使用了CacheMiddleware,将LocaleMiddleware放在CacheMiddleware之后(否则用户可能会从错误的本地化文件中取得缓冲数据)。
例如,MIDDLE_CLASSES可能会是如此:
MIDDLEWARE_CLASSES=(
mon.CommonMiddleware'
django.contrib.sessions.middleware.SessionMiddleware'
LocaleMiddleware按照如下算法确定用户的语言:
首先,在当前用户session的中查找键django_language的值;
如果失败的话,接着查找名为django_language的cookie;
还是失败的话,就在HTTP请求头部查找Accept-Language关键字的值,该关键字是你的浏览器发送的,按优先顺序告诉服务器你的语言偏好。
Django会根据这些语言的顺序逐一搜索直到发现可用的翻译;
以上都失败了的话,就使用全局的LANGUAGE_CODE设定值。
在上述每一处,语言偏好应作为字符串,以标准的语言格式出现。
比如,巴西地区的葡萄牙语表示为pt-br。
如果Django中只有基本语言而没有其衍生的字语言的话,Django将只是用基本语言。
比如,如果用户指定了de-at(澳式德语)但Django只有针对de的翻译,那么de会被选用。
只有在LANGUAGES设置中列出的语言才能被选用。
若希望将语言限制为所提供语言中的某些(因为应用程序并不提供所有语言的表示),则将LANGUAGES设置为所希望提供语言的列表,例如:
LANGUAGES=(
('
de'
_('
German'
)),
en'
English'
上面这个例子限制了语言偏好只能是德语和英语(包括它们的子语言,如de-ch和en-us)。
如果自定义了LANGUAGES,将语言标记为翻译字符串是可以的,但是,请不要使用django.utils.translation中的gettext()(决不要在settings文件中导入django.utils.translation,因为这个模块本身是依赖于settings,这样做会导致无限循环),而是使用一个“虚构的”gettext()。
解决方案就是使用一个“虚假的”gettext()。
以下是一个settings文件的例子:
_=lambdas:
s
这样做的话,make-messages.py仍会寻找并标记出将要被翻译的这些字符串,但翻译不会再运行时进行,故而需要在任何使用LANGUAGES的代码中用“真实的”gettext()来修饰这些语言。
LocaleMiddleware只能选择那些Django已经提供了基础翻译的语言。
如果想要在应用程序中对Django中还没有基础翻译的语言提供翻译,那么必须至少先提供该语言的基本的翻译。
例如,Django使用特定的信息ID来翻译日期和时间格式,故要让系统正常工作,至少要提供这些基本的翻译。
以英语的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第十八章 国际化 第十八