[ZPT] CVS: Zope3/lib/python/Zope/TAL - TALInterpreter.py:1.63.10.3.4.3

Barry Warsaw barry@wooz.org
Tue, 4 Jun 2002 19:04:20 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/TAL
In directory cvs.zope.org:/tmp/cvs-serv30702

Modified Files:
      Tag: fdrake-tal-i18n-branch
	TALInterpreter.py 
Log Message:
First shot at implementing the i18n:translate attribute.  This is the
opcode interpreter part.

interpret(): code cleanup

attrAction(), attrAction_tal(): Handle i18n actions just like the
other actions.  (Also, in the later, do some local var renaming for
clarity).

do_insertTranslation(): Implementation of the `insertTranslation'
opcode.  The crufty bit is for handling implicit message ids,
(i.e. msgid='').  When an implicit msgid is used, the contents of the
tag, whitespace normalized is the msgid.  Unless I'm mistaken, the
easiest way to get the contents is to interpret() it into a StringIO
and then suck out the StringIO's contents.  I'm not sure if we really
want to do recursive processing on the implicit message ids, so this
might change.

translate(): New stub for calls into the TranslationService.  For now
we just upcase the message id.


=== Zope3/lib/python/Zope/TAL/TALInterpreter.py 1.63.10.3.4.2 => 1.63.10.3.4.3 ===
     bytecode_handlers = {}
 
-    def interpret(self, program, None=None):
+    def interpret(self, program):
         oldlevel = self.level
         self.level = oldlevel + 1
         handlers = self.dispatch
@@ -257,7 +257,7 @@
 
     def attrAction(self, item):
         name, value, action = item[:3]
-        if action == 'insert' or (action in ('metal', 'tal', 'xmlns')
+        if action == 'insert' or (action in ('metal', 'tal', 'xmlns', 'i18n')
                                   and not self.showtal):
             return 0, name, value
         macs = self.macroStack
@@ -289,10 +289,10 @@
 
     def attrAction_tal(self, item):
         name, value, action = item[:3]
-        if action in ('metal', 'tal', 'xmlns'):
+        if action in ('metal', 'tal', 'xmlns', 'i18n'):
             return self.attrAction(item)
         ok = 1
-        expr, xlat = item[3:]
+        expr, msgid = item[3:]
         if self.html and name.lower() in BOOLEAN_HTML_ATTRS:
             evalue = self.engine.evaluateBoolean(item[3])
             if evalue is self.Default:
@@ -313,7 +313,7 @@
                         ok = 0
                     value = evalue
         if ok:
-            if xlat:
+            if msgid:
                 value = self.i18n_attribute(value)
             if value is None:
                 value = name
@@ -436,6 +436,36 @@
             self.col = len(s) - (i + 1)
     bytecode_handlers["insertText"] = do_insertText
 
+    def do_insertTranslation(self, stuff):
+        msgid = stuff[0]
+        if msgid == '':
+            # The content is the implicit message id.  The easiest way to get
+            # the interpreted implicit message id is to interpret the
+            # subnodes, but we do /not/ want that going to the output stream.
+            # Fake our own into a StringIO, but be sure to always restore the
+            # original, even in the face of exceptions.
+            #
+            # XXX Do we really want to do recursive processing on the implicit
+            # message id?
+            ostream = self.stream
+            owrite = self._stream_write
+            self.stream = mfp = StringIO()
+            self._stream_write = mfp.write
+            try:
+                self.interpret(stuff[1])
+                msgid = mfp.getvalue()
+            finally:
+                self.stream = ostream
+                self._stream_write = owrite
+            # Now we need to normalize the whitespace in the implicit message
+            # id by stripping leading and trailing whitespace, and folding all
+            # internal whitespace to a single space.
+            msgid = ' '.join(msgid.split())
+        xlated_msgid = self.translate(msgid)
+        s = escape(xlated_msgid)
+        self._stream_write(s)
+    bytecode_handlers['insertTranslation'] = do_insertTranslation
+
     def do_insertStructure(self, stuff):
         self.interpret(stuff[2])
 
@@ -486,6 +516,10 @@
         while iterator.next():
             self.interpret(block)
     bytecode_handlers["loop"] = do_loop
+
+    def translate(self, msgid):
+        # XXX: need to fill this in with TranslationService calls
+        return msgid.upper()
 
     def do_rawtextColumn(self, (s, col)):
         self._stream_write(s)