Package translate :: Package convert :: Module xliff2odf

[hide private]
[frames] | no frames]

# Source Code for Module translate.convert.xliff2odf

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2004-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
     23  """convert OpenDocument (ODF) files to Gettext PO localization files"""
     24
     25  import cStringIO
     26  import zipfile
     27
     28  import lxml.etree as etree
     29
     30  from translate.storage import factory
     31  from translate.storage.xml_extract import unit_tree
     32  from translate.storage.xml_extract import extract
     33  from translate.storage.xml_extract import generate
     34  from translate.storage import odf_shared, odf_io
     35
     36
     37 -def first_child(unit_node):
     38      return unit_node.children.values()[0]
     39
     40
     41 -def translate_odf(template, input_file):
     42
     43      def load_dom_trees(template):
     44          odf_data = odf_io.open_odf(template)
     45          return dict((filename, etree.parse(cStringIO.StringIO(data))) for filename, data in odf_data.iteritems())
     46
     47      def load_unit_tree(input_file, dom_trees):
     48          store = factory.getobject(input_file)
     49          tree = unit_tree.build_unit_tree(store)
     50
     51          def extract_unit_tree(filename, root_dom_element_name):
     52              """Find the subtree in 'tree' which corresponds to the data in XML file 'filename'"""
     53
     54              def get_tree():
     55                  try:
     56                      return tree.children['office:%s' % root_dom_element_name, 0]
     57                  except KeyError:
     58                      return unit_tree.XPathTree()
     59              return (filename, get_tree())
     60
     61          return dict([extract_unit_tree('content.xml', 'document-content'),
     62                       extract_unit_tree('meta.xml', 'document-meta'),
     63                       extract_unit_tree('styles.xml', 'document-styles')])
     64
     65      def translate_dom_trees(unit_trees, dom_trees):
     66          make_parse_state = lambda: extract.ParseState(odf_shared.no_translate_content_elements, odf_shared.inline_elements)
     67          for filename, dom_tree in dom_trees.iteritems():
     68              file_unit_tree = unit_trees[filename]
     69              generate.apply_translations(dom_tree.getroot(), file_unit_tree, generate.replace_dom_text(make_parse_state))
     70          return dom_trees
     71
     72      # Since the convertoptionsparser will give us an open file, we risk that
     73      # it could have been opened in non-binary mode on Windows, and then we'll
     74      # have problems, so let's make sure we have what we want.
     75      template.close()
     76      template = file(template.name, mode='rb')
     77      dom_trees = load_dom_trees(template)
     78      unit_trees = load_unit_tree(input_file, dom_trees)
     79      return translate_dom_trees(unit_trees, dom_trees)
     80
     81
     82 -def write_odf(xlf_data, template, output_file, dom_trees):
     83
     84      def write_content_to_odf(output_zip, dom_trees):
     85          for filename, dom_tree in dom_trees.iteritems():
     86              output_zip.writestr(filename, etree.tostring(dom_tree, encoding='UTF-8', xml_declaration=True))
     87
     88      # Since the convertoptionsparser will give us an open file, we risk that
     89      # it could have been opened in non-binary mode on Windows, and then we'll
     90      # have problems, so let's make sure we have what we want.
     91      template.close()
     92      template = file(template.name, mode='rb')
     93      template_zip = zipfile.ZipFile(template, 'r')
     94      output_file.close()
     95      output_file = file(output_file.name, mode='wb')
     96      output_zip = zipfile.ZipFile(output_file, 'w', compression=zipfile.ZIP_DEFLATED)
     97      # Let's keep the XLIFF file out of the generated ODF for now. Note the
     98      # weird handling of the manifest since it can only be written to the ZIP
     99      # file once.
    100  #    output_zip = odf_io.copy_odf(template_zip, output_zip, dom_trees.keys() + ['META-INF/manifest.xml'])
    101  #    output_zip = odf_io.add_file(output_zip, template_zip.read('META-INF/manifest.xml'), 'translation.xlf', xlf_data)
    102      output_zip = odf_io.copy_odf(template_zip, output_zip, dom_trees.keys())
    103      write_content_to_odf(output_zip, dom_trees)
    104
    105
    106 -def convertxliff(input_file, output_file, template):
    107      """reads in stdin using fromfileclass, converts using convertorclass, writes to stdout"""
    108      xlf_data = input_file.read()
    109      dom_trees = translate_odf(template, cStringIO.StringIO(xlf_data))
    110      write_odf(xlf_data, template, output_file, dom_trees)
    111      output_file.close()
    112      return True
    113
    114  formats = {
    115      ('xlf', 'odt'): ("odt", convertxliff), # Text
    116      ('xlf', 'ods'): ("ods", convertxliff), # Spreadsheet
    117      ('xlf', 'odp'): ("odp", convertxliff), # Presentation
    118      ('xlf', 'odg'): ("odg", convertxliff), # Drawing
    119      ('xlf', 'odc'): ("odc", convertxliff), # Chart
    120      ('xlf', 'odf'): ("odf", convertxliff), # Formula
    121      ('xlf', 'odi'): ("odi", convertxliff), # Image
    122      ('xlf', 'odm'): ("odm", convertxliff), # Master Document
    123      ('xlf', 'ott'): ("ott", convertxliff), # Text template
    124      ('xlf', 'ots'): ("ots", convertxliff), # Spreadsheet template
    125      ('xlf', 'otp'): ("otp", convertxliff), # Presentation template
    126      ('xlf', 'otg'): ("otg", convertxliff), # Drawing template
    127      ('xlf', 'otc'): ("otc", convertxliff), # Chart template
    128      ('xlf', 'otf'): ("otf", convertxliff), # Formula template
    129      ('xlf', 'oti'): ("oti", convertxliff), # Image template
    130      ('xlf', 'oth'): ("oth", convertxliff), # Web page template
    131  }
    132
    133
    134 -def main(argv=None):
    135      from translate.convert import convert
    136
    137      parser = convert.ConvertOptionParser(formats, usetemplates=True, description=__doc__)
    138      parser.run(argv)
    139
    140
    141  if __name__ == '__main__':
    142      main()
    143