Hi, I'm in the process of upgrading a Django application from 1.5 to 1.6 and I've come across a mark_safe + ugettext_lazy issue in form field labels that I think might be a bug introduced in 1.6 (possibly related to the introduction of the new Form.label_suffix?).
Before reporting it I thought I check here first to see if people think it is a bug. In essence, given a label that is a translatable string containing HTML and wrapped in mark_safe, e.g. mark_safe(_("<em>Foo</em>"), calling label_tag on the field in a template: in Django 1.5 results in a non-escaped string: <em>Foo</em> in Django 1.6 results in an escaped string: <em>Foo</em>: (including the default label suffix of ":" for 1.6). I was expecting 1.6 to render: <em>Foo</em>: Here's a shell example for 1.5 and 1.6 that distills what I'm getting: >>> import django >>> django.get_version() '1.5.5' >>> from django import forms >>> from django.template import Template, Context >>> from django.utils.safestring import mark_safe >>> from django.utils.translation import ugettext_lazy as _ >>> class FooForm(forms.Form): ... foo = forms.IntegerField(label=mark_safe(_("<em>Foo</em>"))) ... >>> fooForm = FooForm() >>> fooForm.fields['foo'].label u'<em>Foo</em>' >>> Template("{{ f }}").render(Context({'f': fooForm})) u'<tr><th><label for="id_foo"><em>Foo</em>:</label></th><td><input id="id_foo" name="foo" type="text" /></td></tr>' >>> Template("{{ f.foo.label }}").render(Context({'f': fooForm})) u'<em>Foo</em>' >>> Template("{{ f.foo.label_tag }}").render(Context({'f': fooForm})) u'<label for="id_foo"><em>Foo</em></label>' >>> import django >>> django.get_version() '1.6.1' >>> from django import forms >>> from django.template import Template, Context >>> from django.utils.safestring import mark_safe >>> from django.utils.translation import ugettext_lazy as _ >>> class FooForm(forms.Form): ... foo = forms.IntegerField(label=mark_safe(_("<em>Foo</em>"))) ... >>> fooForm = FooForm() >>> fooForm.fields['foo'].label <django.utils.functional.__proxy__ object at 0xabba38c> >>> Template("{{ f }}").render(Context({'f': fooForm})) u'<tr><th><label for="id_foo"><em>Foo</em>:</label></th><td><input id="id_foo" name="foo" type="number" /></td></tr>' >>> Template("{{ f.foo.label }}").render(Context({'f': fooForm})) u'<em>Foo</em>' >>> Template("{{ f.foo.label_tag }}").render(Context({'f': fooForm})) u'<label for="id_foo"><em>Foo</em>:</label>' It may or may not be related but when I tried delaying the translation as described in https://docs.djangoproject.com/en/dev/topics/i18n/translation/#other-uses-of-lazy-in-delayed-translations I got a TypeError under 1.6 when passing the lazy object to ugettext: >>> import django >>> django.get_version() '1.5.5' >>> from django.utils import six # Python 3 compatibility >>> from django.utils.functional import lazy >>> from django.utils.safestring import mark_safe >>> from django.utils.translation import ugettext_lazy as _ >>> mark_safe_lazy = lazy(mark_safe, six.text_type) >>> lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>")) >>> lazy_string <django.utils.functional.__proxy__ object at 0x9a0052c> >>> from django.utils.translation import ugettext >>> ugettext(lazy_string) u'<p>My <strong>string!</strong></p>' >>> import django >>> django.get_version() '1.6.1' >>> from django.utils import six # Python 3 compatibility >>> from django.utils.functional import lazy >>> from django.utils.safestring import mark_safe >>> from django.utils.translation import ugettext_lazy as _ >>> mark_safe_lazy = lazy(mark_safe, six.text_type) >>> lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>")) >>> lazy_string <django.utils.functional.__proxy__ object at 0xb00b24c> >>> from django.utils.translation import ugettext >>> ugettext(lazy_string) Traceback (most recent call last): File "<console>", line 1, in <module> File ".../lib/python2.7/site-packages/django/utils/translation/__init__.py", line 76, in ugettext return _trans.ugettext(message) File ".../lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 281, in ugettext return do_translate(message, 'ugettext') File ".../lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 256, in do_translate eol_message = message.replace(str('\r\n'), str('\n')).replace(str('\r'), str('\n')) File ".../lib/python2.7/site-packages/django/utils/functional.py", line 129, in __wrapper__ raise TypeError("Lazy object returned unexpected type.") TypeError: Lazy object returned unexpected type. Any ideas as to whether it may be a bug, or whether I'm just doing it wrong and 1.6 has exposed that? Cheers, Neal -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To post to this group, send email to django-users@googlegroups.com. Visit this group at http://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/926b5932-245f-474d-ba11-9f6ed087f416%40googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.