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

Source Code for Module translate.storage.ical

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # Copyright 2007-2008 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 iCalender files for translation 
 23   
 24     Implementation 
 25     ============== 
 26     iCalendar files follow the U{RFC2445<http://tools.ietf.org/html/rfc2445>} 
 27     specification. 
 28   
 29     The iCalendar specification uses the following naming conventions: 
 30       - Component: an event, journal entry, timezone, etc 
 31       - Property: a property of a component: summary, description, start time, etc 
 32       - Attribute: an attribute of a property, e.g. language 
 33   
 34     The following are localisable in this implementation: 
 35       - VEVENT component: SUMMARY, DESCRIPTION, COMMENT and LOCATION properties 
 36   
 37     While other items could be localised this is not seen as important until use 
 38     cases arise.  In such a case simply adjusting the component.name and 
 39     property.name lists to include these will allow expanded localisation. 
 40   
 41     LANGUAGE Attribute 
 42     ------------------ 
 43     While the iCalendar format allows items to have a language attribute this is 
 44     not used. The reason being that for most of the items that we localise they 
 45     are only allowed to occur zero or once.  Thus 'summary' would ideally 
 46     be present in multiple languages in one file, the format does not allow 
 47     such multiple entries.  This is unfortunate as it prevents the creation 
 48     of a single multilingual iCalendar file. 
 49   
 50     Future Format Support 
 51     ===================== 
 52     As this format used U{vobject<http://vobject.skyhouseconsulting.com/>} which 
 53     supports various formats including U{vCard<http://en.wikipedia.org/wiki/VCard>} 
 54     it is possible to expand this format to understand those if needed. 
 55   
 56  """ 
 57  import re 
 58  from StringIO import StringIO 
 59   
 60  import vobject 
 61   
 62  from translate.storage import base 
 63   
 64   
65 -class icalunit(base.TranslationUnit):
66 """An ical entry that is translatable""" 67
68 - def __init__(self, source=None, encoding="UTF-8"):
69 self.location = "" 70 if source: 71 self.source = source 72 super(icalunit, self).__init__(source)
73
74 - def addlocation(self, location):
75 self.location = location
76
77 - def getlocations(self):
78 return [self.location]
79 80
81 -class icalfile(base.TranslationStore):
82 """An ical file""" 83 UnitClass = icalunit 84
85 - def __init__(self, inputfile=None, unitclass=icalunit):
86 """construct an ical file, optionally reading in from inputfile.""" 87 self.UnitClass = unitclass 88 base.TranslationStore.__init__(self, unitclass=unitclass) 89 self.units = [] 90 self.filename = '' 91 self._icalfile = None 92 if inputfile is not None: 93 self.parse(inputfile)
94
95 - def __str__(self):
96 _outicalfile = self._icalfile 97 for unit in self.units: 98 for location in unit.getlocations(): 99 match = re.match('\\[(?P<uid>.+)\\](?P<property>.+)', location) 100 for component in self._icalfile.components(): 101 if component.name != "VEVENT": 102 continue 103 if component.uid.value != match.groupdict()['uid']: 104 continue 105 for property in component.getChildren(): 106 if property.name == match.groupdict()['property']: 107 property.value = unit.target 108 109 if _outicalfile: 110 return str(_outicalfile.serialize()) 111 else: 112 return ""
113
114 - def parse(self, input):
115 """parse the given file or file source string""" 116 if hasattr(input, 'name'): 117 self.filename = input.name 118 elif not getattr(self, 'filename', ''): 119 self.filename = '' 120 if hasattr(input, "read"): 121 inisrc = input.read() 122 input.close() 123 input = inisrc 124 if isinstance(input, str): 125 input = StringIO(input) 126 self._icalfile = vobject.readComponents(input).next() 127 else: 128 self._icalfile = vobject.readComponents(open(input)).next() 129 for component in self._icalfile.components(): 130 if component.name == "VEVENT": 131 for property in component.getChildren(): 132 if property.name in ('SUMMARY', 'DESCRIPTION', 'COMMENT', 'LOCATION'): 133 newunit = self.addsourceunit(property.value) 134 newunit.addnote("Start date: %s" % component.dtstart.value) 135 newunit.addlocation("[%s]%s" % (component.uid.value, property.name))
136