Project Internationalization with Nagare (message extraction)

Goals

Nagare doesn't have tight integration with gettext or Babel, here we're going to see a way to use those tools in a nagare project.

In the first part, we will integrate Babel into the project, in order to manage catalogs and extract messages. In the second part, we will set up effective message translation inside the project.

Requirements

We need a working Nagare Installation.

We will use Babel to extract the template file and manage our catalog files, so let's install it:

$easy_install Babel
...

Then, we will create and register the example application this way

$ nagare-admin create-app example_i18n
Application 'example_i18n' created.
...
$ cd example_i18n
$ python setup.py develop
...
Finished processing dependencies for example-i18n==0.0.1

Set some defaults for Babel commands

Create a setup.cfg in your newly created app folder containing the following

[extract_messages]
keywords = _ , ugettext , lazy_ugettext:1 , N_:1,2 , ungettext:1,2 , lazy_ungettext:1,2
output_file = data/locale/messages.pot
[init_catalog]
input_file = data/locale/messages.pot
output_dir = data/locale
domain = messages
[update_catalog]
input_file = data/locale/messages.pot
output_dir = data/locale
domain = messages
[compile_catalog]
directory = data/locale
domain = messages

Here, we decide to put translation files into data/locale, but this folder is not created by create-app so we have to create it manually:

$ mkdir data/locale

And finally, we add message extractors information into out setup.py file:

VERSION = '0.0.1'
from setuptools import setup, find_packages
setup(
      name = 'example_i18n',
      version = VERSION,
      author = '',
      author_email = '',
      description = '',
      license = '',
      keywords = '',
      url = '',
      packages = find_packages(),
      include_package_data = True,
      package_data = {'' : ['*.cfg']},
      zip_safe = False,
      install_requires = ('nagare', 'Babel'),
      entry_points = """
      [nagare.applications]
      example_i18n = example_i18n.app:app
      """,
      message_extractors = {'example_i18n': [
                ('**.py', 'python', None)]}
     )
Note:
Babel has been added as a dependency for the project, this way typing 'python setup.py develop' should install Babel if it is missing.

Prepare application for internationalization

Edit example_i18n/app.py, put every strings between _() and define a fake _ function:

from __future__ import with_statement
import os
from nagare import presentation
_ = lambda x: x

class Example_i18n(object):
    pass
@presentation.render_for(Example_i18n)
def render(self, h, *args):
    this_file = __file__
    if this_file.endswith('.pyc'):
        this_file = __file__[:-1]
    models_file = os.path.join(os.path.dirname(__file__), 'models.py')
    h.head.css_url('/static/nagare/application.css')
    h.head << h.head.title(_('Up and Running !'))
    with h.div(class_='mybody'):
        with h.div(id='myheader'):
            h << h.a(h.img(src='/static/nagare/img/logo.gif'), id='logo', href='http://www.nagare.org/', title='Nagare home')
            h << h.span(_('Congratulations !'), id='title')
        with h.div(id='main'):
            h << h.h1(_('Your application is running'))
            with h.p:
                h << _('You can now:')
                with h.ul:
                    h << h.li(_('If your application uses a database, add your database entities into '), h.i(models_file))
                    h << h.li(_('Add your application components into '), h.i(this_file), _(' or create new files'))
            h << h.p(_('To learn more, go to the '), h.a(_('official website'), href='http://www.nagare.org/'))
            h << _("Have fun !")
    h << h.div(class_='footer')
    return h.root
# ---------------------------------------------------------------
app = Example_i18n

Message extraction and catalog manipulation

Messages can be extracted:

$ python setup.py extract_messages
running extract_messages
extracting messages from example_i18n/__init__.py
extracting messages from example_i18n/app.py
extracting messages from example_i18n/models.py
writing PO template file to data/locale/messages.pot

A messages.pot file is now created into data/locale

For the next step, we have to initialize a catalog for your preferred locale (fr in this example):

$ python setup.py init_catalog -l fr
running init_catalog
creating catalog 'data/locale/fr/LC_MESSAGES/messages.po' based on 'data/locale/messages.pot'

The catalog is now added and is ready to be edited.

Once edited and filled in with the right translations, we can compile our catalog:

$ python setup.py compile_catalog
running compile_catalog
compiling catalog 'data/locale/fr/LC_MESSAGES/messages.po' to 'data/locale/fr/LC_MESSAGES/messages.mo'

This way we can prepare as many catalogs as locales needed.

Note:
when changing messages in a project we have to do a extract_messages followed by a update_catalog, and add missing translation in every modified catalog.

Next Step

We are using a fake _ function, so nothing is translated at all, the next step is to plug gettext functions into example_i18n application, in order to get effective message translation.

Comments

No comments.