| #!/usr/bin/python2.4 |
| # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| '''Adaptation of the extern.tclib classes for our needs. |
| ''' |
| |
| |
| import re |
| import types |
| |
| from grit import exception |
| import grit.extern.tclib |
| |
| def Identity(i): |
| return i |
| |
| |
| class BaseMessage(object): |
| '''Base class with methods shared by Message and Translation. |
| ''' |
| |
| def __init__(self, text='', placeholders=[], description='', meaning=''): |
| self.parts = [] |
| self.placeholders = [] |
| self.description = description |
| self.meaning = meaning |
| self.dirty = True # True if self.id is (or might be) wrong |
| self.id = 0 |
| |
| if text != '': |
| if not placeholders or placeholders == []: |
| self.AppendText(text) |
| else: |
| tag_map = {} |
| for placeholder in placeholders: |
| tag_map[placeholder.GetPresentation()] = [placeholder, 0] |
| tag_re = '(' + '|'.join(tag_map.keys()) + ')' |
| # This creates a regexp like '(TAG1|TAG2|TAG3)' |
| chunked_text = re.split(tag_re, text) |
| for chunk in chunked_text: |
| if chunk: # ignore empty chunk |
| if tag_map.has_key(chunk): |
| self.AppendPlaceholder(tag_map[chunk][0]) |
| tag_map[chunk][1] += 1 # increase placeholder use count |
| else: |
| self.AppendText(chunk) |
| for key in tag_map.keys(): |
| assert tag_map[key][1] != 0 |
| |
| def GetRealContent(self, escaping_function=Identity): |
| '''Returns the original content, i.e. what your application and users |
| will see. |
| |
| Specify a function to escape each translateable bit, if you like. |
| ''' |
| bits = [] |
| for item in self.parts: |
| if isinstance(item, types.StringTypes): |
| bits.append(escaping_function(item)) |
| else: |
| bits.append(item.GetOriginal()) |
| return ''.join(bits) |
| |
| def GetPresentableContent(self): |
| presentable_content = [] |
| for part in self.parts: |
| if isinstance(part, Placeholder): |
| presentable_content.append(part.GetPresentation()) |
| else: |
| presentable_content.append(part) |
| return ''.join(presentable_content) |
| |
| def AppendPlaceholder(self, placeholder): |
| assert isinstance(placeholder, Placeholder) |
| dup = False |
| for other in self.GetPlaceholders(): |
| if other.presentation == placeholder.presentation: |
| assert other.original == placeholder.original |
| dup = True |
| |
| if not dup: |
| self.placeholders.append(placeholder) |
| self.parts.append(placeholder) |
| self.dirty = True |
| |
| def AppendText(self, text): |
| assert isinstance(text, types.StringTypes) |
| assert text != '' |
| |
| self.parts.append(text) |
| self.dirty = True |
| |
| def GetContent(self): |
| '''Returns the parts of the message. You may modify parts if you wish. |
| Note that you must not call GetId() on this object until you have finished |
| modifying the contents. |
| ''' |
| self.dirty = True # user might modify content |
| return self.parts |
| |
| def GetDescription(self): |
| return self.description |
| |
| def SetDescription(self, description): |
| self.description = description |
| |
| def GetMeaning(self): |
| return self.meaning |
| |
| def GetId(self): |
| if self.dirty: |
| self.id = self.GenerateId() |
| self.dirty = False |
| return self.id |
| |
| def GenerateId(self): |
| # Must use a UTF-8 encoded version of the presentable content, along with |
| # the meaning attribute, to match the TC. |
| return grit.extern.tclib.GenerateMessageId( |
| self.GetPresentableContent().encode('utf-8'), self.meaning) |
| |
| def GetPlaceholders(self): |
| return self.placeholders |
| |
| def FillTclibBaseMessage(self, msg): |
| msg.SetDescription(self.description.encode('utf-8')) |
| |
| for part in self.parts: |
| if isinstance(part, Placeholder): |
| ph = grit.extern.tclib.Placeholder( |
| part.presentation.encode('utf-8'), |
| part.original.encode('utf-8'), |
| part.example.encode('utf-8')) |
| msg.AppendPlaceholder(ph) |
| else: |
| msg.AppendText(part.encode('utf-8')) |
| |
| |
| class Message(BaseMessage): |
| '''A message.''' |
| |
| def __init__(self, text='', placeholders=[], description='', meaning='', |
| assigned_id=None): |
| BaseMessage.__init__(self, text, placeholders, description, meaning) |
| self.assigned_id = assigned_id |
| |
| def ToTclibMessage(self): |
| msg = grit.extern.tclib.Message('utf-8', meaning=self.meaning) |
| self.FillTclibBaseMessage(msg) |
| return msg |
| |
| def GetId(self): |
| '''Use the assigned id if we have one.''' |
| if self.assigned_id: |
| return self.assigned_id |
| |
| return BaseMessage.GetId(self) |
| |
| |
| class Translation(BaseMessage): |
| '''A translation.''' |
| |
| def __init__(self, text='', id='', placeholders=[], description='', meaning=''): |
| BaseMessage.__init__(self, text, placeholders, description, meaning) |
| self.id = id |
| |
| def GetId(self): |
| assert id != '', "ID has not been set." |
| return self.id |
| |
| def SetId(self, id): |
| self.id = id |
| |
| def ToTclibMessage(self): |
| msg = grit.extern.tclib.Message( |
| 'utf-8', id=self.id, meaning=self.meaning) |
| self.FillTclibBaseMessage(msg) |
| return msg |
| |
| |
| class Placeholder(grit.extern.tclib.Placeholder): |
| '''Modifies constructor to accept a Unicode string |
| ''' |
| |
| # Must match placeholder presentation names |
| _NAME_RE = re.compile('[A-Za-z0-9_]+') |
| |
| def __init__(self, presentation, original, example): |
| '''Creates a new placeholder. |
| |
| Args: |
| presentation: 'USERNAME' |
| original: '%s' |
| example: 'Joi' |
| ''' |
| assert presentation != '' |
| assert original != '' |
| assert example != '' |
| if not self._NAME_RE.match(presentation): |
| raise exception.InvalidPlaceholderName(presentation) |
| self.presentation = presentation |
| self.original = original |
| self.example = example |
| |
| def GetPresentation(self): |
| return self.presentation |
| |
| def GetOriginal(self): |
| return self.original |
| |
| def GetExample(self): |
| return self.example |
| |
| |