Opened 12 years ago
Closed 12 years ago
#19132 closed Cleanup/optimization (fixed)
bug in use of mark_safe and i18n _
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Documentation | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I am using a form which defines this field:
terms = forms.BooleanField( error_messages={'required': _('You must accept the terms and conditions')}, label="", help_text=_(mark_safe("I understand and accept the <a href='/terms_and_conditions' target='_blank'>terms of use</a> and <a href='/privacy' target='_blank'>privacy policy</a> of this site.")) )
unfortunately running "./manage.py makemessages --all" does not seem to pickup the help_text named argument.
---
If i change this to:
terms = forms.BooleanField( error_messages={'required': _('You must accept the terms and conditions')}, label="", help_text=mark_safe(_("I understand and accept the <a href='/terms_and_conditions' target='_blank'>terms of use</a> and <a href='/privacy' target='_blank'>privacy policy</a> of this site.")) )
the message in the html is left untranslated.
Change History (10)
comment:1 by , 12 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 12 years ago
Component: | Translations → Internationalization |
---|---|
Resolution: | invalid |
Status: | closed → reopened |
Triage Stage: | Unreviewed → Accepted |
No, even with ugettext_lazy, this does not work. mark_safe is triggering lazy string translation.
>>> from django.utils.translation import ugettext_lazy >>> from django.utils.safestring import mark_safe >>> mark_safe(ugettext_lazy('Home')) u'Home' >>> mark_safe(ugettext_lazy('Home')).__class__ <class 'django.utils.safestring.SafeText'>
I don't know currently if we can do something to prevent this, but a temporary workaround would be to dynamically set the help_text property in the __init__
of the form.
comment:3 by , 12 years ago
Then the reporter presumably needs mark_safe_lazy
, which can be created easily using lazy
in the same way that ugettext_lazy is created, I imagine. I think altering the behaviour of mark_safe
here is likely to be too risky.
comment:4 by , 12 years ago
Resolution: | → invalid |
---|---|
Status: | reopened → closed |
Thanks Luke for the tip, this seems to work nicely:
from django.utils.functional import lazy mark_safe_lazy = lazy(mark_safe, six.text_type) terms = forms.BooleanField(..., help_text=mark_safe_lazy(_("My lazy string)))
comment:5 by , 12 years ago
Hi, yes i am using ugettext_lazy.
Following your tips i did this fix: (thanks for those)
from django.utils.translation import ugettext, ugettext_lazy as _ from django.utils.safestring import mark_safe from django.utils.functional import lazy from types import UnicodeType mark_safe_lazy = lazy(mark_safe, UnicodeType) ... terms = forms.BooleanField( error_messages={'required': _('You must accept the terms and conditions')}, label="", help_text=mark_safe_lazy(_("I understand and accept the <a href='/terms_and_conditions' target='_blank'>terms of use</a> and <a href='/privacy' target='_blank'>privacy policy</a> of this site.")) ) ...
This works now. Isn't this worth including in the documentation, or is it too edge case?
comment:6 by , 12 years ago
Hmm, it's difficult to know where to put in the docs, because there are so many places it could apply - anywhere that you want to use HTML in a class or module level translatable string.
Perhaps we should make a note in the mark_safe
docs, and possibly add the mark_safe_lazy
function, I'm not sure. If it's worth documenting, it's really not much more work to add the function, and would make the documentation probably smaller overall.
comment:7 by , 12 years ago
Maybe here?:
diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt index aaf728b..6692c1a 100644 --- a/docs/topics/i18n/translation.txt +++ b/docs/topics/i18n/translation.txt @@ -427,6 +427,24 @@ In this case, the lazy translations in ``result`` will only be converted to strings when ``result`` itself is used in a string (usually at template rendering time). +Other uses of lazy in delayed translations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For any other case where you would like to delay the translation, but have to +pass the translatable string as argument to another function, you can wrap +this function inside a lazy call yourself. For example:: + + 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) + +And then later:: + + lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>")) +
comment:8 by , 12 years ago
LGTM, and as docs only fix it avoids the problem that we are technically in feature freeze for trunk.
comment:9 by , 12 years ago
Component: | Internationalization → Documentation |
---|---|
Resolution: | invalid |
Status: | closed → reopened |
Type: | Bug → Cleanup/optimization |
comment:10 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
You haven't told us what
_
is defined as.I'm guessing are probably using ugettext, and need to read the docs about lazy translation:
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#lazy-translation