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