7

我想要一个具有以下选择的 ChoiceField:

choices = [(1, '1 thing'),
           (2, '2 things'),
           (3, '3 things'),
           ...]

我想让它翻译。

这不起作用:

choices = [(i, ungettext_lazy('%s thing', '%s things', i) % i) for i in range(1,4)]

因为一旦惰性对象被插入,它就变成了一个 unicode 对象——因为 ChoiceField.choices 在启动时被评估,它的选择将在 Django 启动期间处于活动状态的语言中。

我可以使用ugettext_lazy('%s things' % i),但这需要对每个数字进行翻译,这很愚蠢。这样做的正确方法是什么?

4

3 回答 3

5

在 Django 文档中,Translation ... Working with lazy translation objects中,我看到了一条似乎解决了您的问题的评论。

在模型和实用函数中使用ugettext_lazy()and标记字符串是一种常见的操作。ungettext_lazy()当您在代码的其他地方使用这些对象时,您应该确保不会意外地将它们转换为字符串,因为它们应该尽可能晚地转换(以便正确的语言环境生效)。这需要使用下面描述的辅助函数。

然后它们出现django.utils.functional.lazy(func, *resultclasses)django.utils.functional模块文档目前没有涵盖这些内容。但是,根据django.utils.functional.py源代码,它“将任何可调用对象转换为惰性求值的可调用对象……每次访问时都会评估该函数。”

从延迟翻译中的其他延迟使用中修改他们的示例以合并您的代码,以下代码可能对您有用。

from django.utils import six  # Python 3 compatibility
from django.utils.functional import lazy
from django.utils.safestring import mark_safe

choices = [
    (i, lazy(
        mark_safe(ungettext_lazy('%s thing', '%s things', i) % i),
        six.text_type
    )# lazy()
    for i in range(1,4)
]

此外,django.utils.functional模块文档确实提到了一个函数 decorator allow_lazy(func, *resultclasses)。这使您可以编写自己的函数,该函数将惰性字符串作为参数。“它修改了函数,因此如果使用惰性翻译作为第一个参数调用它,函数评估会延迟,直到需要将其转换为字符串。” lazy(func, *resultclasses)不是装饰器,它修改了可调用对象。

注意我没有在 Django 中尝试过这段代码。我只是传递我在文档中找到的内容。希望它会为您指出可以使用的东西。

于 2012-12-29T05:38:37.773 回答
2

对于那些遇到这个问题的人。不幸的是,@Jim DeLaHunt 的回答并没有完全奏效——它几乎就在那里,但并不完全是需要做的。

重要的区别是:

  1. 你需要扭曲的lazy是一个返回文本值的函数,而不是另一个惰性翻译对象,否则你可能会看到奇怪<django.utils.functional.__proxy__ at ...>而不是实际文本(IIRC Django 不会深入惰性对象链)。所以,使用ungettext,而不是ungettext_lazy

  2. 您只想在包装函数运行时进行字符串插值。如果你写lazy(f("%d" % 42))的插值发生得太早了——在这种情况下,Python 会急切地求值。并且不要忘记变量作用域——你不能只从包装函数中引用迭代器。

在这里,我使用了一个lambda接收数字参数并进行插值的 a。里面的代码lambda只在惰性对象被求值时执行,也就是在渲染选择的时候。

所以,工作代码是:

choices = [
    (
        (i, lazy(
            lambda cnt: ungettext(u"%(count)d thing",
                                  u"%(count)d things", cnt)
                        % {"count": cnt},
            six.text_type
        )(i))
    )
    for i in [1, 2, 3]
]

这将正确地具有与

choices = [
    (1, _("1 thing")),
    (2, _("2 things")),
    (3, _("3 things")),
]

但是翻译数据库中只有一个条目,而不是多个条目。

于 2015-08-06T11:58:52.190 回答
0
于 2012-12-29T04:51:02.560 回答