[Zope3-checkins] CVS: Zope3/src/zope/tal - talgettext.py:1.3

Nathan R. Yergler nathan@yergler.net
Tue, 25 Mar 2003 18:46:36 -0500


Update of /cvs-repository/Zope3/src/zope/tal
In directory cvs.zope.org:/tmp/cvs-serv23850

Modified Files:
	talgettext.py 
Log Message:
Added update mode to talgettext; created rudimentary unit tests.


=== Zope3/src/zope/tal/talgettext.py 1.2 => 1.3 ===
--- Zope3/src/zope/tal/talgettext.py:1.2	Wed Dec 25 09:15:29 2002
+++ Zope3/src/zope/tal/talgettext.py	Tue Mar 25 18:46:03 2003
@@ -22,6 +22,11 @@
 Options:
     -h / --help
         Print this message and exit.
+    -o / --output <file>
+        Output the translation .po file to <file>.
+    -u / --update <file>
+        Update the existing translation <file> with any new translation strings
+        found.
 """
 
 import getopt
@@ -32,7 +37,7 @@
 from zope.tal.talinterpreter import TALInterpreter
 from zope.tal.dummyengine import DummyEngine
 from zope.tal.interfaces import ITALESEngine
-
+from zope.tal.taldefs import TALESError
 
 def usage(code, msg=''):
     # Python 2.1 required
@@ -51,24 +56,118 @@
         return 'who cares'
 
     def translate(self, domain, msgid, mapping):
+        # assume domain and mapping are ignored; if they are not,
+        # unit test must be updated.
         self.catalog[msgid] = ''
 
+class UpdatePOEngine(POEngine):
+    """A slightly-less braindead POEngine which supports loading an existing
+    .po file first."""
+    
+    def __init__ (self, macros=None, filename=None):
+        POEngine.__init__(self, macros)
+
+        self._filename = filename
+        self._loadFile()
+
+    def __add(self, id, str, fuzzy):
+        "Add a non-fuzzy translation to the dictionary."
+        if not fuzzy and str:
+            self.catalog[id] = str
+
+    def _loadFile(self):
+        # shamelessly cribbed from Python's Tools/i18n/msgfmt.py
+        # Nathan R. Yergler (nathan@zope.org)
+        # 25 March 2003
+        
+        ID = 1
+        STR = 2
+
+        try:
+            lines = open(self._filename).readlines()
+        except IOError, msg:
+            print >> sys.stderr, msg
+            sys.exit(1)
+
+        section = None
+        fuzzy = 0
+
+        # Parse the catalog
+        lno = 0
+        for l in lines:
+            lno += 1
+            # If we get a comment line after a msgstr, this is a new entry
+            if l[0] == '#' and section == STR:
+                self.__add(msgid, msgstr, fuzzy)
+                section = None
+                fuzzy = 0
+            # Record a fuzzy mark
+            if l[:2] == '#,' and l.find('fuzzy'):
+                fuzzy = 1
+            # Skip comments
+            if l[0] == '#':
+                continue
+            # Now we are in a msgid section, output previous section
+            if l.startswith('msgid'):
+                if section == STR:
+                    self.__add(msgid, msgstr, fuzzy)
+                section = ID
+                l = l[5:]
+                msgid = msgstr = ''
+            # Now we are in a msgstr section
+            elif l.startswith('msgstr'):
+                section = STR
+                l = l[6:]
+            # Skip empty lines
+            l = l.strip()
+            if not l:
+                continue
+            # XXX: Does this always follow Python escape semantics?
+            l = eval(l)
+            if section == ID:
+                msgid += l
+            elif section == STR:
+                msgstr += l
+            else:
+                print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
+                      'before:'
+                print >> sys.stderr, l
+                sys.exit(1)
+        # Add last entry
+        if section == STR:
+            self.__add(msgid, msgstr, fuzzy)
+
+    def evaluate(self, expression):
+        try:
+            return POEngine.evaluate(self, expression)
+        except TALESError:
+            pass
+    
+    def evaluatePathOrVar(self, expr):
+        return 'who cares'
 
+    def translate (self, domain, msgid, mapping):
+        if (msgid not in self.catalog.keys()):
+            self.catalog[msgid] = ''
+    
 def main():
     try:
         opts, args = getopt.getopt(
             sys.argv[1:],
-            'ho:',
-            ['help', 'output='])
+            'ho:u:',
+            ['help', 'output=', 'update='])
     except getopt.error, msg:
         usage(1, msg)
 
     outfile = None
+    engine = None
     for opt, arg in opts:
         if opt in ('-h', '--help'):
             usage(0)
         elif opt in ('-o', '--output'):
             outfile = arg
+        elif opt in ('-u', '--update'):
+            engine = UpdatePOEngine(filename=arg)
 
     if not args:
         print 'nothing to do'
@@ -79,8 +178,11 @@
         def write(self, s):
             pass
 
-    engine = POEngine()
+    if not engine:
+        engine = POEngine()
+        
     for file in args:
+        print file
         p = HTMLTALParser()
         p.parseFile(file)
         program, macros = p.getCode()