Django ugettext_lazy不适用于表单中的插值字符串

时间:2018-01-29 19:35:47

标签: python django internationalization django-i18n

我有表格:

class UserForm(forms.Form):
fname = forms.CharField(max_length=30, label=_('First Name'), validators=[Alpha()])
lname = forms.CharField(max_length=30, label=_('Last Name {name}').format(name='XXXX'), validators=[Beta()])

我正在使用 form.as_p 呈现此表单,当我更改我的语言名字被翻译但由于某种原因姓氏{name} 使用格式化方法进行字符串插值未翻译,此字符串的翻译也出现在语言目录中。我在Django 1.8和python 2.7上。

更新 似乎由于某些原因,django没有在我的表单中对插值字符串进行惰性求值,它在服务器启动后的第一个请求中调用ugettext_lazy用于插值字符串,并且在实际获取时不会对该字符串进行求值。

1 个答案:

答案 0 :(得分:0)

非常古老的问题,但今天它让我感到困惑,所以这是我的答案:% 运算符在表单初始化时立即执行(即在服务器启动时),因此 label 不再是代理,并且变成一个字符串,这显然打破了翻译机制。 顺便说一句,据我所知,即使您使用 .format() 而不是插值运算符,这也适用,因为该函数的返回仍然是纯字符串而不是代理。

至于解决方案:如果你只需要在几个表单字段中使用插值,简单的方法是在__init__()中设置标签,如下所示:

class MyForm(forms.Form):
    myfield = forms.BooleanField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['myfield'].label = _("Your interpolated %(value)s") % {'value': 'field'}

如果您需要很多字段,更好的解决方案是创建一个接受新 label_mapping kwarg 的自定义字段(或多个,使用 mixin),例如:

class MyCustomField(Field):
    def __init__(label_mapping=None, label=None, *args, **kwargs):
        if label is not None and label_mapping is not None:
            label = label % label_mapping
        super().__init__(label=label, *args, **kwargs)

在我看来,除了删除样板代码之外,这样做的主要优点是保留表单字段的声明性语法。

请注意,我只有几个字段需要注意,所以我实际上并没有使用自定义字段类方法,但我不明白为什么它不应该起作用(经过适当的测试)。