Edgewall Software

Changes between Version 2 and Version 3 of GenshiTutorial/Internationalization


Ignore:
Timestamp:
Oct 31, 2007, 10:25:39 AM (16 years ago)
Author:
cmlenz
Comment:

Moved i18n by palgarvio to a separate page

Legend:

Unmodified
Added
Removed
Modified
  • GenshiTutorial/Internationalization

    v2 v3  
    11= [wiki:GenshiTutorial Genshi Tutorial]: Adding Internationalization =
    22
    3  ''Noone has written this yet. If you'd like to give it a shot, this page is all yours.''
     3To internationalize our application we'll use [http://babel.edgewall.org Babel].
     4{{{
     5easy_install Babel
     6}}}
     7
     8To get the basic info on how to work with message catalog using Babel [http://babel.edgewall.org/wiki/Documentation/0.9/messages.html read this], I'll just follow you through the basic procedures.
     9
     10First 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:
     11{{{
     12# Extraction from Python source files
     13
     14[python: **.py]
     15
     16# Extraction from Genshi HTML and text templates
     17
     18[genshi: **/templates/**.html
     19}}}
     20The 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.
     21
     22Now let's extract some messages to be translated:
     23{{{
     24pybabel extract -o geddit/locale/geddit.pot -F ./mapping.cfg geddit
     25}}}
     26
     27The output should be similar to:
     28{{{
     29extracting messages from geddit/__init__.py
     30extracting messages from geddit/controller.py
     31extracting messages from geddit/form.py
     32extracting messages from geddit/model.py
     33extracting messages from geddit/translator.py
     34extracting messages from geddit/lib/__init__.py
     35extracting messages from geddit/lib/ajax.py
     36extracting messages from geddit/lib/template.py
     37extracting messages from geddit/templates/_comment.html
     38extracting messages from geddit/templates/_form.html
     39extracting messages from geddit/templates/comment.html
     40extracting messages from geddit/templates/index.html
     41extracting messages from geddit/templates/info.html
     42extracting messages from geddit/templates/layout.html
     43extracting messages from geddit/templates/submit.html
     44writing PO template file to geddit/locale/geddit.pot
     45}}}
     46
     47Now let's create the English catalog which normally isn't translated:
     48{{{
     49pybabel init -D geddit -i geddit/locale/geddit.pot -d geddit/locale/ -l en
     50}}}
     51
     52And, since I'm Portuguese, we'll create a Portuguese catalog to serve as an example:
     53{{{
     54pybabel init -D geddit -i geddit/locale/geddit.pot -d geddit/locale/ -l pt_PT
     55}}}
     56On this step you can create a catalog in your mother language if not english so that you can see Geddit translated.
     57
     58Edit the contents of the resulting `geddit.po` for the locale you created, translate it, save and exit.
     59
     60Next step will involve compiling these catalogs so that they can be used by python's gettext module:
     61{{{
     62pybabel compile -D geddit -d geddit/locale/ -f --statistics
     63}}}
     64
     65Now, our Geddit application needs to use and know how to use these translated catalogs.
     66
     67Let's modify `geddit/controller.py` with(this is a diff):
     68{{{
     69#!diff
     70Index: geddit/controller.py
     71===================================================================
     72--- geddit/controller.py        (revision 766)
     73+++ geddit/controller.py        (working copy)
     74@@ -92,8 +92,40 @@
     75             links = sorted(self.data.values(), key=operator.attrgetter('time'))
     76             return template.render(links=links)
     77
     78+    @cherrypy.expose
     79+    def set_lang(self, language):
     80+       import gettext
     81+       import formencode
     82+       import __builtin__
     83+       locale_dir = os.path.join(os.path.dirname(__file__), 'locale')
     84+       domain = 'geddit'
     85+       codeset= 'utf-8'
     86+
     87+       gettext.bindtextdomain(domain, locale_dir)
     88+       gettext.textdomain(domain)
     89+
     90+       try:
     91+            translator = gettext.translation(domain,
     92+                                         locale_dir,
     93+                                         languages=[language],
     94+                                         codeset=codeset)
     95+       except IOError, error:
     96+            language=['en']
     97+            translator = gettext.translation(domain,
     98+                                         locale_dir,
     99+                                         languages=language,
     100+                                         codeset=codeset)
     101+       formencode.api.set_stdtranslation(languages=[language])
     102+       __builtin__._ = translator.ugettext
     103+       raise cherrypy.HTTPRedirect('/')
     104+
     105+
     106
     107 def main(filename):
     108+    import __builtin__
     109+    from gettext import NullTranslations
     110+
     111+    __builtin__._ = NullTranslations().ugettext
     112     # load data from the pickle file, or initialize it to an empty list
     113     if os.path.exists(filename):
     114         fileobj = open(filename, 'rb')
     115}}}
     116
     117Our `geddit/lib/template.py` with(also diff):
     118{{{
     119#!diff
     120Index: geddit/lib/template.py
     121===================================================================
     122--- geddit/lib/template.py      (revision 766)
     123+++ geddit/lib/template.py      (working copy)
     124@@ -4,6 +4,7 @@
     125 from genshi.core import Stream
     126 from genshi.output import encode, get_serializer
     127 from genshi.template import Context, TemplateLoader
     128+from genshi.filters import Translator
     129
     130 from geddit.lib import ajax
     131
     132@@ -42,6 +43,7 @@
     133         template = loader.load(args[0])
     134     else:
     135         template = cherrypy.thread_data.template
     136+    template.filters.insert(0, Translator(_))
     137     ctxt = Context(url=cherrypy.url)
     138     ctxt.push(kwargs)
     139     return template.generate(ctxt)
     140}}}
     141
     142And finaly our `geddit/templates/layout.html` with(also diff):
     143{{{
     144#!diff
     145Index: geddit/templates/layout.html
     146===================================================================
     147--- geddit/templates/layout.html        (revision 766)
     148+++ geddit/templates/layout.html        (working copy)
     149@@ -19,6 +19,16 @@
     150         <a href="/"><img src="${url('/media/logo.gif')}" width="201" height="79" alt="geddit?" /></a>
     151       </div>
     152       <div id="content">
     153+        <form method="post" id="lang_choose" name="lang_choose" action="${url('/set_lang')}">
     154+        <label for="language">Language:</label>
     155+        <select id="language" name="language" onChange="$('#lang_choose').submit()">
     156+          <option value="en">English</option>
     157+          <option value="pt_PT">Portuguese</option>
     158+        </select>
     159+        </form>
     160+        <noscript>
     161+          <input type="submit" name="submit" value="Update"/>
     162+        </noscript>
     163         ${select('*|text()')}
     164       </div>
     165       <div id="footer">
     166}}}
     167
     168This will allow the user to select the language.
     169[[Image(tutorial07.png)]]
     170
     171And that wraps it up!