python-babel / flask-babel

i18n and l10n support for Flask based on Babel and pytz
https://python-babel.github.io/flask-babel/
Other
444 stars 159 forks source link

UnicodeEncodeError in LazyString.__repr__ for python 2 #134

Closed simplylizz closed 4 years ago

simplylizz commented 6 years ago

LazyString.__repr__ calls str.format and if the argument is unicode string with non-ascii symbols then it throws UnicodeEncodeError.

How to reproduce:

In [47]: flask_babel.lazy_gettext(u'qwe').__repr__()
Out[47]: "l'qwe'"

In [48]: flask_babel.lazy_gettext(u'фыв').__repr__()
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-48-174fa9438d66> in <module>()
----> 1 flask_babel.lazy_gettext(u'фыв').__repr__()

/Users/simplylizz/.pyenv/versions/2.7.14/envs/canvas/lib/python2.7/site-packages/flask_babel/speaklater.pyc in __repr__(self)
     18
     19     def __repr__(self):
---> 20         return "l'{0}'".format(text_type(self))
     21
     22     def __str__(self):

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

Perhaps you could fix this with by replacing inside __repr__ str.format call on unicode.format or just by using %s-based formatting which handles such situations without exceptions:

In [56]: LazyString.__repr__ = lambda self: "l'%s'" % (flask_babel._compat.text_type(self), )

In [57]: flask_babel.lazy_gettext(u'qwe').__repr__()
Out[57]: u"l'qwe'"

In [58]: flask_babel.lazy_gettext(u'фыв').__repr__()
Out[58]: u"l'\u0444\u044b\u0432'"
simplylizz commented 6 years ago

Here is correct fix:

def __repr__(self):
    return "l{0}".format(repr(text_type(self)).lstrip('u'))

...and some tests:

   def test_lazy_repr(self):
       string = repr(lazy_gettext(u'Азино 777'))
       if PY2:
           assert string == r"l'\u0410\u0437\u0438\u043d\u043e 777'"
       else:
           assert string == "l'Азино 777'"

       string = repr(lazy_gettext(u'Azino 777'))
       assert string == "l'Azino 777'"

       string = repr(lazy_gettext('Azino 777'))
       assert string == "l'Azino 777'"
TkTech commented 4 years ago

Please note Py2 is no longer supported as of version 2.0.0.