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  from translate.storage import factory 
 32  from translate.storage.poheader import poheader 
 33  from translate.filters import checks 
 34  from translate.filters import autocorrect 
 35  from translate.misc import optrecurse 
 36   
 37  import os 
 38   
39 -def build_checkerconfig(options):
40 """Prepare the checker config from the given options. This is mainly 41 factored out for the sake of unit tests.""" 42 checkerconfig = checks.CheckerConfig(targetlanguage=options.targetlanguage) 43 if options.notranslatefile: 44 options.notranslatefile = os.path.expanduser(options.notranslatefile) 45 if not os.path.exists(options.notranslatefile): 46 self.error("notranslatefile %r does not exist" % options.notranslatefile) 47 notranslatewords = [line.strip() for line in open(options.notranslatefile).readlines()] 48 notranslatewords = dict.fromkeys([key for key in notranslatewords]) 49 checkerconfig.notranslatewords.update(notranslatewords) 50 if options.musttranslatefile: 51 options.musttranslatefile = os.path.expanduser(options.musttranslatefile) 52 if not os.path.exists(options.musttranslatefile): 53 self.error("musttranslatefile %r does not exist" % options.musttranslatefile) 54 musttranslatewords = [line.strip() for line in open(options.musttranslatefile).readlines()] 55 musttranslatewords = dict.fromkeys([key for key in musttranslatewords]) 56 checkerconfig.musttranslatewords.update(musttranslatewords) 57 if options.validcharsfile: 58 options.validcharsfile = os.path.expanduser(options.validcharsfile) 59 if not os.path.exists(options.validcharsfile): 60 self.error("validcharsfile %r does not exist" % options.validcharsfile) 61 validchars = open(options.validcharsfile).read() 62 checkerconfig.updatevalidchars(validchars) 63 return checkerconfig
64
65 -class pocheckfilter:
66 - def __init__(self, options, checkerclasses=None, checkerconfig=None):
67 # excludefilters={}, limitfilters=None, includefuzzy=True, includereview=True, autocorrect=False): 68 """builds a checkfilter using the given checker (a list is allowed too)""" 69 if checkerclasses is None: 70 checkerclasses = [checks.StandardChecker, checks.StandardUnitChecker] 71 self.checker = checks.TeeChecker(checkerconfig=checkerconfig, \ 72 excludefilters=options.excludefilters, \ 73 limitfilters=options.limitfilters, \ 74 checkerclasses=checkerclasses, \ 75 languagecode=checkerconfig.targetlanguage 76 ) 77 self.options = options
78
79 - def getfilterdocs(self):
80 """lists the docs for filters available on checker...""" 81 filterdict = self.checker.getfilters() 82 filterdocs = ["%s\t%s" % (name, filterfunc.__doc__) for (name, filterfunc) in filterdict.iteritems()] 83 filterdocs.sort() 84 return "\n".join(filterdocs)
85
86 - def filterunit(self, unit):
87 """runs filters on an element""" 88 if unit.isheader(): 89 return [] 90 if not self.options.includefuzzy and unit.isfuzzy(): 91 return [] 92 if not self.options.includereview and unit.isreview(): 93 return [] 94 failures = self.checker.run_filters(unit) 95 if failures and self.options.autocorrect: 96 # we can't get away with bad unquoting / requoting if we're going to change the result... 97 correction = autocorrect.correct(unit.source, unit.target) 98 if correction: 99 unit.target = correction 100 return autocorrect 101 else: 102 # ignore failures we can't correct when in autocorrect mode 103 return [] 104 return failures
105
106 - def filterfile(self, transfile):
107 """Runs filters on a translation store object. 108 Parameters: 109 - transfile. A translation store object. 110 Return value: 111 - A new translation store object with the results of the filter included.""" 112 newtransfile = type(transfile)() 113 newtransfile.setsourcelanguage(transfile.getsourcelanguage()) 114 newtransfile.settargetlanguage(transfile.gettargetlanguage()) 115 for unit in transfile.units: 116 filterresult = self.filterunit(unit) 117 if filterresult: 118 if filterresult != autocorrect: 119 for filtername, filtermessage in filterresult.iteritems(): 120 if self.options.addnotes: 121 unit.adderror(filtername, filtermessage) 122 if isinstance(filtermessage, checks.SeriousFilterFailure): 123 unit.markfuzzy() 124 newtransfile.addunit(unit) 125 if isinstance(newtransfile, poheader): 126 newtransfile.updateheader(add=True, **transfile.parseheader()) 127 return newtransfile
128
129 -class FilterOptionParser(optrecurse.RecursiveOptionParser):
130 """a specialized Option Parser for filter tools..."""
131 - def __init__(self, formats):
132 """construct the specialized Option Parser""" 133 optrecurse.RecursiveOptionParser.__init__(self, formats) 134 self.set_usage() 135 self.add_option("-l", "--listfilters", action="callback", dest='listfilters', 136 default=False, callback_kwargs={'dest_value': True}, 137 callback=self.parse_noinput, help="list filters available")
138
139 - def parse_noinput(self, option, opt, value, parser, *args, **kwargs):
140 """this sets an option to true, but also sets input to - to prevent an error""" 141 setattr(parser.values, option.dest, kwargs['dest_value']) 142 parser.values.input = "-"
143
144 - def run(self):
145 """parses the arguments, and runs recursiveprocess with the resulting options""" 146 (options, args) = self.parse_args() 147 if options.filterclass is None: 148 checkerclasses = [checks.StandardChecker, checks.StandardUnitChecker] 149 else: 150 checkerclasses = [options.filterclass, checks.StandardUnitChecker] 151 checkerconfig = build_checkerconfig(options) 152 options.checkfilter = pocheckfilter(options, checkerclasses, checkerconfig) 153 if not options.checkfilter.checker.combinedfilters: 154 self.error("No valid filters were specified") 155 options.inputformats = self.inputformats 156 options.outputoptions = self.outputoptions 157 self.usepsyco(options) 158 if options.listfilters: 159 print options.checkfilter.getfilterdocs() 160 else: 161 self.recursiveprocess(options)
162
163 -def runfilter(inputfile, outputfile, templatefile, checkfilter=None):
164 """reads in inputfile, filters using checkfilter, writes to outputfile""" 165 fromfile = factory.getobject(inputfile) 166 tofile = checkfilter.filterfile(fromfile) 167 if tofile.isempty(): 168 return 0 169 outputfile.write(str(tofile)) 170 return 1
171
172 -def cmdlineparser():
173 formats = {"po":("po", runfilter), "pot":("pot", runfilter), 174 "xliff":("xliff", runfilter), "xlf":("xlf", runfilter), 175 "tmx":("tmx", runfilter), 176 None:("po", runfilter)} 177 178 parser = FilterOptionParser(formats) 179 parser.add_option("", "--review", dest="includereview", 180 action="store_true", default=True, 181 help="include units marked for review (default)") 182 parser.add_option("", "--noreview", dest="includereview", 183 action="store_false", default=True, 184 help="exclude units marked for review") 185 parser.add_option("", "--fuzzy", dest="includefuzzy", 186 action="store_true", default=True, 187 help="include units marked fuzzy (default)") 188 parser.add_option("", "--nofuzzy", dest="includefuzzy", 189 action="store_false", default=True, 190 help="exclude units marked fuzzy") 191 parser.add_option("", "--nonotes", dest="addnotes", 192 action="store_false", default=True, 193 help="don't add notes about the errors") 194 parser.add_option("", "--autocorrect", dest="autocorrect", 195 action="store_true", default=False, 196 help="output automatic corrections where possible rather than describing issues") 197 parser.add_option("", "--language", dest="targetlanguage", default=None, 198 help="set target language code (e.g. af-ZA) [required for spell check and recommended in general]", metavar="LANG") 199 parser.add_option("", "--openoffice", dest="filterclass", 200 action="store_const", default=None, const=checks.OpenOfficeChecker, 201 help="use the standard checks for OpenOffice translations") 202 parser.add_option("", "--mozilla", dest="filterclass", 203 action="store_const", default=None, const=checks.MozillaChecker, 204 help="use the standard checks for Mozilla translations") 205 parser.add_option("", "--drupal", dest="filterclass", 206 action="store_const", default=None, const=checks.DrupalChecker, 207 help="use the standard checks for Drupal translations") 208 parser.add_option("", "--gnome", dest="filterclass", 209 action="store_const", default=None, const=checks.GnomeChecker, 210 help="use the standard checks for Gnome translations") 211 parser.add_option("", "--kde", dest="filterclass", 212 action="store_const", default=None, const=checks.KdeChecker, 213 help="use the standard checks for KDE translations") 214 parser.add_option("", "--wx", dest="filterclass", 215 action="store_const", default=None, const=checks.KdeChecker, 216 help="use the standard checks for wxWidgets translations") 217 parser.add_option("", "--excludefilter", dest="excludefilters", 218 action="append", default=[], type="string", metavar="FILTER", 219 help="don't use FILTER when filtering") 220 parser.add_option("-t", "--test", dest="limitfilters", 221 action="append", default=None, type="string", metavar="FILTER", 222 help="only use test FILTERs specified with this option when filtering") 223 parser.add_option("", "--notranslatefile", dest="notranslatefile", 224 default=None, type="string", metavar="FILE", 225 help="read list of untranslatable words from FILE (must not be translated)") 226 parser.add_option("", "--musttranslatefile", dest="musttranslatefile", 227 default=None, type="string", metavar="FILE", 228 help="read list of translatable words from FILE (must be translated)") 229 parser.add_option("", "--validcharsfile", dest="validcharsfile", 230 default=None, type="string", metavar="FILE", 231 help="read list of all valid characters from FILE (must be in UTF-8)") 232 parser.passthrough.append('checkfilter') 233 parser.description = __doc__ 234 return parser
235
236 -def main():
237 parser = cmdlineparser() 238 parser.run()
239 240 if __name__ == '__main__': 241 main() 242