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