2

I am using python 2.7 and had issue with lines like: LOG.warning(_("text"))

This won't work as LOG.warning is expecting a string (str) and ugettext_lazy only knows how to render unicode.

Now the solution I found was to force unicode rendering before calling the logger:

    text = 'Test trans'
    LOG.warning(u"%s" % _(text))

However, I was surprised to noticed that this code also work:

LOG.warning(_(Test trans %(test)s.') % {'test': 1})
LOG.warning(_('Test trans %s.') % 1)

Can somebody explain why? Does the % operator calls for unicode rendering before replacing the variable?

Thanks in advance.

Anupam
  • 14,950
  • 19
  • 67
  • 94

1 Answers1

3

The u prefix in ugettext_lazy means that the return value of this function is a Unicode string. The _lazy suffix means that the return value becomes lazy, that is, the return value only becomes a Unicode string at the absolutely last opportunity, when a string operation is done on it.

Try running this under python2 manage.py shell to see what I mean:

>>> from django.utils.translation import ugettext_lazy as _
>>> _("hi")
<django.utils.functional.__proxy__ object at 0x10fa23b10>
>>> _("hi") + ""
u'hi'
>>> _("hi %s") % "hello"
u'hi hello'

I'm assuming that your assumption that LOG.warning only accepts non-Unicode strings and lazy strings is correct. In your case, maybe you have your logging configured to do nothing with warning log messages, and so the lazy strings that you are passing to LOG.warning are never evaluated and never converted to normal non-lazy Unicode strings.

Compare with ugettext and gettext_lazy, and you'll see what I mean.

By the way, I highly recommend upgrading to Python 3, the way it deals with Unicode is much clearer and easy to follow in general than Python 2.

Flimm
  • 136,138
  • 45
  • 251
  • 267
  • So if my understanding is correct, "%" ou "+" operator force unicode rendering the same way as in my line `LOG.warning(u"%s" % _(text))`. I can assure you that my logger is properly set up to "do things" with warning level. However it does not evaluate the lazy string in the case of: `_("text")` without anymore operation. So I actually have 3 solutions: ` u"%s" % _(text) _(text).__unicode__() ugettext(text) ` What would be the best ? For logging process, does it make a difference to go back to ugettext ? This code is only executed when an exception occured... – user6920919 Oct 05 '16 at 11:51
  • @user6920919 I wouldn't use the _lazy variants unless I needed that lazy functionality, and I would call `ugettext` when I needed a Unicode string and `gettext` when I needed a non-Unicode string. – Flimm Oct 06 '16 at 09:21