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

Source Code for Module translate.convert.xliff2oo

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