Package translate :: Package convert :: Module prop2po

[hide private]
[frames] | no frames]

# Source Code for Module translate.convert.prop2po

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2002-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  """convert Java/Mozilla .properties files to Gettext PO localization files
     23
     24  See: http://translate.sourceforge.net/wiki/toolkit/prop2po for examples and
     25  usage instructions
     26  """
     27
     28  import sys
     29  from translate.storage import po
     30  from translate.storage import properties
     31
     32 -class prop2po:
     33      """convert a .properties file to a .po file for handling the translation..."""
     34 -    def convertstore(self, thepropfile, duplicatestyle="msgctxt"):
     35          """converts a .properties file to a .po file..."""
     36          thetargetfile = po.pofile()
     37          targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit", x_accelerator_marker="&")
     38          targetheader.addnote("extracted from %s" % thepropfile.filename, "developer")
     39          # we try and merge the header po with any comments at the start of the properties file
     40          appendedheader = 0
     41          waitingcomments = []
     42          for propunit in thepropfile.units:
     43              pounit = self.convertunit(propunit, "developer")
     44              if pounit is None:
     45                  waitingcomments.extend(propunit.comments)
     46              # FIXME the storage class should not be creating blank units
     47              if pounit is "discard":
     48                  continue
     49              if not appendedheader:
     50                  if propunit.isblank():
     51                      pounit = targetheader
     52                  else:
     53                      thetargetfile.addunit(targetheader)
     54                  appendedheader = 1
     55              if pounit is not None:
     56                  pounit.addnote("".join(waitingcomments).rstrip(), "developer", position="prepend")
     57                  waitingcomments = []
     58                  thetargetfile.addunit(pounit)
     59          thetargetfile.removeduplicates(duplicatestyle)
     60          return thetargetfile
     61
     62 -    def mergestore(self, origpropfile, translatedpropfile, blankmsgstr=False, duplicatestyle="msgctxt"):
     63          """converts two .properties files to a .po file..."""
     64          thetargetfile = po.pofile()
     65          targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit")
     66          targetheader.addnote("extracted from %s, %s" % (origpropfile.filename, translatedpropfile.filename), "developer")
     67          translatedpropfile.makeindex()
     68          # we try and merge the header po with any comments at the start of the properties file
     69          appendedheader = 0
     70          waitingcomments = []
     71          # loop through the original file, looking at units one by one
     72          for origprop in origpropfile.units:
     73              origpo = self.convertunit(origprop, "developer")
     74              if origpo is None:
     75                  waitingcomments.extend(origprop.comments)
     76              # FIXME the storage class should not be creating blank units
     77              if origpo is "discard":
     78                  continue
     79              # handle the header case specially...
     80              if not appendedheader:
     81                  if origprop.isblank():
     82                      origpo = targetheader
     83                  else:
     84                      thetargetfile.addunit(targetheader)
     85                  appendedheader = 1
     86              # try and find a translation of the same name...
     87              if origprop.name in translatedpropfile.locationindex:
     88                  translatedprop = translatedpropfile.locationindex[origprop.name]
     89                  # Need to check that this comment is not a copy of the developer comments
     90                  translatedpo = self.convertunit(translatedprop, "translator")
     91              else:
     92                  translatedpo = None
     93              # if we have a valid po unit, get the translation and add it...
     94              if origpo is not None:
     95                  if translatedpo is not None and not blankmsgstr:
     96                      origpo.target = translatedpo.source
     97                  origpo.addnote("".join(waitingcomments).rstrip(), "developer", position="prepend")
     98                  waitingcomments = []
     99                  thetargetfile.addunit(origpo)
    100              elif translatedpo is not None:
    101                  print >> sys.stderr, "error converting original properties definition %s" % origprop.name
    102          thetargetfile.removeduplicates(duplicatestyle)
    103          return thetargetfile
    104
    105 -    def convertunit(self, propunit, commenttype):
    106          """Converts a .properties unit to a .po unit. Returns None if empty
    107          or not for translation."""
    108          if propunit is None:
    109              return None
    110          # escape unicode
    111          pounit = po.pounit(encoding="UTF-8")
    112          if hasattr(propunit, "comments"):
    113              for comment in propunit.comments:
    114                  if "DONT_TRANSLATE" in comment:
    115                      return "discard"
    116              pounit.addnote("".join(propunit.comments).rstrip(), commenttype)
    117          # TODO: handle multiline msgid
    118          if propunit.isblank():
    119              return None
    120          pounit.addlocation(propunit.name)
    121          pounit.source = propunit.source
    122          pounit.target = ""
    123          return pounit
    124
    125 -def convertprop(inputfile, outputfile, templatefile, pot=False, duplicatestyle="msgctxt"):
    126      """reads in inputfile using properties, converts using prop2po, writes to outputfile"""
    127      inputstore = properties.propfile(inputfile)
    128      convertor = prop2po()
    129      if templatefile is None:
    130          outputstore = convertor.convertstore(inputstore, duplicatestyle=duplicatestyle)
    131      else:
    132          templatestore = properties.propfile(templatefile)
    133          outputstore = convertor.mergestore(templatestore, inputstore, blankmsgstr=pot, duplicatestyle=duplicatestyle)
    134      if outputstore.isempty():
    135          return 0
    136      outputfile.write(str(outputstore))
    137      return 1
    138
    139 -def main(argv=None):
    140      from translate.convert import convert
    141      formats = {"properties": ("po", convertprop), ("properties", "properties"): ("po", convertprop)}
    142      parser = convert.ConvertOptionParser(formats, usetemplates=True, usepots=True, description=__doc__)
    143      parser.add_duplicates_option()
    144      parser.passthrough.append("pot")
    145      parser.run(argv)
    146
    147  if __name__ == '__main__':
    148      main()
    149