Code

Opened 7 years ago

Closed 7 years ago

#3600 closed (fixed)

Newforms label translation fails

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

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 7 years ago.
Newforms label and help_text translation patch
newforms_translation_fix_tests.patch (955 bytes) - added by akaihola 7 years ago.
Test which fails before the above patch and succeeds with it

Download all attachments as: .zip

Change History (10)

comment:1 Changed 7 years ago by karsu

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Problem is the same if you use gettext_lazy

comment:2 Changed 7 years ago by anonymous

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')),

Changed 7 years ago by karsu

Newforms label and help_text translation patch

comment:3 Changed 7 years ago by karsu

  • Has patch set
  • Needs tests set

Changed 7 years ago by akaihola

Test which fails before the above patch and succeeds with it

comment:4 Changed 7 years ago by akaihola

  • Needs tests unset

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

comment:5 Changed 7 years ago by Simon G. <dev@…>

  • Triage Stage changed from Unreviewed to Ready for checkin

comment:6 Changed 7 years ago by mtredinnick

  • Patch needs improvement set
  • Triage Stage changed from Ready for checkin to Accepted

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 Changed 7 years ago by karsu

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 Changed 7 years ago by mtredinnick

  • Resolution set to fixed
  • Status changed from new to closed

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

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.