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