Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: localeTools.py

Issue 29562599: Issue 5751 - Removing legacy gecko support (Closed)
Patch Set: Created Oct. 2, 2017, 10:33 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 # This Source Code Form is subject to the terms of the Mozilla Public 1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 4
5 import re 5 import re
6 import os 6 import os
7 import sys 7 import sys
8 import codecs 8 import codecs
9 import json 9 import json
10 import urlparse 10 import urlparse
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 154
155 def unescapeEntity(value): 155 def unescapeEntity(value):
156 return value.replace('&amp;', '&').replace('&lt;', '<').replace('&gt;', '>') .replace('&quot;', '"') 156 return value.replace('&amp;', '&').replace('&lt;', '<').replace('&gt;', '>') .replace('&quot;', '"')
157 157
158 158
159 def mapLocale(type, locale): 159 def mapLocale(type, locale):
160 mapping = langMappingChrome if type == 'ISO-15897' else langMappingGecko 160 mapping = langMappingChrome if type == 'ISO-15897' else langMappingGecko
161 return mapping.get(locale, locale) 161 return mapping.get(locale, locale)
162 162
163 163
164 def parseDTDString(data, path):
165 result = []
166 currentComment = [None]
167
168 parser = ParserCreate()
169 parser.UseForeignDTD(True)
170 parser.SetParamEntityParsing(XML_PARAM_ENTITY_PARSING_ALWAYS)
171
172 def ExternalEntityRefHandler(context, base, systemId, publicId):
173 subparser = parser.ExternalEntityParserCreate(context, 'utf-8')
174 subparser.Parse(data.encode('utf-8'), True)
175 return 1
176
177 def CommentHandler(data):
178 currentComment[0] = data.strip()
179
180 def EntityDeclHandler(entityName, is_parameter_entity, value, base, systemId , publicId, notationName):
181 result.append((unescapeEntity(entityName), currentComment[0], unescapeEn tity(value.strip())))
182 currentComment[0] = None
183
184 parser.ExternalEntityRefHandler = ExternalEntityRefHandler
185 parser.CommentHandler = CommentHandler
186 parser.EntityDeclHandler = EntityDeclHandler
187 parser.Parse('<!DOCTYPE root SYSTEM "foo"><root/>', True)
188
189 for entry in result:
190 yield entry
191
192
193 def escapeProperty(value): 164 def escapeProperty(value):
194 return value.replace('\n', '\\n') 165 return value.replace('\n', '\\n')
195 166
196 167
197 def unescapeProperty(value): 168 def unescapeProperty(value):
198 return value.replace('\\n', '\n') 169 return value.replace('\\n', '\n')
199 170
200 171
201 def parsePropertiesString(data, path): 172 def parsePropertiesString(data, path):
202 currentComment = None 173 currentComment = None
203 for line in data.splitlines(): 174 for line in data.splitlines():
204 match = re.search(r'^\s*[#!]\s*(.*)', line) 175 match = re.search(r'^\s*[#!]\s*(.*)', line)
205 if match: 176 if match:
206 currentComment = match.group(1) 177 currentComment = match.group(1)
207 elif '=' in line: 178 elif '=' in line:
208 key, value = line.split('=', 1) 179 key, value = line.split('=', 1)
209 yield (unescapeProperty(key), currentComment, unescapeProperty(value )) 180 yield (unescapeProperty(key), currentComment, unescapeProperty(value ))
210 currentComment = None 181 currentComment = None
211 elif re.search(r'\S', line): 182 elif re.search(r'\S', line):
212 print >>sys.stderr, 'Unrecognized data in file %s: %s' % (path, line ) 183 print >>sys.stderr, 'Unrecognized data in file %s: %s' % (path, line )
213 184
214 185
215 def parseString(data, path): 186 def parseString(data, path):
216 result = {'_origData': data} 187 result = {'_origData': data}
217 if path.endswith('.dtd'): 188 if path.endswith('.properties'):
Sebastian Noack 2017/10/03 02:22:39 Both, the .dtd and the .properties format are spec
tlucas 2017/10/04 11:48:38 Done.
218 it = parseDTDString(data, path)
219 elif path.endswith('.properties'):
220 it = parsePropertiesString(data, path) 189 it = parsePropertiesString(data, path)
221 else: 190 else:
222 return None 191 return None
223 192
224 for name, comment, value in it: 193 for name, comment, value in it:
225 result[name] = value 194 result[name] = value
226 return result 195 return result
227 196
228 197
229 def readFile(path): 198 def readFile(path):
230 fileHandle = codecs.open(path, 'rb', encoding='utf-8') 199 fileHandle = codecs.open(path, 'rb', encoding='utf-8')
231 data = fileHandle.read() 200 data = fileHandle.read()
232 fileHandle.close() 201 fileHandle.close()
233 return parseString(data, path) 202 return parseString(data, path)
234 203
235 204
236 def generateStringEntry(key, value, path):
237 if path.endswith('.dtd'):
238 return '<!ENTITY %s "%s">\n' % (escapeEntity(key), escapeEntity(value))
239 else:
240 return '%s=%s\n' % (escapeProperty(key), escapeProperty(value))
241
242
243 def toJSON(path): 205 def toJSON(path):
244 fileHandle = codecs.open(path, 'rb', encoding='utf-8') 206 fileHandle = codecs.open(path, 'rb', encoding='utf-8')
245 data = fileHandle.read() 207 data = fileHandle.read()
246 fileHandle.close() 208 fileHandle.close()
247 209
248 if path.endswith('.dtd'): 210 if path.endswith('.properties'):
249 it = parseDTDString(data, path)
250 elif path.endswith('.properties'):
251 it = parsePropertiesString(data, path) 211 it = parsePropertiesString(data, path)
252 else: 212 else:
253 return None 213 return None
254 214
255 result = OrderedDict() 215 result = OrderedDict()
256 for name, comment, value in it: 216 for name, comment, value in it:
257 obj = {'message': value} 217 obj = {'message': value}
258 if comment == None: 218 if comment == None:
259 obj['description'] = name 219 obj['description'] = name
260 else: 220 else:
261 obj['description'] = '%s: %s' % (name, comment) 221 obj['description'] = '%s: %s' % (name, comment)
262 result[name] = obj 222 result[name] = obj
263 return json.dumps(result, ensure_ascii=False, indent=2) 223 return json.dumps(result, ensure_ascii=False, indent=2)
264 224
265 225
266 def fromJSON(path, data): 226 def fromJSON(path, data):
267 data = json.loads(data) 227 data = json.loads(data)
268 if not data: 228 if not data:
269 if os.path.exists(path): 229 if os.path.exists(path):
270 os.remove(path) 230 os.remove(path)
271 return 231 return
272 232
273 dir = os.path.dirname(path) 233 dir = os.path.dirname(path)
274 if not os.path.exists(dir): 234 if not os.path.exists(dir):
275 os.makedirs(dir) 235 os.makedirs(dir)
276 file = codecs.open(path, 'wb', encoding='utf-8') 236 file = codecs.open(path, 'wb', encoding='utf-8')
277 for key, value in data.iteritems(): 237 for key, value in data.iteritems():
278 file.write(generateStringEntry(key, value['message'], path)) 238 file.write('{}={}\n'.format(escapeProperty(key),
239 escapeProperty(value['message'])))
279 file.close() 240 file.close()
280 241
281 242
282 def preprocessChromeLocale(path, metadata, isMaster): 243 def preprocessChromeLocale(path, metadata, isMaster):
283 fileHandle = codecs.open(path, 'rb', encoding='utf-8') 244 fileHandle = codecs.open(path, 'rb', encoding='utf-8')
284 data = json.load(fileHandle) 245 data = json.load(fileHandle)
285 fileHandle.close() 246 fileHandle.close()
286 247
287 for key, value in data.iteritems(): 248 for key, value in data.iteritems():
288 if isMaster: 249 if isMaster:
(...skipping 28 matching lines...) Expand all
317 def setupTranslations(localeConfig, projectName, key): 278 def setupTranslations(localeConfig, projectName, key):
318 # Make a new set from the locales list, mapping to Crowdin friendly format 279 # Make a new set from the locales list, mapping to Crowdin friendly format
319 locales = {mapLocale(localeConfig['name_format'], locale) 280 locales = {mapLocale(localeConfig['name_format'], locale)
320 for locale in localeConfig['locales']} 281 for locale in localeConfig['locales']}
321 282
322 # Fill up with locales that we don't have but the browser supports 283 # Fill up with locales that we don't have but the browser supports
323 if 'chrome' in localeConfig['target_platforms']: 284 if 'chrome' in localeConfig['target_platforms']:
324 for locale in chromeLocales: 285 for locale in chromeLocales:
325 locales.add(mapLocale('ISO-15897', locale)) 286 locales.add(mapLocale('ISO-15897', locale))
326 287
327 if 'gecko' in localeConfig['target_platforms']: 288 if 'gecko-webext' in localeConfig['target_platforms']:
328 firefoxLocales = urllib2.urlopen('http://www.mozilla.org/en-US/firefox/a ll.html').read() 289 firefoxLocales = urllib2.urlopen('http://www.mozilla.org/en-US/firefox/a ll.html').read()
329 for match in re.finditer(r'&amp;lang=([\w\-]+)"', firefoxLocales): 290 for match in re.finditer(r'&amp;lang=([\w\-]+)"', firefoxLocales):
330 locales.add(mapLocale('BCP-47', match.group(1))) 291 locales.add(mapLocale('BCP-47', match.group(1)))
331 langPacks = urllib2.urlopen('https://addons.mozilla.org/en-US/firefox/la nguage-tools/').read() 292 langPacks = urllib2.urlopen('https://addons.mozilla.org/en-US/firefox/la nguage-tools/').read()
332 for match in re.finditer(r'<tr>.*?</tr>', langPacks, re.S): 293 for match in re.finditer(r'<tr>.*?</tr>', langPacks, re.S):
333 if match.group(0).find('Install Language Pack') >= 0: 294 if match.group(0).find('Install Language Pack') >= 0:
334 match2 = re.search(r'lang="([\w\-]+)"', match.group(0)) 295 match2 = re.search(r'lang="([\w\-]+)"', match.group(0))
335 if match2: 296 if match2:
336 locales.add(mapLocale('BCP-47', match2.group(1))) 297 locales.add(mapLocale('BCP-47', match2.group(1)))
337 298
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 if not info.filename.endswith('.json'): 430 if not info.filename.endswith('.json'):
470 continue 431 continue
471 432
472 dir, file = os.path.split(info.filename) 433 dir, file = os.path.split(info.filename)
473 if not re.match(r'^[\w\-]+$', dir) or dir == normalizedDefaultLocale: 434 if not re.match(r'^[\w\-]+$', dir) or dir == normalizedDefaultLocale:
474 continue 435 continue
475 if localeConfig['file_format'] == 'chrome-json' and file.count('.') == 1 : 436 if localeConfig['file_format'] == 'chrome-json' and file.count('.') == 1 :
476 origFile = file 437 origFile = file
477 else: 438 else:
478 origFile = re.sub(r'\.json$', '', file) 439 origFile = re.sub(r'\.json$', '', file)
479 if (localeConfig['file_format'] == 'gecko-dtd' and
480 not origFile.endswith('.dtd') and
481 not origFile.endswith('.properties')):
482 continue
483 440
484 if localeConfig['name_format'] == 'ISO-15897': 441 if localeConfig['name_format'] == 'ISO-15897':
485 mapping = langMappingChrome 442 mapping = langMappingChrome
486 else: 443 else:
487 mapping = langMappingGecko 444 mapping = langMappingGecko
488 445
489 for key, value in mapping.iteritems(): 446 for key, value in mapping.iteritems():
490 if value == dir: 447 if value == dir:
491 dir = key 448 dir = key
492 if localeConfig['name_format'] == 'ISO-15897': 449 if localeConfig['name_format'] == 'ISO-15897':
(...skipping 21 matching lines...) Expand all
514 else: 471 else:
515 fromJSON(path, data) 472 fromJSON(path, data)
516 473
517 # Remove any extra files 474 # Remove any extra files
518 for dir, files in dirs.iteritems(): 475 for dir, files in dirs.iteritems():
519 baseDir = os.path.join(localeConfig['base_path'], dir) 476 baseDir = os.path.join(localeConfig['base_path'], dir)
520 if not os.path.exists(baseDir): 477 if not os.path.exists(baseDir):
521 continue 478 continue
522 for file in os.listdir(baseDir): 479 for file in os.listdir(baseDir):
523 path = os.path.join(baseDir, file) 480 path = os.path.join(baseDir, file)
524 if os.path.isfile(path) and (file.endswith('.json') or file.endswith ('.properties') or file.endswith('.dtd')) and not file in files: 481 valid_extension = os.path.splitext(file)[1] in {'.json',
482 '.properties'}
483 if os.path.isfile(path) and valid_extension and not file in files:
525 os.remove(path) 484 os.remove(path)
OLDNEW

Powered by Google App Engine
This is Rietveld