diff options
-rw-r--r-- | dummyengine.py | 85 | ||||
-rw-r--r-- | tests/test_talinterpreter.py | 71 |
2 files changed, 144 insertions, 12 deletions
diff --git a/dummyengine.py b/dummyengine.py index f75ebe6..aa76c62 100644 --- a/dummyengine.py +++ b/dummyengine.py @@ -299,3 +299,88 @@ class DummyTranslationDomain(object): return unicode(mapping[m.group(m.lastindex).lower()]) cre = re.compile(r'\$(?:([_A-Za-z][-\w]*)|\{([_A-Za-z][-\w]*)\})') return cre.sub(repl, text) + + +class MultipleDomainsDummyEngine(DummyEngine): + + def __init__(self, macros=None): + if macros is None: + macros = {} + self.macros = macros + dict = {'nothing': None, 'default': Default} + self.locals = self.globals = dict + self.stack = [dict] + self.translationDomain = DummyTranslationDomain() + self.lowerDomain = LowerDummyDomain() + self.useEngineAttrDicts = False + + def translate(self, msgid, domain=None, mapping=None, default=None): + if isinstance(msgid, (MessageID, Message)): + domain = msgid.domain + if domain in ['lower', 'a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine']: + translationDomain = self.lowerDomain + else: + translationDomain = self.translationDomain + translationDomain.domain = domain + return translationDomain.translate( + msgid, mapping, default=default) + +class LowerDummyDomain(object): + implements(ITranslationDomain) + + domain = '' + + def translate(self, msgid, mapping=None, context=None, + target_language=None, default=None): + + domain = self.domain + # This is a fake translation service which simply uppercases non + # ${name} placeholder text in the message id. + # + # First, transform a string with ${name} placeholders into a list of + # substrings. Then lowcase everything but the placeholders, then glue + # things back together. + + # If the domain is a string method, then transform the string + # by calling that method. + + # MessageID attributes override arguments + if isinstance(msgid, (MessageID, Message)): + domain = msgid.domain + mapping = msgid.mapping + default = msgid.default + if default is None: # Message doesn't substitute itself for + default = msgid # missing default + + # simulate an unknown msgid by returning None + if msgid == "don't translate me": + text = default + elif domain and hasattr('', domain): + text = getattr(msgid, domain)() + else: + text = msgid.lower() + + def repl(m): + return unicode(mapping[m.group(m.lastindex).lower()]) + cre = re.compile(r'\$(?:([_A-Za-z][-\w]*)|\{([_A-Za-z][-\w]*)\})') + return cre.sub(repl, text) + + def translate(self, msgid, mapping=None, context=None, + target_language=None, default=None): + # This is a fake translation service which simply lowercases non + # ${name} placeholder text in the message id. + # + # First, transform a string with ${name} placeholders into a list of + # substrings. Then upcase everything but the placeholders, then glue + # things back together. + + # simulate an unknown msgid by returning None + if msgid == "don't translate me": + text = default + else: + text = msgid.lower() + + def repl(m, mapping=mapping): + return ustr(mapping[m.group(m.lastindex).lower()]) + cre = re.compile(r'\$(?:(%s)|\{(%s)\})' % (NAME_RE, NAME_RE)) + return cre.sub(repl, text) diff --git a/tests/test_talinterpreter.py b/tests/test_talinterpreter.py index 085c47f..270e17b 100644 --- a/tests/test_talinterpreter.py +++ b/tests/test_talinterpreter.py @@ -22,11 +22,16 @@ import unittest from StringIO import StringIO +from zope.interface import implements +from zope.i18n.interfaces import ITranslationDomain + from zope.tal.taldefs import METALError, I18NError, TAL_VERSION from zope.tal.htmltalparser import HTMLTALParser from zope.tal.talparser import TALParser from zope.tal.talinterpreter import TALInterpreter -from zope.tal.dummyengine import DummyEngine, DummyTranslationDomain +from zope.tal.dummyengine import DummyEngine +from zope.tal.dummyengine import MultipleDomainsDummyEngine +from zope.tal.dummyengine import DummyTranslationDomain from zope.tal.tests import utils from zope.i18nmessageid import MessageID, Message @@ -122,6 +127,10 @@ class MacroExtendTestCase(TestCaseBase): self.assertEqual(actual, expected) + + + + class I18NCornerTestCaseBase(TestCaseBase): def factory(self, msgid, default, mapping={}): @@ -159,16 +168,6 @@ class I18NCornerTestCaseBase(TestCaseBase): '</div>') self._check(program, '<div>FOOVALUE</div>\n') - def test_unused_explicit_domain(self): - # constructs a msgid and set it up in the namespace - self.engine.setLocal('baz', - self.factory('BaZvAlUe', 'default', {})) - program, macros = self._compile( - '<div i18n:translate=""' - ' i18n:domain="a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine"' - ' tal:content="baz" />') - self._check(program, '<div>BAZVALUE</div>\n') - def test_pythonexpr_replace_with_messageid_and_i18nname(self): program, macros = self._compile( '<div i18n:translate="" >' @@ -389,13 +388,60 @@ class I18NCornerTestCaseBase(TestCaseBase): "Foo <span tal:replace='bar' i18n:name='bar' /></div>") self._check(program, u"<div>FOO \u00C0</div>\n") + class I18NCornerTestCaseMessageID(I18NCornerTestCaseBase): - def factory(self, msgid, default=None, mapping={}): + def factory(self, msgid, default=None, mapping={}, domain=None): m = MessageID(msgid, default=default) m.mapping = mapping return m +class UnusedExplicitDomainTestCase(I18NCornerTestCaseMessageID): + + def factory(self, msgid, default=None, mapping={}, domain=None): + m = MessageID(msgid, default=default, domain=domain) + m.mapping = mapping + return m + + + def setUp(self): + self.engine = MultipleDomainsDummyEngine() + # Make sure we'll translate the msgid not its unicode representation + self.engine.setLocal('foo', + self.factory('FoOvAlUe${empty}', 'default', {'empty': ''})) + self.engine.setLocal('bar', 'BaRvAlUe') + self.engine.setLocal('baz', + self.factory('BaZvAlUe', 'default', {})) + # Message ids with different domains + self.engine.setLocal('tolower', + self.factory('ToLower', 'default', {}, domain='lower')) + self.engine.setLocal('toupper', + self.factory('ToUpper', 'default', {})) + self.engine.setLocal('othertolower', + self.factory('OtherToLower', 'a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine', {}, domain='lower')) + + def test_multiple_domains(self): + program, macros = self._compile( + '<div i18n:translate=""' + ' tal:content="toupper" />') + self._check(program, '<div>TOUPPER</div>\n') + program, macros = self._compile( + '<div i18n:translate=""' + ' tal:content="tolower" />') + self._check(program, '<div>tolower</div>\n') + program, macros = self._compile( + '<div i18n:translate=""' + ' tal:content="othertolower" />') + self._check(program, '<div>othertolower</div>\n') + + + def test_unused_explicit_domain(self): + program, macros = self._compile( + '<div i18n:translate=""' + ' i18n:domain="a_very_explicit_domain_setup_by_template_developer_that_wont_be_taken_into_account_by_the_ZPT_engine"' + ' tal:content="baz" />') + self._check(program, '<div>BAZVALUE</div>\n') + class I18NCornerTestCaseMessage(I18NCornerTestCaseBase): def factory(self, msgid, default=None, mapping={}): @@ -622,6 +668,7 @@ def test_suite(): suite.addTest(unittest.makeSuite(ScriptTestCase)) suite.addTest(unittest.makeSuite(I18NCornerTestCaseMessageID)) suite.addTest(unittest.makeSuite(I18NCornerTestCaseMessage)) + suite.addTest(unittest.makeSuite(UnusedExplicitDomainTestCase)) suite.addTest(unittest.makeSuite(TestSourceAnnotations)) # TODO: Deactivated test, since we have not found a solution for this and |