OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python2.4 |
| 2 # Copyright (c) 2011 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 '''A baseclass for simple gatherers that store their gathered resource in a |
| 7 list. |
| 8 ''' |
| 9 |
| 10 import re |
| 11 import types |
| 12 |
| 13 from grit.gather import interface |
| 14 from grit import clique |
| 15 from grit import tclib |
| 16 |
| 17 |
| 18 class SkeletonGatherer(interface.GathererBase): |
| 19 '''Common functionality of gatherers that parse their input as a skeleton of |
| 20 translatable and nontranslatable chunks. |
| 21 ''' |
| 22 |
| 23 def __init__(self): |
| 24 interface.GathererBase.__init__(self) |
| 25 # List of parts of the document. Translateable parts are |
| 26 # clique.MessageClique objects, nontranslateable parts are plain strings. |
| 27 # Translated messages are inserted back into the skeleton using the quoting |
| 28 # rules defined by self.Escape() |
| 29 self.skeleton_ = [] |
| 30 # A list of the names of IDs that need to be defined for this resource |
| 31 # section to compile correctly. |
| 32 self.ids_ = [] |
| 33 # True if Parse() has already been called. |
| 34 self.have_parsed_ = False |
| 35 # True if a translatable chunk has been added |
| 36 self.translatable_chunk_ = False |
| 37 # If not None, all parts of the document will be put into this single |
| 38 # message; otherwise the normal skeleton approach is used. |
| 39 self.single_message_ = None |
| 40 # Number to use for the next placeholder name. Used only if single_message |
| 41 # is not None |
| 42 self.ph_counter_ = 1 |
| 43 |
| 44 def GetText(self): |
| 45 '''Returns the original text of the section''' |
| 46 return self.text_ |
| 47 |
| 48 def Escape(self, text): |
| 49 '''Subclasses can override. Base impl is identity. |
| 50 ''' |
| 51 return text |
| 52 |
| 53 def UnEscape(self, text): |
| 54 '''Subclasses can override. Base impl is identity. |
| 55 ''' |
| 56 return text |
| 57 |
| 58 def GetTextualIds(self): |
| 59 '''Returns the list of textual IDs that need to be defined for this |
| 60 resource section to compile correctly.''' |
| 61 return self.ids_ |
| 62 |
| 63 def _AddTextualId(self, id): |
| 64 self.ids_.append(id) |
| 65 |
| 66 def GetCliques(self): |
| 67 '''Returns the message cliques for each translateable message in the |
| 68 resource section.''' |
| 69 return filter(lambda x: isinstance(x, clique.MessageClique), self.skeleton_) |
| 70 |
| 71 def Translate(self, lang, pseudo_if_not_available=True, |
| 72 skeleton_gatherer=None, fallback_to_english=False): |
| 73 if len(self.skeleton_) == 0: |
| 74 raise exception.NotReady() |
| 75 if skeleton_gatherer: |
| 76 assert len(skeleton_gatherer.skeleton_) == len(self.skeleton_) |
| 77 |
| 78 out = [] |
| 79 for ix in range(len(self.skeleton_)): |
| 80 if isinstance(self.skeleton_[ix], types.StringTypes): |
| 81 if skeleton_gatherer: |
| 82 # Make sure the skeleton is like the original |
| 83 assert(isinstance(skeleton_gatherer.skeleton_[ix], types.StringTypes)) |
| 84 out.append(skeleton_gatherer.skeleton_[ix]) |
| 85 else: |
| 86 out.append(self.skeleton_[ix]) |
| 87 else: |
| 88 if skeleton_gatherer: # Make sure the skeleton is like the original |
| 89 assert(not isinstance(skeleton_gatherer.skeleton_[ix], |
| 90 types.StringTypes)) |
| 91 msg = self.skeleton_[ix].MessageForLanguage(lang, |
| 92 pseudo_if_not_available, |
| 93 fallback_to_english) |
| 94 |
| 95 def MyEscape(text): |
| 96 return self.Escape(text) |
| 97 text = msg.GetRealContent(escaping_function=MyEscape) |
| 98 out.append(text) |
| 99 return ''.join(out) |
| 100 |
| 101 def Parse(self): |
| 102 '''Parses the section. Implemented by subclasses. Idempotent.''' |
| 103 raise NotImplementedError() |
| 104 |
| 105 def _AddNontranslateableChunk(self, chunk): |
| 106 '''Adds a nontranslateable chunk.''' |
| 107 if self.single_message_: |
| 108 ph = tclib.Placeholder('XX%02dXX' % self.ph_counter_, chunk, chunk) |
| 109 self.ph_counter_ += 1 |
| 110 self.single_message_.AppendPlaceholder(ph) |
| 111 else: |
| 112 self.skeleton_.append(chunk) |
| 113 |
| 114 def _AddTranslateableChunk(self, chunk): |
| 115 '''Adds a translateable chunk. It will be unescaped before being added.''' |
| 116 # We don't want empty messages since they are redundant and the TC |
| 117 # doesn't allow them. |
| 118 if chunk == '': |
| 119 return |
| 120 |
| 121 unescaped_text = self.UnEscape(chunk) |
| 122 if self.single_message_: |
| 123 self.single_message_.AppendText(unescaped_text) |
| 124 else: |
| 125 self.skeleton_.append(self.uberclique.MakeClique( |
| 126 tclib.Message(text=unescaped_text))) |
| 127 self.translatable_chunk_ = True |
OLD | NEW |