OLD | NEW |
| (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 '''Support for ALL_ALL.xml format used by Igoogle plug-ins in Google Desktop.''' | |
7 | |
8 import StringIO | |
9 import re | |
10 import xml.sax | |
11 import xml.sax.handler | |
12 import xml.sax.saxutils | |
13 | |
14 from grit.gather import regexp | |
15 from grit import util | |
16 from grit import tclib | |
17 | |
18 # Placeholders can be defined in strings.xml files by putting the name of the | |
19 # placeholder between [![ and ]!] e.g. <MSG>Hello [![USER]!] how are you<MSG> | |
20 PLACEHOLDER_RE = re.compile('(\[!\[|\]!\])') | |
21 | |
22 | |
23 class IgoogleStringsContentHandler(xml.sax.handler.ContentHandler): | |
24 '''A very dumb parser for splitting the strings.xml file into translateable | |
25 and nontranslateable chunks.''' | |
26 | |
27 def __init__(self, parent): | |
28 self.curr_elem = '' | |
29 self.curr_text = '' | |
30 self.parent = parent | |
31 self.resource_name = '' | |
32 self.meaning = '' | |
33 self.translateable = True | |
34 | |
35 def startElement(self, name, attrs): | |
36 if (name != 'messagebundle'): | |
37 self.curr_elem = name | |
38 | |
39 attr_names = attrs.getQNames() | |
40 if 'name' in attr_names: | |
41 self.resource_name = attrs.getValueByQName('name') | |
42 | |
43 att_text = [] | |
44 for attr_name in attr_names: | |
45 att_text.append(' ') | |
46 att_text.append(attr_name) | |
47 att_text.append('=') | |
48 att_text.append( | |
49 xml.sax.saxutils.quoteattr(attrs.getValueByQName(attr_name))) | |
50 | |
51 self.parent._AddNontranslateableChunk("<%s%s>" % | |
52 (name, ''.join(att_text))) | |
53 | |
54 def characters(self, content): | |
55 if self.curr_elem != '': | |
56 self.curr_text += content | |
57 | |
58 def endElement(self, name): | |
59 if name != 'messagebundle': | |
60 self.parent.AddMessage(self.curr_text, self.resource_name, | |
61 self.meaning, self.translateable) | |
62 self.parent._AddNontranslateableChunk("</%s>\n" % name) | |
63 self.curr_elem = '' | |
64 self.curr_text = '' | |
65 self.resource_name = '' | |
66 self.meaning = '' | |
67 self.translateable = True | |
68 | |
69 def ignorableWhitespace(self, whitespace): | |
70 pass | |
71 | |
72 | |
73 class IgoogleStrings(regexp.RegexpGatherer): | |
74 '''Supports the ALL_ALL.xml format used by Igoogle gadgets.''' | |
75 | |
76 def AddMessage(self, msgtext, description, meaning, translateable): | |
77 if msgtext == '': | |
78 return | |
79 | |
80 msg = tclib.Message(description=description, meaning=meaning) | |
81 | |
82 unescaped_text = self.UnEscape(msgtext) | |
83 parts = PLACEHOLDER_RE.split(unescaped_text) | |
84 in_placeholder = False | |
85 for part in parts: | |
86 if part == '': | |
87 continue | |
88 elif part == '[![': | |
89 in_placeholder = True | |
90 elif part == ']!]': | |
91 in_placeholder = False | |
92 else: | |
93 if in_placeholder: | |
94 msg.AppendPlaceholder(tclib.Placeholder(part, '[![%s]!]' % part, | |
95 '(placeholder)')) | |
96 else: | |
97 msg.AppendText(part) | |
98 | |
99 self.skeleton_.append( | |
100 self.uberclique.MakeClique(msg, translateable=translateable)) | |
101 | |
102 # if statement needed because this is supposed to be idempotent (so never | |
103 # set back to false) | |
104 if translateable: | |
105 self.translatable_chunk_ = True | |
106 | |
107 # Although we use the RegexpGatherer base class, we do not use the | |
108 # _RegExpParse method of that class to implement Parse(). Instead, we | |
109 # parse using a SAX parser. | |
110 def Parse(self): | |
111 if self.have_parsed_: | |
112 return | |
113 self.have_parsed_ = True | |
114 | |
115 self.text_ = self._LoadInputFile().strip() | |
116 self._AddNontranslateableChunk(u'<messagebundle>\n') | |
117 stream = StringIO.StringIO(self.text_) | |
118 handler = IgoogleStringsContentHandler(self) | |
119 xml.sax.parse(stream, handler) | |
120 self._AddNontranslateableChunk(u'</messagebundle>\n') | |
121 | |
122 def Escape(self, text): | |
123 return util.EncodeCdata(text) | |
OLD | NEW |