Mercurial > genshi > mirror
changeset 787:d7366797440f trunk
Add support for supplying comments on localizable messages in the i18n filter. Based on patch by Pedro Algarvio on #129.
author | cmlenz |
---|---|
date | Thu, 07 Aug 2008 23:15:11 +0000 |
parents | 291700beaa94 |
children | 31432f30a6fb |
files | genshi/filters/i18n.py genshi/filters/tests/i18n.py |
diffstat | 2 files changed, 66 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/genshi/filters/i18n.py +++ b/genshi/filters/i18n.py @@ -129,9 +129,11 @@ translate = self.translate if not self.extract_text: search_text = False + + ns_prefixes = [] skip = 0 + i18n_comment = I18N_NAMESPACE['comment'] i18n_msg = I18N_NAMESPACE['msg'] - ns_prefixes = [] xml_lang = XML_NAMESPACE['lang'] for kind, data, pos in stream: @@ -180,7 +182,7 @@ if params and type(params) is list: # event tuple params = params[0][1] msgbuf = MessageBuffer(params) - attrs -= i18n_msg + attrs -= (i18n_comment, i18n_msg) yield kind, (tag, attrs), pos @@ -226,13 +228,16 @@ """Extract localizable strings from the given template stream. For every string found, this function yields a ``(lineno, function, - message)`` tuple, where: + message, comments)`` tuple, where: * ``lineno`` is the number of the line on which the string was found, * ``function`` is the name of the ``gettext`` function used (if the string was extracted from embedded Python code), and * ``message`` is the string itself (a ``unicode`` object, or a tuple - of ``unicode`` objects for functions with multiple string arguments). + of ``unicode`` objects for functions with multiple string + arguments). + * ``comments`` is a list of comments related to the message, extracted + from ``i18n:comment`` attributes found in the markup >>> from genshi.template import MarkupTemplate >>> @@ -247,8 +252,8 @@ ... </body> ... </html>''', filename='example.html') >>> - >>> for lineno, funcname, message in Translator().extract(tmpl.stream): - ... print "%d, %r, %r" % (lineno, funcname, message) + >>> for line, func, msg, comments in Translator().extract(tmpl.stream): + ... print "%d, %r, %r" % (line, func, msg) 3, None, u'Example' 6, None, u'Example' 7, '_', u'Hello, %(name)s' @@ -265,10 +270,13 @@ :note: Changed in 0.4.1: For a function with multiple string arguments (such as ``ngettext``), a single item with a tuple of strings is yielded, instead an item for each string argument. + :note: Changed in 0.6: The returned tuples now include a 4th element, + which is a list of comments for the translator """ if not self.extract_text: search_text = False skip = 0 + i18n_comment = I18N_NAMESPACE['comment'] i18n_msg = I18N_NAMESPACE['msg'] xml_lang = XML_NAMESPACE['lang'] @@ -293,33 +301,37 @@ if name in self.include_attrs: text = value.strip() if text: - yield pos[1], None, text + yield pos[1], None, text, [] else: - for lineno, funcname, text in self.extract( + for lineno, funcname, text, comments in self.extract( _ensure(value), gettext_functions, search_text=False): - yield lineno, funcname, text + yield lineno, funcname, text, comments if msgbuf: msgbuf.append(kind, data, pos) - elif i18n_msg in attrs: - params = attrs.get(i18n_msg) - if params and type(params) is list: # event tuple - params = params[0][1] - msgbuf = MessageBuffer(params, pos[1]) + else: + msg_params = attrs.get(i18n_msg) + if msg_params is not None: + if type(msg_params) is list: # event tuple + msg_params = msg_params[0][1] + msgbuf = MessageBuffer( + msg_params, attrs.get(i18n_comment), pos[1] + ) elif not skip and search_text and kind is TEXT: if not msgbuf: text = data.strip() if text and filter(None, [ch.isalpha() for ch in text]): - yield pos[1], None, text + yield pos[1], None, text, [] else: msgbuf.append(kind, data, pos) elif not skip and msgbuf and kind is END: msgbuf.append(kind, data, pos) if not msgbuf.depth: - yield msgbuf.lineno, None, msgbuf.format() + yield msgbuf.lineno, None, msgbuf.format(), \ + filter(None, [msgbuf.comment]) msgbuf = None elif kind is EXPR or kind is EXEC: @@ -327,15 +339,15 @@ msgbuf.append(kind, data, pos) for funcname, strings in extract_from_code(data, gettext_functions): - yield pos[1], funcname, strings + yield pos[1], funcname, strings, [] elif kind is SUB: subkind, substream = data messages = self.extract(substream, gettext_functions, search_text=search_text and not skip, msgbuf=msgbuf) - for lineno, funcname, text in messages: - yield lineno, funcname, text + for lineno, funcname, text, comments in messages: + yield lineno, funcname, text, comments class MessageBuffer(object): @@ -344,7 +356,7 @@ :since: version 0.5 """ - def __init__(self, params=u'', lineno=-1): + def __init__(self, params=u'', comment=None, lineno=-1): """Initialize the message buffer. :param params: comma-separated list of parameter names @@ -353,6 +365,7 @@ belonging to the message was found """ self.params = [name.strip() for name in params.split(',')] + self.comment = comment self.lineno = lineno self.string = [] self.events = {} @@ -545,6 +558,5 @@ tmpl = template_class(fileobj, filename=getattr(fileobj, 'name', None), encoding=encoding) translator = Translator(None, ignore_tags, include_attrs, extract_text) - for lineno, func, message in translator.extract(tmpl.stream, - gettext_functions=keywords): - yield lineno, func, message, [] + for message in translator.extract(tmpl.stream, gettext_functions=keywords): + yield message
--- a/genshi/filters/tests/i18n.py +++ b/genshi/filters/tests/i18n.py @@ -44,7 +44,7 @@ translator = Translator(extract_text=False) messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((3, 'ngettext', (u'Singular', u'Plural', None)), + self.assertEqual((3, 'ngettext', (u'Singular', u'Plural', None), []), messages[0]) def test_extract_plural_form(self): @@ -54,7 +54,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, 'ngettext', (u'Singular', u'Plural', None)), + self.assertEqual((2, 'ngettext', (u'Singular', u'Plural', None), []), messages[0]) def test_extract_funky_plural_form(self): @@ -64,7 +64,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, 'ngettext', (None, None)), messages[0]) + self.assertEqual((2, 'ngettext', (None, None), []), messages[0]) def test_extract_gettext_with_unicode_string(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -73,7 +73,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, 'gettext', u'Gr\xfc\xdfe'), messages[0]) + self.assertEqual((2, 'gettext', u'Gr\xfc\xdfe', []), messages[0]) def test_extract_included_attribute_text(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -82,7 +82,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, None, u'Foo'), messages[0]) + self.assertEqual((2, None, u'Foo', []), messages[0]) def test_extract_attribute_expr(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -91,7 +91,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, '_', u'Save'), messages[0]) + self.assertEqual((2, '_', u'Save', []), messages[0]) def test_extract_non_included_attribute_interpolated(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -100,7 +100,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, None, u'Foo'), messages[0]) + self.assertEqual((2, None, u'Foo', []), messages[0]) def test_extract_text_from_sub(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -109,7 +109,7 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, None, u'Foo'), messages[0]) + self.assertEqual((2, None, u'Foo', []), messages[0]) def test_ignore_tag_with_fixed_xml_lang(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -126,7 +126,8 @@ translator = Translator() messages = list(translator.extract(tmpl.stream)) self.assertEqual(1, len(messages)) - self.assertEqual((2, None, u'(c) 2007 Edgewall Software'), messages[0]) + self.assertEqual((2, None, u'(c) 2007 Edgewall Software', []), + messages[0]) def test_ignore_attribute_with_expression(self): tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/"> @@ -369,6 +370,27 @@ # <p><input type="text" name="num" value="x"/> Einträge pro Seite anzeigen.</p> # </html>""", tmpl.generate().render()) + def test_extract_i18n_msg_with_comment(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> + </html>""") + translator = Translator() + messages = list(translator.extract(tmpl.stream)) + self.assertEqual(1, len(messages)) + self.assertEqual((3, None, u'Foo', ['As in foo bar']), messages[0]) + + def test_translate_i18n_msg_with_comment(self): + tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" + xmlns:i18n="http://genshi.edgewall.org/i18n"> + <p i18n:msg="" i18n:comment="As in foo bar">Foo</p> + </html>""") + gettext = lambda s: u"Voh" + tmpl.filters.insert(0, Translator(gettext)) + self.assertEqual("""<html> + <p>Voh</p> + </html>""", tmpl.generate().render()) + class ExtractTestCase(unittest.TestCase):