From b132a73f15e432eaf43310fce9196ca0c0651465 Mon Sep 17 00:00:00 2001
From:  <>
Date: Thu, 2 Jan 2003 05:25:50 +0000
Subject: This commit was manufactured by cvs2svn to create branch
 'Release_2_1-maint'.

---
 bin/transcheck | 405 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 405 insertions(+)
 create mode 100755 bin/transcheck

(limited to 'bin/transcheck')

diff --git a/bin/transcheck b/bin/transcheck
new file mode 100755
index 00000000..fbb0dcd8
--- /dev/null
+++ b/bin/transcheck
@@ -0,0 +1,405 @@
+#! @PYTHON@
+#
+# transcheck - (c) 2002 by Simone Piunno <pioppo@ferrara.linux.it>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the version 2.0 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""
+Check a given Mailman translation, making sure that variables and
+tags referenced in translation are the same variables and tags in
+the original templates and catalog.
+
+Usage:
+
+cd $MAILMAN_DIR
+%(program)s [-q] <lang>
+
+Where <lang> is your country code (e.g. 'it' for Italy) and -q is
+to ask for a brief summary.
+"""
+
+import sys
+import re
+import os
+import getopt
+
+import paths
+from Mailman.i18n import _
+
+program = sys.argv[0]
+
+
+
+def usage(code, msg=''):
+    if code:
+        fd = sys.stderr
+    else:
+        fd = sys.stdout
+    print >> fd, _(__doc__)
+    if msg:
+        print >> fd, msg
+    sys.exit(code)
+
+
+
+class TransChecker:
+    "check a translation comparing with the original string"
+    def __init__(self, regexp):
+        self.dict = {}
+        self.errs = []
+        self.regexp = re.compile(regexp)
+
+    def checkin(self, string):
+        "scan a string from the original file"
+        for key in self.regexp.findall(string):
+            if self.dict.has_key(key):
+                self.dict[key] += 1
+            else:
+                self.dict[key] = 1
+
+    def checkout(self, string):
+        "scan a translated string"
+        for key in self.regexp.findall(string):
+            if self.dict.has_key(key):
+                self.dict[key] -= 1
+            else:
+                self.errs.append(
+                    "%(key)s was not found" %
+                    { 'key' : key }
+                )
+
+    def computeErrors(self):
+        "check for differences between checked in and checked out"
+        for key in self.dict.keys():
+            if self.dict[key] < 0:
+                self.errs.append(
+                    "Too much %(key)s" %
+                    { 'key'  : key }
+                )
+            if self.dict[key] > 0:
+                self.errs.append(
+                    "Too few %(key)s" %
+                    { 'key'  : key }
+                )
+        return self.errs
+
+    def status(self):
+        if self.errs:
+            return "FAILED"
+        else:
+            return "OK"
+
+    def errorsAsString(self):
+        msg = ""
+        for err in self.errs:
+            msg += " - %(err)s" % { 'err': err }
+        return msg
+
+    def reset(self):
+        self.dict = {}
+        self.errs = []
+
+
+
+class POParser:
+    "parse a .po file extracting msgids and msgstrs"
+    def __init__(self, filename=""):
+        self.status = 0
+        self.files = []
+        self.msgid = ""
+        self.msgstr = ""
+        self.line = 1
+        self.f = None
+        self.esc = { "n": "\n", "r": "\r", "t": "\t" }
+        if filename:
+            self.f = open(filename)
+
+    def open(self, filename):
+        self.f = open(filename)
+
+    def close(self):
+        self.f.close()
+
+    def parse(self):
+        """States table for the finite-states-machine parser:
+            0  idle
+            1  filename-or-comment
+            2  msgid
+            3  msgstr
+            4  end
+        """
+        # each time we can safely re-initialize those vars
+        self.files = []
+        self.msgid = ""
+        self.msgstr = ""
+
+
+        # can't continue if status == 4, this is a dead status
+        if self.status == 4:
+            return 0
+
+        while 1:
+            # continue scanning, char-by-char
+            c = self.f.read(1)
+            if not c:
+                # EOF -> maybe we have a msgstr to save?
+                self.status = 4
+                if self.msgstr:
+                    return 1
+                else:
+                    return 0
+
+            # keep the line count up-to-date
+            if c == "\n":
+                self.line += 1
+
+            # a pound was detected the previous char...
+            if self.status == 1:
+                if c == ":":
+                    # was a line of filenames
+                    row = self.f.readline()
+                    self.files += row.split()
+                    self.line += 1
+                elif c == "\n":
+                    # was a single pount on the line
+                    pass
+                else:
+                    # was a comment... discard
+                    self.f.readline()
+                    self.line += 1
+                # in every case, we switch to idle status
+                self.status = 0;
+                continue
+
+            # in idle status we search for a '#' or for a 'm'
+            if self.status == 0:
+                if   c == "#":
+                    # this could be a comment or a filename
+                    self.status = 1;
+                    continue
+                elif c == "m":
+                    # this should be a msgid start...
+                    s = self.f.read(4)
+                    assert s == "sgid"
+                    # so now we search for a '"'
+                    self.status = 2
+                    continue
+                # in idle only those other chars are possibile
+                assert c in [ "\n", " ", "\t" ]
+
+            # searching for the msgid string
+            if self.status == 2:
+                if c == "\n":
+                    # a double LF is not possible here
+                    c = self.f.read(1)
+                    assert c != "\n"
+                if c == "\"":
+                    # ok, this is the start of the string,
+                    # now search for the end
+                    while 1:
+                        c = self.f.read(1)
+                        if not c:
+                            # EOF, bailout
+                            self.status = 4
+                            return 0
+                        if c == "\\":
+                            # a quoted char...
+                            c = self.f.read(1)
+                            if self.esc.has_key(c):
+                                self.msgid += self.esc[c]
+                            else:
+                                self.msgid += c
+                            continue
+                        if c == "\"":
+                            # end of string found
+                            break
+                        # a normal char, add it
+                        self.msgid += c
+                if c == "m":
+                    # this should be a msgstr identifier
+                    s = self.f.read(5)
+                    assert s == "sgstr"
+                    # ok, now search for the msgstr string
+                    self.status = 3
+
+            # searching for the msgstr string
+            if self.status == 3:
+                if c == "\n":
+                    # a double LF is the end of the msgstr!
+                    c = self.f.read(1)
+                    if c == "\n":
+                        # ok, time to go idle and return
+                        self.status = 0
+                        self.line += 1
+                        return 1
+                if c == "\"":
+                    # start of string found
+                    while 1:
+                        c = self.f.read(1)
+                        if not c:
+                            # EOF, bail out
+                            self.status = 4
+                            return 1
+                        if c == "\\":
+                            # a quoted char...
+                            c = self.f.read(1)
+                            if self.esc.has_key(c):
+                                self.msgid += self.esc[c]
+                            else:
+                                self.msgid += c
+                            continue
+                        if c == "\"":
+                            # end of string
+                            break
+                        # a normal char, add it
+                        self.msgstr += c
+
+
+
+
+def check_file(translatedFile, originalFile, html=0, quiet=0):
+    """check a translated template against the original one
+       search also <MM-*> tags if html is not zero"""
+
+    if html:
+        c = TransChecker("(%\([^)]+\)[0-9]*[sd]|</?MM-[^>]+>)")
+    else:
+        c = TransChecker("(%\([^)]+\)[0-9]*[sd])")
+
+    try:
+        f = open(originalFile)
+    except IOError:
+        if not quiet:
+            print " - Can'open original file " + originalFile
+        return 1
+
+    while 1:
+        line = f.readline()
+        if not line: break
+        c.checkin(line)
+
+    f.close()
+
+    try:
+        f = open(translatedFile)
+    except IOError:
+        if not quiet:
+            print " - Can'open translated file " + translatedFile
+        return 1
+
+    while 1:
+        line = f.readline()
+        if not line: break
+        c.checkout(line)
+
+    f.close()
+
+    n = 0
+    msg = ""
+    for desc in c.computeErrors():
+        n +=1
+        if not quiet:
+            print " - %(desc)s" % { 'desc': desc }
+    return n
+
+
+
+def check_po(file, quiet=0):
+    "scan the po file comparing msgids with msgstrs"
+    n = 0
+    p = POParser(file)
+    c = TransChecker("(%\([^)]+\)[0-9]*[sdu]|%[0-9]*[sdu])")
+    while p.parse():
+        if p.msgstr:
+            c.reset()
+            c.checkin(p.msgid)
+            c.checkout(p.msgstr)
+            for desc in c.computeErrors():
+                n += 1
+                if not quiet:
+                    print " - near line %(line)d %(file)s: %(desc)s" % {
+                        'line': p.line,
+                        'file': p.files,
+                        'desc': desc
+                    }
+    p.close()
+    return n
+
+
+def main():
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'qh', ['quiet', 'help'])
+    except getopt.error, msg:
+        usage(1, msg)
+
+    quiet = 0
+    for opt, arg in opts:
+        if opt in ('-h', '--help'):
+            usage(0)
+        elif opt in ('-q', '--quiet'):
+            quiet = 1
+
+    if len(args) <> 1:
+        usage(1)
+
+    lang = args[0]
+
+    isHtml = re.compile("\.html$");
+    isTxt = re.compile("\.txt$");
+
+    numerrors = 0
+    numfiles = 0
+    try:
+        files = os.listdir("templates/" + lang + "/")
+    except:
+        print "can't open templates/%s/" % lang
+    for file in files:
+        fileEN = "templates/en/" + file
+        fileIT = "templates/" + lang + "/" + file
+        errlist = []
+        if isHtml.search(file):
+            if not quiet:
+                print "HTML checking " + fileIT + "... "
+            n = check_file(fileIT, fileEN, html=1, quiet=quiet)
+            if n:
+                numerrors += n
+                numfiles += 1
+        elif isTxt.search(file):
+            if not quiet:
+                print "TXT  checking " + fileIT + "... "
+            n = check_file(fileIT, fileEN, html=0, quiet=quiet)
+            if n:
+                numerrors += n
+                numfiles += 1
+
+        else:
+            continue
+
+    file = "messages/" + lang + "/LC_MESSAGES/mailman.po"
+    if not quiet:
+        print "PO   checking " + file + "... "
+    n = check_po(file, quiet=quiet)
+    if n:
+        numerrors += n
+        numfiles += 1
+
+    if quiet:
+        print "%(errs)u warnings in %(files)u files" % {
+            'errs':  numerrors,
+            'files': numfiles
+        }
+
+
+if __name__ == '__main__':
+    main()
-- 
cgit v1.2.3