Index: tools/grit/grit/gather/skeleton_gatherer.py |
diff --git a/tools/grit/grit/gather/skeleton_gatherer.py b/tools/grit/grit/gather/skeleton_gatherer.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..15cb3f373be6baeecd272ba328344ab69820cba7 |
--- /dev/null |
+++ b/tools/grit/grit/gather/skeleton_gatherer.py |
@@ -0,0 +1,127 @@ |
+#!/usr/bin/python2.4 |
+# Copyright (c) 2011 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. |
+ |
+'''A baseclass for simple gatherers that store their gathered resource in a |
+list. |
+''' |
+ |
+import re |
+import types |
+ |
+from grit.gather import interface |
+from grit import clique |
+from grit import tclib |
+ |
+ |
+class SkeletonGatherer(interface.GathererBase): |
+ '''Common functionality of gatherers that parse their input as a skeleton of |
+ translatable and nontranslatable chunks. |
+ ''' |
+ |
+ def __init__(self): |
+ interface.GathererBase.__init__(self) |
+ # List of parts of the document. Translateable parts are |
+ # clique.MessageClique objects, nontranslateable parts are plain strings. |
+ # Translated messages are inserted back into the skeleton using the quoting |
+ # rules defined by self.Escape() |
+ self.skeleton_ = [] |
+ # A list of the names of IDs that need to be defined for this resource |
+ # section to compile correctly. |
+ self.ids_ = [] |
+ # True if Parse() has already been called. |
+ self.have_parsed_ = False |
+ # True if a translatable chunk has been added |
+ self.translatable_chunk_ = False |
+ # If not None, all parts of the document will be put into this single |
+ # message; otherwise the normal skeleton approach is used. |
+ self.single_message_ = None |
+ # Number to use for the next placeholder name. Used only if single_message |
+ # is not None |
+ self.ph_counter_ = 1 |
+ |
+ def GetText(self): |
+ '''Returns the original text of the section''' |
+ return self.text_ |
+ |
+ def Escape(self, text): |
+ '''Subclasses can override. Base impl is identity. |
+ ''' |
+ return text |
+ |
+ def UnEscape(self, text): |
+ '''Subclasses can override. Base impl is identity. |
+ ''' |
+ return text |
+ |
+ def GetTextualIds(self): |
+ '''Returns the list of textual IDs that need to be defined for this |
+ resource section to compile correctly.''' |
+ return self.ids_ |
+ |
+ def _AddTextualId(self, id): |
+ self.ids_.append(id) |
+ |
+ def GetCliques(self): |
+ '''Returns the message cliques for each translateable message in the |
+ resource section.''' |
+ return filter(lambda x: isinstance(x, clique.MessageClique), self.skeleton_) |
+ |
+ def Translate(self, lang, pseudo_if_not_available=True, |
+ skeleton_gatherer=None, fallback_to_english=False): |
+ if len(self.skeleton_) == 0: |
+ raise exception.NotReady() |
+ if skeleton_gatherer: |
+ assert len(skeleton_gatherer.skeleton_) == len(self.skeleton_) |
+ |
+ out = [] |
+ for ix in range(len(self.skeleton_)): |
+ if isinstance(self.skeleton_[ix], types.StringTypes): |
+ if skeleton_gatherer: |
+ # Make sure the skeleton is like the original |
+ assert(isinstance(skeleton_gatherer.skeleton_[ix], types.StringTypes)) |
+ out.append(skeleton_gatherer.skeleton_[ix]) |
+ else: |
+ out.append(self.skeleton_[ix]) |
+ else: |
+ if skeleton_gatherer: # Make sure the skeleton is like the original |
+ assert(not isinstance(skeleton_gatherer.skeleton_[ix], |
+ types.StringTypes)) |
+ msg = self.skeleton_[ix].MessageForLanguage(lang, |
+ pseudo_if_not_available, |
+ fallback_to_english) |
+ |
+ def MyEscape(text): |
+ return self.Escape(text) |
+ text = msg.GetRealContent(escaping_function=MyEscape) |
+ out.append(text) |
+ return ''.join(out) |
+ |
+ def Parse(self): |
+ '''Parses the section. Implemented by subclasses. Idempotent.''' |
+ raise NotImplementedError() |
+ |
+ def _AddNontranslateableChunk(self, chunk): |
+ '''Adds a nontranslateable chunk.''' |
+ if self.single_message_: |
+ ph = tclib.Placeholder('XX%02dXX' % self.ph_counter_, chunk, chunk) |
+ self.ph_counter_ += 1 |
+ self.single_message_.AppendPlaceholder(ph) |
+ else: |
+ self.skeleton_.append(chunk) |
+ |
+ def _AddTranslateableChunk(self, chunk): |
+ '''Adds a translateable chunk. It will be unescaped before being added.''' |
+ # We don't want empty messages since they are redundant and the TC |
+ # doesn't allow them. |
+ if chunk == '': |
+ return |
+ |
+ unescaped_text = self.UnEscape(chunk) |
+ if self.single_message_: |
+ self.single_message_.AppendText(unescaped_text) |
+ else: |
+ self.skeleton_.append(self.uberclique.MakeClique( |
+ tclib.Message(text=unescaped_text))) |
+ self.translatable_chunk_ = True |