Package translate :: Package filters :: Module pofilter
[hide private]
[frames] | no frames]

Source Code for Module translate.filters.pofilter

  1  #!/usr/bin/env python 
  2  # 
  3  # Copyright 2004-2007 Zuza Software Foundation 
  4  # 
  5  # This file is part of translate. 
  6  # 
  7  # translate is free software; you can redistribute it and/or modify 
  8  # it under the terms of the GNU General Public License as published by 
  9  # the Free Software Foundation; either version 2 of the License, or 
 10  # (at your option) any later version. 
 11  # 
 12  # translate is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15  # GNU General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU General Public License 
 18  # along with translate; if not, write to the Free Software 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 20   
 21  """Perform quality checks on Gettext PO, XLIFF and TMX localization files 
 22   
 23  Snippet files whenever a test fails.  These can be examined, corrected and 
 24  merged back into the originals using pomerge 
 25   
 26  See: http://translate.sourceforge.net/wiki/toolkit/pofilter for examples and 
 27  usage instructions and http://translate.sourceforge.net/wiki/toolkit/pofilter_tests 
 28  for full descriptions of all tests 
 29  """ 
 30   
 31  import os 
 32   
 33  from translate.storage import factory 
 34  from translate.storage.poheader import poheader 
 35  from translate.filters import checks 
 36  from translate.filters import autocorrect 
 37  from translate.misc import optrecurse 
 38   
 39   
