简体   繁体   中英

Django ugettext_lazy not working for interpolated strings in forms

I have form:

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()])

i am rendering this form using form.as_p , when i change my language First Name gets translated but for some reason Last Name {name} which using format method for string interpolation is not getting translated, translation for this string is also present in the language catalog. I am on Django version 1.8 and python 2.7.

Update: It seems that for some reason django is not doing lazy evaluation of interpolated strings in my forms, It calls ugettext_lazy for the interpolated strings on very first request after server starts and never evaluates that string when it is actually gets rendered.

Very very old question but it bit me today, so here's my answer: the % operator is executed immediately on form initialization (ie on server start), so the label stops being a proxy and becomes a string, which obviously breaks the translation mechanism. By the way, as far as I can tell this would apply even if you used .format() instead of the interpolation operator, because the return of that function is still going to be a plain string instead of a proxy.

As for the solution: if you only need to use interpolation in a few form fields, the easy way is setting the label in __init__() like this:

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'}

A better solution if you need a lot of fields would be to create a custom field (or multiple, with a mixin) that accepts a new label_mapping kwarg, something like:

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)

In my eyes, the main advantage of this, beside removing boilerplate code, would be to keep the declarative syntax of form fields.

Please note I only had a couple fields that required attention so I didn't actually use the custom field class approach, but I don't see why it shouldn't work (after proper testing).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM