#!/usr/local/bin/python2.3 # -*- mode: Python; coding: utf-8; -*- # PO file consistency checker # # Pedro Morais # José Nuno Pires # (c) Copyright 2003, 2004 # Distributable under the terms of the GPL - see COPYING import sys import os import getopt if not "/usr/local/lib/python2.3/site-packages/gettext-lint" in sys.path: sys.path.append("/usr/local/lib/python2.3/site-packages/gettext-lint") from POFile import POFile from Equivalent import Equivalent from util import Output def usage(code = -1): w = sys.stderr.write w('Usage: POFileConsistency [OPTION] ...\n') w('\n') w('Mandatory arguments to long options are mandatory ' 'for short options too.\n') w('\n') w('Options:\n') w(' -h, --help show this help\n') w(' -i, --interactive interactive console mode\n') w(' -e, --equivalent= load an equivalences file\n') w(' -o, --only-empty only check empty msgstrs\n') w(' -m, --match= only check files matching this name\n') w(' -r, --strip-chars= remove this chars from the msgids\n') sys.exit(code) try: opts, args = getopt.getopt(sys.argv[1:], "hioe:m:r:", ["help", "interactive", "only-empty", "equivalent=", "match=", "strip-chars="]) except getopt.GetoptError: usage() interactive = 0 equivalentfiles = [] onlyempty = 0 match = None strip = '' for o, a in opts: if o in ("-h", "--help"): usage(0) if o in ("-i", "--interactive"): interactive = 1 if o in ("-o", "--only-empty"): onlyempty = 1 if o in ("-e", "--equivalent"): equivalentfiles.append(a) if o in ("-m", "--match"): match = a if o in ("-r", "--strip-chars"): strip = a if len(args) < 1: usage() equivalent = Equivalent() for i in equivalentfiles: equivalent.parse(os.path.expandvars(os.path.expanduser(i)), strip) map = {} for filename in args: po = POFile(filename) po.ignoreFuzzy = 1 if po.consistency(map, strip) == 0: sys.stderr.write('error parsing file %s\n' % filename) def addIgnoreConsistency(po, e): header = po.data[0][3] header = header + ('X-POFile-IgnoreConsistency: %s\\n' % e) lines = po.prepare_replace(1) if lines != None: file = open(po.filename, 'w') po.execute_replace(lines, header, 1, file, breaknewlines = 1) file.close() po.data[0] = (po.data[0][0], po.data[0][1], po.data[0][2], header, po.data[0][3]) return 1 return 0 def inconsistent(msgid, result, equivalent): if len(result) < 2: return 0 if equivalent.check(msgid, result): return 0 if onlyempty: ccc = 0 for msgstr in result.keys(): if not msgstr or not len(msgstr): ccc = 1 if ccc == 0: return 0 if match: ccc = 0 for filenames in result.values(): for filename, line in filenames: if filename.find(match) >= 0: ccc = 1 if ccc == 0: return 0 return 1 def consistency(map, equivalent): out = Output("po-file-consistency") for msgid, result in map.iteritems(): if not inconsistent(msgid, result, equivalent): continue out.opentag('inconsistency') out.opentag('msgid', body = msgid, close = 1) for msgstr, filenames in result.iteritems(): out.opentag('msgstr') out.opentag('content', body = msgstr, close = 1) for fx, message in filenames: out.opentag('filename', { 'message': str(message) }, body = fx, close = 1) out.closetag() out.closetag() out.finish() def interactiveConsistency(map, equivalent): current = 0 total = 0 for msgid, result in map.iteritems(): if inconsistent(msgid, result, equivalent): total = total + 1 for msgid, result in map.iteritems(): if not inconsistent(msgid, result, equivalent): continue current = current + 1 print '*** msgid (%d/%d):\n%s' % (current, total, msgid) print c = 0 for msgstr, filenames in result.iteritems(): c = c + 1 print '*** msgstr %d in' % c, for fx, message in filenames: print fx, print ':' print msgstr print addtofilemessage = '' if len(equivalentfiles): addtofilemessage = "'a' to add to ignore list, " x = raw_input("1 - %d to fix consistency, 0 to input text, %s\n" "'l' to add to each file local ignore list, " "other to continue: " % (c, addtofilemessage)) if len(equivalentfiles) and x == 'a': print '+++ Adding to file %s' % equivalentfiles[0] print '+++' efile = open(equivalentfiles[0], 'a') print '+++ %s' % msgid efile.write('\n') efile.write('%s\n' % msgid) for msgstr, filenames in result.iteritems(): print '+++ %s' % msgstr efile.write('%s\n' % msgstr) print efile.close() continue elif x == 'l': for msgstr, filenames in result.iteritems(): for fx, message in filenames: po = POFile(fx) po.parse() po.parseHeader() if addIgnoreConsistency(po, msgid): print '+++ Add ignore consistency to %s - %s' % ( fx, msgid) else: print '+++ Error adding ignore consistency to %s' % fx continue n = -1 try: n = int(x) except: pass if n >= 0 and n <= c: newmsgstr = None if n == 0: newmsgstr = raw_input('Enter new message: ') else: c = 0 for msgstr, filenames in result.iteritems(): c = c + 1 if c == n: newmsgstr = msgstr break c = 0 for msgstr, filenames in result.iteritems(): c = c + 1 if c != n: for fx, message in filenames: print '+++ Fix consistency in %s,%d,%s' % ( fx, message, newmsgstr) po = POFile(fx) po.parse() po.parseHeader() lines = po.prepare_replace(message) if lines != None: file = open(fx, 'w') po.execute_replace(lines, newmsgstr, 1, file) file.close() print if interactive: interactiveConsistency(map, equivalent) else: consistency(map, equivalent)