Edgewall Software

Ticket #426: t426.diff

File t426.diff, 6.7 KB (added by cboos, 12 years ago)

as discussed in comment:5

  • genshi/filters/i18n.py

    # HG changeset patch
    # Parent 924949fd71673266ccb00169f99ae7cd47496d16
    i18n: `MessageBuffer.translate()` now uses the untranslated message as a fallback in case the translated message doesn't parse correctly.
    
    Fixes #426.
    
    
    diff -r 924949fd7167 -r e2398084da93 genshi/filters/i18n.py
    a b class MsgDirective(ExtractableI18NDirect 
    175175            if previous[0] is not END:
    176176                msgbuf.append(*previous)
    177177                previous = None
    178             for event in msgbuf.translate(gettext(msgbuf.format())):
     178            msg = msgbuf.format()
     179            for event in msgbuf.translate(gettext(msg), original=msg):
    179180                yield event
    180181            if previous:
    181182                yield previous
    class ChooseDirective(ExtractableI18NDir 
    411412            if kind is MSGBUF:
    412413                for event in choice:
    413414                    if event[0] is MSGBUF:
    414                         translation = ngettext(singular_msgbuf.format(),
    415                                               plural_msgbuf.format(),
     415                        msg = singular_msgbuf.format()
     416                        translation = ngettext(msg, plural_msgbuf.format(),
    416417                                               numeral)
    417                         for subevent in msgbuf.translate(translation):
     418                        for subevent in msgbuf.translate(translation,
     419                                                         original=msg):
    418420                            yield subevent
    419421                    else:
    420422                        yield event
    class MessageBuffer(object): 
    10151017        """
    10161018        return ''.join(self.string).strip()
    10171019
    1018     def translate(self, string, regex=re.compile(r'%\((\w+)\)s')):
     1020    def translate(self, string, regex=re.compile(r'%\((\w+)\)s'),
     1021                  original=None):
    10191022        """Interpolate the given message translation with the events in the
    10201023        buffer and return the translated stream.
    10211024       
    10221025        :param string: the translated message string
     1026        :param original: the untranslated message string, used as a fallback
     1027                         in case the translated message is unparsable
    10231028        """
    10241029        substream = None
    10251030
    class MessageBuffer(object): 
    10341039                    )
    10351040
    10361041        parts = parse_msg(string)
     1042        if parts is None:
     1043            if original is None:
     1044                raise ValueError("Malformed translated message '%s'" % string)
     1045            parts = parse_msg(original)
     1046            if parts is None:
     1047                raise ValueError("Malformed original message '%s'" % original)
    10371048        parts_counter = {}
    10381049        for order, string in parts:
    10391050            parts_counter.setdefault(order, []).append(None)
    def parse_msg(string, regex=re.compile(r 
    11231134    >>> parse_msg("[1:] Bilder pro Seite anzeigen.")
    11241135    [(1, ''), (0, ' Bilder pro Seite anzeigen.')]
    11251136   
     1137    >>> parse_msg("[1:t][2]t")
     1138
     1139   
    11261140    :param string: the translated message string
    1127     :return: a list of ``(order, string)`` tuples
     1141    :return: a list of ``(order, string)`` tuples or `None` if parsing failed.
    11281142    :rtype: `list`
    11291143    """
    11301144    parts = []
    def parse_msg(string, regex=re.compile(r 
    11461160        if not stack:
    11471161            break
    11481162
     1163    if stack != [0]:
     1164        return None
     1165
    11491166    if string:
    11501167        parts.append((stack[-1], string))
    11511168
  • genshi/filters/tests/i18n.py

    diff -r 924949fd7167 -r e2398084da93 genshi/filters/tests/i18n.py
    a b class MsgDirectiveTestCase(unittest.Test 
    502502          <p>Für <em>Details</em> siehe bitte <a href="help.html">Hilfe</a>.</p>
    503503        </html>""", tmpl.generate().render())
    504504
     505    def test_translate_i18n_msg_multiple_parse_msg_fallback(self):
     506        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
     507            xmlns:i18n="http://genshi.edgewall.org/i18n">
     508          <p i18n:msg="">
     509            Please see <a href="help.html">Help</a> for <em>details</em>.
     510          </p>
     511        </html>""")
     512        gettext = lambda s: u"Für [2:Details] siehe bitte [1 Hilfe]."
     513        translator = Translator(gettext)
     514        translator.setup(tmpl)
     515        self.assertEquals("""<html>
     516          <p>Please see <a href="help.html">Help</a> for <em>details</em>.</p>
     517        </html>""", tmpl.generate().render())
     518
    505519    def test_extract_i18n_msg_multiple_empty(self):
    506520        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
    507521            xmlns:i18n="http://genshi.edgewall.org/i18n">
    class ChooseDirectiveTestCase(unittest.T 
    13811395            <p title="Sachen">Da sind <a href="/things" title="Sachen betrachten">3 Sachen</a>.</p>
    13821396        </html>""", tmpl.generate(link="/things", num=3).render(encoding=None))
    13831397
     1398    def test_translate_i18n_choose_as_element_with_attributes_parse_msg_fallback(self):
     1399        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
     1400            xmlns:i18n="http://genshi.edgewall.org/i18n">
     1401          <i18n:choose numeral="num" params="num">
     1402            <p i18n:singular="" title="Things">
     1403              There is <a href="$link" title="View thing">${num} thing</a>.
     1404            </p>
     1405            <p i18n:plural="" title="Things">
     1406              There are <a href="$link" title="View things">${num} things</a>.
     1407            </p>
     1408          </i18n:choose>
     1409        </html>""")
     1410        translations = DummyTranslations({
     1411            'Things': 'Sachen',
     1412            'View thing': 'Sache betrachten',
     1413            'View things': 'Sachen betrachten',
     1414            ('There is [1:%(num)s thing].', 0): 'Da ist [1 %(num)s Sache].',
     1415            ('There are [1:%(num)s things].', 1): 'Da sind [1 %(num)s Sachen].'
     1416        })
     1417        translator = Translator(translations)
     1418        translator.setup(tmpl)
     1419        self.assertEqual(u"""<html>
     1420            <p title="Sachen">There is <a href="/things" title="Sache betrachten">1 thing</a>.</p>
     1421        </html>""", tmpl.generate(link="/things", num=1).render(encoding=None))
     1422        self.assertEqual(u"""<html>
     1423            <p title="Sachen">There are <a href="/things" title="Sachen betrachten">3 things</a>.</p>
     1424        </html>""", tmpl.generate(link="/things", num=3).render(encoding=None))
     1425
    13841426    def test_translate_i18n_choose_and_py_strip(self):
    13851427        tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"
    13861428            xmlns:i18n="http://genshi.edgewall.org/i18n">