40 -def build_checkerconfig(options):
41 """Prepare the checker config from the given options. This is mainly 42 factored out for the sake of unit tests.""" 43 checkerconfig = checks.CheckerConfig(targetlanguage=options.targetlanguage) 44 if options.notranslatefile: 45 options.notranslatefile = os.path.expanduser(options.notranslatefile) 46 if not os.path.exists(options.notranslatefile): 47 self.error("notranslatefile %r does not exist" % options.notranslatefile) 48 notranslatewords = [line.strip() for line in open(options.notranslatefile).readlines()] 49 notranslatewords = dict.fromkeys([key for key in notranslatewords]) 50 checkerconfig.notranslatewords.update(notranslatewords) 51 if options.musttranslatefile: 52 options.musttranslatefile = os.path.expanduser(options.musttranslatefile) 53 if not os.path.exists(options.musttranslatefile): 54 self.error("musttranslatefile %r does not exist" % options.musttranslatefile) 55 musttranslatewords = [line.strip() for line in open(options.musttranslatefile).readlines()] 56 musttranslatewords = dict.fromkeys([key for key in musttranslatewords]) 57 checkerconfig.musttranslatewords.update(musttranslatewords) 58 if options.validcharsfile: 59 options.validcharsfile = os.path.expanduser(options.validcharsfile) 60 if not os.path.exists(options.validcharsfile): 61 self.error("validcharsfile %r does not exist" % options.validcharsfile) 62 validchars = open(options.validcharsfile).read() 63 checkerconfig.updatevalidchars(validchars) 64 return checkerconfig
65 66
67 -class pocheckfilter:
68
69 - def __init__(self, options, checkerclasses=None, checkerconfig=None):
70 # excludefilters={}, limitfilters=None, includefuzzy=True, includereview=True, autocorrect=False): 71 """builds a checkfilter using the given checker (a list is allowed too)""" 72 if checkerclasses is None: 73 checkerclasses = [checks.StandardChecker, checks.StandardUnitChecker] 74 self.checker = checks.TeeChecker(checkerconfig=checkerconfig, 75 excludefilters=options.excludefilters, 76 limitfilters=options.limitfilters, 77 checkerclasses=checkerclasses, 78 languagecode=checkerconfig.targetlanguage) 79 self.options = options
80
81 - def getfilterdocs(self):
82 """lists the docs for filters available on checker...""" 83 filterdict = self.checker.getfilters() 84 filterdocs = ["%s\t%s" % (name, filterfunc.__doc__) for (name, filterfunc) in filterdict.iteritems()] 85 filterdocs.sort() 86 return "\n".join(filterdocs)
87
88 - def filterunit(self, unit):
89 """runs filters on an element""" 90 if unit.isheader(): 91 return [] 92 if not self.options.includefuzzy and unit.isfuzzy(): 93 return [] 94 if not self.options.includereview and unit.isreview(): 95 return [] 96 failures = self.checker.run_filters(unit) 97 if failures and self.options.autocorrect: 98 # we can't get away with bad unquoting / requoting if we're going to change the result... 99 correction = autocorrect.correct(unit.source, unit.target) 100 if correction: 101 unit.target = correction 102 return autocorrect 103 else: 104 # ignore failures we can't correct when in autocorrect mode 105 return [] 106 return failures
107
108 - def filterfile(self, transfile):
109 """Runs filters on a translation store object. 110 Parameters: 111 - transfile. A translation store object. 112 Return value: 113 - A new translation store object with the results of the filter included.""" 114 newtransfile = type(transfile)() 115 newtransfile.setsourcelanguage(transfile.getsourcelanguage()) 116 newtransfile.settargetlanguage(transfile.gettargetlanguage()) 117 for unit in transfile.units: 118 filterresult = self.filterunit(unit) 119 if filterresult: 120 if filterresult != autocorrect: 121 for filtername, filtermessage in filterresult.iteritems(): 122 if self.options.addnotes: 123 unit.adderror(filtername, filtermessage) 124 if isinstance(filtermessage, checks.SeriousFilterFailure): 125 unit.markfuzzy() 126 newtransfile.addunit(unit) 127 if isinstance(newtransfile, poheader): 128 newtransfile.updateheader(add=True, **transfile.parseheader()) 129 return newtransfile
130 131
132 -class FilterOptionParser(optrecurse.RecursiveOptionParser):
133 """a specialized Option Parser for filter tools...""" 134
135 - def __init__(self, formats):
136 """construct the specialized Option Parser""" 137 optrecurse.RecursiveOptionParser.__init__(self, formats) 138 self.set_usage() 139 self.add_option("-l", "--listfilters", action="callback", dest='listfilters', 140 default=False, callback_kwargs={'dest_value': True}, 141 callback=self.parse_noinput, help="list filters available")
142
143 - def parse_noinput(self, option, opt, value, parser, *args, **kwargs):
144 """this sets an option to true, but also sets input to - to prevent an error""" 145 setattr(parser.values, option.dest, kwargs['dest_value']) 146 parser.values.input = "-"
147
148 - def run(self):
149 """parses the arguments, and runs recursiveprocess with the resulting options""" 150 (options, args) = self.parse_args() 151 if options.filterclass is None: 152 checkerclasses = [checks.StandardChecker, checks.StandardUnitChecker] 153 else: 154 checkerclasses = [options.filterclass, checks.StandardUnitChecker] 155 checkerconfig = build_checkerconfig(options) 156 options.checkfilter = pocheckfilter(options, checkerclasses, checkerconfig) 157 if not options.checkfilter.checker.combinedfilters: 158 self.error("No valid filters were specified") 159 options.inputformats = self.inputformats 160 options.outputoptions = self.outputoptions 161 self.usepsyco(options) 162 if options.listfilters: 163 print options.checkfilter.getfilterdocs() 164 else: 165 self.recursiveprocess(options)
166 167
168 -def runfilter(inputfile, outputfile, templatefile, checkfilter=None):
169 """reads in inputfile, filters using checkfilter, writes to outputfile""" 170 fromfile = factory.getobject(inputfile) 171 tofile = checkfilter.filterfile(fromfile) 172 if tofile.isempty(): 173 return 0 174 outputfile.write(str(tofile)) 175 return 1
176 177
178 -def cmdlineparser():
179 formats = {"po": ("po", runfilter), "pot": ("pot", runfilter), 180 "xliff": ("xliff", runfilter), "xlf": ("xlf", runfilter), 181 "tmx": ("tmx", runfilter), 182 None: ("po", runfilter)} 183 184 parser = FilterOptionParser(formats) 185 parser.add_option("", "--review", dest="includereview", 186 action="store_true", default=True, 187 help="include units marked for review (default)") 188 parser.add_option("", "--noreview", dest="includereview", 189 action="store_false", default=True, 190 help="exclude units marked for review") 191 parser.add_option("", "--fuzzy", dest="includefuzzy", 192 action="store_true", default=True, 193 help="include units marked fuzzy (default)") 194 parser.add_option("", "--nofuzzy", dest="includefuzzy", 195 action="store_false", default=True, 196 help="exclude units marked fuzzy") 197 parser.add_option("", "--nonotes", dest="addnotes", 198 action="store_false", default=True, 199 help="don't add notes about the errors") 200 parser.add_option("", "--autocorrect", dest="autocorrect", 201 action="store_true", default=False, 202 help="output automatic corrections where possible rather than describing issues") 203 parser.add_option("", "--language", dest="targetlanguage", default=None, 204 help="set target language code (e.g. af-ZA) [required for spell check and recommended in general]", metavar="LANG") 205 parser.add_option("", "--openoffice", dest="filterclass", 206 action="store_const", default=None, const=checks.OpenOfficeChecker, 207 help="use the standard checks for OpenOffice translations") 208 parser.add_option("", "--mozilla", dest="filterclass", 209 action="store_const", default=None, const=checks.MozillaChecker, 210 help="use the standard checks for Mozilla translations") 211 parser.add_option("", "--drupal", dest="filterclass", 212 action="store_const", default=None, const=checks.DrupalChecker, 213 help="use the standard checks for Drupal translations") 214 parser.add_option("", "--gnome", dest="filterclass", 215 action="store_const", default=None, const=checks.GnomeChecker, 216 help="use the standard checks for Gnome translations") 217 parser.add_option("", "--kde", dest="filterclass", 218 action="store_const", default=None, const=checks.KdeChecker, 219 help="use the standard checks for KDE translations") 220 parser.add_option("", "--wx", dest="filterclass", 221 action="store_const", default=None, const=checks.KdeChecker, 222 help="use the standard checks for wxWidgets translations") 223 parser.add_option("", "--excludefilter", dest="excludefilters", 224 action="append", default=[], type="string", metavar="FILTER", 225 help="don't use FILTER when filtering") 226 parser.add_option("-t", "--test", dest="limitfilters", 227 action="append", default=None, type="string", metavar="FILTER", 228 help="only use test FILTERs specified with this option when filtering") 229 parser.add_option("", "--notranslatefile", dest="notranslatefile", 230 default=None, type="string", metavar="FILE", 231 help="read list of untranslatable words from FILE (must not be translated)") 232 parser.add_option("", "--musttranslatefile", dest="musttranslatefile", 233 default=None, type="string", metavar="FILE", 234 help="read list of translatable words from FILE (must be translated)") 235 parser.add_option("", "--validcharsfile", dest="validcharsfile", 236 default=None, type="string", metavar="FILE", 237 help="read list of all valid characters from FILE (must be in UTF-8)") 238 parser.passthrough.append('checkfilter') 239 parser.description = __doc__ 240 return parser
241 242
243 -def main():
244 parser = cmdlineparser() 245 parser.run()
246 247 248 if __name__ == '__main__': 249 main() 250