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