Mercurial > genshi > mirror
diff genshi/filters/tests/i18n.py @ 849:878c4313c7d5 trunk
Merged advanced-i18n branch back into trunk.
author | cmlenz |
---|---|
date | Tue, 10 Nov 2009 20:54:06 +0000 |
parents | da90cee22560 |
children | e8f596c726c4 |
line wrap: on
line diff
--- a/genshi/filters/tests/i18n.py +++ b/genshi/filters/tests/i18n.py @@ -18,16 +18,26 @@ import unittest from genshi.core import Attrs -from genshi.template import MarkupTemplate +from genshi.template import MarkupTemplate, Context from genshi.filters.i18n import Translator, extract from genshi.input import HTML class DummyTranslations(NullTranslations): + _domains = {} - def __init__(self, catalog): + def __init__(self, catalog=()): NullTranslations.__init__(self) - self._catalog = catalog + self._catalog = catalog or {} + self.plural = lambda n: n != 1 + + def add_domain(self, domain, catalog): + translation = DummyTranslations(catalog) + translation.add_fallback(self) + self._domains[domain] = translation + + def _domain_call(self, func, domain, *args, **kwargs): + return getattr(self._domains.get(domain, self), func)(*args, **kwargs) def ugettext(self, message): missing = object() @@ -38,6 +48,23 @@ return unicode(message) return tmsg + def dugettext(self, domain, message): + return self._domain_call('ugettext', domain, message) + + def ungettext(self, msgid1, msgid2, n): + try: + return self._catalog[(msgid1, self.plural(n))] + except KeyError: + if self._fallback: + return self._fallback.ngettext(msgid1, msgid2, n) + if n == 1: + return msgid1 + else: + return msgid2 + + def dungettext(self, domain, singular, plural, numeral): + return self._domain_call('ungettext', domain, singular, plural, numeral) + class TranslatorTestCase(unittest.TestCase): @@ -162,6 +189,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Please see [1:Help] for details.', messages[0][2]) @@ -175,8 +203,7 @@ </html>""") gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]." translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Für Details siehe bitte <a href="help.html">Hilfe</a>.</p> </html>""", tmpl.generate().render()) @@ -189,6 +216,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Please see [1:[2:Help] page] for details.', @@ -203,12 +231,39 @@ </html>""") gettext = lambda s: u"Für Details siehe bitte [1:[2:Hilfeseite]]." translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Für Details siehe bitte <a href="help.html"><em>Hilfeseite</em></a>.</p> </html>""", tmpl.generate().render()) + def test_extract_i18n_msg_label_with_nested_input(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:msg=""> + <label><input type="text" size="3" name="daysback" value="30" /> days back</label> + </div> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual('[1:[2:] days back]', + messages[0][2]) + + def test_translate_i18n_msg_label_with_nested_input(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:msg=""> + <label><input type="text" size="3" name="daysback" value="30" /> foo bar</label> + </div> + </html>""") + gettext = lambda s: "[1:[2:] foo bar]" + translator = Translator(gettext) + translator.setup(tmpl) + self.assertEqual("""<html> + <div><label><input type="text" size="3" name="daysback" value="30"/> foo bar</label></div> + </html>""", tmpl.generate().render()) + def test_extract_i18n_msg_empty(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" xmlns:i18n="http://genshi.edgewall.org/i18n"> @@ -217,6 +272,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Show me [1:] entries per page.', messages[0][2]) @@ -230,8 +286,7 @@ </html>""") gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p><input type="text" name="num"/> Einträge pro Seite anzeigen.</p> </html>""", tmpl.generate().render()) @@ -244,6 +299,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Please see [1:Help] for [2:details].', messages[0][2]) @@ -257,8 +313,7 @@ </html>""") gettext = lambda s: u"Für [2:Details] siehe bitte [1:Hilfe]." translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Für <em>Details</em> siehe bitte <a href="help.html">Hilfe</a>.</p> </html>""", tmpl.generate().render()) @@ -271,6 +326,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Show me [1:] entries per page, starting at page [2:].', @@ -285,8 +341,7 @@ </html>""") gettext = lambda s: u"[1:] Einträge pro Seite, beginnend auf Seite [2:]." translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p><input type="text" name="num"/> Eintr\xc3\xa4ge pro Seite, beginnend auf Seite <input type="text" name="num"/>.</p> </html>""", tmpl.generate().render()) @@ -299,6 +354,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Hello, %(name)s!', messages[0][2]) @@ -312,8 +368,7 @@ </html>""") gettext = lambda s: u"Hallo, %(name)s!" translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Hallo, Jim!</p> </html>""", tmpl.generate(user=dict(name='Jim')).render()) @@ -327,8 +382,7 @@ </html>""") gettext = lambda s: u"%(name)s, sei gegrüßt!" translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Jim, sei gegrüßt!</p> </html>""", tmpl.generate(user=dict(name='Jim')).render()) @@ -342,8 +396,7 @@ </html>""") gettext = lambda s: u"Sei gegrüßt, [1:Alter]!" translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Sei gegrüßt, <a href="#42">Alter</a>!</p> </html>""", tmpl.generate(anchor='42').render()) @@ -356,6 +409,7 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Posted by %(name)s at %(time)s', messages[0][2]) @@ -369,8 +423,7 @@ </html>""") gettext = lambda s: u"%(name)s schrieb dies um %(time)s" translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) entry = { 'author': 'Jim', 'time': datetime(2008, 4, 1, 14, 30) @@ -387,30 +440,41 @@ </p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual('Show me [1:] entries per page.', messages[0][2]) - # FIXME: this currently fails :-/ -# def test_translate_i18n_msg_with_directive(self): -# tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" -# xmlns:i18n="http://genshi.edgewall.org/i18n"> -# <p i18n:msg=""> -# Show me <input type="text" name="num" py:attrs="{'value': x}" /> entries per page. -# </p> -# </html>""") -# gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." -# tmpl.filters.insert(0, Translator(gettext)) -# self.assertEqual("""<html> -# <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> -# </html>""", tmpl.generate().render()) + def test_translate_i18n_msg_with_directive(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg=""> + Show me <input type="text" name="num" py:attrs="{'value': 'x'}" /> entries per page. + </p> + </html>""") + gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." + translator = Translator(gettext) + translator.setup(tmpl) + self.assertEqual("""<html> + <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> + </html>""", tmpl.generate().render()) def test_extract_i18n_msg_with_comment(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:comment="As in foo bar" i18n:msg="">Foo</p> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, None, u'Foo', ['As in foo bar']), messages[0]) + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> </html>""") translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((3, None, u'Foo', ['As in foo bar']), messages[0]) @@ -422,8 +486,7 @@ </html>""") gettext = lambda s: u"Voh" translator = Translator(gettext) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Voh</p> </html>""", tmpl.generate().render()) @@ -461,12 +524,908 @@ <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> </html>""") translator = Translator(DummyTranslations({'Foo': 'Voh'})) - tmpl.filters.insert(0, translator) - tmpl.add_directives(Translator.NAMESPACE, translator) + translator.setup(tmpl) self.assertEqual("""<html> <p>Voh</p> </html>""", tmpl.generate().render()) + def test_translate_i18n_msg_and_py_strip_directives(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" py:strip="">Foo</p> + <p py:strip="" i18n:msg="">Foo</p> + </html>""") + translator = Translator(DummyTranslations({'Foo': 'Voh'})) + translator.setup(tmpl) + self.assertEqual("""<html> + Voh + Voh + </html>""", tmpl.generate().render()) + + def test_i18n_msg_ticket_300_extract(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:msg params="date, author"> + Changed ${ '10/12/2008' } ago by ${ 'me, the author' } + </i18n:msg> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual( + (3, None, u'Changed %(date)s ago by %(author)s', []), messages[0] + ) + + def test_i18n_msg_ticket_300_translate(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:msg params="date, author"> + Changed ${ date } ago by ${ author } + </i18n:msg> + </html>""") + translations = DummyTranslations({ + u'Changed %(date)s ago by %(author)s': u'Modificado à %(date)s por %(author)s' + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + Modificado à um dia por Pedro + </html>""", tmpl.generate(date='um dia', author="Pedro").render()) + + + def test_i18n_msg_ticket_251_extract(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg=""><tt><b>Translation[ 0 ]</b>: <em>One coin</em></tt></p> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual( + (3, None, u'[1:[2:Translation\\[\xa00\xa0\\]]: [3:One coin]]', []), messages[0] + ) + + def test_i18n_msg_ticket_251_translate(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg=""><tt><b>Translation[ 0 ]</b>: <em>One coin</em></tt></p> + </html>""") + translations = DummyTranslations({ + u'[1:[2:Translation\\[\xa00\xa0\\]]: [3:One coin]]': + u'[1:[2:Trandução\\[\xa00\xa0\\]]: [3:Uma moeda]]' + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p><tt><b>Trandução[ 0 ]</b>: <em>Uma moeda</em></tt></p> + </html>""", tmpl.generate().render()) + + def test_extract_i18n_msg_with_other_directives_nested(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" py:with="q = quote_plus(message[:80])">Before you do that, though, please first try + <strong><a href="${trac.homepage}search?ticket=yes&noquickjump=1&q=$q">searching</a> + for similar issues</strong>, as it is quite likely that this problem + has been reported before. For questions about installation + and configuration of Trac, please try the + <a href="${trac.homepage}wiki/MailingList">mailing list</a> + instead of filing a ticket. + </p> + </html>""") + translator = Translator() + translator.setup(tmpl) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual( + u'Before you do that, though, please first try\n ' + u'[1:[2:searching]\n for similar issues], as it is ' + u'quite likely that this problem\n has been reported ' + u'before. For questions about installation\n and ' + u'configuration of Trac, please try the\n ' + u'[3:mailing list]\n instead of filing a ticket.', + messages[0][2] + ) + + def test_translate_i18n_msg_with_other_directives_nested(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="">Before you do that, though, please first try + <strong><a href="${trac.homepage}search?ticket=yes&noquickjump=1&q=q">searching</a> + for similar issues</strong>, as it is quite likely that this problem + has been reported before. For questions about installation + and configuration of Trac, please try the + <a href="${trac.homepage}wiki/MailingList">mailing list</a> + instead of filing a ticket. + </p> + </html>""") + translations = DummyTranslations({ + u'Before you do that, though, please first try\n ' + u'[1:[2:searching]\n for similar issues], as it is ' + u'quite likely that this problem\n has been reported ' + u'before. For questions about installation\n and ' + u'configuration of Trac, please try the\n ' + u'[3:mailing list]\n instead of filing a ticket.': + u'Antes de o fazer, porém,\n ' + u'[1:por favor tente [2:procurar]\n por problemas semelhantes], uma vez que ' + u'é muito provável que este problema\n já tenha sido reportado ' + u'anteriormente. Para questões relativas à instalação\n e ' + u'configuração do Trac, por favor tente a\n ' + u'[3:mailing list]\n em vez de criar um assunto.' + }) + translator = Translator(translations) + translator.setup(tmpl) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + ctx = Context() + ctx.push({'trac': {'homepage': 'http://trac.edgewall.org/'}}) + self.assertEqual("""<html> + <p>Antes de o fazer, porém, + <strong>por favor tente <a href="http://trac.edgewall.org/search?ticket=yes&noquickjump=1&q=q">procurar</a> + por problemas semelhantes</strong>, uma vez que é muito provável que este problema + já tenha sido reportado anteriormente. Para questões relativas à instalação + e configuração do Trac, por favor tente a + <a href="http://trac.edgewall.org/wiki/MailingList">mailing list</a> + em vez de criar um assunto.</p> + </html>""", tmpl.generate(ctx).render()) + + def test_i18n_msg_with_other_nested_directives_with_reordered_content(self): + # See: http://genshi.edgewall.org/ticket/300#comment:10 + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p py:if="not editable" class="hint" i18n:msg=""> + <strong>Note:</strong> This repository is defined in + <code><a href="${ 'href.wiki(TracIni)' }">trac.ini</a></code> + and cannot be edited on this page. + </p> + </html>""") + translations = DummyTranslations({ + u'[1:Note:] This repository is defined in\n ' + u'[2:[3:trac.ini]]\n and cannot be edited on this page.': + u'[1:Nota:] Este repositório está definido em \n ' + u'[2:[3:trac.ini]]\n e não pode ser editado nesta página.', + }) + translator = Translator(translations) + translator.setup(tmpl) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual( + u'[1:Note:] This repository is defined in\n ' + u'[2:[3:trac.ini]]\n and cannot be edited on this page.', + messages[0][2] + ) + self.assertEqual("""<html> + <p class="hint"><strong>Nota:</strong> Este repositório está definido em + <code><a href="href.wiki(TracIni)">trac.ini</a></code> + e não pode ser editado nesta página.</p> + </html>""", tmpl.generate(editable=False).render()) + + def test_translate_i18n_domain_with_msg_directives(self): + #"""translate with i18n:domain and nested i18n:msg directives """ + + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:domain="foo"> + <p i18n:msg="">FooBar</p> + <p i18n:msg="">Bar</p> + </div> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <div> + <p>BarFoo</p> + <p>PT_Foo</p> + </div> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_domain_with_inline_directives(self): + #"""translate with inlined i18n:domain and i18n:msg directives""" + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" i18n:domain="foo">FooBar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>BarFoo</p> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_domain_without_msg_directives(self): + #"""translate domain call without i18n:msg directives still uses current domain""" + + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="">Bar</p> + <div i18n:domain="foo"> + <p i18n:msg="">FooBar</p> + <p i18n:msg="">Bar</p> + <p>Bar</p> + </div> + <p>Bar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>Voh</p> + <div> + <p>BarFoo</p> + <p>PT_Foo</p> + <p>PT_Foo</p> + </div> + <p>Voh</p> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_domain_as_directive_not_attribute(self): + #"""translate with domain as directive""" + + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:domain name="foo"> + <p i18n:msg="">FooBar</p> + <p i18n:msg="">Bar</p> + <p>Bar</p> + </i18n:domain> + <p>Bar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>BarFoo</p> + <p>PT_Foo</p> + <p>PT_Foo</p> + <p>Voh</p> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_domain_nested_directives(self): + #"""translate with nested i18n:domain directives""" + + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="">Bar</p> + <div i18n:domain="foo"> + <p i18n:msg="">FooBar</p> + <p i18n:domain="bar" i18n:msg="">Bar</p> + <p>Bar</p> + </div> + <p>Bar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'}) + translations.add_domain('bar', {'Bar': 'bar_Bar'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>Voh</p> + <div> + <p>BarFoo</p> + <p>bar_Bar</p> + <p>foo_Bar</p> + </div> + <p>Voh</p> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_domain_with_empty_nested_domain_directive(self): + #"""translate with empty nested i18n:domain directive does not use dngettext""" + + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="">Bar</p> + <div i18n:domain="foo"> + <p i18n:msg="">FooBar</p> + <p i18n:domain="" i18n:msg="">Bar</p> + <p>Bar</p> + </div> + <p>Bar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'foo_Bar'}) + translations.add_domain('bar', {'Bar': 'bar_Bar'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>Voh</p> + <div> + <p>BarFoo</p> + <p>Voh</p> + <p>foo_Bar</p> + </div> + <p>Voh</p> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_choose_as_attribute(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="one"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </div> + <div i18n:choose="two"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </div> + </html>""") + translations = DummyTranslations() + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <div> + <p>FooBar</p> + </div> + <div> + <p>FooBars</p> + </div> + </html>""", tmpl.generate(one=1, two=2).render()) + + def test_translate_i18n_choose_as_directive(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:choose numeral="two"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </i18n:choose> + <i18n:choose numeral="one"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </i18n:choose> + </html>""") + translations = DummyTranslations() + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>FooBars</p> + <p>FooBar</p> + </html>""", tmpl.generate(one=1, two=2).render()) + + def test_translate_i18n_choose_as_attribute_with_params(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="two; fname, lname"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translations = DummyTranslations({ + ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', + ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', + 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', + 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <div> + <p>Vohs John Doe</p> + </div> + </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) + + def test_translate_i18n_choose_as_attribute_with_params_and_domain_as_param(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" + i18n:domain="foo"> + <div i18n:choose="two; fname, lname"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translations = DummyTranslations() + translations.add_domain('foo', { + ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', + ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', + 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', + 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <div> + <p>Vohs John Doe</p> + </div> + </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) + + def test_translate_i18n_choose_as_directive_with_params(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:choose numeral="two" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + <i18n:choose numeral="one" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </html>""") + translations = DummyTranslations({ + ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', + ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', + 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', + 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>Vohs John Doe</p> + <p>Voh John Doe</p> + </html>""", tmpl.generate(one=1, two=2, + fname='John', lname='Doe').render()) + + def test_translate_i18n_choose_as_directive_with_params_and_domain_as_directive(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:domain name="foo"> + <i18n:choose numeral="two" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </i18n:domain> + <i18n:choose numeral="one" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </html>""") + translations = DummyTranslations() + translations.add_domain('foo', { + ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', + ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', + 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', + 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>Vohs John Doe</p> + <p>Foo John Doe</p> + </html>""", tmpl.generate(one=1, two=2, + fname='John', lname='Doe').render()) + + def test_extract_i18n_choose_as_attribute(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="one"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </div> + <div i18n:choose="two"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </div> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(2, len(messages)) + self.assertEqual((3, 'ngettext', (u'FooBar', u'FooBars'), []), messages[0]) + self.assertEqual((7, 'ngettext', (u'FooBar', u'FooBars'), []), messages[1]) + + def test_extract_i18n_choose_as_directive(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:choose numeral="two"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </i18n:choose> + <i18n:choose numeral="one"> + <p i18n:singular="">FooBar</p> + <p i18n:plural="">FooBars</p> + </i18n:choose> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(2, len(messages)) + self.assertEqual((3, 'ngettext', (u'FooBar', u'FooBars'), []), messages[0]) + self.assertEqual((7, 'ngettext', (u'FooBar', u'FooBars'), []), messages[1]) + + def test_extract_i18n_choose_as_attribute_with_params(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="two; fname, lname"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), []), + messages[0]) + + def test_extract_i18n_choose_as_attribute_with_params_and_domain_as_param(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" + i18n:domain="foo"> + <div i18n:choose="two; fname, lname"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((4, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), []), + messages[0]) + + def test_extract_i18n_choose_as_directive_with_params(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:choose numeral="two" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + <i18n:choose numeral="one" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(2, len(messages)) + self.assertEqual((3, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), []), + messages[0]) + self.assertEqual((7, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), []), + messages[1]) + + def test_extract_i18n_choose_as_directive_with_params_and_domain_as_directive(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:domain name="foo"> + <i18n:choose numeral="two" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </i18n:domain> + <i18n:choose numeral="one" params="fname, lname"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(2, len(messages)) + self.assertEqual((4, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), []), + messages[0]) + self.assertEqual((9, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), []), + messages[1]) + + def test_extract_i18n_choose_as_attribute_with_params_and_comment(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="two; fname, lname" i18n:comment="As in Foo Bar"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), + [u'As in Foo Bar']), + messages[0]) + + def test_extract_i18n_choose_as_directive_with_params_and_comment(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <i18n:choose numeral="two" params="fname, lname" i18n:comment="As in Foo Bar"> + <p i18n:singular="">Foo ${fname} ${lname}</p> + <p i18n:plural="">Foos ${fname} ${lname}</p> + </i18n:choose> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, 'ngettext', (u'Foo %(fname)s %(lname)s', + u'Foos %(fname)s %(lname)s'), + [u'As in Foo Bar']), + messages[0]) + + def test_translate_i18n_domain_with_nested_inlcudes(self): + import os, shutil, tempfile + from genshi.template.loader import TemplateLoader + dirname = tempfile.mkdtemp(suffix='genshi_test') + try: + for idx in range(7): + file1 = open(os.path.join(dirname, 'tmpl%d.html' % idx), 'w') + try: + file1.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" py:strip=""> + <div>Included tmpl$idx</div> + <p i18n:msg="idx">Bar $idx</p> + <p i18n:domain="bar">Bar</p> + <p i18n:msg="idx" i18n:domain="">Bar $idx</p> + <p i18n:domain="" i18n:msg="idx">Bar $idx</p> + <py:if test="idx < 6"> + <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> + </py:if> + </html>""") + finally: + file1.close() + + file2 = open(os.path.join(dirname, 'tmpl10.html'), 'w') + try: + file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" + i18n:domain="foo"> + <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> + </html>""") + finally: + file2.close() + + def callback(template): + translations = DummyTranslations({'Bar %(idx)s': 'Voh %(idx)s'}) + translations.add_domain('foo', {'Bar %(idx)s': 'foo_Bar %(idx)s'}) + translations.add_domain('bar', {'Bar': 'bar_Bar'}) + translator = Translator(translations) + translator.setup(template) + loader = TemplateLoader([dirname], callback=callback) + tmpl = loader.load('tmpl10.html') + + self.assertEqual("""<html> + <div>Included tmpl0</div> + <p>foo_Bar 0</p> + <p>bar_Bar</p> + <p>Voh 0</p> + <p>Voh 0</p> + <div>Included tmpl1</div> + <p>foo_Bar 1</p> + <p>bar_Bar</p> + <p>Voh 1</p> + <p>Voh 1</p> + <div>Included tmpl2</div> + <p>foo_Bar 2</p> + <p>bar_Bar</p> + <p>Voh 2</p> + <p>Voh 2</p> + <div>Included tmpl3</div> + <p>foo_Bar 3</p> + <p>bar_Bar</p> + <p>Voh 3</p> + <p>Voh 3</p> + <div>Included tmpl4</div> + <p>foo_Bar 4</p> + <p>bar_Bar</p> + <p>Voh 4</p> + <p>Voh 4</p> + <div>Included tmpl5</div> + <p>foo_Bar 5</p> + <p>bar_Bar</p> + <p>Voh 5</p> + <p>Voh 5</p> + <div>Included tmpl6</div> + <p>foo_Bar 6</p> + <p>bar_Bar</p> + <p>Voh 6</p> + <p>Voh 6</p> + </html>""", tmpl.generate(idx=-1).render()) + finally: + shutil.rmtree(dirname) + + def test_translate_i18n_domain_with_nested_inlcudes_with_translatable_attrs(self): + import os, shutil, tempfile + from genshi.template.loader import TemplateLoader + dirname = tempfile.mkdtemp(suffix='genshi_test') + try: + for idx in range(4): + file1 = open(os.path.join(dirname, 'tmpl%d.html' % idx), 'w') + try: + file1.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" py:strip=""> + <div>Included tmpl$idx</div> + <p title="${dg('foo', 'Bar %(idx)s') % dict(idx=idx)}" i18n:msg="idx">Bar $idx</p> + <p title="Bar" i18n:domain="bar">Bar</p> + <p title="Bar" i18n:msg="idx" i18n:domain="">Bar $idx</p> + <p i18n:msg="idx" i18n:domain="" title="Bar">Bar $idx</p> + <p i18n:domain="" i18n:msg="idx" title="Bar">Bar $idx</p> + <py:if test="idx < 3"> + <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> + </py:if> + </html>""") + finally: + file1.close() + + file2 = open(os.path.join(dirname, 'tmpl10.html'), 'w') + try: + file2.write("""<html xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" + i18n:domain="foo"> + <xi:include href="tmpl${idx}.html" py:with="idx = idx+1"/> + </html>""") + finally: + file2.close() + + translations = DummyTranslations({'Bar %(idx)s': 'Voh %(idx)s', + 'Bar': 'Voh'}) + translations.add_domain('foo', {'Bar %(idx)s': 'foo_Bar %(idx)s'}) + translations.add_domain('bar', {'Bar': 'bar_Bar'}) + translator = Translator(translations) + + def callback(template): + translator.setup(template) + loader = TemplateLoader([dirname], callback=callback) + tmpl = loader.load('tmpl10.html') + + self.assertEqual("""<html> + <div>Included tmpl0</div> + <p title="foo_Bar 0">foo_Bar 0</p> + <p title="bar_Bar">bar_Bar</p> + <p title="Voh">Voh 0</p> + <p title="Voh">Voh 0</p> + <p title="Voh">Voh 0</p> + <div>Included tmpl1</div> + <p title="foo_Bar 1">foo_Bar 1</p> + <p title="bar_Bar">bar_Bar</p> + <p title="Voh">Voh 1</p> + <p title="Voh">Voh 1</p> + <p title="Voh">Voh 1</p> + <div>Included tmpl2</div> + <p title="foo_Bar 2">foo_Bar 2</p> + <p title="bar_Bar">bar_Bar</p> + <p title="Voh">Voh 2</p> + <p title="Voh">Voh 2</p> + <p title="Voh">Voh 2</p> + <div>Included tmpl3</div> + <p title="foo_Bar 3">foo_Bar 3</p> + <p title="bar_Bar">bar_Bar</p> + <p title="Voh">Voh 3</p> + <p title="Voh">Voh 3</p> + <p title="Voh">Voh 3</p> + </html>""", tmpl.generate(idx=-1, + dg=translations.dugettext).render()) + finally: + shutil.rmtree(dirname) + + def test_translate_i18n_msg_and_comment_with_py_strip_directives(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" i18n:comment="As in foo bar" py:strip="">Foo</p> + <p py:strip="" i18n:msg="" i18n:comment="As in foo bar">Foo</p> + </html>""") + translator = Translator(DummyTranslations({'Foo': 'Voh'})) + translator.setup(tmpl) + self.assertEqual("""<html> + Voh + Voh + </html>""", tmpl.generate().render()) + + def test_translate_i18n_choose_and_py_strip(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="two; fname, lname"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translations = DummyTranslations({ + ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', + ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', + 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', + 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <div> + <p>Vohs John Doe</p> + </div> + </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) + + def test_translate_i18n_choose_and_domain_and_py_strip(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" + i18n:domain="foo"> + <div i18n:choose="two; fname, lname"> + <p i18n:singular="">Foo $fname $lname</p> + <p i18n:plural="">Foos $fname $lname</p> + </div> + </html>""") + translations = DummyTranslations() + translations.add_domain('foo', { + ('Foo %(fname)s %(lname)s', 0): 'Voh %(fname)s %(lname)s', + ('Foo %(fname)s %(lname)s', 1): 'Vohs %(fname)s %(lname)s', + 'Foo %(fname)s %(lname)s': 'Voh %(fname)s %(lname)s', + 'Foos %(fname)s %(lname)s': 'Vohs %(fname)s %(lname)s', + }) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <div> + <p>Vohs John Doe</p> + </div> + </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render()) + + def test_extract_i18n_msg_with_py_strip(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" py:strip=""> + Please see <a href="help.html">Help</a> for details. + </p> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, None, u'Please see [1:Help] for details.', []), + messages[0]) + + def test_extract_i18n_msg_with_py_strip_and_comment(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" py:strip="" i18n:comment="Foo"> + Please see <a href="help.html">Help</a> for details. + </p> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, None, u'Please see [1:Help] for details.', + ['Foo']), messages[0]) + + def test_extract_i18n_choose_as_attribute_and_py_strip(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <div i18n:choose="one" py:strip=""> + <p i18n:singular="" py:strip="">FooBar</p> + <p i18n:plural="" py:strip="">FooBars</p> + </div> + </html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, 'ngettext', (u'FooBar', u'FooBars'), []), messages[0]) + + def test_translate_i18n_domain_with_inline_directive_on_START_NS(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" i18n:domain="foo"> + <p i18n:msg="">FooBar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual("""<html> + <p>BarFoo</p> + </html>""", tmpl.generate().render()) + + def test_translate_i18n_domain_with_inline_directive_on_START_NS_with_py_strip(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n" + i18n:domain="foo" py:strip=""> + <p i18n:msg="">FooBar</p> + </html>""") + translations = DummyTranslations({'Bar': 'Voh'}) + translations.add_domain('foo', {'FooBar': 'BarFoo'}) + translator = Translator(translations) + translator.setup(tmpl) + self.assertEqual(""" + <p>BarFoo</p> + """, tmpl.generate().render()) class ExtractTestCase(unittest.TestCase): @@ -504,12 +1463,12 @@ def test_text_template_extraction(self): buf = StringIO("""${_("Dear %(name)s") % {'name': name}}, - + ${ngettext("Your item:", "Your items", len(items))} #for item in items * $item #end - + All the best, Foobar""") results = list(extract(buf, ['_', 'ngettext'], [], { @@ -563,6 +1522,60 @@ </html>""") self.assertEqual([], list(extract(buf, ['_'], [], {}))) + def test_extract_py_def_directive_with_py_strip(self): + # Failed extraction from Trac + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" py:strip=""> + <py:def function="diff_options_fields(diff)"> + <label for="style">View differences</label> + <select id="style" name="style"> + <option selected="${diff.style == 'inline' or None}" + value="inline">inline</option> + <option selected="${diff.style == 'sidebyside' or None}" + value="sidebyside">side by side</option> + </select> + <div class="field"> + Show <input type="text" name="contextlines" id="contextlines" size="2" + maxlength="3" value="${diff.options.contextlines < 0 and 'all' or diff.options.contextlines}" /> + <label for="contextlines">lines around each change</label> + </div> + <fieldset id="ignore" py:with="options = diff.options"> + <legend>Ignore:</legend> + <div class="field"> + <input type="checkbox" id="ignoreblanklines" name="ignoreblanklines" + checked="${options.ignoreblanklines or None}" /> + <label for="ignoreblanklines">Blank lines</label> + </div> + <div class="field"> + <input type="checkbox" id="ignorecase" name="ignorecase" + checked="${options.ignorecase or None}" /> + <label for="ignorecase">Case changes</label> + </div> + <div class="field"> + <input type="checkbox" id="ignorewhitespace" name="ignorewhitespace" + checked="${options.ignorewhitespace or None}" /> + <label for="ignorewhitespace">White space changes</label> + </div> + </fieldset> + <div class="buttons"> + <input type="submit" name="update" value="${_('Update')}" /> + </div> + </py:def></html>""") + translator = Translator() + tmpl.add_directives(Translator.NAMESPACE, translator) + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(10, len(messages)) + self.assertEqual([ + (3, None, u'View differences', []), + (6, None, u'inline', []), + (8, None, u'side by side', []), + (10, None, u'Show', []), + (13, None, u'lines around each change', []), + (16, None, u'Ignore:', []), + (20, None, u'Blank lines', []), + (25, None, u'Case changes',[]), + (30, None, u'White space changes', []), + (34, '_', u'Update', [])], messages) + def suite(): suite = unittest.TestSuite()