# -*- coding: utf-8 -*- # # Copyright (C) 2007-2010 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://genshi.edgewall.org/wiki/License. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://genshi.edgewall.org/log/. from datetime import datetime from gettext import NullTranslations import unittest import six from genshi.core import Attrs from genshi.template import MarkupTemplate, Context from genshi.filters.i18n import Translator, extract from genshi.input import HTML from genshi.compat import IS_PYTHON2, StringIO from genshi.tests.test_utils import doctest_suite class DummyTranslations(NullTranslations): _domains = {} def __init__(self, catalog=()): NullTranslations.__init__(self) 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) if IS_PYTHON2: def ugettext(self, message): missing = object() tmsg = self._catalog.get(message, missing) if tmsg is missing: if self._fallback: return self._fallback.ugettext(message) return six.text_type(message) return tmsg else: def gettext(self, message): missing = object() tmsg = self._catalog.get(message, missing) if tmsg is missing: if self._fallback: return self._fallback.gettext(message) return six.text_type(message) return tmsg if IS_PYTHON2: def dugettext(self, domain, message): return self._domain_call('ugettext', domain, message) else: def dgettext(self, domain, message): return self._domain_call('gettext', 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 if not IS_PYTHON2: ngettext = ungettext del ungettext if IS_PYTHON2: def dungettext(self, domain, singular, plural, numeral): return self._domain_call( 'ungettext', domain, singular, plural, numeral) else: def dngettext(self, domain, singular, plural, numeral): return self._domain_call( 'ngettext', domain, singular, plural, numeral) if IS_PYTHON2: def upgettext(self, context, message): try: return self._catalog[(context, message)] except KeyError: if self._fallback: return self._fallback.upgettext(context, message) return unicode(message) else: def pgettext(self, context, message): try: return self._catalog[(context, message)] except KeyError: if self._fallback: return self._fallback.upgettext(context, message) return message if IS_PYTHON2: def dupgettext(self, domain, context, message): return self._domain_call('upgettext', domain, context, message) else: def dpgettext(self, domain, context, message): return self._domain_call('pgettext', domain, context, message) def unpgettext(self, context, msgid1, msgid2, n): try: return self._catalog[(context, msgid1, self.plural(n))] except KeyError: if self._fallback: return self._fallback.unpgettext(context, msgid1, msgid2, n) if n == 1: return msgid1 else: return msgid2 if not IS_PYTHON2: npgettext = unpgettext del unpgettext if IS_PYTHON2: def dunpgettext(self, domain, context, msgid1, msgid2, n): return self._domain_call('unpgettext', context, msgid1, msgid2, n) else: def dnpgettext(self, domain, context, msgid1, msgid2, n): return self._domain_call('npgettext', context, msgid1, msgid2, n) class TranslatorTestCase(unittest.TestCase): def test_translate_included_attribute_text(self): """ Verify that translated attributes end up in a proper `Attrs` instance. """ html = HTML(u""" """) translator = Translator(lambda s: u"Voh") stream = list(html.filter(translator)) kind, data, pos = stream[2] assert isinstance(data[1], Attrs) def test_extract_included_empty_attribute_text(self): tmpl = MarkupTemplate(u""" ... """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual([], messages) def test_translate_included_empty_attribute_text(self): tmpl = MarkupTemplate(u""" ... """) translator = Translator(DummyTranslations({'': 'Project-Id-Version'})) translator.setup(tmpl) self.assertEqual(""" ... """, tmpl.generate().render()) def test_extract_without_text(self): tmpl = MarkupTemplate("""
Foo
${ngettext("Singular", "Plural", num)} """) translator = Translator(extract_text=False) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((3, 'ngettext', ('Singular', 'Plural', None), []), messages[0]) def test_extract_plural_form(self): tmpl = MarkupTemplate(""" ${ngettext("Singular", "Plural", num)} """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, 'ngettext', ('Singular', 'Plural', None), []), messages[0]) def test_extract_funky_plural_form(self): tmpl = MarkupTemplate(""" ${ngettext(len(items), *widget.display_names)} """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, 'ngettext', (None, None), []), messages[0]) def test_extract_gettext_with_unicode_string(self): tmpl = MarkupTemplate(""" ${gettext("Grüße")} """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, 'gettext', u'Gr\xfc\xdfe', []), messages[0]) def test_extract_included_attribute_text(self): tmpl = MarkupTemplate(""" """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, None, 'Foo', []), messages[0]) def test_extract_attribute_expr(self): tmpl = MarkupTemplate(""" """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, '_', 'Save', []), messages[0]) def test_extract_non_included_attribute_interpolated(self): tmpl = MarkupTemplate(""" Foo """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, None, 'Foo', []), messages[0]) def test_extract_text_from_sub(self): tmpl = MarkupTemplate("""(c) 2007 Edgewall Software
""") translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(0, len(messages)) def test_extract_tag_with_variable_xml_lang(self): tmpl = MarkupTemplate("""(c) 2007 Edgewall Software
""") translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, None, '(c) 2007 Edgewall Software', []), messages[0]) def test_ignore_attribute_with_expression(self): tmpl = MarkupTemplate(""" """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(0, len(messages)) def test_translate_with_translations_object(self): tmpl = MarkupTemplate("""Foo
""") translator = Translator(DummyTranslations({'Foo': 'Voh'})) translator.setup(tmpl) self.assertEqual("""Voh
""", tmpl.generate().render()) def test_extract_included_attribute_text_with_spaces(self): tmpl = MarkupTemplate(""" ... """) translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((2, None, 'Foo', []), messages[0]) def test_translate_included_attribute_text_with_spaces(self): tmpl = MarkupTemplate(""" ... """) translator = Translator(DummyTranslations({'Foo': 'Voh'})) translator.setup(tmpl) self.assertEqual(""" ... """, tmpl.generate().render()) class MsgDirectiveTestCase(unittest.TestCase): def test_extract_i18n_msg(self): tmpl = MarkupTemplate("""Please see Help for details.
""") 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]) def test_translate_i18n_msg(self): tmpl = MarkupTemplate("""Please see Help for details.
""") gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]." translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Für Details siehe bitte Hilfe.
""".encode('utf-8'), tmpl.generate().render(encoding='utf-8')) def test_extract_i18n_msg_nonewline(self): tmpl = MarkupTemplate("""Please see Help
""") 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]', messages[0][2]) def test_translate_i18n_msg_nonewline(self): tmpl = MarkupTemplate("""Please see Help
""") gettext = lambda s: u"Für Details siehe bitte [1:Hilfe]" translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Für Details siehe bitte Hilfe
""", tmpl.generate().render()) def test_extract_i18n_msg_elt_nonewline(self): tmpl = MarkupTemplate("""Please see Help
""") translator = Translator() translator.setup(tmpl) messages = list(translator.extract(tmpl.stream)) self.assertEqual(3, len(messages)) self.assertEqual('A helpful paragraph', messages[0][2]) self.assertEqual(3, messages[0][0]) self.assertEqual('Click for help', messages[1][2]) self.assertEqual(4, messages[1][0]) self.assertEqual('Please see [1:Help]', messages[2][2]) self.assertEqual(3, messages[2][0]) def test_translate_i18n_msg_with_attributes(self): tmpl = MarkupTemplate("""Please see Help
""") translator = Translator(lambda msgid: { 'A helpful paragraph': 'Ein hilfreicher Absatz', 'Click for help': u'Klicken für Hilfe', 'Please see [1:Help]': u'Siehe bitte [1:Hilfe]' }[msgid]) translator.setup(tmpl) self.assertEqual(u"""Siehe bitte Hilfe
""", tmpl.generate().render(encoding=None)) def test_extract_i18n_msg_with_dynamic_attributes(self): tmpl = MarkupTemplate("""Please see Help
""") translator = Translator() translator.setup(tmpl) messages = list(translator.extract(tmpl.stream)) self.assertEqual(3, len(messages)) self.assertEqual('A helpful paragraph', messages[0][2]) self.assertEqual(3, messages[0][0]) self.assertEqual('Click for help', messages[1][2]) self.assertEqual(4, messages[1][0]) self.assertEqual('Please see [1:Help]', messages[2][2]) self.assertEqual(3, messages[2][0]) def test_translate_i18n_msg_with_dynamic_attributes(self): tmpl = MarkupTemplate("""Please see Help
""") translator = Translator(lambda msgid: { 'A helpful paragraph': 'Ein hilfreicher Absatz', 'Click for help': u'Klicken für Hilfe', 'Please see [1:Help]': u'Siehe bitte [1:Hilfe]' }[msgid]) translator.setup(tmpl) self.assertEqual(u"""Siehe bitte Hilfe
""", tmpl.generate(_=translator.translate).render(encoding=None)) def test_extract_i18n_msg_as_element_with_attributes(self): tmpl = MarkupTemplate("""Please see Help page for details.
""") 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.', messages[0][2]) def test_translate_i18n_msg_nested(self): tmpl = MarkupTemplate("""Please see Help page for details.
""") gettext = lambda s: u"Für Details siehe bitte [1:[2:Hilfeseite]]." translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Für Details siehe bitte Hilfeseite.
""", tmpl.generate().render()) def test_extract_i18n_msg_label_with_nested_input(self): tmpl = MarkupTemplate("""Show me entries per page.
""") 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]) def test_translate_i18n_msg_empty(self): tmpl = MarkupTemplate("""Show me entries per page.
""") gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Einträge pro Seite anzeigen.
""", tmpl.generate().render()) def test_extract_i18n_msg_multiple(self): tmpl = MarkupTemplate("""Please see Help for details.
""") 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]) def test_translate_i18n_msg_multiple(self): tmpl = MarkupTemplate("""Please see Help for details.
""") gettext = lambda s: u"Für [2:Details] siehe bitte [1:Hilfe]." translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Für Details siehe bitte Hilfe.
""", tmpl.generate().render()) def test_extract_i18n_msg_multiple_empty(self): tmpl = MarkupTemplate("""Show me entries per page, starting at page .
""") 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:].', messages[0][2]) def test_translate_i18n_msg_multiple_empty(self): tmpl = MarkupTemplate("""Show me entries per page, starting at page .
""", encoding='utf-8') gettext = lambda s: u"[1:] Einträge pro Seite, beginnend auf Seite [2:]." translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Eintr\u00E4ge pro Seite, beginnend auf Seite .
""".encode('utf-8'), tmpl.generate().render(encoding='utf-8')) def test_extract_i18n_msg_with_param(self): tmpl = MarkupTemplate("""Hello, ${user.name}!
""") 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]) def test_translate_i18n_msg_with_param(self): tmpl = MarkupTemplate("""Hello, ${user.name}!
""") gettext = lambda s: u"Hallo, %(name)s!" translator = Translator(gettext) translator.setup(tmpl) self.assertEqual("""Hallo, Jim!
""", tmpl.generate(user=dict(name='Jim')).render()) def test_translate_i18n_msg_with_param_reordered(self): tmpl = MarkupTemplate("""Hello, ${user.name}!
""") gettext = lambda s: u"%(name)s, sei gegrüßt!" translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Jim, sei gegrüßt!
""", tmpl.generate(user=dict(name='Jim')).render()) def test_translate_i18n_msg_with_attribute_param(self): tmpl = MarkupTemplate("""Hello, dude!
""") gettext = lambda s: u"Sei gegrüßt, [1:Alter]!" translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Sei gegrüßt, Alter!
""", tmpl.generate(anchor='42').render()) def test_extract_i18n_msg_with_two_params(self): tmpl = MarkupTemplate("""Posted by ${post.author} at ${entry.time.strftime('%H:%m')}
""") 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]) def test_translate_i18n_msg_with_two_params(self): tmpl = MarkupTemplate("""Written by ${entry.author} at ${entry.time.strftime('%H:%M')}
""") gettext = lambda s: u"%(name)s schrieb dies um %(time)s" translator = Translator(gettext) translator.setup(tmpl) entry = { 'author': 'Jim', 'time': datetime(2008, 4, 1, 14, 30) } self.assertEqual("""Jim schrieb dies um 14:30
""", tmpl.generate(entry=entry).render()) def test_extract_i18n_msg_with_directive(self): tmpl = MarkupTemplate("""Show me entries per page.
""") 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]) def test_translate_i18n_msg_with_directive(self): tmpl = MarkupTemplate("""Show me entries per page.
""") gettext = lambda s: u"[1:] Einträge pro Seite anzeigen." translator = Translator(gettext) translator.setup(tmpl) self.assertEqual(u"""Einträge pro Seite anzeigen.
""", tmpl.generate().render()) def test_extract_i18n_msg_with_comment(self): tmpl = MarkupTemplate("""Foo
""") translator = Translator() tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((3, None, 'Foo', ['As in foo bar']), messages[0]) tmpl = MarkupTemplate("""Foo
""") translator = Translator() tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((3, None, 'Foo', ['As in foo bar']), messages[0]) def test_translate_i18n_msg_with_comment(self): tmpl = MarkupTemplate("""Foo
""") gettext = lambda s: u"Voh" translator = Translator(gettext) translator.setup(tmpl) self.assertEqual("""Voh
""", tmpl.generate().render()) def test_extract_i18n_msg_with_attr(self): tmpl = MarkupTemplate("""Foo
""") translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(2, len(messages)) self.assertEqual((3, None, 'Foo bar', []), messages[0]) self.assertEqual((3, None, 'Foo', []), messages[1]) def test_translate_i18n_msg_with_attr(self): tmpl = MarkupTemplate("""Foo
""") gettext = lambda s: u"Voh" translator = Translator(DummyTranslations({ 'Foo': 'Voh', 'Foo bar': u'Voh bär' })) tmpl.filters.insert(0, translator) tmpl.add_directives(Translator.NAMESPACE, translator) self.assertEqual(u"""Voh
""", tmpl.generate().render()) def test_translate_i18n_msg_and_py_strip_directives(self): tmpl = MarkupTemplate("""Foo
Foo
""") translator = Translator(DummyTranslations({'Foo': 'Voh'})) translator.setup(tmpl) self.assertEqual(""" Voh Voh """, tmpl.generate().render()) def test_i18n_msg_ticket_300_extract(self): tmpl = MarkupTemplate("""Translation[ 0 ]: One coin
""") 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("""Translation[ 0 ]: One coin
""") 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(u"""Trandução[ 0 ]: Uma moeda
""".encode('utf-8'), tmpl.generate().render(encoding='utf-8')) def test_extract_i18n_msg_with_other_directives_nested(self): tmpl = MarkupTemplate("""Before you do that, though, please first try searching for similar issues, as it is quite likely that this problem has been reported before. For questions about installation and configuration of Trac, please try the mailing list instead of filing a ticket.
""") translator = Translator() translator.setup(tmpl) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual( 'Before you do that, though, please first try\n ' '[1:[2:searching]\n for similar issues], as it is ' 'quite likely that this problem\n has been reported ' 'before. For questions about installation\n and ' 'configuration of Trac, please try the\n ' '[3:mailing list]\n instead of filing a ticket.', messages[0][2] ) def test_translate_i18n_msg_with_other_directives_nested(self): tmpl = MarkupTemplate("""Before you do that, though, please first try searching for similar issues, as it is quite likely that this problem has been reported before. For questions about installation and configuration of Trac, please try the mailing list instead of filing a ticket.
""") translations = DummyTranslations({ 'Before you do that, though, please first try\n ' '[1:[2:searching]\n for similar issues], as it is ' 'quite likely that this problem\n has been reported ' 'before. For questions about installation\n and ' 'configuration of Trac, please try the\n ' '[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(u"""Antes de o fazer, porém, por favor tente procurar por problemas semelhantes, 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 mailing list em vez de criar um assunto.
""", 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("""
Note: This repository is defined in
trac.ini
and cannot be edited on this page.
Nota: Este repositório está definido em
trac.ini
e não pode ser editado nesta página.
Please see Help for details.
""") translator = Translator() tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((3, None, 'Please see [1:Help] for details.', []), messages[0]) def test_extract_i18n_msg_with_py_strip_and_comment(self): tmpl = MarkupTemplate("""Please see Help for details.
""") translator = Translator() tmpl.add_directives(Translator.NAMESPACE, translator) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) self.assertEqual((3, None, 'Please see [1:Help] for details.', ['Foo']), messages[0]) def test_translate_i18n_msg_and_comment_with_py_strip_directives(self): tmpl = MarkupTemplate("""Foo
Foo
""") translator = Translator(DummyTranslations({'Foo': 'Voh'})) translator.setup(tmpl) self.assertEqual(""" Voh Voh """, tmpl.generate().render()) def test_translate_i18n_msg_ticket_404(self): tmpl = MarkupTemplate("""$first $second KEPT Inside a tag tail
""") translator = Translator(DummyTranslations()) translator.setup(tmpl) self.assertEqual("""FIRST SECOND KEPT Inside a tag tail""" """
""", tmpl.generate(first="FIRST", second="SECOND").render()) def test_translate_i18n_msg_ticket_404_regression(self): tmpl = MarkupTemplate("""FooBar
FooBars
FooBar
FooBars
FooBar
FooBars
FooBar
FooBars
FooBar
FooBars
FooBars
FooBar
""", tmpl.generate(one=1, two=2).render()) def test_translate_i18n_choose_as_directive_singular_and_plural_with_strip(self): tmpl = MarkupTemplate("""FooBar Singular with Strip
FooBars Plural without Strip
FooBar singular without strip
FooBars plural with strip
FooBar singular without strip
FooBars plural with strip
FooBar singular with strip
FooBars plural without strip
FooBars Plural without Strip
FooBars plural with stripFooBar singular without strip
FooBar singular with strip """, tmpl.generate(one=1, two=2).render()) def test_translate_i18n_choose_plural_singular_as_directive(self): # Ticket 371 tmpl = MarkupTemplate("""Foo $fname $lname
Foos $fname $lname
Vohs John Doe
Foo $fname $lname
Foos $fname $lname
Vohs John Doe
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Vohs John Doe
Voh John Doe
""", 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("""Foo ${fname} ${lname}
Foos ${fname} ${lname}
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Vohs John Doe
Foo John Doe
""", tmpl.generate(one=1, two=2, fname='John', lname='Doe').render()) def test_extract_i18n_choose_as_attribute(self): tmpl = MarkupTemplate("""FooBar
FooBars
FooBar
FooBars
FooBar
FooBars
FooBar
FooBars
Foo $fname $lname
Foos $fname $lname
Foo $fname $lname
Foos $fname $lname
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Foo $fname $lname
Foos $fname $lname
Foo ${fname} ${lname}
Foos ${fname} ${lname}
Da ist 1 Sache.
""", tmpl.generate(link="/things", num=1).render(encoding=None)) self.assertEqual(u"""Da sind 3 Sachen.
""", tmpl.generate(link="/things", num=3).render(encoding=None)) def test_extract_i18n_choose_as_element_with_attributes(self): tmpl = MarkupTemplate("""There is ${num} thing.
There are ${num} things.
There is ${num} thing.
There are ${num} things.
Da ist 1 Sache.
""", tmpl.generate(link="/things", num=1).render(encoding=None)) self.assertEqual(u"""Da sind 3 Sachen.
""", tmpl.generate(link="/things", num=3).render(encoding=None)) def test_translate_i18n_choose_and_py_strip(self): tmpl = MarkupTemplate("""Foo $fname $lname
Foos $fname $lname
Vohs John Doe
Foo $fname $lname
Foos $fname $lname
Vohs John Doe
Foo $fname $lname
Foos $fname $lname
Foo $fname $lname
Foos $fname $lname
Vohs John Doe
Foo $fname $lname
Foos $fname $lname
FooBar
FooBars
FooBar
Bar
BarFoo
PT_Foo
FooBar
""") translations = DummyTranslations({'Bar': 'Voh'}) translations.add_domain('foo', {'FooBar': 'BarFoo'}) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""BarFoo
""", 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("""Bar
FooBar
Bar
Bar
Bar
""") translations = DummyTranslations({'Bar': 'Voh'}) translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""Voh
BarFoo
PT_Foo
PT_Foo
Voh
""", tmpl.generate().render()) def test_translate_i18n_domain_as_directive_not_attribute(self): #"""translate with domain as directive""" tmpl = MarkupTemplate("""FooBar
Bar
Bar
Bar
""") translations = DummyTranslations({'Bar': 'Voh'}) translations.add_domain('foo', {'FooBar': 'BarFoo', 'Bar': 'PT_Foo'}) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""BarFoo
PT_Foo
PT_Foo
Voh
""", tmpl.generate().render()) def test_translate_i18n_domain_nested_directives(self): #"""translate with nested i18n:domain directives""" tmpl = MarkupTemplate("""Bar
FooBar
Bar
Bar
Bar
""") 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("""Voh
BarFoo
bar_Bar
foo_Bar
Voh
""", 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("""Bar
FooBar
Bar
Bar
Bar
""") 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("""Voh
BarFoo
Voh
foo_Bar
Voh
""", tmpl.generate().render()) def test_translate_i18n_domain_with_inline_directive_on_START_NS(self): tmpl = MarkupTemplate("""FooBar
""") translations = DummyTranslations({'Bar': 'Voh'}) translations.add_domain('foo', {'FooBar': 'BarFoo'}) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""BarFoo
""", tmpl.generate().render()) def test_translate_i18n_domain_with_inline_directive_on_START_NS_with_py_strip(self): tmpl = MarkupTemplate("""FooBar
""") translations = DummyTranslations({'Bar': 'Voh'}) translations.add_domain('foo', {'FooBar': 'BarFoo'}) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""BarFoo
""", tmpl.generate().render()) def test_translate_i18n_domain_with_nested_includes(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("""Bar $idx
Bar
Bar $idx
Bar $idx
foo_Bar 0
bar_Bar
Voh 0
Voh 0
foo_Bar 1
bar_Bar
Voh 1
Voh 1
foo_Bar 2
bar_Bar
Voh 2
Voh 2
foo_Bar 3
bar_Bar
Voh 3
Voh 3
foo_Bar 4
bar_Bar
Voh 4
Voh 4
foo_Bar 5
bar_Bar
Voh 5
Voh 5
foo_Bar 6
bar_Bar
Voh 6
Voh 6
""", tmpl.generate(idx=-1).render()) finally: shutil.rmtree(dirname) def test_translate_i18n_domain_with_nested_includes_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("""Bar $idx
Bar
Bar $idx
Bar $idx
Bar $idx
foo_Bar 0
bar_Bar
Voh 0
Voh 0
Voh 0
foo_Bar 1
bar_Bar
Voh 1
Voh 1
Voh 1
foo_Bar 2
bar_Bar
Voh 2
Voh 2
Voh 2
foo_Bar 3
bar_Bar
Voh 3
Voh 3
Voh 3
""", tmpl.generate(idx=-1, dg=dgettext).render()) finally: shutil.rmtree(dirname) class ExtractTestCase(unittest.TestCase): def test_markup_template_extraction(self): buf = StringIO("""${_("Hello, %(name)s") % dict(name=username)}
${ngettext("You have %d item", "You have %d items", num)}
""") results = list(extract(buf, ['_', 'ngettext'], [], {})) self.assertEqual([ (3, None, 'Example', []), (6, None, 'Example', []), (7, '_', 'Hello, %(name)s', []), (8, 'ngettext', ('You have %d item', 'You have %d items', None), []), ], results) def test_extraction_without_text(self): buf = StringIO("""Foo
${ngettext("Singular", "Plural", num)} """) results = list(extract(buf, ['_', 'ngettext'], [], { 'extract_text': 'no' })) self.assertEqual([ (3, 'ngettext', ('Singular', 'Plural', None), []), ], results) 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'], [], { 'template_class': 'genshi.template:TextTemplate' })) self.assertEqual([ (1, '_', 'Dear %(name)s', []), (3, 'ngettext', ('Your item:', 'Your items', None), []), (7, None, 'All the best,\n Foobar', []) ], results) def test_extraction_with_keyword_arg(self): buf = StringIO(""" ${gettext('Foobar', foo='bar')} """) results = list(extract(buf, ['gettext'], [], {})) self.assertEqual([ (2, 'gettext', ('Foobar'), []), ], results) def test_extraction_with_nonstring_arg(self): buf = StringIO(""" ${dgettext(curdomain, 'Foobar')} """) results = list(extract(buf, ['dgettext'], [], {})) self.assertEqual([ (2, 'dgettext', (None, 'Foobar'), []), ], results) def test_extraction_inside_ignored_tags(self): buf = StringIO(""" """) results = list(extract(buf, ['_'], [], {})) self.assertEqual([ (5, '_', 'Please wait...', []), ], results) def test_extraction_inside_ignored_tags_with_directives(self): buf = StringIO(""" """) self.assertEqual([], list(extract(buf, ['_'], [], {}))) def test_extract_py_def_directive_with_py_strip(self): # Failed extraction from Trac tmpl = MarkupTemplate("""Foo, bar.
Foo, bar.
""") results = list(extract(buf, ['_'], [], {})) self.assertEqual((3, 'pgettext', ('foo', 'Foo, bar.'), []), results[0]) self.assertEqual((4, None, 'Foo, bar.', []), results[1]) def test_translate_msgcontext(self): tmpl = MarkupTemplate("""Foo, bar.
Foo, bar.
""") translations = { ('foo', 'Foo, bar.'): 'Fooo! Barrr!', 'Foo, bar.': 'Foo --- bar.' } translator = Translator(DummyTranslations(translations)) translator.setup(tmpl) self.assertEqual("""Fooo! Barrr!
Foo --- bar.
""", tmpl.generate().render()) def test_translate_msgcontext_with_domain(self): tmpl = MarkupTemplate("""Foo, bar. foo
Foo, bar.
""") translations = DummyTranslations({ ('foo', 'Foo, bar.'): 'Fooo! Barrr!', 'Foo, bar.': 'Foo --- bar.' }) translations.add_domain('bar', { ('foo', 'foo'): 'BARRR', ('foo', 'Foo, bar.'): 'Bar, bar.' }) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""Bar, bar. BARRR
Foo --- bar.
""", tmpl.generate().render()) def test_translate_msgcontext_with_plurals(self): tmpl = MarkupTemplate("""There is ${num} bar There are ${num} bars
Hay 1 barre
""", tmpl.generate(num=1).render()) self.assertEqual("""Hay 2 barres
""", tmpl.generate(num=2).render()) def test_translate_context_with_msg(self): tmpl = MarkupTemplate("""Foo There is ${num} bar Bar
""") translations = DummyTranslations({ ('foo', 'Foo [1:There is %(num)s bar] Bar'): 'Voh [1:Hay %(num)s barre] Barre' }) translator = Translator(translations) translator.setup(tmpl) self.assertEqual("""Voh Hay 1 barre Barre
""", tmpl.generate(num=1).render()) def suite(): suite = unittest.TestSuite() suite.addTest(doctest_suite(Translator.__module__)) suite.addTest(unittest.makeSuite(TranslatorTestCase, 'test')) suite.addTest(unittest.makeSuite(MsgDirectiveTestCase, 'test')) suite.addTest(unittest.makeSuite(ChooseDirectiveTestCase, 'test')) suite.addTest(unittest.makeSuite(DomainDirectiveTestCase, 'test')) suite.addTest(unittest.makeSuite(ExtractTestCase, 'test')) suite.addTest(unittest.makeSuite(ContextDirectiveTestCase, 'test')) return suite if __name__ == '__main__': unittest.main(defaultTest='suite')