Django语言切换,针对一段代码块,切换语言以便在一个语言环境下进行翻译。

20
我有一个django项目,使用一个worker进程向用户发送电子邮件。Worker进程侦听rabbitmq服务器并获取有关要发送的电子邮件、模板变量、要发送到的电子邮件地址等所有详细信息。使用django模板和render_to_string创建电子邮件正文。

然而,我想要国际化这个项目。我们的一些用户将在英语中使用网站,另一些用户将在其他语言中使用。他们应该用他们的语言接收电子邮件。我尝试i18n电子邮件worker进程(使用django.utils.translations.ugettext/ugettext_lazy),使电子邮件主题和电子邮件正文具有_(...)或{% blocktrans %} 等响应内容。

然而,由于电子邮件是在不同的后台工作进程中呈现和发送的,普通的django语言检测过程似乎不适用。没有用户会话,也没有Cookie或HTTP标头可供查看。在将消息发送到rabbitmq服务器时,可以存储语言代码.

但是如何告诉django/gettext在某个时刻使用该语言。

例如,我的发送电子邮件的函数可能如下所示:

def send_email(details):
  lang = details['lang']
  name = details['name']
  email_address = details['email_address']

  switch_gettext_to_this_language_what_goes_here(lang):
  # ?????
  email_subject = _("Welcome to $SITE")  

我该输入什么来切换Django的翻译/ gettext 到特定语言代码,以便_()会使用该语言代码?

5个回答

48

如@SteveMayne在评论中指出的(但值得一提的是),您现在可以使用上下文管理器translation.override(适用于Django 1.6,未检查早期版本):

from django.utils import translation
print(_("Hello"))  # Will print to Hello if default = 'en'

# Make a block where the language will be Danish
with translation.override('dk'):
    print(_("Hello"))  # print "Hej"

它基本上使用了与@bitrut答案相同的东西,但它是内置于Django中的,因此它减少了依赖...

1
它一直存在,至少可以追溯到Django 1.4! - Anentropic
覆盖(override)更加安全,因为在完成操作后你不需要考虑设置原始语言! - benzkji

15

您可以使用上下文管理器以一种简洁的方式强制指定语言:

class force_lang:
    def __init__(self, new_lang):
        self.new_lang = new_lang
        self.old_lang = translation.get_language()
    def __enter__(self):
       translation.activate(self.new_lang)
    def __exit__(self, type, value, tb):
       translation.activate(self.old_lang)

然后您可以使用with语句:

with force_lang('en'):
    ...

18
现在这已经包含在了"translation.override"类中。使用with translation.override('en'):即可。 - Steve Mayne

14

最简单的切换语言方式是:

from django.utils.translation import activate
activate('en')
# do smthg
activate('pl')
# do something in other language

要小心使用这个,因为它会改变此进程/线程的其余执行上下文。


3
请注意,django.utils.translation 现在有一个 override(lang) 上下文管理器,它将在退出时自动重置原始语言环境。 - bruno desthuilliers

5
使用 django-i18nexthttps://pypi.python.org/pypi/django-i18next)非常简单。
加载模板标签。
{% load i18n i18next %}

以下代码会强制让位于overridelocale块中的任何内容使用荷兰语环境。
{% overridelocale 'nl' %}
    <p>
        <a href="/login/">{% trans "Log in" %}</a>
    </p>
{% endoverridelocale %}

以下代码会强制为放在overridelocale块中的任何内容设置俄语区域设置。
{% overridelocale 'ru' %}
    <p>
        <a href="/login/">{% trans "Log in" %}</a>
    </p>
{% endoverridelocale %}

以下代码将强制应用英文区域设置于放置在 overridelocale 代码块中的所有内容。
{% overridelocale 'en' %}
    <p>
        <a href="/login/">{% trans "Log in" %}</a>
    </p>
{% endoverridelocale %}

Django核心中有一个{% language 'CODE' %}模板标签:https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#std:templatetag-language - Taha Jahangir

1

原来Django文档解释了如何

Django提供了丰富的i18n工具,可用于视图和模板,但它并不限制使用Django特定的代码。Django翻译机制可用于将任意文本翻译为Django支持的任何语言(当然,必须存在适当的翻译目录)。您可以加载翻译目录,激活它并将文本翻译为所选语言,但请记住切换回原始语言,因为激活翻译目录是基于每个线程进行的,这种更改将影响在同一线程中运行的代码。


2
是的,只需使用 from django.utils import translation; translation.activate(language_code) - Filip Dupanović

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接