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

Side by Side Diff: grit/format/android_xml.py

Issue 1442863002: Remove contents of grit's SVN repository. (Closed) Base URL: http://grit-i18n.googlecode.com/svn/trunk/
Patch Set: 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « grit/format/__init__.py ('k') | grit/format/android_xml_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 """Produces localized strings.xml files for Android.
7
8 In cases where an "android" type output file is requested in a grd, the classes
9 in android_xml will process the messages and translations to produce a valid
10 strings.xml that is properly localized with the specified language.
11
12 For example if the following output tag were to be included in a grd file
13 <outputs>
14 ...
15 <output filename="values-es/strings.xml" type="android" lang="es" />
16 ...
17 </outputs>
18
19 for a grd file with the following messages:
20
21 <message name="IDS_HELLO" desc="Simple greeting">Hello</message>
22 <message name="IDS_WORLD" desc="The world">world</message>
23
24 and there existed an appropriate xtb file containing the Spanish translations,
25 then the output would be:
26
27 <?xml version="1.0" encoding="utf-8"?>
28 <resources xmlns:android="http://schemas.android.com/apk/res/android">
29 <string name="hello">"Hola"</string>
30 <string name="world">"mundo"</string>
31 </resources>
32
33 which would be written to values-es/strings.xml and usable by the Android
34 resource framework.
35
36 Advanced usage
37 --------------
38
39 To process only certain messages in a grd file, tag each desired message by
40 adding "android_java" to formatter_data. Then set the environmental variable
41 ANDROID_JAVA_TAGGED_ONLY to "true" when building the grd file. For example:
42
43 <message name="IDS_HELLO" formatter_data="android_java">Hello</message>
44
45 To generate Android plurals (aka "quantity strings"), use the ICU plural syntax
46 in the grd file. This will automatically be transformed into a <purals> element
47 in the output xml file. For example:
48
49 <message name="IDS_CATS">
50 {NUM_CATS, plural,
51 =1 {1 cat}
52 other {# cats}}
53 </message>
54
55 will produce
56
57 <plurals name="cats">
58 <item quantity="one">1 Katze</item>
59 <item quantity="other">%d Katzen</item>
60 </plurals>
61 """
62
63 import os
64 import re
65 import types
66 import xml.sax.saxutils
67
68 from grit import lazy_re
69 from grit.node import message
70
71
72 # When this environmental variable has value "true", only tagged messages will
73 # be outputted.
74 _TAGGED_ONLY_ENV_VAR = 'ANDROID_JAVA_TAGGED_ONLY'
75 _TAGGED_ONLY_DEFAULT = False
76
77 # In tagged-only mode, only messages with this tag will be ouputted.
78 _EMIT_TAG = 'android_java'
79
80 _NAME_PATTERN = lazy_re.compile('IDS_(?P<name>[A-Z0-9_]+)\Z')
81
82 # Most strings are output as a <string> element. Note the double quotes
83 # around the value to preserve whitespace.
84 _STRING_TEMPLATE = u'<string name="%s">"%s"</string>\n'
85
86 # Some strings are output as a <plurals> element.
87 _PLURALS_TEMPLATE = '<plurals name="%s">\n%s</plurals>\n'
88 _PLURALS_ITEM_TEMPLATE = ' <item quantity="%s">%s</item>\n'
89 _PLURALS_PATTERN = lazy_re.compile(r'\{[A-Z_]+,\s*plural,(?P<items>.*)\}$', flag s=re.S)
90 _PLURALS_ITEM_PATTERN = lazy_re.compile(r'(?P<quantity>\S+)\s*\{(?P<value>.*?)\} ')
91 _PLURALS_QUANTITY_MAP = {
92 '=0': 'zero',
93 'zero': 'zero',
94 '=1': 'one',
95 'one': 'one',
96 '=2': 'two',
97 'two': 'two',
98 'few': 'few',
99 'many': 'many',
100 'other': 'other',
101 }
102
103
104 def Format(root, lang='en', output_dir='.'):
105 yield ('<?xml version="1.0" encoding="utf-8"?>\n'
106 '<resources '
107 'xmlns:android="http://schemas.android.com/apk/res/android">\n')
108
109 tagged_only = _TAGGED_ONLY_DEFAULT
110 if _TAGGED_ONLY_ENV_VAR in os.environ:
111 tagged_only = os.environ[_TAGGED_ONLY_ENV_VAR].lower()
112 if tagged_only == 'true':
113 tagged_only = True
114 elif tagged_only == 'false':
115 tagged_only = False
116 else:
117 raise Exception('env variable ANDROID_JAVA_TAGGED_ONLY must have value '
118 'true or false. Invalid value: %s' % tagged_only)
119
120 for item in root.ActiveDescendants():
121 with item:
122 if ShouldOutputNode(item, tagged_only):
123 yield _FormatMessage(item, lang)
124
125 yield '</resources>\n'
126
127
128 def ShouldOutputNode(node, tagged_only):
129 """Returns true if node should be outputted.
130
131 Args:
132 node: a Node from the grd dom
133 tagged_only: true, if only tagged messages should be outputted
134 """
135 return (isinstance(node, message.MessageNode) and
136 (not tagged_only or _EMIT_TAG in node.formatter_data))
137
138
139 def _FormatPluralMessage(message):
140 """Compiles ICU plural syntax to the body of an Android <plurals> element.
141
142 1. In a .grd file, we can write a plural string like this:
143
144 <message name="IDS_THINGS">
145 {NUM_THINGS, plural,
146 =1 {1 thing}
147 other {# things}}
148 </message>
149
150 2. The Android equivalent looks like this:
151
152 <plurals name="things">
153 <item quantity="one">1 thing</item>
154 <item quantity="other">%d things</item>
155 </plurals>
156
157 This method takes the body of (1) and converts it to the body of (2).
158
159 If the message is *not* a plural string, this function returns `None`.
160 If the message includes quantities without an equivalent format in Android,
161 it raises an exception.
162 """
163 ret = {}
164 plural_match = _PLURALS_PATTERN.match(message)
165 if not plural_match:
166 return None
167 body_in = plural_match.group('items').strip()
168 lines = []
169 for item_match in _PLURALS_ITEM_PATTERN.finditer(body_in):
170 quantity_in = item_match.group('quantity')
171 quantity_out = _PLURALS_QUANTITY_MAP.get(quantity_in)
172 value_in = item_match.group('value')
173 value_out = '"' + value_in.replace('#', '%d') + '"'
174 if quantity_out:
175 lines.append(_PLURALS_ITEM_TEMPLATE % (quantity_out, value_out))
176 else:
177 raise Exception('Unsupported plural quantity for android '
178 'strings.xml: %s' % quantity_in)
179 return ''.join(lines)
180
181
182 def _FormatMessage(item, lang):
183 """Writes out a single string as a <resource/> element."""
184
185 mangled_name = item.GetTextualIds()[0]
186 match = _NAME_PATTERN.match(mangled_name)
187 if not match:
188 raise Exception('Unexpected resource name: %s' % mangled_name)
189 name = match.group('name').lower()
190
191 value = item.ws_at_start + item.Translate(lang) + item.ws_at_end
192 # Replace < > & with &lt; &gt; &amp; to ensure we generate valid XML and
193 # replace ' " with \' \" to conform to Android's string formatting rules.
194 value = xml.sax.saxutils.escape(value, {"'": "\\'", '"': '\\"'})
195
196 plurals = _FormatPluralMessage(value)
197 if plurals:
198 return _PLURALS_TEMPLATE % (name, plurals)
199 else:
200 return _STRING_TEMPLATE % (name, value)
OLDNEW
« no previous file with comments | « grit/format/__init__.py ('k') | grit/format/android_xml_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698