Opened 17 years ago

Closed 17 years ago

#3600 closed (fixed)

Newforms label translation fails

Reported by: Timo Owned by: Adrian Holovaty
Component: Forms Version: dev
Severity: Keywords: newforms translation internationalization
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Newforms' labels can be translated with gettext during initialization.

class TestForm(forms.Form):
    name = forms.CharField(label=capfirst(_('name')), max_length=255)

But this works only at first time. If you want to change your language during session ('/i18n/setlang/') the labels are not translated to the new language you are requesting.

Attachments (2)

newforms_translation_fix.patch (1.9 KB ) - added by karsu 17 years ago.
Newforms label and help_text translation patch
newforms_translation_fix_tests.patch (955 bytes ) - added by Antti Kaihola 17 years ago.
Test which fails before the above patch and succeeds with it

Download all attachments as: .zip

Change History (10)

comment:1 by karsu, 17 years ago

Problem is the same if you use gettext_lazy

comment:2 by anonymous, 17 years ago

views.py

from django.utils.translation import gettext_lazy
from django.shortcuts import render_to_response
from django.template import RequestContext
from django import newforms as forms

class TestForm(forms.Form):
    first_name = forms.CharField(label=gettext_lazy('First name'), help_text=_('First name'))
    last_name = forms.CharField(label=gettext_lazy('Last name'), help_text=_('Last name'))

def test(request):
    form = TestForm() 

    return render_to_response('test.html', RequestContext(request, {
        'form': form,}))

test.html

{% load i18n %}
<html>
    <head>
        <title>bug</title>
    </head>
    <body>
        <form  action="/i18n/setlang/?next=." method="get"><b>{% trans "language"%}:</b>
            <select onchange="this.form.submit();" name="language">
                <option value="">-------</option>
                <option value="en">{% trans "English" %}</option>
                <option value="fi">{% trans "Finnish" %}</option>
            </select>
        </form>
        <h1>{% trans "user" %}</h1>
        <table>
            {{ form }}
        </table>
    </body>
</html>

settings.py

   'django.middleware.locale.LocaleMiddleware',

urls.py

(r'^i18n/', include('django.conf.urls.i18n')),

by karsu, 17 years ago

Newforms label and help_text translation patch

comment:3 by karsu, 17 years ago

Has patch: set
Needs tests: set

by Antti Kaihola, 17 years ago

Test which fails before the above patch and succeeds with it

comment:4 by Antti Kaihola, 17 years ago

Needs tests: unset

The tests patch above adds a single simple test case for forms field with translated labels.

comment:5 by Simon G. <dev@…>, 17 years ago

Triage Stage: UnreviewedReady for checkin

comment:6 by Malcolm Tredinnick, 17 years ago

Patch needs improvement: set
Triage Stage: Ready for checkinAccepted

I'm not happy with this patch. It fixes the symptom, but not the cause of the problem. We want to be turning things into unicode as early as possible, so doing it in the Field class is the right thing. Moving the unicode conversion until later is inconsistent and leaves us with multiple encodings floating around internally -- something we are trying to slowly get rid of. A better fix is to work out why we aren't then translating that unicode value, which is, I suspect a deeper problem.

This is a genuine bug and the test case is good to have, but it isn't the right fix. I want to dig a bit deeper into this before committing anything.

comment:7 by karsu, 17 years ago

It is good idea to put unicode to Field class!

I have tried to underestand that translation problem. I have noticed if I create new instance from SomeForm class only at first time it defines 'base_fields'. Now if you have some "dynamic" data in form class for example: translation, choices etc, all Fields datas will be generate to "static". Once a new instance from SomeForm is created base_fields are copied and their "old" data is used while generating data to create new form fields.

Test case for ChoiceField dymanic data

from django.db import models
class City(models.Model):
    name = models.CharField(maxlength=100)

form_tests = r"""
>>> from django.newforms import *

>>> def get_all_cities():
...     for i in City.objects.all():
...         yield (i.id, i.name)

>>> c = City.objects.create(name="Helsinki")
>>> c.save()
>>> c = City.objects.create(name="Lahti")
>>> c.save()

>>> class CityForm(Form):
...     cities = ChoiceField(choices=get_all_cities())

>>> f = CityForm()
>>> print f.as_p()
<p><label for="id_cities">Cities:</label> <select name="cities" id="id_cities">
<option value="1">Helsinki</option>
<option value="2">Lahti</option>
</select></p>

>>> c = City.objects.create(name="London")
>>> c.save()

>>> print [(city) for city in get_all_cities()]
[(1, 'Helsinki'), (2, 'Lahti'), (3, 'London')]

>>> f = CityForm()
>>> print f.as_p()
<p><label for="id_cities">Cities:</label> <select name="cities" id="id_cities">
<option value="1">Helsinki</option>
<option value="2">Lahti</option>
<option value="3">London</option>
</select></p>
"""

__test__ = {
    'form_tests': form_tests,
}

if __name__ == "__main__":
    import doctest
    doctest.testmod()

comment:8 by Malcolm Tredinnick, 17 years ago

Resolution: fixed
Status: newclosed

(In [4904]) Fixed #3600 -- Made smart_unicode respect deferred evaluation in the case
of strings translated with gettext_lazy and friends.

Note: See TracTickets for help on using tickets.
Back to Top