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