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

Side by Side Diff: grit/format/rc.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
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 '''Support for formatting an RC file for compilation.
7 '''
8
9 import os
10 import types
11 import re
12 from functools import partial
13
14 from grit import util
15 from grit.node import misc
16
17
18 def Format(root, lang='en', output_dir='.'):
19 from grit.node import empty, include, message, structure
20
21 yield _FormatHeader(root, lang, output_dir)
22
23 for item in root.ActiveDescendants():
24 if isinstance(item, empty.MessagesNode):
25 # Write one STRINGTABLE per <messages> container.
26 # This is hacky: it iterates over the children twice.
27 yield 'STRINGTABLE\nBEGIN\n'
28 for subitem in item.ActiveDescendants():
29 if isinstance(subitem, message.MessageNode):
30 with subitem:
31 yield FormatMessage(subitem, lang)
32 yield 'END\n\n'
33 elif isinstance(item, include.IncludeNode):
34 with item:
35 yield FormatInclude(item, lang, output_dir)
36 elif isinstance(item, structure.StructureNode):
37 with item:
38 yield FormatStructure(item, lang, output_dir)
39
40
41 '''
42 This dictionary defines the language charset pair lookup table, which is used
43 for replacing the GRIT expand variables for language info in Product Version
44 resource. The key is the language ISO country code, and the value
45 is the language and character-set pair, which is a hexadecimal string
46 consisting of the concatenation of the language and character-set identifiers.
47 The first 4 digit of the value is the hex value of LCID, the remaining
48 4 digits is the hex value of character-set id(code page)of the language.
49
50 LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
51 Codepage resource: http://www.science.co.il/language/locale-codes.asp
52
53 We have defined three GRIT expand_variables to be used in the version resource
54 file to set the language info. Here is an example how they should be used in
55 the VS_VERSION_INFO section of the resource file to allow GRIT to localize
56 the language info correctly according to product locale.
57
58 VS_VERSION_INFO VERSIONINFO
59 ...
60 BEGIN
61 BLOCK "StringFileInfo"
62 BEGIN
63 BLOCK "[GRITVERLANGCHARSETHEX]"
64 BEGIN
65 ...
66 END
67 END
68 BLOCK "VarFileInfo"
69 BEGIN
70 VALUE "Translation", [GRITVERLANGID], [GRITVERCHARSETID]
71 END
72 END
73
74 '''
75
76 _LANGUAGE_CHARSET_PAIR = {
77 # Language neutral LCID, unicode(1200) code page.
78 'neutral' : '000004b0',
79 # LANG_USER_DEFAULT LCID, unicode(1200) code page.
80 'userdefault' : '040004b0',
81 'ar' : '040104e8',
82 'fi' : '040b04e4',
83 'ko' : '041203b5',
84 'es' : '0c0a04e4',
85 'bg' : '040204e3',
86 # No codepage for filipino, use unicode(1200).
87 'fil' : '046404e4',
88 'fr' : '040c04e4',
89 'lv' : '042604e9',
90 'sv' : '041d04e4',
91 'ca' : '040304e4',
92 'de' : '040704e4',
93 'lt' : '042704e9',
94 # Do not use! This is only around for backwards
95 # compatibility and will be removed - use fil instead
96 'tl' : '0c0004b0',
97 'zh-CN' : '080403a8',
98 'zh-TW' : '040403b6',
99 'zh-HK' : '0c0403b6',
100 'el' : '040804e5',
101 'no' : '001404e4',
102 'nb' : '041404e4',
103 'nn' : '081404e4',
104 'th' : '041e036a',
105 'he' : '040d04e7',
106 'iw' : '040d04e7',
107 'pl' : '041504e2',
108 'tr' : '041f04e6',
109 'hr' : '041a04e4',
110 # No codepage for Hindi, use unicode(1200).
111 'hi' : '043904b0',
112 'pt-PT' : '081604e4',
113 'pt-BR' : '041604e4',
114 'uk' : '042204e3',
115 'cs' : '040504e2',
116 'hu' : '040e04e2',
117 'ro' : '041804e2',
118 # No codepage for Urdu, use unicode(1200).
119 'ur' : '042004b0',
120 'da' : '040604e4',
121 'is' : '040f04e4',
122 'ru' : '041904e3',
123 'vi' : '042a04ea',
124 'nl' : '041304e4',
125 'id' : '042104e4',
126 'sr' : '081a04e2',
127 'en-GB' : '0809040e',
128 'it' : '041004e4',
129 'sk' : '041b04e2',
130 'et' : '042504e9',
131 'ja' : '041103a4',
132 'sl' : '042404e2',
133 'en' : '040904b0',
134 # LCID for Mexico; Windows does not support L.A. LCID.
135 'es-419' : '080a04e4',
136 # No codepage for Bengali, use unicode(1200).
137 'bn' : '044504b0',
138 'fa' : '042904e8',
139 # No codepage for Gujarati, use unicode(1200).
140 'gu' : '044704b0',
141 # No codepage for Kannada, use unicode(1200).
142 'kn' : '044b04b0',
143 # Malay (Malaysia) [ms-MY]
144 'ms' : '043e04e4',
145 # No codepage for Malayalam, use unicode(1200).
146 'ml' : '044c04b0',
147 # No codepage for Marathi, use unicode(1200).
148 'mr' : '044e04b0',
149 # No codepage for Oriya , use unicode(1200).
150 'or' : '044804b0',
151 # No codepage for Tamil, use unicode(1200).
152 'ta' : '044904b0',
153 # No codepage for Telugu, use unicode(1200).
154 'te' : '044a04b0',
155 # No codepage for Amharic, use unicode(1200). >= Vista.
156 'am' : '045e04b0',
157 'sw' : '044104e4',
158 'af' : '043604e4',
159 'eu' : '042d04e4',
160 'fr-CA' : '0c0c04e4',
161 'gl' : '045604e4',
162 # No codepage for Zulu, use unicode(1200).
163 'zu' : '043504b0',
164 'fake-bidi' : '040d04e7',
165 }
166
167 # Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
168 #
169 # There is no appropriate sublang for Spanish (Latin America) [es-419], so we
170 # use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other
171 # Latin American countries, Mexican Spanish is supported by VERSIONINFO:
172 # http://msdn.microsoft.com/en-us/library/aa381058.aspx
173
174 _LANGUAGE_DIRECTIVE_PAIR = {
175 'neutral' : 'LANG_NEUTRAL, SUBLANG_NEUTRAL',
176 'userdefault' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
177 'ar' : 'LANG_ARABIC, SUBLANG_DEFAULT',
178 'fi' : 'LANG_FINNISH, SUBLANG_DEFAULT',
179 'ko' : 'LANG_KOREAN, SUBLANG_KOREAN',
180 'es' : 'LANG_SPANISH, SUBLANG_SPANISH_MODERN',
181 'bg' : 'LANG_BULGARIAN, SUBLANG_DEFAULT',
182 # LANG_FILIPINO (100) not in VC 7 winnt.h.
183 'fil' : '100, SUBLANG_DEFAULT',
184 'fr' : 'LANG_FRENCH, SUBLANG_FRENCH',
185 'lv' : 'LANG_LATVIAN, SUBLANG_DEFAULT',
186 'sv' : 'LANG_SWEDISH, SUBLANG_SWEDISH',
187 'ca' : 'LANG_CATALAN, SUBLANG_DEFAULT',
188 'de' : 'LANG_GERMAN, SUBLANG_GERMAN',
189 'lt' : 'LANG_LITHUANIAN, SUBLANG_LITHUANIAN',
190 # Do not use! See above.
191 'tl' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
192 'zh-CN' : 'LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED',
193 'zh-TW' : 'LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL',
194 'zh-HK' : 'LANG_CHINESE, SUBLANG_CHINESE_HONGKONG',
195 'el' : 'LANG_GREEK, SUBLANG_DEFAULT',
196 'no' : 'LANG_NORWEGIAN, SUBLANG_DEFAULT',
197 'nb' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL',
198 'nn' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK',
199 'th' : 'LANG_THAI, SUBLANG_DEFAULT',
200 'he' : 'LANG_HEBREW, SUBLANG_DEFAULT',
201 'iw' : 'LANG_HEBREW, SUBLANG_DEFAULT',
202 'pl' : 'LANG_POLISH, SUBLANG_DEFAULT',
203 'tr' : 'LANG_TURKISH, SUBLANG_DEFAULT',
204 'hr' : 'LANG_CROATIAN, SUBLANG_DEFAULT',
205 'hi' : 'LANG_HINDI, SUBLANG_DEFAULT',
206 'pt-PT' : 'LANG_PORTUGUESE, SUBLANG_PORTUGUESE',
207 'pt-BR' : 'LANG_PORTUGUESE, SUBLANG_DEFAULT',
208 'uk' : 'LANG_UKRAINIAN, SUBLANG_DEFAULT',
209 'cs' : 'LANG_CZECH, SUBLANG_DEFAULT',
210 'hu' : 'LANG_HUNGARIAN, SUBLANG_DEFAULT',
211 'ro' : 'LANG_ROMANIAN, SUBLANG_DEFAULT',
212 'ur' : 'LANG_URDU, SUBLANG_DEFAULT',
213 'da' : 'LANG_DANISH, SUBLANG_DEFAULT',
214 'is' : 'LANG_ICELANDIC, SUBLANG_DEFAULT',
215 'ru' : 'LANG_RUSSIAN, SUBLANG_DEFAULT',
216 'vi' : 'LANG_VIETNAMESE, SUBLANG_DEFAULT',
217 'nl' : 'LANG_DUTCH, SUBLANG_DEFAULT',
218 'id' : 'LANG_INDONESIAN, SUBLANG_DEFAULT',
219 'sr' : 'LANG_SERBIAN, SUBLANG_SERBIAN_LATIN',
220 'en-GB' : 'LANG_ENGLISH, SUBLANG_ENGLISH_UK',
221 'it' : 'LANG_ITALIAN, SUBLANG_DEFAULT',
222 'sk' : 'LANG_SLOVAK, SUBLANG_DEFAULT',
223 'et' : 'LANG_ESTONIAN, SUBLANG_DEFAULT',
224 'ja' : 'LANG_JAPANESE, SUBLANG_DEFAULT',
225 'sl' : 'LANG_SLOVENIAN, SUBLANG_DEFAULT',
226 'en' : 'LANG_ENGLISH, SUBLANG_ENGLISH_US',
227 # No L.A. sublang exists.
228 'es-419' : 'LANG_SPANISH, SUBLANG_SPANISH_MEXICAN',
229 'bn' : 'LANG_BENGALI, SUBLANG_DEFAULT',
230 'fa' : 'LANG_PERSIAN, SUBLANG_DEFAULT',
231 'gu' : 'LANG_GUJARATI, SUBLANG_DEFAULT',
232 'kn' : 'LANG_KANNADA, SUBLANG_DEFAULT',
233 'ms' : 'LANG_MALAY, SUBLANG_DEFAULT',
234 'ml' : 'LANG_MALAYALAM, SUBLANG_DEFAULT',
235 'mr' : 'LANG_MARATHI, SUBLANG_DEFAULT',
236 'or' : 'LANG_ORIYA, SUBLANG_DEFAULT',
237 'ta' : 'LANG_TAMIL, SUBLANG_DEFAULT',
238 'te' : 'LANG_TELUGU, SUBLANG_DEFAULT',
239 'am' : 'LANG_AMHARIC, SUBLANG_DEFAULT',
240 'sw' : 'LANG_SWAHILI, SUBLANG_DEFAULT',
241 'af' : 'LANG_AFRIKAANS, SUBLANG_DEFAULT',
242 'eu' : 'LANG_BASQUE, SUBLANG_DEFAULT',
243 'fr-CA' : 'LANG_FRENCH, SUBLANG_FRENCH_CANADIAN',
244 'gl' : 'LANG_GALICIAN, SUBLANG_DEFAULT',
245 'zu' : 'LANG_ZULU, SUBLANG_DEFAULT',
246 'pa' : 'LANG_PUNJABI, SUBLANG_PUNJABI_INDIA',
247 'sa' : 'LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA',
248 'si' : 'LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA',
249 'ne' : 'LANG_NEPALI, SUBLANG_NEPALI_NEPAL',
250 'ti' : 'LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA',
251 'fake-bidi' : 'LANG_HEBREW, SUBLANG_DEFAULT',
252 }
253
254 # A note on 'no-specific-language' in the following few functions:
255 # Some build systems may wish to call GRIT to scan for dependencies in
256 # a language-agnostic way, and can then specify this fake language as
257 # the output context. It should never be used when output is actually
258 # being generated.
259
260 def GetLangCharsetPair(language):
261 if _LANGUAGE_CHARSET_PAIR.has_key(language):
262 return _LANGUAGE_CHARSET_PAIR[language]
263 elif language == 'no-specific-language':
264 return ''
265 else:
266 print 'Warning:GetLangCharsetPair() found undefined language %s' %(language)
267 return ''
268
269 def GetLangDirectivePair(language):
270 if _LANGUAGE_DIRECTIVE_PAIR.has_key(language):
271 return _LANGUAGE_DIRECTIVE_PAIR[language]
272 else:
273 # We don't check for 'no-specific-language' here because this
274 # function should only get called when output is being formatted,
275 # and at that point we would not want to get
276 # 'no-specific-language' passed as the language.
277 print ('Warning:GetLangDirectivePair() found undefined language %s' %
278 language)
279 return 'unknown language: see tools/grit/format/rc.py'
280
281 def GetLangIdHex(language):
282 if _LANGUAGE_CHARSET_PAIR.has_key(language):
283 langcharset = _LANGUAGE_CHARSET_PAIR[language]
284 lang_id = '0x' + langcharset[0:4]
285 return lang_id
286 elif language == 'no-specific-language':
287 return ''
288 else:
289 print 'Warning:GetLangIdHex() found undefined language %s' %(language)
290 return ''
291
292
293 def GetCharsetIdDecimal(language):
294 if _LANGUAGE_CHARSET_PAIR.has_key(language):
295 langcharset = _LANGUAGE_CHARSET_PAIR[language]
296 charset_decimal = int(langcharset[4:], 16)
297 return str(charset_decimal)
298 elif language == 'no-specific-language':
299 return ''
300 else:
301 print 'Warning:GetCharsetIdDecimal() found undefined language %s' % language
302 return ''
303
304
305 def GetUnifiedLangCode(language) :
306 r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
307 if r.match(language) :
308 underscore = language.find('_')
309 return language[0:underscore] + '-' + language[underscore + 1:].upper()
310 else :
311 return language
312
313
314 def RcSubstitutions(substituter, lang):
315 '''Add language-based substitutions for Rc files to the substitutor.'''
316 unified_lang_code = GetUnifiedLangCode(lang)
317 substituter.AddSubstitutions({
318 'GRITVERLANGCHARSETHEX': GetLangCharsetPair(unified_lang_code),
319 'GRITVERLANGID': GetLangIdHex(unified_lang_code),
320 'GRITVERCHARSETID': GetCharsetIdDecimal(unified_lang_code)})
321
322
323 def _FormatHeader(root, lang, output_dir):
324 '''Returns the required preamble for RC files.'''
325 assert isinstance(lang, types.StringTypes)
326 assert isinstance(root, misc.GritNode)
327 # Find the location of the resource header file, so that we can include
328 # it.
329 resource_header = 'resource.h' # fall back to this
330 language_directive = ''
331 for output in root.GetOutputFiles():
332 if output.attrs['type'] == 'rc_header':
333 resource_header = os.path.abspath(output.GetOutputFilename())
334 resource_header = util.MakeRelativePath(output_dir, resource_header)
335 if output.attrs['lang'] != lang:
336 continue
337 if output.attrs['language_section'] == '':
338 # If no language_section is requested, no directive is added
339 # (Used when the generated rc will be included from another rc
340 # file that will have the appropriate language directive)
341 language_directive = ''
342 elif output.attrs['language_section'] == 'neutral':
343 # If a neutral language section is requested (default), add a
344 # neutral language directive
345 language_directive = 'LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL'
346 elif output.attrs['language_section'] == 'lang':
347 language_directive = 'LANGUAGE %s' % GetLangDirectivePair(lang)
348 resource_header = resource_header.replace('\\', '\\\\')
349 return '''// This file is automatically generated by GRIT. Do not edit.
350
351 #include "%s"
352 #include <winresrc.h>
353 #ifdef IDC_STATIC
354 #undef IDC_STATIC
355 #endif
356 #define IDC_STATIC (-1)
357
358 %s
359
360
361 ''' % (resource_header, language_directive)
362 # end _FormatHeader() function
363
364
365 def FormatMessage(item, lang):
366 '''Returns a single message of a string table.'''
367 message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
368 # Escape quotation marks (RC format uses doubling-up
369 message = message.replace('"', '""')
370 # Replace linebreaks with a \n escape
371 message = util.LINEBREAKS.sub(r'\\n', message)
372 if hasattr(item.GetRoot(), 'GetSubstituter'):
373 substituter = item.GetRoot().GetSubstituter()
374 message = substituter.Substitute(message)
375
376 name_attr = item.GetTextualIds()[0]
377
378 return ' %-15s "%s"\n' % (name_attr, message)
379
380
381 def _FormatSection(item, lang, output_dir):
382 '''Writes out an .rc file section.'''
383 assert isinstance(lang, types.StringTypes)
384 from grit.node import structure
385 assert isinstance(item, structure.StructureNode)
386
387 if item.IsExcludedFromRc():
388 return ''
389 else:
390 text = item.gatherer.Translate(
391 lang, skeleton_gatherer=item.GetSkeletonGatherer(),
392 pseudo_if_not_available=item.PseudoIsAllowed(),
393 fallback_to_english=item.ShouldFallbackToEnglish()) + '\n\n'
394
395 # Replace the language expand_variables in version rc info.
396 if item.ExpandVariables() and hasattr(item.GetRoot(), 'GetSubstituter'):
397 substituter = item.GetRoot().GetSubstituter()
398 text = substituter.Substitute(text)
399
400 return text
401
402
403 def FormatInclude(item, lang, output_dir, type=None, process_html=False):
404 '''Formats an item that is included in an .rc file (e.g. an ICON).
405
406 Args:
407 item: an IncludeNode or StructureNode
408 lang, output_dir: standard formatter parameters
409 type: .rc file resource type, e.g. 'ICON' (ignored unless item is a
410 StructureNode)
411 process_html: False/True (ignored unless item is a StructureNode)
412 '''
413 assert isinstance(lang, types.StringTypes)
414 from grit.node import structure
415 from grit.node import include
416 assert isinstance(item, (structure.StructureNode, include.IncludeNode))
417
418 if isinstance(item, include.IncludeNode):
419 type = item.attrs['type'].upper()
420 process_html = item.attrs['flattenhtml'] == 'true'
421 filename_only = item.attrs['filenameonly'] == 'true'
422 relative_path = item.attrs['relativepath'] == 'true'
423 else:
424 assert (isinstance(item, structure.StructureNode) and item.attrs['type'] in
425 ['admin_template', 'chrome_html', 'chrome_scaled_image', 'igoogle',
426 'muppet', 'tr_html', 'txt'])
427 filename_only = False
428 relative_path = False
429
430 # By default, we use relative pathnames to included resources so that
431 # sharing the resulting .rc files is possible.
432 #
433 # The FileForLanguage() Function has the side effect of generating the file
434 # if needed (e.g. if it is an HTML file include).
435 file_for_lang = item.FileForLanguage(lang, output_dir)
436 if file_for_lang is None:
437 return ''
438
439 filename = os.path.abspath(file_for_lang)
440 if process_html:
441 filename = item.Process(output_dir)
442 elif filename_only:
443 filename = os.path.basename(filename)
444 elif relative_path:
445 filename = util.MakeRelativePath(output_dir, filename)
446
447 filename = filename.replace('\\', '\\\\') # escape for the RC format
448
449 if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
450 return ''
451 else:
452 return '%-18s %-18s "%s"\n' % (item.attrs['name'], type, filename)
453
454
455 def _DoNotFormat(item, lang, output_dir):
456 return ''
457
458
459 # Formatter instance to use for each type attribute
460 # when formatting Structure nodes.
461 _STRUCTURE_FORMATTERS = {
462 'accelerators' : _FormatSection,
463 'dialog' : _FormatSection,
464 'menu' : _FormatSection,
465 'rcdata' : _FormatSection,
466 'version' : _FormatSection,
467 'admin_template' : partial(FormatInclude, type='ADM'),
468 'chrome_html' : partial(FormatInclude, type='BINDATA',
469 process_html=True),
470 'chrome_scaled_image' : partial(FormatInclude, type='BINDATA'),
471 'igoogle' : partial(FormatInclude, type='XML'),
472 'muppet' : partial(FormatInclude, type='XML'),
473 'tr_html' : partial(FormatInclude, type='HTML'),
474 'txt' : partial(FormatInclude, type='TXT'),
475 'policy_template_metafile': _DoNotFormat,
476 }
477
478
479 def FormatStructure(item, lang, output_dir):
480 formatter = _STRUCTURE_FORMATTERS[item.attrs['type']]
481 return formatter(item, lang, output_dir)
OLDNEW
« no previous file with comments | « grit/format/policy_templates/writers/xml_writer_base_unittest.py ('k') | grit/format/rc_header.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698