changeset 871:7eb6f506bb54

Allow the use of `i18n:singular` and `i18n:plural` as directives and not just as attributes. If `py:strip` is involved on `i18n:singular` or `i18n:plural` directives, only apply the strip directive once the singular or plural form has been chosen and translated. Fixes #371.
author palgarvio
date Tue, 23 Feb 2010 16:03:26 +0000
parents 1ea88e82713d
children e966d7a20d48
files genshi/filters/i18n.py genshi/filters/tests/i18n.py
diffstat 2 files changed, 105 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/filters/i18n.py
+++ b/genshi/filters/i18n.py
@@ -193,19 +193,36 @@
 
 class ChooseBranchDirective(I18NDirective):
     __slots__ = ['params']
-
+        
     def __call__(self, stream, directives, ctxt, **vars):
         self.params = ctxt.get('_i18n.choose.params', [])[:]
         msgbuf = MessageBuffer(self)
 
         stream = iter(_apply_directives(stream, directives, ctxt, vars))
-        yield stream.next() # the outer start tag
+        
         previous = stream.next()
+        if previous[0] is START:
+            yield previous
+        else:
+            msgbuf.append(*previous)
+            
+        try:
+            previous = stream.next()
+        except StopIteration:
+            # For example <i18n:singular> or <i18n:plural> directives
+            yield MSGBUF, (), -1 # the place holder for msgbuf output
+            ctxt['_i18n.choose.%s' % type(self).__name__] = msgbuf
+            return
+        
         for kind, data, pos in stream:
             msgbuf.append(*previous)
             previous = kind, data, pos
         yield MSGBUF, (), -1 # the place holder for msgbuf output
-        yield previous # the outer end tag
+
+        if previous[0] is END:
+            yield previous # the outer end tag
+        else:
+            msgbuf.append(*previous)
         ctxt['_i18n.choose.%s' % type(self).__name__] = msgbuf
 
 
@@ -330,12 +347,27 @@
         for kind, event, pos in stream:
             if kind is SUB:
                 subdirectives, substream = event
+                strip_directive_present = []
+                for idx, subdirective in enumerate(subdirectives):
+                    if isinstance(subdirective, StripDirective):
+                        # XXX: Any strip directive should be applied AFTER the
+                        # event's have been translated and singular or plural
+                        # form has been chosen. So, by having py:strip on
+                        # an i18n:singular element is as if i18n:plural had it
+                        # too.
+                        strip_directive_present.append(subdirectives.pop(idx))
                 if isinstance(subdirectives[0],
                               SingularDirective) and not singular_stream:
                     # Apply directives to update context
                     singular_stream = list(_apply_directives(substream,
                                                              subdirectives,
                                                              ctxt, vars))
+                    if strip_directive_present:
+                        singular_stream = list(
+                            _apply_directives(singular_stream,
+                                              strip_directive_present,
+                                              ctxt, vars)
+                        )
                     new_stream.append((MSGBUF, (), ('', -1))) # msgbuf place holder
                     singular_msgbuf = ctxt.get('_i18n.choose.SingularDirective')
                 elif isinstance(subdirectives[0],
--- a/genshi/filters/tests/i18n.py
+++ b/genshi/filters/tests/i18n.py
@@ -932,6 +932,32 @@
           <p>FooBar</p>
         </html>""", tmpl.generate(one=1, two=2).render())
 
+    def test_translate_i18n_choose_plural_singular_as_directive(self):
+        # Ticket 371
+        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
+            xmlns:i18n="http://genshi.edgewall.org/i18n">
+        <i18n:choose numeral="two">
+          <i18n:singular>FooBar</i18n:singular>
+          <i18n:plural>FooBars</i18n:plural>
+        </i18n:choose>
+        <i18n:choose numeral="one">
+          <i18n:singular>FooBar</i18n:singular>
+          <i18n:plural>FooBars</i18n:plural>
+        </i18n:choose>
+        </html>""")
+        translations = DummyTranslations({
+            ('FooBar', 0): 'FuBar',
+            ('FooBars', 1): 'FuBars',
+            'FooBar': 'FuBar',
+            'FooBars': 'FuBars',
+        })
+        translator = Translator(translations)
+        translator.setup(tmpl)
+        self.assertEqual("""<html>
+          FuBars
+          FuBar
+        </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">
@@ -1403,6 +1429,50 @@
             <p>Vohs John Doe</p>
           </div>
         </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render())
+        
+    def test_translate_i18n_choose_and_singular_with_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="" py:strip="">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>
+            Vohs John Doe
+          </div>
+        </html>""", tmpl.generate(two=2, fname='John', lname='Doe').render())
+        
+    def test_translate_i18n_choose_and_plural_with_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="" py:strip="">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>
+            Voh John Doe
+          </div>
+        </html>""", tmpl.generate(two=1, fname='John', lname='Doe').render())
 
     def test_extract_i18n_msg_with_py_strip(self):
         tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
Copyright (C) 2012-2017 Edgewall Software