虽然Django提供了一套丰富的用于视图和模板的国际化工具,但它并未将使用限制在Django特定的代码中。 Django翻译机制可用于将任意文本转换为Django支持的任何语言(当然,只要存在适当的翻译目录)。
您可以加载翻译目录,激活它并将文本翻译为您选择的语言,但请记住切换回原始语言,因为激活翻译目录是基于每个线程完成的,并且这种更改会影响在同一线程中运行的代码。
例如:
from django.utils import translation
def welcome_translated(language):
cur_language = translation.get_language()
try:
translation.activate(language)
text = translation.ugettext('welcome')
finally:
translation.activate(cur_language)
return text
使用值'de'调用此函数将为您提供“Willkommen”,无论LANGUAGE_CODE和中间件设置的语言如何。
特别感兴趣的函数是django.utils.translation.get_language(),它返回当前线程中使用的语言,django.utils.translation.activate(),它激活当前线程的翻译目录,以及django.utils.translation。 check_for_language()检查Django是否支持给定的语言。
实施说明
Django的特殊翻译
Django的翻译机制使用Python自带的标准gettext模块。 如果你知道gettext,你可以用Django翻译的方式记下这些特殊的:
-
字符串域是django或djangojs。 该字符串域用于区分将数据存储在公用消息文件库(通常为/ usr / share / locale /)中的不同程序。 django域用于python和模板转换字符串,并被加载到全局转换目录中。 djangojs域名仅用于JavaScript翻译目录,以确保这些域名尽可能小。
-
Django不单独使用xgettext。 它使用围绕xgettext和msgfmt的Python包装。 这主要是为了方便。
Django如何发现语言偏好
准备好翻译之后 - 或者,如果您只是想使用Django附带的翻译版本,则需要为您的应用激活翻译。
在幕后,Django有一个非常灵活的模型来决定应该使用哪种语言 - 安装范围内,针对特定用户,还是两者兼而有之。
要设置安装范围的语言首选项,请设置LANGUAGE_CODE。 Django使用这种语言作为默认翻译 - 如果通过语言环境中间件采用的方法之一找不到更好的匹配翻译,则为最终尝试(见下文)。
如果你只想用你的母语运行Django,你只需要设置LANGUAGE_CODE并确保相应的消息文件及其编译版本(.mo)存在。
如果您想让每个用户指定他们喜欢的语言,那么您还需要使用LocaleMiddleware。 LocaleMiddleware基于来自请求的数据启用语言选择。它为每个用户定制内容。
要使用LocaleMiddleware,请将'django.middleware.locale.LocaleMiddleware'添加到MIDDLEWARE_CLASSES设置中。由于中间件顺序很重要,因此您应遵循以下准则:
-
确保它是安装的第一批中间件之一。
-
它应该在SessionMiddleware之后,因为LocaleMiddleware使用会话数据。 它应该在CommonMiddleware之前出现,因为CommonMiddleware需要激活的语言才能解析所请求的URL。
-
如果您使用CacheMiddleware,请将LocaleMiddleware放在后面。 例如,您的MIDDLEWARE_CLASSES可能如下所示:
MIDDLEWARE_CLASSES = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', ]
有关中间件的更多信息,请参见第17章。
LocaleMiddleware尝试按照以下算法确定用户的语言首选项: -
首先,它在请求的URL中查找语言前缀。 只有在您的根URLconf中使用i18n_patterns功能时才会执行此操作。 有关语言前缀以及如何国际化URL模式的更多信息,请参阅url-internationalization。
-
如果失败,它会在当前用户的会话中查找LANGUAGE_SESSION_KEY键。
-
如果没有,它会寻找一个cookie。 所用Cookie的名称由LANGUAGE_COOKIE_NAME设置设置。 (默认名称是django_language。)
-
否则,它会查看Accept-Language HTTP标头。 这个头文件由浏览器发送,并按照优先顺序告诉服务器你喜欢哪种语言。 Django尝试使用标题中的每种语言,直到找到具有可用翻译的语言。
-
如果失败了,它将使用全局LANGUAGE_CODE设置。
注意:
-
在这些地方的每一个地方,语言偏好都以标准语言格式作为字符串。 例如,巴西葡萄牙语是pt-br。
-
如果基本语言可用但指定的子语言不是,则Django使用基本语言。 例如,如果用户指定de-at(奥地利德语),但Django只有de可用,Django使用de。
-
只能选择LANGUAGES设置中列出的语言。 如果您想将语言选择限制为所提供语言的子集(因为您的应用程序不提供所有这些语言),请将LANGUAGES设置为语言列表。 例如:
LANGUAGES = [ ('de', _('German')), ('en', _('English')), ]
本示例将可用于自动选择的语言限制为德语和英语(以及任何子语言,如de-ch或en-us)。
-
如果您定义了自定义LANGUAGES设置,如前面的项目符号所述,您可以将语言名称标记为翻译字符串 - 但使用ugettext_lazy()而不是ugettext()来避免循环导入。 以下是一个示例设置文件:
from django.utils.translation import ugettext_lazy as _ LANGUAGES = [ ('de', _('German')), ('en', _('English')), ]
一旦LocaleMiddleware确定了用户的偏好,它就会为每个HttpRequest使用request.LANGUAGE_CODE。 随意在你的视图代码中读取这个值。 这里有一个简单的例子:
from django.http import HttpResponse
def hello_world(request, count):
if request.LANGUAGE_CODE == 'de-at':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")
请注意,使用静态(无中间件)转换时,语言在settings.LANGUAGE_CODE中,而在动态(中间件)转换时,它在request.LANGUAGE_CODE中。
Django如何发现翻译
在运行时,Django构建了一个直接转换的内存统一目录。 为了达到这个目的,它通过遵循以下算法来查找翻译:它检查加载编译的消息文件(.mo)的不同文件路径的顺序以及相同文字的多个翻译的优先顺序:
-
LOCALE_PATHS中列出的目录具有最高的优先顺序,首先出现的目录优先级高于稍后出现的目录。
-
然后,它查找并使用它是否存在INSTALLED_APPS中列出的每个已安装应用程序中的区域设置目录。 首先出现的优先级高于后来出现的优先级。
-
最后,Django在django / conf / locale中提供的基础转换被用作后备。
在任何情况下,包含翻译的目录的名称都应该使用区域名称表示法命名。 例如。 de,pt_BR,es_AR等
这样,您可以编写包含自己翻译的应用程序,并且可以在项目中覆盖基本翻译。 或者,您可以从多个应用程序中构建一个大型项目,并将所有翻译放入您正在撰写的项目特定的大型通用消息文件中。 这是你的选择。
所有的消息文件存储库的结构都是一样的。 他们是:
- 在您的设置文件中的LOCALE_PATHS中列出的所有路径都将搜索<language> / LC_MESSAGES / language.(po | mo)
- $ APPPATH/local/<language>/ LC_MESSAGES/ django.(PO| MO)。
- $ PYTHONPATH/ django./ CONF /local/<language>/ LC_MESSAGES/ django.(PO| MO)。
要创建消息文件,可以使用django-admin makemessages工具。 你使用django-admin compilemessages来生成gettext使用的二进制.mo文件。
你也可以运行django-admin compilemessages来让编译器处理LOCALE_PATHS设置中的所有目录。
下一步是什么?
在下一章中,我们将讨论Django中的安全性。
网友评论