| 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 |