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  from StringIO import StringIO 
 31  import tempfile 
 32  import os 
 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 -class SubtitleUnit(base.TranslationUnit):
56 """A subtitle entry that is translatable""" 57
58 - def __init__(self, source=None, encoding="utf_8"):
59 self._start = None 60 self._end = None 61 if source: 62 self.source = source 63 super(SubtitleUnit, self).__init__(source)
64
65 - def getnotes(self, origin=None):
66 if origin in ['programmer', 'developer', 'source code', None]: 67 return "visible for %d seconds" % self._duration 68 else: 69 return ''
70
71 - def getlocations(self):
72 return ["%s-->%s" % (self._start, self._end)]
73
74 - def getid(self):
75 return self.getlocations()[0]
76
77 -class SubtitleFile(base.TranslationStore):
78 """A subtitle file""" 79 UnitClass = SubtitleUnit
80 - def __init__(self, inputfile=None, unitclass=UnitClass):
81 """construct an Subtitle file, optionally reading in from inputfile.""" 82 self.UnitClass = unitclass 83 base.TranslationStore.__init__(self, unitclass=unitclass) 84 self.units = [] 85 self.filename = None 86 self._subtitlefile = None 87 self._encoding = 'utf_8' 88 if inputfile is not None: 89 self._parsefile(inputfile)
90
91 - def __str__(self):
92 subtitles = [] 93 for unit in self.units: 94 subtitle = Subtitle() 95 subtitle.main_text = unit.target or unit.source 96 subtitle.start = unit._start 97 subtitle.end = unit._end 98 subtitles.append(subtitle) 99 output = StringIO() 100 self._subtitlefile.write_to_file(subtitles, documents.MAIN, output) 101 return output.getvalue().encode(self._subtitlefile.encoding)
102
103 - def _parse(self):
104 try: 105 self._encoding = detect(self.filename) 106 if self._encoding == 'ascii': 107 self._encoding = 'utf_8' 108 self._format = determine(self.filename, self._encoding) 109 self._subtitlefile = new(self._format, self.filename, self._encoding) 110 for subtitle in self._subtitlefile.read(): 111 newunit = self.addsourceunit(subtitle.main_text) 112 newunit._start = subtitle.start 113 newunit._end = subtitle.end 114 newunit._duration = subtitle.duration_seconds 115 except Exception, e: 116 raise base.ParseError(e)
117
118 - def _parsefile(self, storefile):
119 if hasattr(storefile, 'name'): 120 self.filename = storefile.name 121 storefile.close() 122 elif hasattr(storefile, 'filename'): 123 self.filename = storefile.filename 124 storefile.close() 125 elif isinstance(storefile, basestring): 126 self.filename = storefile 127 128 if self.filename and os.path.exists(self.filename): 129 self._parse() 130 else: 131 self.parse(storefile.read())
132 133 @classmethod
134 - def parsefile(cls, storefile):
135 """parse the given file""" 136 newstore = cls() 137 newstore._parsefile(storefile) 138 return newstore
139
140 - def parse(self, input):
141 if isinstance(input, basestring): 142 # Gaupol does not allow parsing from strings 143 if self.filename: 144 tmpfile, tmpfilename = tempfile.mkstemp(suffix=self.filename) 145 else: 146 tmpfile, tmpfilename = tempfile.mkstemp() 147 tmpfile = open(tmpfilename, 'w') 148 tmpfile.write(input) 149 tmpfile.close() 150 self._parsefile(tmpfilename) 151 os.remove(tmpfilename) 152 else: 153 self._parsefile(input)
154
155 156 ############# format specific classes ################### 157 158 # the generic SubtitleFile can adapt to any format, but only the 159 # specilized classes can be used to construct a new file 160 161 -class SubRipFile(SubtitleFile):
162 """specialized class for SubRipFile's only""" 163 Name = _("SubRip subtitles file") 164 Extensions = ['srt']
165 - def __init__(self, *args, **kwargs):
166 super(SubRipFile, self).__init__(*args, **kwargs) 167 if self._subtitlefile is None: 168 self._subtitlefile = SubRip(self.filename or '', self._encoding) 169 if self._subtitlefile.newline is None: 170 self._subtitlefile.newline = newlines.UNIX
171
172 -class MicroDVDFile(SubtitleFile):
173 """specialized class for SubRipFile's only""" 174 Name = _("MicroDVD subtitles file") 175 Extensions = ['sub']
176 - def __init__(self, *args, **kwargs):
177 super(SubRipFile, self).__init__(*args, **kwargs) 178 if self._subtitlefile is None: 179 self._subtitlefile = MicroDVD(self.filename or '', self._encoding) 180 if self._subtitlefile.newline is None: 181 self._subtitlefile.newline = newlines.UNIX
182
183 -class AdvSubStationAlphaFile(SubtitleFile):
184 """specialized class for SubRipFile's only""" 185 Name = _("Advanced Substation Alpha subtitles file") 186 Extensions = ['ass']
187 - def __init__(self, *args, **kwargs):
188 super(SubRipFile, self).__init__(*args, **kwargs) 189 if self._subtitlefile is None: 190 self._subtitlefile = AdvSubStationAlpha(self.filename or '', self._encoding) 191 if self._subtitlefile.newline is None: 192 self._subtitlefile.newline = newlines.UNIX
193
194 -class SubStationAlphaFile(SubtitleFile):
195 """specialized class for SubRipFile's only""" 196 Name = _("Substation Alpha subtitles file") 197 Extensions = ['ssa']
198 - def __init__(self, *args, **kwargs):
199 super(SubRipFile, self).__init__(*args, **kwargs) 200 if self._subtitlefile is None: 201 self._subtitlefile = SubStationAlpha(self.filename or '', self._encoding) 202 if self._subtitlefile.newline is None: 203 self._subtitlefile.newline = newlines.UNIX
204