| Index: grit/tclib.py
|
| ===================================================================
|
| --- grit/tclib.py (revision 202)
|
| +++ grit/tclib.py (working copy)
|
| @@ -1,235 +0,0 @@
|
| -#!/usr/bin/env python
|
| -# Copyright (c) 2012 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
|
| -from grit import lazy_re
|
| -import grit.extern.tclib
|
| -
|
| -
|
| -# Matches whitespace sequences which can be folded into a single whitespace
|
| -# character. This matches single characters so that non-spaces are replaced
|
| -# with spaces.
|
| -_FOLD_WHITESPACE = re.compile(r'\s+')
|
| -
|
| -
|
| -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.meaning = meaning
|
| - self.dirty = True # True if self.id is (or might be) wrong
|
| - self.id = 0
|
| - self.SetDescription(description)
|
| -
|
| - if text != '':
|
| - if not placeholders or placeholders == []:
|
| - self.AppendText(text)
|
| - else:
|
| - tag_map = {}
|
| - for placeholder in placeholders:
|
| - tag_map[placeholder.GetPresentation()] = [placeholder, 0]
|
| - # This creates a regexp like '(TAG1|TAG2|TAG3)'.
|
| - # The tags have to be sorted in order of decreasing length, so that
|
| - # longer tags are substituted before shorter tags that happen to be
|
| - # substrings of the longer tag.
|
| - # E.g. "EXAMPLE_FOO_NAME" must be matched before "EXAMPLE_FOO",
|
| - # otherwise "EXAMPLE_FOO" splits "EXAMPLE_FOO_NAME" too.
|
| - tags = tag_map.keys()
|
| - tags.sort(cmp=lambda x,y: len(x) - len(y) or cmp(x, y), reverse=True)
|
| - tag_re = '(' + '|'.join(tags) + ')'
|
| - 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 = _FOLD_WHITESPACE.sub(' ', 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):
|
| - super(Message, self).__init__(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 super(Message, self).GetId()
|
| -
|
| - def HasAssignedId(self):
|
| - '''Returns True if this message has an assigned id.'''
|
| - return bool(self.assigned_id)
|
| -
|
| -
|
| -class Translation(BaseMessage):
|
| - '''A translation.'''
|
| -
|
| - def __init__(self, text='', id='', placeholders=[], description='', meaning=''):
|
| - super(Translation, self).__init__(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 = lazy_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
|
| -
|
| -
|
|
|