Package translate :: Package convert :: Module pot2po

[hide private]
[frames] | no frames]

# Source Code for Module translate.convert.pot2po

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2004-2007 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  """convert Gettext PO templates (.pot) to PO localization files, preserving existing translations
     23
     24  See: http://translate.sourceforge.net/wiki/toolkit/pot2po for examples and
     25  usage instructions
     26  """
     27
     28  from translate.storage import po
     29  from translate.storage import factory
     30  from translate.search import match
     31  from translate.misc.multistring import multistring
     32
     33  # We don't want to reinitialise the TM each time, so let's store it here.
     34  tmmatcher = None
     35
     36 -def memory(tmfiles, max_candidates=1, min_similarity=75, max_length=1000):
     37      """Returns the TM store to use. Only initialises on first call."""
     38      global tmmatcher
     39      # Only initialise first time
     40      if tmmatcher is None:
     41          if isinstance(tmfiles, list):
     42              tmstore = [factory.getobject(tmfile) for tmfile in tmfiles]
     43          else:
     44              tmstore = factory.getobject(tmfiles)
     45          tmmatcher = match.matcher(tmstore, max_candidates=max_candidates, min_similarity=min_similarity, max_length=max_length)
     46      return tmmatcher
     47
     48 -def convertpot(inputpotfile, outputpofile, templatepofile, tm=None, min_similarity=75, fuzzymatching=True, **kwargs):
     49      inputpot = po.pofile(inputpotfile)
     50      templatepo = None
     51      if templatepofile is not None:
     52          templatepo = po.pofile(templatepofile)
     53      outputpo = convertpot_stores(inputpot, templatepo, tm, min_similarity, fuzzymatching, **kwargs)
     54      outputpofile.write(str(outputpo))
     55      return 1
     56
     57 -def convertpot_stores(inputpot, templatepo, tm=None, min_similarity=75, fuzzymatching=True, **kwargs):
     58      """reads in inputpotfile, adjusts header, writes to outputpofile. if templatepofile exists, merge translations from it into outputpofile"""
     59      inputpot.makeindex()
     60      thetargetfile = po.pofile()
     61      # header values
     62      charset = "UTF-8"
     63      encoding = "8bit"
     64      project_id_version = None
     65      pot_creation_date = None
     66      po_revision_date = None
     67      last_translator = None
     68      language_team = None
     69      mime_version = None
     70      plural_forms = None
     71      kwargs = {}
     72      if templatepo is not None:
     73          fuzzyfilematcher = None
     74          if fuzzymatching:
     75              for unit in templatepo.units:
     76                  if unit.isobsolete():
     77                      unit.resurrect()
     78              try:
     79                  fuzzyfilematcher = match.matcher(templatepo, max_candidates=1, min_similarity=min_similarity, max_length=3000, usefuzzy=True)
     80                  fuzzyfilematcher.addpercentage = False
     81              except ValueError:
     82                  # Probably no usable units
     83                  pass
     84
     85          templatepo.makeindex()
     86          templateheadervalues = templatepo.parseheader()
     87          for key, value in templateheadervalues.iteritems():
     88              if key == "Project-Id-Version":
     89                  project_id_version = value
     90              elif key == "Last-Translator":
     91                  last_translator = value
     92              elif key == "Language-Team":
     93                  language_team = value
     94              elif key == "PO-Revision-Date":
     95                  po_revision_date = value
     96              elif key in ("POT-Creation-Date", "MIME-Version"):
     97                  # don't know how to handle these keys, or ignoring them
     98                  pass
     99              elif key == "Content-Type":
    100                  kwargs[key] = value
    101              elif key == "Content-Transfer-Encoding":
    102                  encoding = value
    103              elif key == "Plural-Forms":
    104                  plural_forms = value
    105              else:
    106                  kwargs[key] = value
    107      fuzzyglobalmatcher = None
    108      if fuzzymatching and tm:
    109          fuzzyglobalmatcher = memory(tm, max_candidates=1, min_similarity=min_similarity, max_length=1000)
    110          fuzzyglobalmatcher.addpercentage = False
    111      inputheadervalues = inputpot.parseheader()
    112      for key, value in inputheadervalues.iteritems():
    113          if key in ("Project-Id-Version", "Last-Translator", "Language-Team", "PO-Revision-Date", "Content-Type", "Content-Transfer-Encoding", "Plural-Forms"):
    114              # want to carry these from the template so we ignore them
    115              pass
    116          elif key == "POT-Creation-Date":
    117              pot_creation_date = value
    118          elif key == "MIME-Version":
    119              mime_version = value
    120          else:
    121              kwargs[key] = value
    122      targetheader = thetargetfile.makeheader(charset=charset, encoding=encoding, project_id_version=project_id_version,
    123          pot_creation_date=pot_creation_date, po_revision_date=po_revision_date, last_translator=last_translator,
    124          language_team=language_team, mime_version=mime_version, plural_forms=plural_forms, **kwargs)
    125      # Get the header comments and fuzziness state
    126      if templatepo is not None and len(templatepo.units) > 0:
    127          if templatepo.units[0].isheader():
    128              if templatepo.units[0].getnotes("translator"):
    129                  targetheader.addnote(templatepo.units[0].getnotes("translator"), "translator")
    130              if inputpot.units[0].getnotes("developer"):
    131                  targetheader.addnote(inputpot.units[0].getnotes("developer"), "developer")
    132              targetheader.markfuzzy(templatepo.units[0].isfuzzy())
    133      elif len(inputpot.units) > 0 and inputpot.units[0].isheader():
    134          targetheader.addnote(inputpot.units[0].getnotes())
    135      thetargetfile.addunit(targetheader)
    136      # Do matching
    137      for inputpotunit in inputpot.units:
    138          if not (inputpotunit.isheader() or inputpotunit.isobsolete()):
    139              if templatepo:
    140                  possiblematches = []
    141                  for location in inputpotunit.getlocations():
    142                      templatepounit = templatepo.locationindex.get(location, None)
    143                      if templatepounit is not None:
    144                          possiblematches.append(templatepounit)
    145                  if len(inputpotunit.getlocations()) == 0:
    146                      templatepounit = templatepo.findunit(inputpotunit.source)
    147                  if templatepounit:
    148                      possiblematches.append(templatepounit)
    149                  for templatepounit in possiblematches:
    150                      if inputpotunit.source == templatepounit.source and templatepounit.target:
    151                          inputpotunit.merge(templatepounit, authoritative=True)
    152                          break
    153                  else:
    154                      fuzzycandidates = []
    155                      if fuzzyfilematcher:
    156                          fuzzycandidates = fuzzyfilematcher.matches(inputpotunit.source)
    157                          if fuzzycandidates:
    158                              inputpotunit.merge(fuzzycandidates[0])
    159                              original = templatepo.findunit(fuzzycandidates[0].source)
    160                              if original:
    161                                  original.reused = True
    162                      if fuzzyglobalmatcher and not fuzzycandidates:
    163                          fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.source)
    164                          if fuzzycandidates:
    165                              inputpotunit.merge(fuzzycandidates[0])
    166              else:
    167                  if fuzzyglobalmatcher:
    168                      fuzzycandidates = fuzzyglobalmatcher.matches(inputpotunit.source)
    169                      if fuzzycandidates:
    170                          inputpotunit.merge(fuzzycandidates[0])
    171              if inputpotunit.hasplural() and len(inputpotunit.target) == 0:
    172                  # Let's ensure that we have the correct number of plural forms:
    173                  nplurals, plural = thetargetfile.getheaderplural()
    174                  if nplurals and nplurals.isdigit() and nplurals != '2':
    175                      inputpotunit.target = multistring([""]*int(nplurals))
    176              thetargetfile.addunit(inputpotunit)
    177
    178      #Let's take care of obsoleted messages
    179      if templatepo:
    180          newlyobsoleted = []
    181          for unit in templatepo.units:
    182              if unit.isheader():
    183                  continue
    184              if unit.target and not (inputpot.findunit(unit.source) or hasattr(unit, "reused")):
    185                  #not in .pot, make it obsolete
    186                  unit.makeobsolete()
    187                  newlyobsoleted.append(unit)
    188              elif unit.isobsolete():
    189                  thetargetfile.addunit(unit)
    190          for unit in newlyobsoleted:
    191              thetargetfile.addunit(unit)
    192      return thetargetfile
    193
    194 -def main(argv=None):
    195      from translate.convert import convert
    196      formats = {"pot": ("po", convertpot), ("pot", "po"): ("po", convertpot)}
    197      parser = convert.ConvertOptionParser(formats, usepots=True, usetemplates=True,
    198          allowmissingtemplate=True, description=__doc__)
    199      parser.add_option("", "--tm", dest="tm", default=None,
    200          help="The file to use as translation memory when fuzzy matching")
    201      parser.passthrough.append("tm")
    202      defaultsimilarity = 75
    203      parser.add_option("-s", "--similarity", dest="min_similarity", default=defaultsimilarity,
    204          type="float", help="The minimum similarity for inclusion (default: %d%%)" % defaultsimilarity)
    205      parser.passthrough.append("min_similarity")
    206      parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_false",
    207          default=True, help="Disable fuzzy matching")
    208      parser.passthrough.append("fuzzymatching")
    209      parser.run(argv)
    210
    211
    212  if __name__ == '__main__':
    213      main()
    214