Package translate :: Package storage :: Module omegat |
[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.omegat

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2009 Zuza Software Foundation
      5  #
      6  # This file is part of the Translate Toolkit.
      7  #
      8  # This program 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  # This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
     20
     21  """Manage the OmegaT glossary format
     22
     23     OmegaT glossary format is used by the
     24     U{OmegaT<http://www.omegat.org/en/omegat.html>} computer aided
     25     translation tool.
     26
     27     It is a bilingual base class derived format with L{OmegaTFile}
     28     and L{OmegaTUnit} providing file and unit level access.
     29
     30     Format Implementation
     31     =====================
     32     The OmegaT glossary format is a simple Tab Separated Value (TSV) file
     33     with the columns: source, target, comment.
     34
     35     The dialect of the TSV files is specified by L{OmegaTDialect}.
     36
     37     Encoding
     38     --------
     39     The files are either UTF-8 or encoded using the system default.  UTF-8
     40     encoded files use the .utf8 extension while system encoded files use
     41     the .tab extension.
     42  """
     43
     44  import csv
     45  import locale
     46  import os.path
     47  import sys
     48  import time
     49  from translate.storage import base
     50
     51  OMEGAT_FIELDNAMES = ["source", "target", "comment"]
     52  """Field names for an OmegaT glossary unit"""
     53
     54
     55 -class OmegaTDialect(csv.Dialect):
     56      """Describe the properties of an OmegaT generated TAB-delimited file."""
     57      delimiter = "\t"
     58      lineterminator = "\r\n"
     59      quoting = csv.QUOTE_NONE
     60      if sys.version_info < (2, 5, 0):
     61          # We need to define the following items for csv in Python < 2.5
     62          quoting = csv.QUOTE_MINIMAL   # OmegaT does not quote anything FIXME So why MINIMAL?
     63          doublequote = False
     64          skipinitialspace = False
     65          escapechar = None
     66          quotechar = '"'
     67  csv.register_dialect("omegat", OmegaTDialect)
     68
     69 -class OmegaTUnit(base.TranslationUnit):
     70      """An OmegaT translation memory unit"""
     71 -    def __init__(self, source=None):
     72          self._dict = {}
     73          if source:
     74              self.source = source
     75          super(OmegaTUnit, self).__init__(source)
     76
     77 -    def getdict(self):
     78          """Get the dictionary of values for a OmegaT line"""
     79          return self._dict
     80
     81 -    def setdict(self, newdict):
     82          """Set the dictionary of values for a OmegaT line
     83
     84          @param newdict: a new dictionary with OmegaT line elements
     85          @type newdict: Dict
     86          """
     87          # TODO First check that the values are OK
     88          self._dict = newdict
     89      dict = property(getdict, setdict)
     90
     91 -    def _get_field(self, key):
     92          if key not in self._dict:
     93              return None
     94          elif self._dict[key]:
     95              return self._dict[key].decode('utf-8')
     96          else:
     97              return ""
     98
     99 -    def _set_field(self, key, newvalue):
    100          if newvalue is None:
    101              self._dict[key] = None
    102          if isinstance(newvalue, unicode):
    103              newvalue = newvalue.encode('utf-8')
    104          if not key in self._dict or newvalue != self._dict[key]:
    105              self._dict[key] = newvalue
    106
    107 -    def getnotes(self, origin=None):
    108          return self._get_field('comment')
    109
    110 -    def getsource(self):
    111          return self._get_field('source')
    112
    113 -    def setsource(self, newsource):
    114          self._rich_source = None
    115          return self._set_field('source', newsource)
    116      source = property(getsource, setsource)
    117
    118 -    def gettarget(self):
    119          return self._get_field('target')
    120
    121 -    def settarget(self, newtarget):
    122          self._rich_target = None
    123          return self._set_field('target', newtarget)
    124      target = property(gettarget, settarget)
    125
    126 -    def settargetlang(self, newlang):
    127          self._dict['target-lang'] = newlang
    128      targetlang = property(None, settargetlang)
    129
    130 -    def __str__(self):
    131          return str(self._dict)
    132
    133 -    def istranslated(self):
    134          return bool(self._dict.get('target', None))
    135
    136
    137 -class OmegaTFile(base.TranslationStore):
    138      """An OmegaT translation memory file"""
    139      # FIXME: uncomment this when we next open from string freeze
    140      #Name = _("OmegaT Glossary")
    141      Name = None
    142      Mimetypes  = ["application/x-omegat-glossary"]
    143      Extensions = ["utf8"]
    144 -    def __init__(self, inputfile=None, unitclass=OmegaTUnit):
    145          """Construct an OmegaT glossary, optionally reading in from inputfile."""
    146          self.UnitClass = unitclass
    147          base.TranslationStore.__init__(self, unitclass=unitclass)
    148          self.filename = ''
    149          self.extension = ''
    150          self._encoding = self._get_encoding()
    151          if inputfile is not None:
    152              self.parse(inputfile)
    153
    154 -    def _get_encoding(self):
    155          return 'utf-8'
    156
    157 -    def parse(self, input):
    158          """parsese the given file or file source string"""
    159          if hasattr(input, 'name'):
    160              self.filename = input.name
    161          elif not getattr(self, 'filename', ''):
    162              self.filename = ''
    163          if hasattr(input, "read"):
    164              tmsrc = input.read()
    165              input.close()
    166              input = tmsrc
    167          try:
    168              input = input.decode(self._encoding).encode('utf-8')
    169          except:
    170              raise ValueError("OmegaT files are either UTF-8 encoded or use the default system encoding")
    171          lines = csv.DictReader(input.split("\n"), fieldnames=OMEGAT_FIELDNAMES, dialect="omegat")
    172          for line in lines:
    173              newunit = OmegaTUnit()
    174              newunit.dict = line
    175              self.addunit(newunit)
    176
    177 -    def __str__(self):
    178          output = csv.StringIO()
    179          writer = csv.DictWriter(output, fieldnames=OMEGAT_FIELDNAMES, dialect="omegat")
    180          unit_count = 0
    181          for unit in self.units:
    182              if unit.istranslated():
    183                  unit_count += 1
    184                  writer.writerow(unit.dict)
    185          if unit_count == 0:
    186              return ""
    187          output.reset()
    188          decoded = "".join(output.readlines()).decode('utf-8')
    189          try:
    190              return decoded.encode(self._encoding)
    191          except UnicodeEncodeError:
    192              return decoded.encode('utf-8')
    193
    194 -class OmegaTFileTab(OmegaTFile):
    195      """An OmegT translation memory file in the default system encoding"""
    196      # FIXME: uncomment this when we next open from string freeze
    197      #Name = _("OmegaT Glossary")
    198      Name = None
    199      Mimetypes  = ["application/x-omegat-glossary"]
    200      Extensions = ["tab"]
    201
    202 -    def _get_encoding(self):
    203          return locale.getdefaultlocale()[1]
    204