Package translate :: Package convert :: Module po2oo
[hide private]
[frames] | no frames]

Source Code for Module translate.convert.po2oo

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  #  
  4  # Copyright 2004-2006 Zuza Software Foundation 
  5  #  
  6  # This file is part of translate. 
  7  # 
  8  # translate is free software; you can redistribute it and/or modify 
  9  # it under the terms of the GNU General Public License as published by 
 10  # the Free Software Foundation; either version 2 of the License, or 
 11  # (at your option) any later version. 
 12  #  
 13  # translate is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License 
 19  # along with translate; if not, write to the Free Software 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 21  # 
 22   
 23  """convert Gettext PO localization files to an OpenOffice.org (SDF) localization file 
 24   
 25  see: http://translate.sourceforge.net/wiki/toolkit/po2oo for examples and  
 26  usage instructions 
 27  """ 
 28   
 29  import sys 
 30  import os 
 31  from translate.storage import oo 
 32  from translate.storage import factory 
 33  from translate.filters import pofilter 
 34  from translate.filters import checks 
 35  from translate.filters import autocorrect  
 36  import time 
 37   
38 -class reoo:
39 - def __init__(self, templatefile, languages=None, timestamp=None, includefuzzy=False, long_keys=False, filteraction="exclude"):
40 """construct a reoo converter for the specified languages (timestamp=0 means leave unchanged)""" 41 # languages is a pair of language ids 42 self.long_keys = long_keys 43 self.readoo(templatefile) 44 self.languages = languages 45 self.filteraction = filteraction 46 if timestamp is None: 47 self.timestamp = time.strptime("2002-02-02 02:02:02", "%Y-%m-%d %H:%M:%S") 48 else: 49 self.timestamp = timestamp 50 if self.timestamp: 51 self.timestamp_str = time.strftime("%Y-%m-%d %H:%M:%S", self.timestamp) 52 else: 53 self.timestamp_str = None 54 self.includefuzzy = includefuzzy
55
56 - def makeindex(self):
57 """makes an index of the oo keys that are used in the source file""" 58 self.index = {} 59 for ookey, theoo in self.o.ookeys.iteritems(): 60 sourcekey = oo.makekey(ookey, self.long_keys) 61 self.index[sourcekey] = theoo
62
63 - def readoo(self, of):
64 """read in the oo from the file""" 65 oosrc = of.read() 66 self.o = oo.oofile() 67 self.o.parse(oosrc) 68 self.makeindex()
69
70 - def handleunit(self, unit):
71 # TODO: make this work for multiple columns in oo... 72 locations = unit.getlocations() 73 # technically our formats should just have one location for each entry... 74 # but we handle multiple ones just to be safe... 75 for location in locations: 76 subkeypos = location.rfind('.') 77 subkey = location[subkeypos+1:] 78 key = location[:subkeypos] 79 # this is just to handle our old system of using %s/%s:%s instead of %s/%s#%s 80 key = key.replace(':', '#') 81 # this is to handle using / instead of \ in the sourcefile... 82 key = key.replace('\\', '/') 83 key = oo.normalizefilename(key) 84 if self.index.has_key(key): 85 # now we need to replace the definition of entity with msgstr 86 theoo = self.index[key] # find the oo 87 self.applytranslation(key, subkey, theoo, unit) 88 else: 89 print >> sys.stderr, "couldn't find key %s from po in %d keys" % (key, len(self.index)) 90 try: 91 sourceunitlines = str(unit) 92 if isinstance(sourceunitlines, unicode): 93 sourceunitlines = sourceunitlines.encode("utf-8") 94 print >> sys.stderr, sourceunitlines 95 except: 96 print >> sys.stderr, "error outputting source unit %r" % (str(unit),)
97
98 - def applytranslation(self, key, subkey, theoo, unit):
99 """applies the translation from the source unit to the oo unit""" 100 if not self.includefuzzy and unit.isfuzzy(): 101 return 102 makecopy = False 103 if self.languages is None: 104 part1 = theoo.lines[0] 105 if len(theoo.lines) > 1: 106 part2 = theoo.lines[1] 107 else: 108 makecopy = True 109 else: 110 part1 = theoo.languages[self.languages[0]] 111 if self.languages[1] in theoo.languages: 112 part2 = theoo.languages[self.languages[1]] 113 else: 114 makecopy = True 115 if makecopy: 116 part2 = oo.ooline(part1.getparts()) 117 unquotedid = unit.source 118 unquotedstr = unit.target 119 # If there is no translation, we don't want to add a line 120 if len(unquotedstr) == 0: 121 return 122 if isinstance(unquotedstr, unicode): 123 unquotedstr = unquotedstr.encode("UTF-8") 124 # finally set the new definition in the oo, but not if its empty 125 if len(unquotedstr) > 0: 126 setattr(part2, subkey, unquotedstr) 127 # set the modified time 128 if self.timestamp_str: 129 part2.timestamp = self.timestamp_str 130 if self.languages: 131 part2.languageid = self.languages[1] 132 if makecopy: 133 theoo.addline(part2)
134
135 - def convertstore(self, sourcestore):
136 self.p = sourcestore 137 # translate the strings 138 for unit in self.p.units: 139 # there may be more than one element due to msguniq merge 140 if filter.validelement(unit, self.p.filename, self.filteraction): 141 self.handleunit(unit) 142 # return the modified oo file object 143 return self.o
144
145 -def getmtime(filename):
146 import stat 147 return time.localtime(os.stat(filename)[stat.ST_MTIME])
148
149 -class oocheckfilter(pofilter.pocheckfilter):
150 - def validelement(self, unit, filename, filteraction):
151 """Returns whether or not to use unit in conversion. (filename is just for error reporting)""" 152 if filteraction == "none": 153 return True 154 filterresult = self.filterunit(unit) 155 if filterresult: 156 if filterresult != autocorrect: 157 for filtername, filtermessage in filterresult.iteritems(): 158 location = unit.getlocations()[0].encode('utf-8') 159 if filtername in self.options.error: 160 print >> sys.stderr, "Error at %s::%s: %s" % (filename, location, filtermessage) 161 return not filteraction in ["exclude-all", "exclude-serious"] 162 if filtername in self.options.warning or self.options.alwayswarn: 163 print >> sys.stderr, "Warning at %s::%s: %s" % (filename, location, filtermessage) 164 return not filteraction in ["exclude-all"] 165 return True
166
167 -class oofilteroptions:
168 error = ['variables', 'xmltags', 'escapes'] 169 warning = ['blank'] 170 #To only issue warnings for tests listed in warning, change the following to False: 171 alwayswarn = True 172 limitfilters = error + warning 173 #To use all available tests, uncomment the following: 174 #limitfilters = [] 175 #To exclude certain tests, list them in here: 176 excludefilters = {} 177 includefuzzy = False 178 includereview = False 179 autocorrect = False
180 181 options = oofilteroptions() 182 filter = oocheckfilter(options, [checks.OpenOfficeChecker, checks.StandardUnitChecker], checks.openofficeconfig) 183
184 -def convertoo(inputfile, outputfile, templatefile, sourcelanguage=None, targetlanguage=None, timestamp=None, includefuzzy=False, multifilestyle="single", filteraction=None):
185 inputstore = factory.getobject(inputfile) 186 inputstore.filename = getattr(inputfile, 'name', '') 187 if not targetlanguage: 188 raise ValueError("You must specify the target language") 189 if not sourcelanguage: 190 if targetlanguage.isdigit(): 191 sourcelanguage = "01" 192 else: 193 sourcelanguage = "en-US" 194 languages = (sourcelanguage, targetlanguage) 195 if templatefile is None: 196 raise ValueError("must have template file for oo files") 197 else: 198 convertor = reoo(templatefile, languages=languages, timestamp=timestamp, includefuzzy=includefuzzy, long_keys=multifilestyle != "single", filteraction=filteraction) 199 outputstore = convertor.convertstore(inputstore) 200 # TODO: check if we need to manually delete missing items 201 outputfile.write(str(outputstore)) 202 return True
203
204 -def main(argv=None):
205 from translate.convert import convert 206 formats = {("po", "oo"):("oo", convertoo), ("xlf", "oo"):("oo", convertoo), ("po", "sdf"):("sdf", convertoo)} 207 # always treat the input as an archive unless it is a directory 208 archiveformats = {(None, "output"): oo.oomultifile, (None, "template"): oo.oomultifile} 209 parser = convert.ArchiveConvertOptionParser(formats, usetemplates=True, description=__doc__, archiveformats=archiveformats) 210 parser.add_option("-l", "--language", dest="targetlanguage", default=None, 211 help="set target language code (e.g. af-ZA) [required]", metavar="LANG") 212 parser.add_option("", "--source-language", dest="sourcelanguage", default=None, 213 help="set source language code (default en-US)", metavar="LANG") 214 parser.add_option("-T", "--keeptimestamp", dest="timestamp", default=None, action="store_const", const=0, 215 help="don't change the timestamps of the strings") 216 parser.add_option("", "--nonrecursiveoutput", dest="allowrecursiveoutput", default=True, action="store_false", help="don't treat the output oo as a recursive store") 217 parser.add_option("", "--nonrecursivetemplate", dest="allowrecursivetemplate", default=True, action="store_false", help="don't treat the template oo as a recursive store") 218 parser.add_option("", "--filteraction", dest="filteraction", default="none", metavar="ACTION", 219 help="action on pofilter failure: none (default), warn, exclude-serious, exclude-all") 220 parser.add_fuzzy_option() 221 parser.add_multifile_option() 222 parser.passthrough.append("sourcelanguage") 223 parser.passthrough.append("targetlanguage") 224 parser.passthrough.append("timestamp") 225 parser.passthrough.append("filteraction") 226 parser.run(argv)
227 228 if __name__ == '__main__': 229 main() 230