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

Side by Side Diff: grit/tclib.py

Issue 1442863002: Remove contents of grit's SVN repository. (Closed) Base URL: http://grit-i18n.googlecode.com/svn/trunk/
Patch Set: 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « grit/shortcuts_unittests.py ('k') | grit/tclib_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 '''Adaptation of the extern.tclib classes for our needs.
7 '''
8
9
10 import re
11 import types
12
13 from grit import exception
14 from grit import lazy_re
15 import grit.extern.tclib
16
17
18 # Matches whitespace sequences which can be folded into a single whitespace
19 # character. This matches single characters so that non-spaces are replaced
20 # with spaces.
21 _FOLD_WHITESPACE = re.compile(r'\s+')
22
23
24 def Identity(i):
25 return i
26
27
28 class BaseMessage(object):
29 '''Base class with methods shared by Message and Translation.
30 '''
31
32 def __init__(self, text='', placeholders=[], description='', meaning=''):
33 self.parts = []
34 self.placeholders = []
35 self.meaning = meaning
36 self.dirty = True # True if self.id is (or might be) wrong
37 self.id = 0
38 self.SetDescription(description)
39
40 if text != '':
41 if not placeholders or placeholders == []:
42 self.AppendText(text)
43 else:
44 tag_map = {}
45 for placeholder in placeholders:
46 tag_map[placeholder.GetPresentation()] = [placeholder, 0]
47 # This creates a regexp like '(TAG1|TAG2|TAG3)'.
48 # The tags have to be sorted in order of decreasing length, so that
49 # longer tags are substituted before shorter tags that happen to be
50 # substrings of the longer tag.
51 # E.g. "EXAMPLE_FOO_NAME" must be matched before "EXAMPLE_FOO",
52 # otherwise "EXAMPLE_FOO" splits "EXAMPLE_FOO_NAME" too.
53 tags = tag_map.keys()
54 tags.sort(cmp=lambda x,y: len(x) - len(y) or cmp(x, y), reverse=True)
55 tag_re = '(' + '|'.join(tags) + ')'
56 chunked_text = re.split(tag_re, text)
57 for chunk in chunked_text:
58 if chunk: # ignore empty chunk
59 if tag_map.has_key(chunk):
60 self.AppendPlaceholder(tag_map[chunk][0])
61 tag_map[chunk][1] += 1 # increase placeholder use count
62 else:
63 self.AppendText(chunk)
64 for key in tag_map.keys():
65 assert tag_map[key][1] != 0
66
67 def GetRealContent(self, escaping_function=Identity):
68 '''Returns the original content, i.e. what your application and users
69 will see.
70
71 Specify a function to escape each translateable bit, if you like.
72 '''
73 bits = []
74 for item in self.parts:
75 if isinstance(item, types.StringTypes):
76 bits.append(escaping_function(item))
77 else:
78 bits.append(item.GetOriginal())
79 return ''.join(bits)
80
81 def GetPresentableContent(self):
82 presentable_content = []
83 for part in self.parts:
84 if isinstance(part, Placeholder):
85 presentable_content.append(part.GetPresentation())
86 else:
87 presentable_content.append(part)
88 return ''.join(presentable_content)
89
90 def AppendPlaceholder(self, placeholder):
91 assert isinstance(placeholder, Placeholder)
92 dup = False
93 for other in self.GetPlaceholders():
94 if other.presentation == placeholder.presentation:
95 assert other.original == placeholder.original
96 dup = True
97
98 if not dup:
99 self.placeholders.append(placeholder)
100 self.parts.append(placeholder)
101 self.dirty = True
102
103 def AppendText(self, text):
104 assert isinstance(text, types.StringTypes)
105 assert text != ''
106
107 self.parts.append(text)
108 self.dirty = True
109
110 def GetContent(self):
111 '''Returns the parts of the message. You may modify parts if you wish.
112 Note that you must not call GetId() on this object until you have finished
113 modifying the contents.
114 '''
115 self.dirty = True # user might modify content
116 return self.parts
117
118 def GetDescription(self):
119 return self.description
120
121 def SetDescription(self, description):
122 self.description = _FOLD_WHITESPACE.sub(' ', description)
123
124 def GetMeaning(self):
125 return self.meaning
126
127 def GetId(self):
128 if self.dirty:
129 self.id = self.GenerateId()
130 self.dirty = False
131 return self.id
132
133 def GenerateId(self):
134 # Must use a UTF-8 encoded version of the presentable content, along with
135 # the meaning attribute, to match the TC.
136 return grit.extern.tclib.GenerateMessageId(
137 self.GetPresentableContent().encode('utf-8'), self.meaning)
138
139 def GetPlaceholders(self):
140 return self.placeholders
141
142 def FillTclibBaseMessage(self, msg):
143 msg.SetDescription(self.description.encode('utf-8'))
144
145 for part in self.parts:
146 if isinstance(part, Placeholder):
147 ph = grit.extern.tclib.Placeholder(
148 part.presentation.encode('utf-8'),
149 part.original.encode('utf-8'),
150 part.example.encode('utf-8'))
151 msg.AppendPlaceholder(ph)
152 else:
153 msg.AppendText(part.encode('utf-8'))
154
155
156 class Message(BaseMessage):
157 '''A message.'''
158
159 def __init__(self, text='', placeholders=[], description='', meaning='',
160 assigned_id=None):
161 super(Message, self).__init__(text, placeholders, description, meaning)
162 self.assigned_id = assigned_id
163
164 def ToTclibMessage(self):
165 msg = grit.extern.tclib.Message('utf-8', meaning=self.meaning)
166 self.FillTclibBaseMessage(msg)
167 return msg
168
169 def GetId(self):
170 '''Use the assigned id if we have one.'''
171 if self.assigned_id:
172 return self.assigned_id
173
174 return super(Message, self).GetId()
175
176 def HasAssignedId(self):
177 '''Returns True if this message has an assigned id.'''
178 return bool(self.assigned_id)
179
180
181 class Translation(BaseMessage):
182 '''A translation.'''
183
184 def __init__(self, text='', id='', placeholders=[], description='', meaning='' ):
185 super(Translation, self).__init__(text, placeholders, description, meaning)
186 self.id = id
187
188 def GetId(self):
189 assert id != '', "ID has not been set."
190 return self.id
191
192 def SetId(self, id):
193 self.id = id
194
195 def ToTclibMessage(self):
196 msg = grit.extern.tclib.Message(
197 'utf-8', id=self.id, meaning=self.meaning)
198 self.FillTclibBaseMessage(msg)
199 return msg
200
201
202 class Placeholder(grit.extern.tclib.Placeholder):
203 '''Modifies constructor to accept a Unicode string
204 '''
205
206 # Must match placeholder presentation names
207 _NAME_RE = lazy_re.compile('^[A-Za-z0-9_]+$')
208
209 def __init__(self, presentation, original, example):
210 '''Creates a new placeholder.
211
212 Args:
213 presentation: 'USERNAME'
214 original: '%s'
215 example: 'Joi'
216 '''
217 assert presentation != ''
218 assert original != ''
219 assert example != ''
220 if not self._NAME_RE.match(presentation):
221 raise exception.InvalidPlaceholderName(presentation)
222 self.presentation = presentation
223 self.original = original
224 self.example = example
225
226 def GetPresentation(self):
227 return self.presentation
228
229 def GetOriginal(self):
230 return self.original
231
232 def GetExample(self):
233 return self.example
234
235
OLDNEW
« no previous file with comments | « grit/shortcuts_unittests.py ('k') | grit/tclib_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698