Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Unified Diff: tools/grit/grit/xtb_reader.py

Issue 1410853008: Move grit from DEPS into src. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: webview licenses Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/grit/grit/util_unittest.py ('k') | tools/grit/grit/xtb_reader_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/grit/grit/xtb_reader.py
diff --git a/tools/grit/grit/xtb_reader.py b/tools/grit/grit/xtb_reader.py
new file mode 100755
index 0000000000000000000000000000000000000000..b92da39e80c4f0a27aa609d5ed62b91aa0245c5d
--- /dev/null
+++ b/tools/grit/grit/xtb_reader.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 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.
+
+'''Fast and efficient parser for XTB files.
+'''
+
+
+import sys
+import xml.sax
+import xml.sax.handler
+
+import grit.node.base
+
+
+class XtbContentHandler(xml.sax.handler.ContentHandler):
+ '''A content handler that calls a given callback function for each
+ translation in the XTB file.
+ '''
+
+ def __init__(self, callback, defs=None, debug=False, target_platform=None):
+ self.callback = callback
+ self.debug = debug
+ # 0 if we are not currently parsing a translation, otherwise the message
+ # ID of that translation.
+ self.current_id = 0
+ # Empty if we are not currently parsing a translation, otherwise the
+ # parts we have for that translation - a list of tuples
+ # (is_placeholder, text)
+ self.current_structure = []
+ # Set to the language ID when we see the <translationbundle> node.
+ self.language = ''
+ # Keep track of the if block we're inside. We can't nest ifs.
+ self.if_expr = None
+ # Root defines to be used with if expr.
+ if defs:
+ self.defines = defs
+ else:
+ self.defines = {}
+ # Target platform for build.
+ if target_platform:
+ self.target_platform = target_platform
+ else:
+ self.target_platform = sys.platform
+
+ def startElement(self, name, attrs):
+ if name == 'translation':
+ assert self.current_id == 0 and len(self.current_structure) == 0, (
+ "Didn't expect a <translation> element here.")
+ self.current_id = attrs.getValue('id')
+ elif name == 'ph':
+ assert self.current_id != 0, "Didn't expect a <ph> element here."
+ self.current_structure.append((True, attrs.getValue('name')))
+ elif name == 'translationbundle':
+ self.language = attrs.getValue('lang')
+ elif name in ('if', 'then', 'else'):
+ assert self.if_expr is None, "Can't nest <if> or use <else> in xtb files"
+ self.if_expr = attrs.getValue('expr')
+
+ def endElement(self, name):
+ if name == 'translation':
+ assert self.current_id != 0
+
+ defs = self.defines
+ def pp_ifdef(define):
+ return define in defs
+ def pp_if(define):
+ return define in defs and defs[define]
+
+ # If we're in an if block, only call the callback (add the translation)
+ # if the expression is True.
+ should_run_callback = True
+ if self.if_expr:
+ should_run_callback = grit.node.base.Node.EvaluateExpression(
+ self.if_expr, self.defines, self.target_platform)
+ if should_run_callback:
+ self.callback(self.current_id, self.current_structure)
+
+ self.current_id = 0
+ self.current_structure = []
+ elif name == 'if':
+ assert self.if_expr is not None
+ self.if_expr = None
+
+ def characters(self, content):
+ if self.current_id != 0:
+ # We are inside a <translation> node so just add the characters to our
+ # structure.
+ #
+ # This naive way of handling characters is OK because in the XTB format,
+ # <ph> nodes are always empty (always <ph name="XXX"/>) and whitespace
+ # inside the <translation> node should be preserved.
+ self.current_structure.append((False, content))
+
+
+class XtbErrorHandler(xml.sax.handler.ErrorHandler):
+ def error(self, exception):
+ pass
+
+ def fatalError(self, exception):
+ raise exception
+
+ def warning(self, exception):
+ pass
+
+
+def Parse(xtb_file, callback_function, defs=None, debug=False,
+ target_platform=None):
+ '''Parse xtb_file, making a call to callback_function for every translation
+ in the XTB file.
+
+ The callback function must have the signature as described below. The 'parts'
+ parameter is a list of tuples (is_placeholder, text). The 'text' part is
+ either the raw text (if is_placeholder is False) or the name of the placeholder
+ (if is_placeholder is True).
+
+ Args:
+ xtb_file: open('fr.xtb')
+ callback_function: def Callback(msg_id, parts): pass
+ defs: None, or a dictionary of preprocessor definitions.
+ debug: Default False. Set True for verbose debug output.
+ target_platform: None, or a sys.platform-like identifier of the build
+ target platform.
+
+ Return:
+ The language of the XTB, e.g. 'fr'
+ '''
+ # Start by advancing the file pointer past the DOCTYPE thing, as the TC
+ # uses a path to the DTD that only works in Unix.
+ # TODO(joi) Remove this ugly hack by getting the TC gang to change the
+ # XTB files somehow?
+ front_of_file = xtb_file.read(1024)
+ xtb_file.seek(front_of_file.find('<translationbundle'))
+
+ handler = XtbContentHandler(callback=callback_function, defs=defs,
+ debug=debug, target_platform=target_platform)
+ xml.sax.parse(xtb_file, handler)
+ assert handler.language != ''
+ return handler.language
+
« no previous file with comments | « tools/grit/grit/util_unittest.py ('k') | tools/grit/grit/xtb_reader_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698