Package translate :: Package storage :: Module subtitles

[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.subtitles

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2008-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  """Class that manages subtitle files for translation
     23
     24     This class makes use of the subtitle functionality of L{gaupol}
     25     @see: gaupo/agents/open.py::open_main
     26
     27     a patch to gaupol is required to open utf-8 files successfully
     28  """
     29
     30  import os
     31  from StringIO import StringIO
     32  import tempfile
     33
     34  try:
     35      from aeidon import Subtitle
     36      from aeidon import documents
     37      from aeidon.encodings import detect
     38      from aeidon.util import detect_format as determine
     39      from aeidon.files import new
     40      from aeidon.files import MicroDVD, SubStationAlpha, AdvSubStationAlpha, SubRip
     41      from aeidon import newlines
     42  except ImportError:
     43      from gaupol.subtitle import Subtitle
     44      from gaupol import documents
     45      from gaupol.encodings import detect
     46      from gaupol import FormatDeterminer
     47      _determiner = FormatDeterminer()
     48      determine = _determiner.determine
     49      from gaupol.files import new
     50      from gaupol.files import MicroDVD, SubStationAlpha, AdvSubStationAlpha, SubRip
     51      from gaupol.newlines import newlines
     52
     53  from translate.storage import base
     54
     55
     56 -class SubtitleUnit(base.TranslationUnit):
     57      """A subtitle entry that is translatable"""
     58
     59 -    def __init__(self, source=None, encoding="utf_8"):
     60          self._start = None
     61          self._end = None
     62          if source:
     63              self.source = source
     64          super(SubtitleUnit, self).__init__(source)
     65
     66 -    def getnotes(self, origin=None):
     67          if origin in ['programmer', 'developer', 'source code', None]:
     68              return "visible for %d seconds" % self._duration
     69          else:
     70              return ''
     71
     72 -    def getlocations(self):
     73          return ["%s-->%s" % (self._start, self._end)]
     74
     75 -    def getid(self):
     76          return self.getlocations()[0]
     77
     78
     79 -class SubtitleFile(base.TranslationStore):
     80      """A subtitle file"""
     81      UnitClass = SubtitleUnit
     82
     83 -    def __init__(self, inputfile=None, unitclass=UnitClass):
     84          """construct an Subtitle file, optionally reading in from inputfile."""
     85          self.UnitClass = unitclass
     86          base.TranslationStore.__init__(self, unitclass=unitclass)
     87          self.units = []
     88          self.filename = None
     89          self._subtitlefile = None
     90          self._encoding = 'utf_8'
     91          if inputfile is not None:
     92              self._parsefile(inputfile)
     93
     94 -    def __str__(self):
     95          subtitles = []
     96          for unit in self.units:
     97              subtitle = Subtitle()
     98              subtitle.main_text = unit.target or unit.source
     99              subtitle.start = unit._start
    100              subtitle.end = unit._end
    101              subtitles.append(subtitle)
    102          output = StringIO()
    103          self._subtitlefile.write_to_file(subtitles, documents.MAIN, output)
    104          return output.getvalue().encode(self._subtitlefile.encoding)
    105
    106 -    def _parse(self):
    107          try:
    108              self._encoding = detect(self.filename)
    109              if self._encoding == 'ascii':
    110                  self._encoding = 'utf_8'
    111              self._format = determine(self.filename, self._encoding)
    112              self._subtitlefile = new(self._format, self.filename, self._encoding)
    113              for subtitle in self._subtitlefile.read():
    114                  newunit = self.addsourceunit(subtitle.main_text)
    115                  newunit._start = subtitle.start
    116                  newunit._end = subtitle.end
    117                  newunit._duration = subtitle.duration_seconds
    118          except Exception, e:
    119              raise base.ParseError(e)
    120
    121 -    def _parsefile(self, storefile):
    122          if hasattr(storefile, 'name'):
    123              self.filename = storefile.name
    124              storefile.close()
    125          elif hasattr(storefile, 'filename'):
    126              self.filename = storefile.filename
    127              storefile.close()
    128          elif isinstance(storefile, basestring):
    129              self.filename = storefile
    130
    131          if self.filename and os.path.exists(self.filename):
    132              self._parse()
    133          else:
    134              self.parse(storefile.read())
    135
    136      @classmethod
    137 -    def parsefile(cls, storefile):
    138          """parse the given file"""
    139          newstore = cls()
    140          newstore._parsefile(storefile)
    141          return newstore
    142
    143 -    def parse(self, input):
    144          if isinstance(input, basestring):
    145              # Gaupol does not allow parsing from strings
    146              if self.filename:
    147                  tmpfile, tmpfilename = tempfile.mkstemp(suffix=self.filename)
    148              else:
    149                  tmpfile, tmpfilename = tempfile.mkstemp()
    150              tmpfile = open(tmpfilename, 'w')
    151              tmpfile.write(input)
    152              tmpfile.close()
    153              self._parsefile(tmpfilename)
    154              os.remove(tmpfilename)
    155          else:
    156              self._parsefile(input)
    157
    158
    159  ############# format specific classes ###################
    160
    161  # the generic SubtitleFile can adapt to any format, but only the
    162  # specilized classes can be used to construct a new file
    163
    164
    165 -class SubRipFile(SubtitleFile):
    166      """specialized class for SubRipFile's only"""
    167      Name = _("SubRip subtitles file")
    168      Extensions = ['srt']
    169
    170 -    def __init__(self, *args, **kwargs):
    171          super(SubRipFile, self).__init__(*args, **kwargs)
    172          if self._subtitlefile is None:
    173              self._subtitlefile = SubRip(self.filename or '', self._encoding)
    174          if self._subtitlefile.newline is None:
    175              self._subtitlefile.newline = newlines.UNIX
    176
    177
    178 -class MicroDVDFile(SubtitleFile):
    179      """specialized class for SubRipFile's only"""
    180      Name = _("MicroDVD subtitles file")
    181      Extensions = ['sub']
    182
    183 -    def __init__(self, *args, **kwargs):
    184          super(SubRipFile, self).__init__(*args, **kwargs)
    185          if self._subtitlefile is None:
    186              self._subtitlefile = MicroDVD(self.filename or '', self._encoding)
    187          if self._subtitlefile.newline is None:
    188              self._subtitlefile.newline = newlines.UNIX
    189
    190
    191 -class AdvSubStationAlphaFile(SubtitleFile):
    192      """specialized class for SubRipFile's only"""
    193      Name = _("Advanced Substation Alpha subtitles file")
    194      Extensions = ['ass']
    195
    196 -    def __init__(self, *args, **kwargs):
    197          super(SubRipFile, self).__init__(*args, **kwargs)
    198          if self._subtitlefile is None:
    199              self._subtitlefile = AdvSubStationAlpha(self.filename or '', self._encoding)
    200          if self._subtitlefile.newline is None:
    201              self._subtitlefile.newline = newlines.UNIX
    202
    203
    204 -class SubStationAlphaFile(SubtitleFile):
    205      """specialized class for SubRipFile's only"""
    206      Name = _("Substation Alpha subtitles file")
    207      Extensions = ['ssa']
    208
    209 -    def __init__(self, *args, **kwargs):
    210          super(SubRipFile, self).__init__(*args, **kwargs)
    211          if self._subtitlefile is None:
    212              self._subtitlefile = SubStationAlpha(self.filename or '', self._encoding)
    213          if self._subtitlefile.newline is None:
    214              self._subtitlefile.newline = newlines.UNIX
    215