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

Side by Side Diff: grit/util.py

Issue 9965022: Allow substitution of messages as variables in other messages. (Closed) Base URL: https://grit-i18n.googlecode.com/svn/trunk
Patch Set: Fix unit tests for policy writers. Created 8 years, 8 months 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/tool/transl2tc_unittest.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 '''Utilities used by GRIT. 6 '''Utilities used by GRIT.
7 ''' 7 '''
8 8
9 import sys 9 import sys
10 import os.path 10 import os.path
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 def IsVerbose(): 401 def IsVerbose():
402 return verbose 402 return verbose
403 403
404 def IsExtraVerbose(): 404 def IsExtraVerbose():
405 return extra_verbose 405 return extra_verbose
406 406
407 def GetCurrentYear(): 407 def GetCurrentYear():
408 '''Returns the current 4-digit year as an integer.''' 408 '''Returns the current 4-digit year as an integer.'''
409 return time.localtime()[0] 409 return time.localtime()[0]
410 410
411 def ParseDefine(define):
412 '''Parses a define argument and returns the name and value.
413
414 The format is either "NAME=VAL" or "NAME", using True as the default value.
415 Values of "1" and "0" are transformed to True and False respectively.
416
417 Args:
418 define: a string of the form "NAME=VAL" or "NAME".
419
420 Returns:
421 A (name, value) pair. name is a string, value a string or boolean.
422 '''
423 parts = [part.strip() for part in define.split('=')]
424 assert len(parts) >= 1
425 name = parts[0]
426 val = True
427 if len(parts) > 1:
428 val = parts[1]
429 if val == "1": val = True
430 elif val == "0": val = False
431 return (name, val)
432
433
434 class Substituter(object):
435 '''Finds and substitutes variable names in text strings.
436
437 Given a dictionary of variable names and values, prepares to
438 search for patterns of the form [VAR_NAME] in a text.
439 The value will be substituted back efficiently.
440 Also applies to tclib.Message objects.
441 '''
442
443 def __init__(self):
444 '''Create an empty substituter.'''
445 self.substitutions_ = {}
446 self.dirty_ = True
447
448 def AddSubstitutions(self, subs):
449 '''Add new values to the substitutor.
450
451 Args:
452 subs: A dictionary of new substitutions.
453 '''
454 self.substitutions_.update(subs)
455 self.dirty_ = True
456
457 def AddMessages(self, messages, lang):
458 '''Adds substitutions extracted from node.Message objects.
459
460 Args:
461 messages: a list of node.Message objects.
462 lang: The translation language to use in substitutions.
463 '''
464 subs = [(str(msg.attrs['name']), msg.Translate(lang)) for msg in messages]
465 self.AddSubstitutions(dict(subs))
466 self.dirty_ = True
467
468 def GetExp(self):
469 '''Obtain a regular expression that will find substitution keys in text.
470
471 Create and cache if the substituter has been updated. Use the cached value
472 otherwise. Keys will be enclosed in [square brackets] in text.
473
474 Returns:
475 A regular expression object.
476 '''
477 if self.dirty_:
478 components = ['\[%s\]' % (k,) for k in self.substitutions_.keys()]
479 self.exp = re.compile("(%s)" % ('|'.join(components),))
480 self.dirty_ = False
481 return self.exp
482
483 def Substitute(self, text):
484 '''Substitute the variable values in the given text.
485
486 Text of the form [message_name] will be replaced by the message's value.
487
488 Args:
489 text: A string of text.
490
491 Returns:
492 A string of text with substitutions done.
493 '''
494 return ''.join([self._SubFragment(f) for f in self.GetExp().split(text)])
495
496 def _SubFragment(self, fragment):
497 '''Utility function for Substitute.
498
499 Performs a simple substitution if the fragment is exactly of the form
500 [message_name].
501
502 Args:
503 fragment: A simple string.
504
505 Returns:
506 A string with the substitution done.
507 '''
508 if len(fragment) > 2 and fragment[0] == '[' and fragment[-1] == ']':
509 sub = self.substitutions_.get(fragment[1:-1], None)
510 if sub is not None:
511 return sub
512 return fragment
513
514 def SubstituteMessage(self, msg):
515 '''Apply substitutions to a tclib.Message object.
516
517 Text of the form [message_name] will be replaced by a new placeholder,
518 whose presentation will take the form the message_name_{UsageCount}, and
519 whose example will be the message's value. Existing placeholders are
520 not affected.
521
522 Args:
523 msg: A tclib.Message object.
524
525 Returns:
526 A tclib.Message object, with substitutions done.
527 '''
528 from grit import tclib # avoid circular import
529 counts = {}
530 text = msg.GetPresentableContent()
531 placeholders = []
532 newtext = ''
533 for f in self.GetExp().split(text):
534 sub = self._SubFragment(f)
535 if f != sub:
536 f = str(f)
537 count = counts.get(f, 0) + 1
538 counts[f] = count
539 name = "%s_%d" % (f[1:-1], count)
540 placeholders.append(tclib.Placeholder(name, f, sub))
541 newtext += name
542 else:
543 newtext += f
544 if placeholders:
545 return tclib.Message(newtext, msg.GetPlaceholders() + placeholders,
546 msg.GetDescription(), msg.GetMeaning())
547 else:
548 return msg
OLDNEW
« no previous file with comments | « grit/tool/transl2tc_unittest.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698