Edgewall Software

GenshiTutorial/Internationalization

Version 5 (modified by cmlenz, 6 years ago)

Note error

Genshi Tutorial: Adding Internationalization

To internationalize our application we'll use  Babel.

easy_install Babel

To get the basic info on how to work with message catalog using Babel  read this, I'll just follow you through the basic procedures.

First we'll create a locale directory under geddit which will hold the message catalogs. Next, we'll create a mapping file which will tell Babel how to handle the several type of files. Create a mappings.cfg on the directory above the geddit one and add inside:

# Extraction from Python source files

[python: **.py]

# Extraction from Genshi HTML and text templates

[genshi: **/templates/**.html

The above will tell Babel that .py files should be handled by the python extractor and that the .html files should be handled by the Genshi extractor.

Now let's extract some messages to be translated:

pybabel extract -o geddit/locale/geddit.pot -F ./mappings.cfg geddit

The output should be similar to:

extracting messages from geddit/__init__.py
extracting messages from geddit/controller.py
extracting messages from geddit/form.py
extracting messages from geddit/model.py
extracting messages from geddit/translator.py
extracting messages from geddit/lib/__init__.py
extracting messages from geddit/lib/ajax.py
extracting messages from geddit/lib/template.py
extracting messages from geddit/templates/_comment.html
extracting messages from geddit/templates/_form.html
extracting messages from geddit/templates/comment.html
extracting messages from geddit/templates/index.html
extracting messages from geddit/templates/info.html
extracting messages from geddit/templates/layout.html
extracting messages from geddit/templates/submit.html
writing PO template file to geddit/locale/geddit.pot

Now let's create the English catalog which normally isn't translated:

pybabel init -D geddit -i geddit/locale/geddit.pot -d geddit/locale/ -l en

And, since I'm Portuguese, we'll create a Portuguese catalog to serve as an example:

pybabel init -D geddit -i geddit/locale/geddit.pot -d geddit/locale/ -l pt_PT

On this step you can create a catalog in your mother language if not english so that you can see Geddit translated.

Edit the contents of the resulting geddit.po for the locale you created, translate it, save and exit.

Next step will involve compiling these catalogs so that they can be used by python's gettext module:

pybabel compile -D geddit -d geddit/locale/ -f --statistics

Now, our Geddit application needs to use and know how to use these translated catalogs.

Let's modify geddit/controller.py with(this is a diff):

  • geddit/controller.py

     
    9292            links = sorted(self.data.values(), key=operator.attrgetter('time')) 
    9393            return template.render(links=links) 
    9494 
     95    @cherrypy.expose 
     96    def set_lang(self, language): 
     97       import gettext 
     98       import formencode 
     99       import __builtin__ 
     100       locale_dir = os.path.join(os.path.dirname(__file__), 'locale') 
     101       domain = 'geddit' 
     102       codeset= 'utf-8' 
     103 
     104       gettext.bindtextdomain(domain, locale_dir) 
     105       gettext.textdomain(domain) 
     106 
     107       try: 
     108            translator = gettext.translation(domain, 
     109                                         locale_dir, 
     110                                         languages=[language], 
     111                                         codeset=codeset) 
     112       except IOError, error: 
     113            language=['en'] 
     114            translator = gettext.translation(domain, 
     115                                         locale_dir, 
     116                                         languages=language, 
     117                                         codeset=codeset) 
     118       formencode.api.set_stdtranslation(languages=[language]) 
     119       __builtin__._ = translator.ugettext 
     120       raise cherrypy.HTTPRedirect('/') 
     121 
     122 
    95123 
    96124def main(filename): 
     125    import __builtin__ 
     126    from gettext import NullTranslations 
     127 
     128    __builtin__._ = NullTranslations().ugettext 
    97129    # load data from the pickle file, or initialize it to an empty list 
    98130    if os.path.exists(filename): 
    99131        fileobj = open(filename, 'rb') 

Our geddit/lib/template.py with(also diff):

  • geddit/lib/template.py

     
    44from genshi.core import Stream 
    55from genshi.output import encode, get_serializer 
    66from genshi.template import Context, TemplateLoader 
     7from genshi.filters import Translator 
    78 
    89from geddit.lib import ajax 
    910 
     
    4243        template = loader.load(args[0]) 
    4344    else: 
    4445        template = cherrypy.thread_data.template 
     46    template.filters.insert(0, Translator(_)) 
    4547    ctxt = Context(url=cherrypy.url) 
    4648    ctxt.push(kwargs) 
    4749    return template.generate(ctxt) 

WARNING: there's an error in the above code, please see #238.

And finaly our geddit/templates/layout.html with(also diff):

  • geddit/templates/layout.html

     
    1919        <a href="/"><img src="${url('/media/logo.gif')}" width="201" height="79" alt="geddit?" /></a> 
    2020      </div> 
    2121      <div id="content"> 
     22        <form method="post" id="lang_choose" name="lang_choose" action="${url('/set_lang')}"> 
     23        <label for="language">Language:</label> 
     24        <select id="language" name="language" onChange="$('#lang_choose').submit()"> 
     25          <option value="en">English</option> 
     26          <option value="pt_PT">Portuguese</option> 
     27        </select> 
     28        </form> 
     29        <noscript> 
     30          <input type="submit" name="submit" value="Update"/> 
     31        </noscript> 
    2232        ${select('*|text()')} 
    2333      </div> 
    2434      <div id="footer"> 

This will allow the user to select the language. Move screenshot over, too

And that wraps it up!

Attachments