Ticket #426: t426.2.diff
| File t426.2.diff, 6.7 KB (added by cboos, 12 years ago) |
|---|
-
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 genshi/filters/i18n.py
a b class MsgDirective(ExtractableI18NDirect 175 175 if previous[0] is not END: 176 176 msgbuf.append(*previous) 177 177 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): 179 180 yield event 180 181 if previous: 181 182 yield previous … … class ChooseDirective(ExtractableI18NDir 411 412 if kind is MSGBUF: 412 413 for event in choice: 413 414 if event[0] is MSGBUF: 414 translation = ngettext(singular_msgbuf.format(), 415 plural_msgbuf.format(), 416 numeral) 417 for subevent in msgbuf.translate(translation): 415 smsg = singular_msgbuf.format() 416 pmsg = plural_msgbuf.format() 417 orig = (pmsg, smsg)[numeral == 1] 418 translation = ngettext(smsg, pmsg, numeral) 419 for subevent in msgbuf.translate(translation, 420 original=orig): 418 421 yield subevent 419 422 else: 420 423 yield event … … class MessageBuffer(object): 1015 1018 """ 1016 1019 return ''.join(self.string).strip() 1017 1020 1018 def translate(self, string, regex=re.compile(r'%\((\w+)\)s')): 1021 def translate(self, string, regex=re.compile(r'%\((\w+)\)s'), 1022 original=None): 1019 1023 """Interpolate the given message translation with the events in the 1020 1024 buffer and return the translated stream. 1021 1025 1022 1026 :param string: the translated message string 1027 :param original: the untranslated message string, used as a fallback 1028 in case the translated message is unparsable 1023 1029 """ 1024 1030 substream = None 1025 1031 … … class MessageBuffer(object): 1034 1040 ) 1035 1041 1036 1042 parts = parse_msg(string) 1043 if parts is None: 1044 if original is None: 1045 raise ValueError("Malformed translated message '%s'" % string) 1046 parts = parse_msg(original) 1047 if parts is None: 1048 raise ValueError("Malformed original message '%s'" % original) 1037 1049 parts_counter = {} 1038 1050 for order, string in parts: 1039 1051 parts_counter.setdefault(order, []).append(None) … … def parse_msg(string, regex=re.compile(r 1123 1135 >>> parse_msg("[1:] Bilder pro Seite anzeigen.") 1124 1136 [(1, ''), (0, ' Bilder pro Seite anzeigen.')] 1125 1137 1138 >>> parse_msg("[1:t][2]t") 1139 1140 1126 1141 :param string: the translated message string 1127 :return: a list of ``(order, string)`` tuples 1142 :return: a list of ``(order, string)`` tuples or `None` if parsing failed. 1128 1143 :rtype: `list` 1129 1144 """ 1130 1145 parts = [] … … def parse_msg(string, regex=re.compile(r 1146 1161 if not stack: 1147 1162 break 1148 1163 1164 if stack != [0]: 1165 return None 1166 1149 1167 if string: 1150 1168 parts.append((stack[-1], string)) 1151 1169 -
genshi/filters/tests/i18n.py
diff -r 924949fd7167 genshi/filters/tests/i18n.py
a b class MsgDirectiveTestCase(unittest.Test 502 502 <p>Für <em>Details</em> siehe bitte <a href="help.html">Hilfe</a>.</p> 503 503 </html>""", tmpl.generate().render()) 504 504 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 505 519 def test_extract_i18n_msg_multiple_empty(self): 506 520 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 507 521 xmlns:i18n="http://genshi.edgewall.org/i18n"> … … class ChooseDirectiveTestCase(unittest.T 1381 1395 <p title="Sachen">Da sind <a href="/things" title="Sachen betrachten">3 Sachen</a>.</p> 1382 1396 </html>""", tmpl.generate(link="/things", num=3).render(encoding=None)) 1383 1397 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 is [1:%(num)s thing].', 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 1384 1426 def test_translate_i18n_choose_and_py_strip(self): 1385 1427 tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" 1386 1428 xmlns:i18n="http://genshi.edgewall.org/i18n">
