Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Unified Diff: tools/grit/grit/tclib.py

Issue 1410853008: Move grit from DEPS into src. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: webview licenses Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/grit/grit/shortcuts_unittests.py ('k') | tools/grit/grit/tclib_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/grit/grit/tclib.py
diff --git a/tools/grit/grit/tclib.py b/tools/grit/grit/tclib.py
new file mode 100755
index 0000000000000000000000000000000000000000..b4c15db04dfb1ec37b60a2883f353f2d2c640c26
--- /dev/null
+++ b/tools/grit/grit/tclib.py
@@ -0,0 +1,235 @@
+#!/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
+
+
« no previous file with comments | « tools/grit/grit/shortcuts_unittests.py ('k') | tools/grit/grit/tclib_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698