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

Unified Diff: tools/grit/grit/format/android_xml.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/format/__init__.py ('k') | tools/grit/grit/format/android_xml_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/grit/grit/format/android_xml.py
diff --git a/tools/grit/grit/format/android_xml.py b/tools/grit/grit/format/android_xml.py
new file mode 100755
index 0000000000000000000000000000000000000000..be9d79546d973fb0d6a0e7c15655f15f9ab9f254
--- /dev/null
+++ b/tools/grit/grit/format/android_xml.py
@@ -0,0 +1,200 @@
+#!/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.
+
+"""Produces localized strings.xml files for Android.
+
+In cases where an "android" type output file is requested in a grd, the classes
+in android_xml will process the messages and translations to produce a valid
+strings.xml that is properly localized with the specified language.
+
+For example if the following output tag were to be included in a grd file
+ <outputs>
+ ...
+ <output filename="values-es/strings.xml" type="android" lang="es" />
+ ...
+ </outputs>
+
+for a grd file with the following messages:
+
+ <message name="IDS_HELLO" desc="Simple greeting">Hello</message>
+ <message name="IDS_WORLD" desc="The world">world</message>
+
+and there existed an appropriate xtb file containing the Spanish translations,
+then the output would be:
+
+ <?xml version="1.0" encoding="utf-8"?>
+ <resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <string name="hello">"Hola"</string>
+ <string name="world">"mundo"</string>
+ </resources>
+
+which would be written to values-es/strings.xml and usable by the Android
+resource framework.
+
+Advanced usage
+--------------
+
+To process only certain messages in a grd file, tag each desired message by
+adding "android_java" to formatter_data. Then set the environmental variable
+ANDROID_JAVA_TAGGED_ONLY to "true" when building the grd file. For example:
+
+ <message name="IDS_HELLO" formatter_data="android_java">Hello</message>
+
+To generate Android plurals (aka "quantity strings"), use the ICU plural syntax
+in the grd file. This will automatically be transformed into a <purals> element
+in the output xml file. For example:
+
+ <message name="IDS_CATS">
+ {NUM_CATS, plural,
+ =1 {1 cat}
+ other {# cats}}
+ </message>
+
+ will produce
+
+ <plurals name="cats">
+ <item quantity="one">1 Katze</item>
+ <item quantity="other">%d Katzen</item>
+ </plurals>
+"""
+
+import os
+import re
+import types
+import xml.sax.saxutils
+
+from grit import lazy_re
+from grit.node import message
+
+
+# When this environmental variable has value "true", only tagged messages will
+# be outputted.
+_TAGGED_ONLY_ENV_VAR = 'ANDROID_JAVA_TAGGED_ONLY'
+_TAGGED_ONLY_DEFAULT = False
+
+# In tagged-only mode, only messages with this tag will be ouputted.
+_EMIT_TAG = 'android_java'
+
+_NAME_PATTERN = lazy_re.compile('IDS_(?P<name>[A-Z0-9_]+)\Z')
+
+# Most strings are output as a <string> element. Note the double quotes
+# around the value to preserve whitespace.
+_STRING_TEMPLATE = u'<string name="%s">"%s"</string>\n'
+
+# Some strings are output as a <plurals> element.
+_PLURALS_TEMPLATE = '<plurals name="%s">\n%s</plurals>\n'
+_PLURALS_ITEM_TEMPLATE = ' <item quantity="%s">%s</item>\n'
+_PLURALS_PATTERN = lazy_re.compile(r'\{[A-Z_]+,\s*plural,(?P<items>.*)\}$', flags=re.S)
+_PLURALS_ITEM_PATTERN = lazy_re.compile(r'(?P<quantity>\S+)\s*\{(?P<value>.*?)\}')
+_PLURALS_QUANTITY_MAP = {
+ '=0': 'zero',
+ 'zero': 'zero',
+ '=1': 'one',
+ 'one': 'one',
+ '=2': 'two',
+ 'two': 'two',
+ 'few': 'few',
+ 'many': 'many',
+ 'other': 'other',
+}
+
+
+def Format(root, lang='en', output_dir='.'):
+ yield ('<?xml version="1.0" encoding="utf-8"?>\n'
+ '<resources '
+ 'xmlns:android="http://schemas.android.com/apk/res/android">\n')
+
+ tagged_only = _TAGGED_ONLY_DEFAULT
+ if _TAGGED_ONLY_ENV_VAR in os.environ:
+ tagged_only = os.environ[_TAGGED_ONLY_ENV_VAR].lower()
+ if tagged_only == 'true':
+ tagged_only = True
+ elif tagged_only == 'false':
+ tagged_only = False
+ else:
+ raise Exception('env variable ANDROID_JAVA_TAGGED_ONLY must have value '
+ 'true or false. Invalid value: %s' % tagged_only)
+
+ for item in root.ActiveDescendants():
+ with item:
+ if ShouldOutputNode(item, tagged_only):
+ yield _FormatMessage(item, lang)
+
+ yield '</resources>\n'
+
+
+def ShouldOutputNode(node, tagged_only):
+ """Returns true if node should be outputted.
+
+ Args:
+ node: a Node from the grd dom
+ tagged_only: true, if only tagged messages should be outputted
+ """
+ return (isinstance(node, message.MessageNode) and
+ (not tagged_only or _EMIT_TAG in node.formatter_data))
+
+
+def _FormatPluralMessage(message):
+ """Compiles ICU plural syntax to the body of an Android <plurals> element.
+
+ 1. In a .grd file, we can write a plural string like this:
+
+ <message name="IDS_THINGS">
+ {NUM_THINGS, plural,
+ =1 {1 thing}
+ other {# things}}
+ </message>
+
+ 2. The Android equivalent looks like this:
+
+ <plurals name="things">
+ <item quantity="one">1 thing</item>
+ <item quantity="other">%d things</item>
+ </plurals>
+
+ This method takes the body of (1) and converts it to the body of (2).
+
+ If the message is *not* a plural string, this function returns `None`.
+ If the message includes quantities without an equivalent format in Android,
+ it raises an exception.
+ """
+ ret = {}
+ plural_match = _PLURALS_PATTERN.match(message)
+ if not plural_match:
+ return None
+ body_in = plural_match.group('items').strip()
+ lines = []
+ for item_match in _PLURALS_ITEM_PATTERN.finditer(body_in):
+ quantity_in = item_match.group('quantity')
+ quantity_out = _PLURALS_QUANTITY_MAP.get(quantity_in)
+ value_in = item_match.group('value')
+ value_out = '"' + value_in.replace('#', '%d') + '"'
+ if quantity_out:
+ lines.append(_PLURALS_ITEM_TEMPLATE % (quantity_out, value_out))
+ else:
+ raise Exception('Unsupported plural quantity for android '
+ 'strings.xml: %s' % quantity_in)
+ return ''.join(lines)
+
+
+def _FormatMessage(item, lang):
+ """Writes out a single string as a <resource/> element."""
+
+ mangled_name = item.GetTextualIds()[0]
+ match = _NAME_PATTERN.match(mangled_name)
+ if not match:
+ raise Exception('Unexpected resource name: %s' % mangled_name)
+ name = match.group('name').lower()
+
+ value = item.ws_at_start + item.Translate(lang) + item.ws_at_end
+ # Replace < > & with &lt; &gt; &amp; to ensure we generate valid XML and
+ # replace ' " with \' \" to conform to Android's string formatting rules.
+ value = xml.sax.saxutils.escape(value, {"'": "\\'", '"': '\\"'})
+
+ plurals = _FormatPluralMessage(value)
+ if plurals:
+ return _PLURALS_TEMPLATE % (name, plurals)
+ else:
+ return _STRING_TEMPLATE % (name, value)
« no previous file with comments | « tools/grit/grit/format/__init__.py ('k') | tools/grit/grit/format/android_xml_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698