Edgewall Software

Changes between Version 101 and Version 102 of GenshiTutorial


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

I18n section moved to GenshiTutorial/Internationalization

Legend:

Unmodified
Added
Removed
Modified
  • GenshiTutorial

    v101 v102  
    14731473Just like above, we've added the import of the Genshi `HTML()` function. On the `<content>` element we've added the `type="xhtml"` attribute, and we've added a wrapper `<div>` inside that element to declare the XHTML namespace. Finally, inside that `<div>`, we inject the comment text as an HTML-parsed stream, analogous to what we've done in the HTML template.
    14741474
    1475 
    1476 === Internationalize The Application (I18N) ===
    1477 To internationalize our application we'll use [http://babel.edgewall.org Babel].
    1478 {{{
    1479 easy_install Babel
    1480 }}}
    1481 
    1482 To 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.
    1483 
    1484 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:
    1485 {{{
    1486 # Extraction from Python source files
    1487 
    1488 [python: **.py]
    1489 
    1490 # Extraction from Genshi HTML and text templates
    1491 
    1492 [genshi: **/templates/**.html
    1493 }}}
    1494 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.
    1495 
    1496 Now let's extract some messages to be translated:
    1497 {{{
    1498 pybabel extract -o geddit/locale/geddit.pot -F ./mapping.cfg geddit
    1499 }}}
    1500 
    1501 The output should be similar to:
    1502 {{{
    1503 extracting messages from geddit/__init__.py
    1504 extracting messages from geddit/controller.py
    1505 extracting messages from geddit/form.py
    1506 extracting messages from geddit/model.py
    1507 extracting messages from geddit/translator.py
    1508 extracting messages from geddit/lib/__init__.py
    1509 extracting messages from geddit/lib/ajax.py
    1510 extracting messages from geddit/lib/template.py
    1511 extracting messages from geddit/templates/_comment.html
    1512 extracting messages from geddit/templates/_form.html
    1513 extracting messages from geddit/templates/comment.html
    1514 extracting messages from geddit/templates/index.html
    1515 extracting messages from geddit/templates/info.html
    1516 extracting messages from geddit/templates/layout.html
    1517 extracting messages from geddit/templates/submit.html
    1518 writing PO template file to geddit/locale/geddit.pot
    1519 }}}
    1520 
    1521 Now let's create the English catalog which normally isn't translated:
    1522 {{{
    1523 pybabel init -D geddit -i geddit/locale/geddit.pot -d geddit/locale/ -l en
    1524 }}}
    1525 
    1526 And, since I'm Portuguese, we'll create a Portuguese catalog to serve as an example:
    1527 {{{
    1528 pybabel init -D geddit -i geddit/locale/geddit.pot -d geddit/locale/ -l pt_PT
    1529 }}}
    1530 On this step you can create a catalog in your mother language if not english so that you can see Geddit translated.
    1531 
    1532 Edit the contents of the resulting `geddit.po` for the locale you created, translate it, save and exit.
    1533 
    1534 Next step will involve compiling these catalogs so that they can be used by python's gettext module:
    1535 {{{
    1536 pybabel compile -D geddit -d geddit/locale/ -f --statistics
    1537 }}}
    1538 
    1539 Now, our Geddit application needs to use and know how to use these translated catalogs.
    1540 
    1541 Let's modify `geddit/controller.py` with(this is a diff):
    1542 {{{
    1543 #!diff
    1544 Index: geddit/controller.py
    1545 ===================================================================
    1546 --- geddit/controller.py        (revision 766)
    1547 +++ geddit/controller.py        (working copy)
    1548 @@ -92,8 +92,40 @@
    1549              links = sorted(self.data.values(), key=operator.attrgetter('time'))
    1550              return template.render(links=links)
    1551 
    1552 +    @cherrypy.expose
    1553 +    def set_lang(self, language):
    1554 +       import gettext
    1555 +       import formencode
    1556 +       import __builtin__
    1557 +       locale_dir = os.path.join(os.path.dirname(__file__), 'locale')
    1558 +       domain = 'geddit'
    1559 +       codeset= 'utf-8'
    1560 +
    1561 +       gettext.bindtextdomain(domain, locale_dir)
    1562 +       gettext.textdomain(domain)
    1563 +
    1564 +       try:
    1565 +            translator = gettext.translation(domain,
    1566 +                                         locale_dir,
    1567 +                                         languages=[language],
    1568 +                                         codeset=codeset)
    1569 +       except IOError, error:
    1570 +            language=['en']
    1571 +            translator = gettext.translation(domain,
    1572 +                                         locale_dir,
    1573 +                                         languages=language,
    1574 +                                         codeset=codeset)
    1575 +       formencode.api.set_stdtranslation(languages=[language])
    1576 +       __builtin__._ = translator.ugettext
    1577 +       raise cherrypy.HTTPRedirect('/')
    1578 +
    1579 +
    1580 
    1581  def main(filename):
    1582 +    import __builtin__
    1583 +    from gettext import NullTranslations
    1584 +
    1585 +    __builtin__._ = NullTranslations().ugettext
    1586      # load data from the pickle file, or initialize it to an empty list
    1587      if os.path.exists(filename):
    1588          fileobj = open(filename, 'rb')
    1589 }}}
    1590 
    1591 Our `geddit/lib/template.py` with(also diff):
    1592 {{{
    1593 #!diff
    1594 Index: geddit/lib/template.py
    1595 ===================================================================
    1596 --- geddit/lib/template.py      (revision 766)
    1597 +++ geddit/lib/template.py      (working copy)
    1598 @@ -4,6 +4,7 @@
    1599  from genshi.core import Stream
    1600  from genshi.output import encode, get_serializer
    1601  from genshi.template import Context, TemplateLoader
    1602 +from genshi.filters import Translator
    1603 
    1604  from geddit.lib import ajax
    1605 
    1606 @@ -42,6 +43,7 @@
    1607          template = loader.load(args[0])
    1608      else:
    1609          template = cherrypy.thread_data.template
    1610 +    template.filters.insert(0, Translator(_))
    1611      ctxt = Context(url=cherrypy.url)
    1612      ctxt.push(kwargs)
    1613      return template.generate(ctxt)
    1614 }}}
    1615 
    1616 And finaly our `geddit/templates/layout.html` with(also diff):
    1617 {{{
    1618 #!diff
    1619 Index: geddit/templates/layout.html
    1620 ===================================================================
    1621 --- geddit/templates/layout.html        (revision 766)
    1622 +++ geddit/templates/layout.html        (working copy)
    1623 @@ -19,6 +19,16 @@
    1624          <a href="/"><img src="${url('/media/logo.gif')}" width="201" height="79" alt="geddit?" /></a>
    1625        </div>
    1626        <div id="content">
    1627 +        <form method="post" id="lang_choose" name="lang_choose" action="${url('/set_lang')}">
    1628 +        <label for="language">Language:</label>
    1629 +        <select id="language" name="language" onChange="$('#lang_choose').submit()">
    1630 +          <option value="en">English</option>
    1631 +          <option value="pt_PT">Portuguese</option>
    1632 +        </select>
    1633 +        </form>
    1634 +        <noscript>
    1635 +          <input type="submit" name="submit" value="Update"/>
    1636 +        </noscript>
    1637          ${select('*|text()')}
    1638        </div>
    1639        <div id="footer">
    1640 }}}
    1641 
    1642 This will allow the user to select the language.
    1643 [[Image(tutorial07.png)]]
    1644 
    1645 And that wraps it up!
    1646 
    16471475== Summary ==
    16481476