Package translate :: Package convert :: Module po2dtd

[hide private]
[frames] | no frames]

# Source Code for Module translate.convert.po2dtd

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2002-2009 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  """script that converts a .po file to a UTF-8 encoded .dtd file as used by mozilla
     23  either done using a template or just using the .po file"""
     24
     25  import warnings
     26
     27  from translate.storage import dtd
     28  from translate.storage import po
     29  from translate.misc import quote
     30  from translate.convert import accesskey
     31
     32
     33 -def getmixedentities(entities):
     34      """returns a list of mixed .label and .accesskey entities from a list of entities"""
     35      mixedentities = []    # those entities which have a .label and .accesskey combined
     36      # search for mixed entities...
     37      for entity in entities:
     38          for labelsuffix in dtd.labelsuffixes:
     39              if entity.endswith(labelsuffix):
     40                  entitybase = entity[:entity.rfind(labelsuffix)]
     41                  # see if there is a matching accesskey, making this a mixed entity
     42                  for akeytype in dtd.accesskeysuffixes:
     43                      if entitybase + akeytype in entities:
     44                          # add both versions to the list of mixed entities
     45                          mixedentities += [entity, entitybase+akeytype]
     46      return mixedentities
     47
     48
     49 -def applytranslation(entity, dtdunit, inputunit, mixedentities):
     50      """applies the translation for entity in the po unit to the dtd unit"""
     51      # this converts the po-style string to a dtd-style string
     52      unquotedstr = inputunit.target
     53      # check there aren't missing entities...
     54      if len(unquotedstr.strip()) == 0:
     55          return
     56      # handle mixed entities
     57      for labelsuffix in dtd.labelsuffixes:
     58          if entity.endswith(labelsuffix):
     59              if entity in mixedentities:
     60                  unquotedstr, akey = accesskey.extract(unquotedstr)
     61                  break
     62      else:
     63          for akeytype in dtd.accesskeysuffixes:
     64              if entity.endswith(akeytype):
     65                  if entity in mixedentities:
     66                      label, unquotedstr = accesskey.extract(unquotedstr)
     67                      if not unquotedstr:
     68                          warnings.warn("Could not find accesskey for %s" % entity)
     69                      else:
     70                          original = dtd.unquotefromdtd(dtdunit.definition)
     71                          # For the sake of diffs we keep the case of the
     72                          # accesskey the same if we know the translation didn't
     73                          # change. Casing matters in XUL.
     74                          if unquotedstr == dtdunit.source and original.lower() == unquotedstr.lower():
     75                              if original.isupper():
     76                                  unquotedstr = unquotedstr.upper()
     77                              elif original.islower():
     78                                  unquotedstr = unquotedstr.lower()
     79      if len(unquotedstr) > 0:
     80          dtdunit.definition = dtd.quotefordtd(dtd.removeinvalidamps(entity, unquotedstr))
     81
     82
     83 -class redtd:
     84      """this is a convertor class that creates a new dtd based on a template using translations in a po"""
     85
     86 -    def __init__(self, dtdfile):
     87          self.dtdfile = dtdfile
     88
     89 -    def convertstore(self, inputstore, includefuzzy=False):
     90          # translate the strings
     91          for inunit in inputstore.units:
     92              # there may be more than one entity due to msguniq merge
     93              if includefuzzy or not inunit.isfuzzy():
     94                  self.handleinunit(inunit)
     95          return self.dtdfile
     96
     97 -    def handleinunit(self, inunit):
     98          entities = inunit.getlocations()
     99          mixedentities = getmixedentities(entities)
    100          for entity in entities:
    101              if entity in self.dtdfile.index:
    102                  # now we need to replace the definition of entity with msgstr
    103                  dtdunit = self.dtdfile.index[entity] # find the dtd
    104                  applytranslation(entity, dtdunit, inunit, mixedentities)
    105
    106
    107 -class po2dtd:
    108      """this is a convertor class that creates a new dtd file based on a po file without a template"""
    109
    110 -    def convertcomments(self, inputunit, dtdunit):
    111          entities = inputunit.getlocations()
    112          if len(entities) > 1:
    113              # don't yet handle multiple entities
    114              dtdunit.comments.append(("conversionnote", '<!-- CONVERSION NOTE - multiple entities -->\n'))
    115              dtdunit.entity = entities[0]
    116          elif len(entities) == 1:
    117              dtdunit.entity = entities[0]
    118          else:
    119              # this produces a blank entity, which doesn't write anything out
    120              dtdunit.entity = ""
    121
    122          if inputunit.isfuzzy():
    123              dtdunit.comments.append(("potype", "fuzzy\n"))
    124          for note in inputunit.getnotes("translator").split("\n"):
    125              if not note:
    126                  continue
    127              note = quote.unstripcomment(note)
    128              if (note.find('LOCALIZATION NOTE') == -1) or (note.find('GROUP') == -1):
    129                  dtdunit.comments.append(("comment", note))
    130          # msgidcomments are special - they're actually localization notes
    131          msgidcomment = inputunit._extract_msgidcomments()
    132          if msgidcomment:
    133              locnote = quote.unstripcomment("LOCALIZATION NOTE ("+dtdunit.entity+"): "+msgidcomment)
    134              dtdunit.comments.append(("locnote", locnote))
    135
    136 -    def convertstrings(self, inputunit, dtdunit):
    137          if inputunit.istranslated():
    138              unquoted = inputunit.target
    139          else:
    140              unquoted = inputunit.source
    141          dtdunit.definition = dtd.quotefordtd(dtd.removeinvalidamps(dtdunit.entity, unquoted))
    142
    143 -    def convertunit(self, inputunit):
    144          dtdunit = dtd.dtdunit()
    145          self.convertcomments(inputunit, dtdunit)
    146          self.convertstrings(inputunit, dtdunit)
    147          return dtdunit
    148
    149 -    def convertstore(self, inputstore, includefuzzy=False):
    150          outputstore = dtd.dtdfile()
    151          self.currentgroups = []
    152          for inputunit in inputstore.units:
    153              if includefuzzy or not inputunit.isfuzzy():
    154                  dtdunit = self.convertunit(inputunit)
    155                  if dtdunit is not None:
    156                      outputstore.addunit(dtdunit)
    157          return outputstore
    158
    159
    160 -def convertdtd(inputfile, outputfile, templatefile, includefuzzy=False):
    161      inputstore = po.pofile(inputfile)
    162      if templatefile is None:
    163          convertor = po2dtd()
    164      else:
    165          templatestore = dtd.dtdfile(templatefile)
    166          convertor = redtd(templatestore)
    167      outputstore = convertor.convertstore(inputstore, includefuzzy)
    168      outputfile.write(str(outputstore))
    169      return 1
    170
    171
    172 -def main(argv=None):
    173      # handle command line options
    174      from translate.convert import convert
    175      formats = {"po": ("dtd", convertdtd), ("po", "dtd"): ("dtd", convertdtd)}
    176      parser = convert.ConvertOptionParser(formats, usetemplates=True, description=__doc__)
    177      parser.add_fuzzy_option()
    178      parser.run(argv)
    179
    180
    181  if __name__ == '__main__':
    182      main()
    183