Search code examples
python-2.7tornadogettext

Error translating Tornado template with gettext


I've got this site running on top with Tornado and its template engine that I want to Internationalize, so I thought on using gettext to help me with that.

Since my site is already in Portuguese, my message.po (template) file has all msgid's in portuguese as well (example):

#: base.html:30 base.html:51
msgid   "Início"
msgstr  ""

It was generated with xgettext:

xgettext -i *.html -L Python --from-code UTF-8

Later I used Poedit to generate the translation file en_US.po and later compile it as en_US.mo. Stored in my translation folder:

translation/en_US/LC_MESSAGES/site.mo 

So far, so good.

I've created a really simple RequestHandler that would render and return the translated site.

import os
import logging
from tornado.web import RequestHandler
import tornado.locale as locale

LOG = logging.getLogger(__name__)

class SiteHandler(RequestHandler):

    def initialize(self):
        locale.load_gettext_translations(os.path.join(os.path.dirname(__file__), '../translations'), "site")

    def get(self, page):
        LOG.debug("PAGE REQUESTED: %s", page)
        self.render("site/%s.html" %page)

As far as I know that should work perfectly, but somehow I've encountered some issues:

1 - How do I tell Tornado that my template has its text in Portuguese so it won't go looking for a pt locale which I don't have?

2 - When asking for the site with en_US locale, it loads ok but when Tornado is going to translate, it throws an encoding exception.

TypeError: not all arguments converted during string formatting
ERROR:views.site:Could not load template
Traceback (most recent call last):
  File "/Users/ademarizu/Dev/git/new_plugin/site/src/main/py/views/site.py", line 20, in get
    self.render("site/%s.html" %page)
  File "/Users/ademarizu/Dev/virtualEnvs/execute/lib/python2.7/site-packages/tornado/web.py", line 664, in render
    html = self.render_string(template_name, **kwargs)
  File "/Users/ademarizu/Dev/virtualEnvs/execute/lib/python2.7/site-packages/tornado/web.py", line 771, in render_string
    return t.generate(**namespace)
  File "/Users/ademarizu/Dev/virtualEnvs/execute/lib/python2.7/site-packages/tornado/template.py", line 278, in generate
    return execute()
  File "site/home_html.generated.py", line 11, in _tt_execute
    _tt_tmp = _("Início")  # site/base.html:30
  File "/Users/ademarizu/Dev/virtualEnvs/execute/lib/python2.7/site-packages/tornado/locale.py", line 446, in translate
    return self.gettext(message)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/gettext.py", line 406, in ugettext
    return self._fallback.ugettext(message)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/gettext.py", line 407, in ugettext
    return unicode(message)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)

Any help?

Ah, I'm running python 2.7 btw!


Solution

  • 1 - How do I tell Tornado that my template has its text in Portuguese so it won't go looking for a pt locale which I don't have?

    This is what the set_default_locale method is for. Call tornado.locale.set_default_locale('pt') (or pt_BR, etc) once at startup to tell tornado that your template source is in Portuguese.

    2 - When asking for the site with en_US locale, it loads ok but when Tornado is going to translate, it throws an encoding exception.

    Remember that in Python 2, strings containing non-ascii characters need to be marked as unicode. Instead of _("Início"), use _(u"Início").