django / mark_safe / translatables
Look at this snippet of Django code in models.py, and in particular
the help_text bit:
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe
class MyModel(models.Model):
    my_field = models.CharField(max_length=123,
                                help_text=mark_safe(_('Some <b>help</b> text.')))
For those unfamiliar with Django. A quick run-down:
- The definition of 
MyModelcreates a mapping between the MyModel class and a underlyingapp_mymodeltable in a database. - That table will consist of two columns: 
id, an automatic integer as primary key (created by default), andmy_field, a varchar/text field of at most 123 characters. - With minimal effort a HTML form can be generated from this. That
form will show 
my_fieldas a text input box and near it the text we defined inhelp_text. - The 
_()-function has the gettext functions run over it so the text can be served in different languages with minimal effort. - The 
mark_safe()-function tells the template rendererer that this output is already safe to use in HTML. Without it, the user would see:Some <b>help</b> text. 
Unfortunately this doesn’t do what you would expect.
Let’s examine why.
There is a reason why we use the ugettext_lazy wrapper in models.py.
This code is executed once at startup / first run, and the language that
was selected at that time would be substituted if we used the
non-lazy ugettext. The lazy variant makes sure the substitution takes
place at the last possible time.
mark_safe forces the translation to happen immediately.
In the best case that means someone else can get the help text served in
the wrong language. In the worst case, you get a recursive import when
the translation routines attempt to import all INSTALLED_APPS while
looking for locale files. Your MyModel might be referenced from one of
those apps. The result: recursion and a resulting ImportError.
...
File "someapp/models.py", line 5, in <module>
    class MyModel(models.Model):
File "someapp/models.py", line 6, in <module>
    my_field = models.CharField(max_length=123,
File "django/utils/safestring.py", line 101, in mark_safe
    return SafeUnicode(s)
...
File "django/utils/translation/trans_real.py", line 180, in _fetch
    app = import_module(appname)
File "django/utils/importlib.py", line 35, in import_module
    __import__(name)
...
ImportError: cannot import name MyModel
Lessons learnt: if you’re using translations then don’t call mark_safe
on anything until it’s view time.
In this case, we would fix it by adding the mark_safe call to the
Form constructor. We know that that is run for every form
instantiation, so that’s late enough.
class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)
        self.fields['my_field'].help_text = mark_safe(self.fields['my_field'].help_text)
But suggestions for prettier solutions are welcome.
Update 2013-03-21
The Django 1.4 docs provide the better solution:
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)