bgoncalv / rpms / gettext

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