diff genshi/filters/i18n.py @ 790:da90cee22560 trunk

Merged the custom-directives branch back into trunk.
author cmlenz
date Wed, 10 Sep 2008 20:53:09 +0000
parents 31432f30a6fb
children f9e23d472a6e
line wrap: on
line diff
--- a/genshi/filters/i18n.py
+++ b/genshi/filters/i18n.py
@@ -23,7 +23,8 @@
 
 from genshi.core import Attrs, Namespace, QName, START, END, TEXT, START_NS, \
                         END_NS, XML_NAMESPACE, _ensure
-from genshi.template.base import Template, EXPR, SUB
+from genshi.template.base import DirectiveFactory, EXPR, SUB, _apply_directives
+from genshi.template.directives import Directive
 from genshi.template.markup import MarkupTemplate, EXEC
 
 __all__ = ['Translator', 'extract']
@@ -32,7 +33,42 @@
 I18N_NAMESPACE = Namespace('http://genshi.edgewall.org/i18n')
 
 
-class Translator(object):
+class CommentDirective(Directive):
+
+    __slots__ = []
+
+    @classmethod
+    def attach(cls, template, stream, value, namespaces, pos):
+        return None, stream
+
+
+class MsgDirective(Directive):
+
+    __slots__ = ['params']
+
+    def __init__(self, value, template, hints=None, namespaces=None,
+                 lineno=-1, offset=-1):
+        Directive.__init__(self, None, template, namespaces, lineno, offset)
+        self.params = [name.strip() for name in value.split(',')]
+
+    def __call__(self, stream, directives, ctxt, **vars):
+        msgbuf = MessageBuffer(self.params)
+
+        stream = iter(stream)
+        yield stream.next() # the outer start tag
+        previous = stream.next()
+        for event in stream:
+            msgbuf.append(*previous)
+            previous = event
+
+        gettext = ctxt.get('_i18n.gettext')
+        for event in msgbuf.translate(gettext(msgbuf.format())):
+            yield event
+
+        yield previous # the outer end tag
+
+
+class Translator(DirectiveFactory):
     """Can extract and translate localizable strings from markup streams and
     templates.
     
@@ -85,12 +121,18 @@
     exclude specific parts of a template from being extracted and translated.
     """
 
+    directives = [
+        ('comment', CommentDirective),
+        ('msg', MsgDirective)
+    ]
+
     IGNORE_TAGS = frozenset([
         QName('script'), QName('http://www.w3.org/1999/xhtml}script'),
         QName('style'), QName('http://www.w3.org/1999/xhtml}style')
     ])
     INCLUDE_ATTRS = frozenset(['abbr', 'alt', 'label', 'prompt', 'standby',
                                'summary', 'title'])
+    NAMESPACE = I18N_NAMESPACE
 
     def __init__(self, translate=NullTranslations(), ignore_tags=IGNORE_TAGS,
                  include_attrs=INCLUDE_ATTRS, extract_text=True):
@@ -113,7 +155,7 @@
         self.include_attrs = include_attrs
         self.extract_text = extract_text
 
-    def __call__(self, stream, ctxt=None, search_text=True, msgbuf=None):
+    def __call__(self, stream, ctxt=None, search_text=True):
         """Translate any localizable strings in the given stream.
         
         This function shouldn't be called directly. Instead, an instance of
@@ -126,23 +168,23 @@
         :param ctxt: the template context (not used)
         :param search_text: whether text nodes should be translated (used
                             internally)
-        :param msgbuf: a `MessageBuffer` object or `None` (used internally)
         :return: the localized stream
         """
         ignore_tags = self.ignore_tags
         include_attrs = self.include_attrs
+        skip = 0
+        xml_lang = XML_NAMESPACE['lang']
+
         if type(self.translate) is FunctionType:
             gettext = self.translate
         else:
             gettext = self.translate.ugettext
-        if not self.extract_text:
-            search_text = False
+        if ctxt:
+            ctxt['_i18n.gettext'] = gettext
 
-        ns_prefixes = []
-        skip = 0
-        i18n_comment = I18N_NAMESPACE['comment']
-        i18n_msg = I18N_NAMESPACE['msg']
-        xml_lang = XML_NAMESPACE['lang']
+        extract_text = self.extract_text
+        if not extract_text:
+            search_text = False
 
         for kind, data, pos in stream:
 
@@ -168,7 +210,7 @@
                 changed = False
                 for name, value in attrs:
                     newval = value
-                    if search_text and isinstance(value, basestring):
+                    if extract_text and isinstance(value, basestring):
                         if name in include_attrs:
                             newval = gettext(value)
                     else:
@@ -182,48 +224,23 @@
                 if changed:
                     attrs = Attrs(new_attrs)
 
-                if msgbuf:
-                    msgbuf.append(kind, data, pos)
-                    continue
-                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)
-                attrs -= (i18n_comment, i18n_msg)
-
                 yield kind, (tag, attrs), pos
 
             elif search_text and kind is TEXT:
-                if not msgbuf:
-                    text = data.strip()
-                    if text:
-                        data = data.replace(text, unicode(gettext(text)))
-                    yield kind, data, pos
-                else:
-                    msgbuf.append(kind, data, pos)
-
-            elif msgbuf and kind is EXPR:
-                msgbuf.append(kind, data, pos)
-
-            elif not skip and msgbuf and kind is END:
-                msgbuf.append(kind, data, pos)
-                if not msgbuf.depth:
-                    for event in msgbuf.translate(gettext(msgbuf.format())):
-                        yield event
-                    msgbuf = None
-                    yield kind, data, pos
+                text = data.strip()
+                if text:
+                    data = data.replace(text, unicode(gettext(text)))
+                yield kind, data, pos
 
             elif kind is SUB:
-                subkind, substream = data
-                new_substream = list(self(substream, ctxt, msgbuf=msgbuf))
-                yield kind, (subkind, new_substream), pos
-
-            elif kind is START_NS and data[1] == I18N_NAMESPACE:
-                ns_prefixes.append(data[0])
-
-            elif kind is END_NS and data in ns_prefixes:
-                ns_prefixes.remove(data)
+                directives, substream = data
+                # If this is an i18n:msg directive, no need to translate text
+                # nodes here
+                is_msg = filter(None, [isinstance(d, MsgDirective)
+                                       for d in directives])
+                substream = list(self(substream, ctxt,
+                                      search_text=not is_msg))
+                yield kind, (directives, substream), pos
 
             else:
                 yield kind, data, pos
@@ -372,7 +389,9 @@
         :param lineno: the line number on which the first stream event
                        belonging to the message was found
         """
-        self.params = [name.strip() for name in params.split(',')]
+        if isinstance(params, basestring):
+            params = [name.strip() for name in params.split(',')]
+        self.params = params
         self.comment = comment
         self.lineno = lineno
         self.string = []
Copyright (C) 2012-2017 Edgewall Software