Chromium Code Reviews| Index: grit/format/android_xml.py |
| diff --git a/grit/format/android_xml.py b/grit/format/android_xml.py |
| index d960bf49ddb8f009575b36f3a146cd25edbef8f8..5b2c080f8c482cc4619e5de61eb4ee36afc56dfb 100644 |
| --- a/grit/format/android_xml.py |
| +++ b/grit/format/android_xml.py |
| @@ -58,6 +58,7 @@ would generate |
| """ |
| import os |
| +import re |
| import types |
| import xml.sax.saxutils |
| @@ -96,6 +97,13 @@ _SIMPLE_TEMPLATE = u'<string name="%s">%s</string>\n' |
| _PRODUCT_TEMPLATE = u'<string name="%s" product="%s">%s</string>\n' |
| +# Some strings have a plural equivalent |
| +_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>.*?)\}') |
| + |
| + |
| def Format(root, lang='en', output_dir='.'): |
| yield ('<?xml version="1.0" encoding="utf-8"?>\n' |
| '<resources ' |
| @@ -131,6 +139,51 @@ def ShouldOutputNode(node, tagged_only): |
| (not tagged_only or _EMIT_TAG in node.formatter_data)) |
| +def _FormatPluralMessage(message): |
| + """Compile ICU plural syntax to the body of an Android <plurals> element. |
|
newt (away)
2015/08/04 03:14:26
nit: "Compiles"
conleyo
2015/08/04 16:53:02
Done.
|
| + |
| + 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() |
| + body_out = u'' |
|
newt (away)
2015/08/04 03:14:26
A better idiom for concatenating strings in python
conleyo
2015/08/04 16:53:02
Done.
|
| + for item_match in _PLURALS_ITEM_PATTERN.finditer(body_in): |
| + quantity = item_match.group('quantity') |
| + value = item_match.group('value').replace('#', '%d') |
| + if quantity == '=0': |
| + body_out += _PLURALS_ITEM_TEMPLATE % ('zero', value) |
| + elif quantity == '=1': |
| + body_out += _PLURALS_ITEM_TEMPLATE % ('one', value) |
| + elif quantity == 'other': |
| + body_out += _PLURALS_ITEM_TEMPLATE % ('other', value) |
| + else: |
|
newt (away)
2015/08/04 03:14:26
Why not handle "=2", "few" and "many"?
conleyo
2015/08/04 16:53:02
Done.
|
| + raise Exception('Unsupported plural quantity for android ' |
| + 'strings.xml: %s' % quantity) |
| + return body_out |
| + |
| + |
| def _FormatMessage(item, lang): |
| """Writes out a single string as a <resource/> element.""" |
| @@ -138,6 +191,7 @@ def _FormatMessage(item, lang): |
| # Replace < > & with < > & 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) |
| # Wrap the string in double quotes to preserve whitespace. |
| value = '"' + value + '"' |
| @@ -152,7 +206,9 @@ def _FormatMessage(item, lang): |
| product = item.formatter_data.get(_PRODUCT_TAG, product) |
| name = item.formatter_data.get(_NAME_TAG, name) |
| - if product: |
| + if plurals: |
| + return _PLURALS_TEMPLATE % (name, plurals) |
| + elif product: |
| return _PRODUCT_TEMPLATE % (name, product, value) |
| else: |
| return _SIMPLE_TEMPLATE % (name, value) |