summaryrefslogtreecommitdiffstats
path: root/msghack.py
diff options
context:
space:
mode:
Diffstat (limited to 'msghack.py')
-rwxr-xr-xmsghack.py421
1 files changed, 421 insertions, 0 deletions
diff --git a/msghack.py b/msghack.py
new file mode 100755
index 0000000..8d700e9
--- /dev/null
+++ b/msghack.py
@@ -0,0 +1,421 @@
+#!/usr/bin/python
+## -*- coding: utf-8 -*-
+## Copyright (C) 2001, 2008 Red Hat, Inc.
+## Copyright (C) 2001 Trond Eivind Glomsrød <teg@redhat.com>
+
+## v0.2 - 2001-08-21
+
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+
+## 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+"""
+A msghack replacement
+"""
+
+import string
+import sys
+
+class GTMessage:
+ """
+ A class containing a message, its msgid and various references pointing at it
+ """
+
+ def __init__(self,id=None,message=None,refs=[]):
+ """
+ The constructor for the GTMessage class
+ @self The object instance
+ @message The message
+ @id The messageid associated with the object
+ """
+ self._message=string.strip(message)
+ self._id=string.strip(id)
+ self._refs=[]
+ for ref in refs:
+ self._refs.append(ref)
+
+ def __str__(self):
+ """
+ Return a string representation of the object
+ @self The object instance
+ """
+ res=""
+ for ref in self._refs:
+ res=res+ref+"\n"
+ res=res+"msgid %s\nmsgstr %s\n" % (self._id,self._message)
+ return res
+
+ def invertedStrings(self):
+ """
+ Returns a string representation, but with msgid and msgstr inverted.
+ Note: Don't invert the "" string
+ @self The object instance
+ """
+ res=""
+ for ref in self._refs:
+ res=res+ref+"\n"
+ if not self._id=="\"\"":
+ res=res+"msgid %s\nmsgstr %s\n" % (self._message,self._id)
+ else:
+ res=res+"msgid %s\nmsgstr %s\n" % (self._id,self._message)
+ return res
+
+ def emptyMsgStrings(self):
+ """
+ Return a string representation of the object, but leave the msgstr
+ empty - create a pot file from a po file
+ Note: Won't remove the "" string
+ @self The object instance
+ """
+ res=""
+ for ref in self._refs:
+ res=res+ref+"\n"
+ if not self._id=="\"\"":
+ res=res+"msgid %s\nmsgstr \"\"\n" % (self._id)
+ else:
+ res=res+"msgid %s\nmsgstr %s\n" % (self._id,self._message)
+ return res
+
+ def compareMessage(self,msg):
+ """
+ Return if the messages have identical msgids, 0 otherwise
+ @self The object instance
+ @msg The message to compare to
+ """
+
+ if self._id == msg._id:
+ return 1
+ return 0
+
+
+class GTMasterMessage:
+ """
+ A class containing a message, its msgid and various references pointing at it
+ The difference between GTMessage and GTMasterMessage is that this class
+ can do less operations, but is able to store multiple msgstrs with identifiers
+ (usually language, like 'msgst(no)'
+ """
+
+ def __init__(self,id=None,refs=[]):
+ """
+ The constructor for the GTMessage class
+ @self The object instance
+ @id The messageid associated with the object
+ """
+ self._id=id
+ self._refs=[]
+ self._messages=[]
+ for ref in refs:
+ self._refs.append(ref)
+
+ def addMessage(self,message,identifier):
+ """
+ Add a new message and identifier to the GTMasterMessage object
+ @self The object instance
+ @message The message to append
+ @identifier The identifier of the message
+ """
+ self._messages.append((identifier,message))
+
+ def __str__(self):
+ """
+ Return a string representation of the object
+ @self The object instance
+ """
+ res=""
+ for ref in self._refs:
+ res=res+ref+"\n"
+ res=res+"msgid %s\n" % self._id
+ for message in self._messages:
+ res=res+"msgstr(%s) %s\n" %(message[0],message[1])
+ res=res+"\n"
+ return res
+
+class GTFile:
+ """
+ A class containing the GTMessages contained in a file
+ """
+
+ def __init__(self,filename):
+ """
+ The constructor of the GTMFile class
+ @self The object instance
+ @filename The file to initialize from
+ """
+ self._filename=filename
+ self._messages=[]
+ self.readFile(filename)
+
+ def __str__(self):
+ """
+ Return a string representation of the object
+ @self The object instance
+ """
+ res=""
+ for message in self._messages:
+ res=res+str(message)+"\n"
+ return res
+
+ def invertedStrings(self):
+ """
+ Return a string representation of the object, with msgid and msgstr
+ swapped. Will remove duplicates...
+ @self The object instance
+ """
+
+ msght={}
+ msgar=[]
+
+ for message in self._messages:
+ if message._id=='""' and len(msgar)==0:
+ msgar.append(GTMessage(message._id,message._message,message._refs))
+ continue
+ msg=GTMessage(message._message,message._id,message._refs)
+ if not msght.has_key(msg._id):
+ msght[msg._id]=msg
+ msgar.append(msg)
+ else:
+ msg2=msght[msg._id]
+ for ref in msg._refs:
+ msg2._refs.append(ref)
+ res=""
+ for message in msgar:
+ res=res+str(message)+"\n"
+ return res
+
+ def msgidDupes(self):
+ """
+ Search for duplicates in the msgids.
+ @self The object instance
+ """
+ msgids={}
+ res=""
+ for message in self._messages:
+ msgid=message._id
+ if msgids.has_key(msgid):
+ res=res+"Duplicate: %s\n" % (msgid)
+ else:
+ msgids[msgid]=1
+ return res
+
+ def getMsgstr(self,msgid):
+ """
+ Return the msgstr matching the given id. 'None' if missing
+ @self The object instance
+ @msgid The msgid key
+ """
+
+ for message in self._messages:
+ if msgid == message._id:
+ return message._message
+ return None
+
+ def emptyMsgStrings(self):
+ """
+ Return a string representation of the object, but leave the msgstr
+ empty - create a pot file from a po file
+ @self The object instance
+ """
+
+ res=""
+ for message in self._messages:
+ res=res+message.emptyMsgStrings()+"\n"
+ return res
+
+
+ def append(self,B):
+ """
+ Append entries from dictionary B which aren't
+ already present in this dictionary
+ @self The object instance
+ @B the dictionary to append messages from
+ """
+
+ for message in B._messages:
+ if not self.getMsgstr(message._id):
+ self._messages.append(message)
+
+
+ def readFile(self,filename):
+ """
+ Read the contents of a file into the GTFile object
+ @self The object instance
+ @filename The name of the file to read
+ """
+
+ file=open(filename,"r")
+ msgid=""
+ msgstr=""
+ refs=[]
+ lines=[]
+ inmsgid=0
+ inmsgstr=0
+ templines=file.readlines()
+ for line in templines:
+ lines.append(string.strip(line))
+ for line in lines:
+ pos=string.find(line,'"')
+ pos2=string.rfind(line,'"')
+ if line and line[0]=="#":
+ refs.append(string.strip(line))
+ if inmsgstr==0 and line[:6]=="msgstr":
+ msgstr=""
+ inmsgstr=1
+ inmsgid=0
+ if inmsgstr==1:
+ if pos==-1:
+ inmsgstr=0
+ #Handle entries with and without "" consistently
+ if msgid[:2]=='""' and len(msgid)>4:
+ msgid=msgid[2:]
+ if msgstr[:2]=='""' and len(msgstr)>4:
+ msgstr=msgstr[2:]
+ message=GTMessage(msgid,msgstr,refs)
+ self._messages.append(message)
+ msgstr=""
+ msgid=""
+ refs=[]
+ else:
+ msgstr=msgstr+line[pos:pos2+1]+"\n"
+ if inmsgid==0 and line[:5]=="msgid":
+ msgid=""
+ inmsgid=1
+ if inmsgid==1:
+ if pos==-1:
+ inmsgid=0
+ else:
+ msgid=msgid+line[pos:pos2+1]+"\n"
+ if msgstr and msgid:
+ message=GTMessage(msgid,msgstr,refs)
+ self._messages.append(message)
+
+
+class GTMaster:
+ """
+ A class containing a master catalogue of gettext dictionaries
+ """
+
+ def __init__(self,dicts):
+ """
+ The constructor for the GTMaster class
+ @self The object instance
+ @dicts An array of dictionaries to merge
+ """
+ self._messages=[]
+ self.createMaster(dicts)
+
+ def createMaster(self,dicts):
+ """
+ Create the master catalogue
+ @self The object instance
+ @dicts An array of dictionaries to merge
+ """
+
+ self._master=dicts[0]
+ self._dicts=dicts[1:]
+
+ for message in self._master._messages:
+ gtm=GTMasterMessage(message._id,message._refs)
+ gtm.addMessage(message._message,self._master._filename[:-3])
+ for dict in self._dicts:
+ res=dict.getMsgstr(message._id)
+ if(res):
+ gtm.addMessage(res,dict._filename[:-3])
+ self._messages.append(gtm)
+
+ def __str__(self):
+ """
+ Return a string representation of the object
+ @self The object instance
+ """
+ res=""
+ for message in self._messages:
+ res=res+str(message)+"\n"
+ return res
+
+def printUsage():
+ "Print the usage messages"
+ print "Usage: ", str(sys.argv[0])," [OPTION] file.po [ref.po]\n\
+This program can be used to alter .po files in ways no sane mind would think about.\n\
+ -o result will be written to FILE\n\
+ --invert invert a po file by switching msgid and msgstr\n\
+ --master join any number of files in a master-formatted catalog\n\
+ --empty empty the contents of the .po file, creating a .pot\n\
+ --append append entries from ref.po that don't exist in file.po\n\
+\n\
+Note: It is just a replacement of msghack for backward support.\n"
+
+
+if __name__=="__main__":
+ output=None
+ res=None
+ if("-o") in sys.argv:
+ if (len(sys.argv)<=sys.argv.index("-o")+1):
+ print "file.po and ref.po are not specified!\n"
+ printUsage()
+ exit(1)
+ output=sys.argv[sys.argv.index("-o")+1]
+ sys.argv.remove("-o")
+ sys.argv.remove(output)
+ if("--invert") in sys.argv:
+ if (len(sys.argv)<=sys.argv.index("--invert")+1):
+ print "file.po is not specified!\n"
+ printUsage()
+ exit(1)
+ file=sys.argv[sys.argv.index("--invert")+1]
+ gtf=GTFile(file)
+ res1=gtf.msgidDupes()
+ if res1:
+ sys.stderr.write(res1)
+ sys.exit(1)
+ res=str(gtf.invertedStrings())
+ elif("--empty") in sys.argv:
+ if (len(sys.argv)<=sys.argv.index("--empty")+1):
+ print "file.po is not specified!\n"
+ printUsage()
+ exit(1)
+ file=sys.argv[sys.argv.index("--empty")+1]
+ gtf=GTFile(file)
+ res=str(gtf.emptyMsgStrings())
+ elif("--master") in sys.argv:
+ if (len(sys.argv)<=sys.argv.index("--master")+1):
+ print "file.po is not specified!\n"
+ printUsage()
+ exit(1)
+ loc=sys.argv.index("--master")+1
+ gtfs=[]
+ for file in sys.argv[loc:]:
+ gtfs.append(GTFile(file))
+ master=GTMaster(gtfs)
+ res=str(master)
+ elif("--append") in sys.argv:
+ if (len(sys.argv)<=sys.argv.index("--append")+2):
+ print "file.po and/or ref.po are not specified!\n"
+ printUsage()
+ exit(1)
+ file=sys.argv[sys.argv.index("--append")+1]
+ file2=sys.argv[sys.argv.index("--append")+2]
+ gtf=GTFile(file)
+ gtf2=GTFile(file2)
+ gtf.append(gtf2)
+ res=str(gtf)
+ else:
+ #print "Not implemented: "+str(sys.argv)
+ printUsage()
+ sys.exit(1)
+ if not output:
+ print res
+ else:
+ file=open(output,"w")
+ file.write(res)
+ sys.exit(0)