Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django translations and gettext: The deprecation of the % (string interpolation) operator

Although Django Django does not yet support Python 3, it eventually will, so I want to keep my code the more "future-proof" possible.

Since Python 2.7 the string interpolation operator (%) is being deprecated. And I realized that every string that needs to be translated is using the % interpolation syntax. And in the Django docs there is no mention of the new str.format method (the "new" official way of string formatting)...

Maybe there is a limitation of the gettext library, but I don't think so, since the string appears identical in the .PO files.

The question is if I can use the new string format method for translation.

The old way:

class Post(models.Model):
    title = models.CharField(max_length=50)
    date = models.DateField()
    # ...
    def __unicode__(self):
        return _('%(title)s (%(date)s)') % {
            'title': self.title,
            'date': self.date,
        }

The "new" way:

class Post(models.Model):
    title = models.CharField(max_length=50)
    date = models.DateField()
    # ...
    def __unicode__(self):
        return _('{title} ({date})').format(
            title=self.title,
            date=self.date,
        )

Also, ugettext_lazy does not really return strings, but Promises, objects that are evaluated only when needed.

like image 362
Armando Pérez Marqués Avatar asked Jun 12 '12 15:06

Armando Pérez Marqués


1 Answers

You could use it safely. For example

ugettext_lazy('{foo}').format(foo='bar')

The translation program xgettext, which is used by Django, does not care about the content to be translated. It just searches .py file for keywords such as ugettext_lazy or _ to collect the translatable strings(refs the manual of xgettext and Django code)

Furthermore, the .format() method above is a wrapper provided by the proxy object, like:

>>> ugettext_lazy(u'{foo}').format
<bound method __proxy__.__wrapper__ of <django.utils.functional.__proxy__ object at 0x102f19050>>

The invoking of the above .format() would get u'{foo}' to be translated to some unicode value, then call value.format with actual arguments. You could see that the translation and value.format happen in different stages.

like image 81
okm Avatar answered Oct 12 '22 06:10

okm