Edgewall Software

Ticket #129: i18n_directives_full.patch

File i18n_directives_full.patch, 74.8 KB (added by palgarvio, 5 months ago)
  • genshi/filters/tests/i18n.py

     
    1313 
    1414from datetime import datetime 
    1515import doctest 
    16 from gettext import NullTranslations 
     16from gettext import NullTranslations, c2py 
    1717from StringIO import StringIO 
    1818import unittest 
    1919 
    2020from genshi.core import Attrs 
    2121from genshi.template import MarkupTemplate 
    22 from genshi.filters.i18n import Translator, extract 
     22from genshi.filters.i18n import Translator, extract, setup_i18n 
    2323from genshi.input import HTML 
    2424 
    2525 
    2626class DummyTranslations(NullTranslations): 
     27    _domains = {} 
    2728 
    28     def __init__(self, catalog): 
     29    def __init__(self, catalog=()): 
    2930        NullTranslations.__init__(self) 
    30         self._catalog = catalog 
     31        self._catalog = catalog or {} 
     32        self.plural = c2py('(n != 1)') 
     33         
     34    def add_domain(self, domain, catalog): 
     35        translation = DummyTranslations(catalog) 
     36        translation.add_fallback(self) 
     37        self._domains[domain] = translation 
     38         
     39    def _domain_call(self, func, domain, *args, **kwargs): 
     40        return getattr(self._domains.get(domain, self), func)(*args, **kwargs) 
    3141 
    3242    def ugettext(self, message): 
    3343        missing = object() 
     
    3747                return self._fallback.ugettext(message) 
    3848            return unicode(message) 
    3949        return tmsg 
     50     
     51    def dugettext(self, domain, message): 
     52        return self._domain_call('ugettext', domain, message) 
     53     
     54    def ungettext(self, msgid1, msgid2, n): 
     55        try: 
     56            return self._catalog[(msgid1, self.plural(n))] 
     57        except KeyError: 
     58            if self._fallback: 
     59                return self._fallback.ngettext(msgid1, msgid2, n) 
     60            if n == 1: 
     61                return msgid1 
     62            else: 
     63                return msgid2 
     64             
     65    def dungettext(self, domain, singular, plural, numeral): 
     66        return self._domain_call('ungettext', domain, singular, plural, numeral) 
    4067 
    4168 
    4269class TranslatorTestCase(unittest.TestCase): 
     
    162189          </p> 
    163190        </html>""") 
    164191        translator = Translator() 
     192        tmpl.add_directives(Translator.NAMESPACE, translator) 
    165193        messages = list(translator.extract(tmpl.stream)) 
    166194        self.assertEqual(1, len(messages)) 
    167195        self.assertEqual('Please see [1:Help] for details.', messages[0][2]) 
     
    175203        </html>""") 
    176204        gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]." 
    177205        translator = Translator(gettext) 
    178         tmpl.filters.insert(0, translator) 
    179         tmpl.add_directives(Translator.NAMESPACE, translator) 
     206        setup_i18n(tmpl, translator) 
    180207        self.assertEqual("""<html> 
    181208          <p>Für Details siehe bitte <a href="help.html">Hilfe</a>.</p> 
    182209        </html>""", tmpl.generate().render()) 
     
    189216          </p> 
    190217        </html>""") 
    191218        translator = Translator() 
     219        tmpl.add_directives(Translator.NAMESPACE, translator) 
    192220        messages = list(translator.extract(tmpl.stream)) 
    193221        self.assertEqual(1, len(messages)) 
    194222        self.assertEqual('Please see [1:[2:Help] page] for details.', 
     
    203231        </html>""") 
    204232        gettext = lambda s: u"Für Details siehe bitte [1:[2:Hilfeseite]]." 
    205233        translator = Translator(gettext) 
    206         tmpl.filters.insert(0, translator) 
    207         tmpl.add_directives(Translator.NAMESPACE, translator) 
     234        setup_i18n(tmpl, translator) 
    208235        self.assertEqual("""<html> 
    209236          <p>Für Details siehe bitte <a href="help.html"><em>Hilfeseite</em></a>.</p> 
    210237        </html>""", tmpl.generate().render()) 
     
    217244          </p> 
    218245        </html>""") 
    219246        translator = Translator() 
     247        tmpl.add_directives(Translator.NAMESPACE, translator) 
    220248        messages = list(translator.extract(tmpl.stream)) 
    221249        self.assertEqual(1, len(messages)) 
    222250        self.assertEqual('Show me [1:] entries per page.', messages[0][2]) 
     
    230258        </html>""") 
    231259        gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." 
    232260        translator = Translator(gettext) 
    233         tmpl.filters.insert(0, translator) 
    234         tmpl.add_directives(Translator.NAMESPACE, translator) 
     261        setup_i18n(tmpl, translator) 
    235262        self.assertEqual("""<html> 
    236263          <p><input type="text" name="num"/> Einträge pro Seite anzeigen.</p> 
    237264        </html>""", tmpl.generate().render()) 
     
    244271          </p> 
    245272        </html>""") 
    246273        translator = Translator() 
     274        tmpl.add_directives(Translator.NAMESPACE, translator) 
    247275        messages = list(translator.extract(tmpl.stream)) 
    248276        self.assertEqual(1, len(messages)) 
    249277        self.assertEqual('Please see [1:Help] for [2:details].', messages[0][2]) 
     
    257285        </html>""") 
    258286        gettext = lambda s: u"Für [2:Details] siehe bitte [1:Hilfe]." 
    259287        translator = Translator(gettext) 
    260         tmpl.filters.insert(0, translator) 
    261         tmpl.add_directives(Translator.NAMESPACE, translator) 
     288        setup_i18n(tmpl, translator) 
    262289        self.assertEqual("""<html> 
    263290          <p>Für <em>Details</em> siehe bitte <a href="help.html">Hilfe</a>.</p> 
    264291        </html>""", tmpl.generate().render()) 
     
    271298          </p> 
    272299        </html>""") 
    273300        translator = Translator() 
     301        tmpl.add_directives(Translator.NAMESPACE, translator) 
    274302        messages = list(translator.extract(tmpl.stream)) 
    275303        self.assertEqual(1, len(messages)) 
    276304        self.assertEqual('Show me [1:] entries per page, starting at page [2:].', 
     
    285313        </html>""") 
    286314        gettext = lambda s: u"[1:] Einträge pro Seite, beginnend auf Seite [2:]." 
    287315        translator = Translator(gettext) 
    288         tmpl.filters.insert(0, translator) 
    289         tmpl.add_directives(Translator.NAMESPACE, translator) 
     316        setup_i18n(tmpl, translator) 
    290317        self.assertEqual("""<html> 
    291318          <p><input type="text" name="num"/> Eintr\xc3\xa4ge pro Seite, beginnend auf Seite <input type="text" name="num"/>.</p> 
    292319        </html>""", tmpl.generate().render()) 
     
    299326          </p> 
    300327        </html>""") 
    301328        translator = Translator() 
     329        tmpl.add_directives(Translator.NAMESPACE, translator) 
    302330        messages = list(translator.extract(tmpl.stream)) 
    303331        self.assertEqual(1, len(messages)) 
    304332        self.assertEqual('Hello, %(name)s!', messages[0][2]) 
     
    312340        </html>""") 
    313341        gettext = lambda s: u"Hallo, %(name)s!" 
    314342        translator = Translator(gettext) 
    315         tmpl.filters.insert(0, translator) 
    316         tmpl.add_directives(Translator.NAMESPACE, translator) 
     343        setup_i18n(tmpl, translator) 
    317344        self.assertEqual("""<html> 
    318345          <p>Hallo, Jim!</p> 
    319346        </html>""", tmpl.generate(user=dict(name='Jim')).render()) 
     
    327354        </html>""") 
    328355        gettext = lambda s: u"%(name)s, sei gegrüßt!" 
    329356        translator = Translator(gettext) 
    330         tmpl.filters.insert(0, translator) 
    331         tmpl.add_directives(Translator.NAMESPACE, translator) 
     357        setup_i18n(tmpl, translator) 
    332358        self.assertEqual("""<html> 
    333359          <p>Jim, sei gegrüßt!</p> 
    334360        </html>""", tmpl.generate(user=dict(name='Jim')).render()) 
     
    342368        </html>""") 
    343369        gettext = lambda s: u"Sei gegrüßt, [1:Alter]!" 
    344370        translator = Translator(gettext) 
    345         tmpl.filters.insert(0, translator) 
    346         tmpl.add_directives(Translator.NAMESPACE, translator) 
     371        setup_i18n(tmpl, translator) 
    347372        self.assertEqual("""<html> 
    348373          <p>Sei gegrüßt, <a href="#42">Alter</a>!</p> 
    349374        </html>""", tmpl.generate(anchor='42').render()) 
     
    356381          </p> 
    357382        </html>""") 
    358383        translator = Translator() 
     384        tmpl.add_directives(Translator.NAMESPACE, translator) 
    359385        messages = list(translator.extract(tmpl.stream)) 
    360386        self.assertEqual(1, len(messages)) 
    361387        self.assertEqual('Posted by %(name)s at %(time)s', messages[0][2]) 
     
    369395        </html>""") 
    370396        gettext = lambda s: u"%(name)s schrieb dies um %(time)s" 
    371397        translator = Translator(gettext) 
    372         tmpl.filters.insert(0, translator) 
    373         tmpl.add_directives(Translator.NAMESPACE, translator) 
     398        setup_i18n(tmpl, translator) 
    374399        entry = { 
    375400            'author': 'Jim', 
    376401            'time': datetime(2008, 4, 1, 14, 30) 
     
    387412          </p> 
    388413        </html>""") 
    389414        translator = Translator() 
     415        tmpl.add_directives(Translator.NAMESPACE, translator) 
    390416        messages = list(translator.extract(tmpl.stream)) 
    391417        self.assertEqual(1, len(messages)) 
    392418        self.assertEqual('Show me [1:] entries per page.', messages[0][2]) 
    393419 
    394     # FIXME: this currently fails :-/ 
    395 #    def test_translate_i18n_msg_with_directive(self): 
    396 #        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
    397 #            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
    398 #          <p i18n:msg=""> 
    399 #            Show me <input type="text" name="num" py:attrs="{'value': x}" /> entries per page. 
    400 #          </p> 
    401 #        </html>""") 
    402 #        gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." 
    403 #        tmpl.filters.insert(0, Translator(gettext)) 
    404 #        self.assertEqual("""<html> 
    405 #          <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> 
    406 #        </html>""", tmpl.generate().render()) 
     420    def test_translate_i18n_msg_with_directive(self): 
     421        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     422            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     423          <p i18n:msg=""> 
     424            Show me <input type="text" name="num" py:attrs="{'value': 'x'}" /> entries per page. 
     425          </p> 
     426        </html>""") 
     427        gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." 
     428        translator = Translator(gettext) 
     429        setup_i18n(tmpl, translator) 
     430        self.assertEqual("""<html> 
     431          <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> 
     432        </html>""", tmpl.generate().render()) 
    407433 
    408434    def test_extract_i18n_msg_with_comment(self): 
    409435        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
    410436            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     437          <p i18n:comment="As in foo bar" i18n:msg="">Foo</p> 
     438        </html>""") 
     439        translator = Translator() 
     440        tmpl.add_directives(Translator.NAMESPACE, translator) 
     441        messages = list(translator.extract(tmpl.stream)) 
     442        self.assertEqual(1, len(messages)) 
     443        self.assertEqual((3, None, u'Foo', ['As in foo bar']), messages[0]) 
     444        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     445            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
    411446          <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> 
    412447        </html>""") 
    413448        translator = Translator() 
     449        tmpl.add_directives(Translator.NAMESPACE, translator) 
    414450        messages = list(translator.extract(tmpl.stream)) 
    415451        self.assertEqual(1, len(messages)) 
    416452        self.assertEqual((3, None, u'Foo', ['As in foo bar']), messages[0]) 
     
    422458        </html>""") 
    423459        gettext = lambda s: u"Voh" 
    424460        translator = Translator(gettext) 
    425         tmpl.filters.insert(0, translator) 
    426         tmpl.add_directives(Translator.NAMESPACE, translator) 
     461        setup_i18n(tmpl, translator) 
    427462        self.assertEqual("""<html> 
    428463          <p>Voh</p> 
    429464        </html>""", tmpl.generate().render()) 
     
    461496          <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> 
    462497        </html>""") 
    463498        translator = Translator(DummyTranslations({'Foo': 'Voh'})) 
    464         tmpl.filters.insert(0, translator) 
    465         tmpl.add_directives(Translator.NAMESPACE, translator) 
     499        setup_i18n(tmpl, translator) 
     500        self.assertEqual("""<html> 
     501          <p>Voh</p> 
     502        </html>""", tmpl.generate().render()) 
     503         
     504    def test_translate_i18n_domain_with_msg_directives(self): 
     505        #"""translate with i18n:domain and nested i18n:msg directives """ 
     506 
     507        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     508            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     509          <div i18n:domain="foo"> 
     510            <p i18n:msg="">FooBar</p> 
     511            <p i18n:msg="">Bar</p> 
     512          </div> 
     513        </html>""") 
     514        translations = DummyTranslations({'Bar': 'Voh'}) 
     515        translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) 
     516        translator = Translator(translations) 
     517        setup_i18n(tmpl, translator) 
     518        self.assertEqual("""<html> 
     519          <div> 
     520            <p>BarFoo</p> 
     521            <p>PT_Foo</p> 
     522          </div> 
     523        </html>""", tmpl.generate().render()) 
     524         
     525    def test_translate_i18n_domain_with_inline_directives(self): 
     526        #"""translate with inlined i18n:domain and i18n:msg directives""" 
     527        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     528            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     529          <p i18n:msg="" i18n:domain="foo">FooBar</p> 
     530        </html>""") 
     531        translations = DummyTranslations({'Bar': 'Voh'}) 
     532        translations.add_domain('foo', {'FooBar': 'BarFoo'}) 
     533        translator = Translator(translations) 
     534        setup_i18n(tmpl, translator) 
     535        self.assertEqual("""<html> 
     536          <p>BarFoo</p> 
     537        </html>""", tmpl.generate().render()) 
     538         
     539    def test_translate_i18n_domain_without_msg_directives(self): 
     540        #"""translate domain call without i18n:msg directives still uses current domain""" 
     541         
     542        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     543            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     544          <p i18n:msg="">Bar</p> 
     545          <div i18n:domain="foo"> 
     546            <p i18n:msg="">FooBar</p> 
     547            <p i18n:msg="">Bar</p>             
     548            <p>Bar</p> 
     549          </div>           
     550          <p>Bar</p> 
     551        </html>""") 
     552        translations = DummyTranslations({'Bar': 'Voh'}) 
     553        translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) 
     554        translator = Translator(translations) 
     555        setup_i18n(tmpl, translator) 
     556        self.assertEqual("""<html> 
     557          <p>Voh</p> 
     558          <div> 
     559            <p>BarFoo</p> 
     560            <p>PT_Foo</p> 
     561            <p>PT_Foo</p> 
     562          </div> 
     563          <p>Voh</p> 
     564        </html>""", tmpl.generate().render()) 
     565         
     566    def test_translate_i18n_domain_as_directive_not_attribute(self): 
     567        #"""translate with domain as directive""" 
     568         
     569        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     570            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     571        <i18n:domain name="foo"> 
     572          <p i18n:msg="">FooBar</p> 
     573          <p i18n:msg="">Bar</p> 
     574          <p>Bar</p> 
     575        </i18n:domain> 
     576          <p>Bar</p> 
     577        </html>""") 
     578        translations = DummyTranslations({'Bar': 'Voh'}) 
     579        translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) 
     580        translator = Translator(translations) 
     581        setup_i18n(tmpl, translator) 
     582        self.assertEqual("""<html> 
     583          <p>BarFoo</p> 
     584          <p>PT_Foo</p> 
     585          <p>PT_Foo</p> 
     586          <p>Voh</p> 
     587        </html>""", tmpl.generate().render()) 
     588         
     589    def test_translate_i18n_domain_nested_directives(self): 
     590        #"""translate with nested i18n:domain directives""" 
     591         
     592        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     593            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     594          <p i18n:msg="">Bar</p> 
     595          <div i18n:domain="foo"> 
     596            <p i18n:msg="">FooBar</p> 
     597            <p i18n:domain="bar" i18n:msg="">Bar</p>             
     598            <p>Bar</p> 
     599          </div>           
     600          <p>Bar</p> 
     601        </html>""") 
     602        translations = DummyTranslations({'Bar': 'Voh'}) 
     603        translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'}) 
     604        translations.add_domain('bar', {'Bar': 'bar_Bar'}) 
     605        translator = Translator(translations) 
     606        setup_i18n(tmpl, translator) 
     607        self.assertEqual("""<html> 
     608          <p>Voh</p> 
     609          <div> 
     610            <p>BarFoo</p> 
     611            <p>bar_Bar</p> 
     612            <p>foo_Bar</p> 
     613          </div> 
     614          <p>Voh</p> 
     615        </html>""", tmpl.generate().render()) 
     616         
     617    def test_translate_i18n_domain_with_empty_nested_domain_directive(self): 
     618        #"""translate with empty nested i18n:domain directive does not use dngettext""" 
     619         
     620        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     621            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     622          <p i18n:msg="">Bar</p> 
     623          <div i18n:domain="foo"> 
     624            <p i18n:msg="">FooBar</p> 
     625            <p i18n:domain="" i18n:msg="">Bar</p>             
     626            <p>Bar</p> 
     627          </div>           
     628          <p>Bar</p> 
     629        </html>""") 
     630        translations = DummyTranslations({'Bar': 'Voh'}) 
     631        translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'}) 
     632        translations.add_domain('bar', {'Bar': 'bar_Bar'}) 
     633        translator = Translator(translations) 
     634        setup_i18n(tmpl, translator) 
    466635        self.assertEqual("""<html> 
    467636          <p>Voh</p> 
     637          <div> 
     638            <p>BarFoo</p> 
     639            <p>Voh</p> 
     640            <p>foo_Bar</p> 
     641          </div> 
     642          <p>Voh</p> 
    468643        </html>""", tmpl.generate().render()) 
    469644 
     645    def test_translate_i18n_choose_as_attribute(self): 
     646        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     647            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     648          <div i18n:choose="one"> 
     649            <p i18n:singular="">FooBar</p> 
     650            <p i18n:plural="">FooBars</p> 
     651          </div> 
     652          <div i18n:choose="two"> 
     653            <p i18n:singular="">FooBar</p> 
     654            <p i18n:plural="">FooBars</p> 
     655          </div> 
     656        </html>""") 
     657        translations = DummyTranslations() 
     658        translator = Translator(translations) 
     659        setup_i18n(tmpl, translator) 
     660        self.assertEqual("""<html> 
     661          <div> 
     662            <p>FooBar</p> 
     663          </div> 
     664          <div> 
     665            <p>FooBars</p> 
     666          </div> 
     667        </html>""", tmpl.generate(one=1, two=2).render()) 
     668         
     669    def test_translate_i18n_choose_as_directive(self): 
     670        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     671            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     672        <i18n:choose numeral="two"> 
     673          <p i18n:singular="">FooBar</p> 
     674          <p i18n:plural="">FooBars</p> 
     675        </i18n:choose> 
     676        <i18n:choose numeral="one"> 
     677          <p i18n:singular="">FooBar</p> 
     678          <p i18n:plural="">FooBars</p> 
     679        </i18n:choose> 
     680        </html>""") 
     681        translations = DummyTranslations() 
     682        translator = Translator(translations) 
     683        setup_i18n(tmpl, translator) 
     684        self.assertEqual("""<html> 
     685          <p>FooBars</p> 
     686          <p>FooBar</p> 
     687        </html>""", tmpl.generate(one=1, two=2).render()) 
     688         
     689    def test_translate_i18n_choose_as_attribute_with_params(self): 
     690        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     691            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     692          <div i18n:choose="two; fname, lname"> 
     693            <p i18n:singular="">Foo $fname $lname</p> 
     694            <p i18n:plural="">Foos $fname $lname</p> 
     695          </div> 
     696        </html>""") 
     697        translations = DummyTranslations({ 
     698            ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', 
     699            ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', 
     700                 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', 
     701                'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', 
     702        }) 
     703        translator = Translator(translations) 
     704        setup_i18n(tmpl, translator) 
     705        self.assertEqual("""<html> 
     706          <div> 
     707            <p>Vohs John Doe</p> 
     708          </div> 
     709        </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) 
     710         
     711    def test_translate_i18n_choose_as_attribute_with_params_and_domain_as_param(self): 
     712        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     713            xmlns:i18n="http://genshi.edgewall.org/i18n" 
     714            i18n:domain="foo"> 
     715          <div i18n:choose="two; fname, lname"> 
     716            <p i18n:singular="">Foo $fname $lname</p> 
     717            <p i18n:plural="">Foos $fname $lname</p> 
     718          </div> 
     719        </html>""") 
     720        translations = DummyTranslations() 
     721        translations.add_domain('foo', { 
     722            ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', 
     723            ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', 
     724                 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', 
     725                'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', 
     726        }) 
     727        translator = Translator(translations) 
     728        setup_i18n(tmpl, translator) 
     729        self.assertEqual("""<html> 
     730          <div> 
     731            <p>Vohs John Doe</p> 
     732          </div> 
     733        </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) 
     734         
     735    def test_translate_i18n_choose_as_directive_with_params(self): 
     736        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     737            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     738        <i18n:choose numeral="two" params="fname, lname"> 
     739          <p i18n:singular="">Foo ${fname} ${lname}</p> 
     740          <p i18n:plural="">Foos ${fname} ${lname}</p> 
     741        </i18n:choose> 
     742        <i18n:choose numeral="one" params="fname, lname"> 
     743          <p i18n:singular="">Foo ${fname} ${lname}</p> 
     744          <p i18n:plural="">Foos ${fname} ${lname}</p> 
     745        </i18n:choose> 
     746        </html>""") 
     747        translations = DummyTranslations({ 
     748            ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', 
     749            ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', 
     750                 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', 
     751                'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', 
     752        }) 
     753        translator = Translator(translations) 
     754        setup_i18n(tmpl, translator) 
     755        self.assertEqual("""<html> 
     756          <p>Vohs John Doe</p> 
     757          <p>Voh John Doe</p> 
     758        </html>""", tmpl.generate(one=1, two=2, 
     759                                  fname='John', lname='Doe').render()) 
     760         
     761    def test_translate_i18n_choose_as_directive_with_params_and_domain_as_directive(self): 
     762        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     763            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     764        <i18n:domain name="foo"> 
     765        <i18n:choose numeral="two" params="fname, lname"> 
     766          <p i18n:singular="">Foo ${fname} ${lname}</p> 
     767          <p i18n:plural="">Foos ${fname} ${lname}</p> 
     768        </i18n:choose> 
     769        </i18n:domain> 
     770        <i18n:choose numeral="one" params="fname, lname"> 
     771          <p i18n:singular="">Foo ${fname} ${lname}</p> 
     772          <p i18n:plural="">Foos ${fname} ${lname}</p> 
     773        </i18n:choose> 
     774        </html>""") 
     775        translations = DummyTranslations() 
     776        translations.add_domain('foo', { 
     777            ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', 
     778            ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', 
     779                 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', 
     780                'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', 
     781        }) 
     782        translator = Translator(translations) 
     783        setup_i18n(tmpl, translator) 
     784        self.assertEqual("""<html> 
     785          <p>Vohs John Doe</p> 
     786          <p>Foo John Doe</p> 
     787        </html>""", tmpl.generate(one=1, two=2, 
     788                                  fname='John', lname='Doe').render()) 
     789 
     790    def test_extract_i18n_choose_as_attribute(self): 
     791        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     792            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     793          <div i18n:choose="one"> 
     794            <p i18n:singular="">FooBar</p> 
     795            <p i18n:plural="">FooBars</p> 
     796          </div> 
     797          <div i18n:choose="two"> 
     798            <p i18n:singular="">FooBar</p> 
     799            <p i18n:plural="">FooBars</p> 
     800          </div> 
     801        </html>""") 
     802        translator = Translator() 
     803        tmpl.add_directives(Translator.NAMESPACE, translator) 
     804        messages = list(translator.extract(tmpl.stream)) 
     805        self.assertEqual(2, len(messages)) 
     806        self.assertEqual((3, 'ngettext', (u'FooBar', u'FooBars'), []), messages[0]) 
     807        self.assertEqual((7, 'ngettext', (u'FooBar', u'FooBars'), []), messages[1]) 
     808         
     809    def test_extract_i18n_choose_as_directive(self): 
     810        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     811            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     812        <i18n:choose numeral="two"> 
     813          <p i18n:singular="">FooBar</p> 
     814          <p i18n:plural="">FooBars</p> 
     815        </i18n:choose> 
     816        <i18n:choose numeral="one"> 
     817          <p i18n:singular="">FooBar</p> 
     818          <p i18n:plural="">FooBars</p> 
     819        </i18n:choose> 
     820        </html>""") 
     821        translator = Translator() 
     822        tmpl.add_directives(Translator.NAMESPACE, translator) 
     823        messages = list(translator.extract(tmpl.stream)) 
     824        self.assertEqual(2, len(messages)) 
     825        self.assertEqual((3, 'ngettext', (u'FooBar', u'FooBars'), []), messages[0]) 
     826        self.assertEqual((7, 'ngettext', (u'FooBar', u'FooBars'), []), messages[1]) 
     827         
     828    def test_extract_i18n_choose_as_attribute_with_params(self): 
     829        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     830            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     831          <div i18n:choose="two; fname, lname"> 
     832            <p i18n:singular="">Foo $fname $lname</p> 
     833            <p i18n:plural="">Foos $fname $lname</p> 
     834          </div> 
     835        </html>""") 
     836        translator = Translator() 
     837        tmpl.add_directives(Translator.NAMESPACE, translator) 
     838        messages = list(translator.extract(tmpl.stream)) 
     839        self.assertEqual(1, len(messages)) 
     840        self.assertEqual((3, 'ngettext', (u'Foo %(fname)s %(lname)s', 
     841                                          u'Foos %(fname)s %(lname)s'), []), 
     842                         messages[0]) 
     843 
     844    def test_extract_i18n_choose_as_attribute_with_params_and_domain_as_param(self): 
     845        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     846            xmlns:i18n="http://genshi.edgewall.org/i18n" 
     847            i18n:domain="foo"> 
     848          <div i18n:choose="two; fname, lname"> 
     849            <p i18n:singular="">Foo $fname $lname</p> 
     850            <p i18n:plural="">Foos $fname $lname</p> 
     851          </div> 
     852        </html>""") 
     853        translator = Translator() 
     854        tmpl.add_directives(Translator.NAMESPACE, translator) 
     855        messages = list(translator.extract(tmpl.stream)) 
     856        self.assertEqual(1, len(messages)) 
     857        self.assertEqual((4, 'ngettext', (u'Foo %(fname)s %(lname)s', 
     858                                          u'Foos %(fname)s %(lname)s'), []), 
     859                         messages[0]) 
     860 
     861    def test_extract_i18n_choose_as_directive_with_params(self): 
     862        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 
     863            xmlns:i18n="http://genshi.edgewall.org/i18n"> 
     864        <i18n:choose numeral="two" params="fname, lname"> 
     865          <p i18n:singular="">Foo ${fname} ${lname}</p> 
     866          <p i18n:plural="">Foos ${fname} ${lname}</p> 
     867        </i18n:choose> 
     868        <i18n:choose numeral="one" params="fname, lname"> 
     869          <p i18n:singular="">Foo ${fname} ${lname}</p> 
     870          <p i18n:plural="">Foos ${fname} ${lname}</p> 
     871        </i18n:choose> 
     872        </html>""") 
     873        translator = Translator() 
     874        tmpl.add_directives(