OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright 2013 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 """ | |
7 localize.py -- Generates an output file from the given template replacing | |
8 variables and localizing strings. | |
9 | |
10 The script uses Jinja2 template processing library (src/third_party/jinja2). | |
11 Variables available to the templates: | |
12 - |languages| - the list of languages passed on the command line. ('-l'). | |
13 - Each KEY=VALUE define ('-d') can be accesses as |KEY|. | |
14 - |official_build| is set to '1' when CHROME_BUILD_TYPE environment variable | |
15 is set to "_official". | |
16 | |
17 Filters: | |
18 - GetCodepage - returns the code page for the given language. | |
19 - GetCodepageDecimal same as GetCodepage, but returns a decimal value. | |
20 - GetLangId - returns Win32 LANGID. | |
21 - GetPrimaryLanguage - returns a named Win32 constant specifing the primary | |
22 language ID. | |
23 - GetSublanguage - returns a named Win32 constant specifing the sublanguage | |
24 ID. | |
25 | |
26 Globals: | |
27 - SelectLanguage(language) - allows to select the language to the used by | |
28 {% trans %}{% endtrans %} statements. | |
29 | |
30 """ | |
31 | |
32 import io | |
33 import json | |
34 from optparse import OptionParser | |
35 import os | |
36 import sys | |
37 | |
38 # Win32 primary languages IDs. | |
39 _LANGUAGE_PRIMARY = { | |
40 'LANG_NEUTRAL' : 0x00, | |
41 'LANG_INVARIANT' : 0x7f, | |
42 'LANG_AFRIKAANS' : 0x36, | |
43 'LANG_ALBANIAN' : 0x1c, | |
44 'LANG_ALSATIAN' : 0x84, | |
45 'LANG_AMHARIC' : 0x5e, | |
46 'LANG_ARABIC' : 0x01, | |
47 'LANG_ARMENIAN' : 0x2b, | |
48 'LANG_ASSAMESE' : 0x4d, | |
49 'LANG_AZERI' : 0x2c, | |
50 'LANG_BASHKIR' : 0x6d, | |
51 'LANG_BASQUE' : 0x2d, | |
52 'LANG_BELARUSIAN' : 0x23, | |
53 'LANG_BENGALI' : 0x45, | |
54 'LANG_BRETON' : 0x7e, | |
55 'LANG_BOSNIAN' : 0x1a, | |
56 'LANG_BULGARIAN' : 0x02, | |
57 'LANG_CATALAN' : 0x03, | |
58 'LANG_CHINESE' : 0x04, | |
59 'LANG_CORSICAN' : 0x83, | |
60 'LANG_CROATIAN' : 0x1a, | |
61 'LANG_CZECH' : 0x05, | |
62 'LANG_DANISH' : 0x06, | |
63 'LANG_DARI' : 0x8c, | |
64 'LANG_DIVEHI' : 0x65, | |
65 'LANG_DUTCH' : 0x13, | |
66 'LANG_ENGLISH' : 0x09, | |
67 'LANG_ESTONIAN' : 0x25, | |
68 'LANG_FAEROESE' : 0x38, | |
69 'LANG_FILIPINO' : 0x64, | |
70 'LANG_FINNISH' : 0x0b, | |
71 'LANG_FRENCH' : 0x0c, | |
72 'LANG_FRISIAN' : 0x62, | |
73 'LANG_GALICIAN' : 0x56, | |
74 'LANG_GEORGIAN' : 0x37, | |
75 'LANG_GERMAN' : 0x07, | |
76 'LANG_GREEK' : 0x08, | |
77 'LANG_GREENLANDIC' : 0x6f, | |
78 'LANG_GUJARATI' : 0x47, | |
79 'LANG_HAUSA' : 0x68, | |
80 'LANG_HEBREW' : 0x0d, | |
81 'LANG_HINDI' : 0x39, | |
82 'LANG_HUNGARIAN' : 0x0e, | |
83 'LANG_ICELANDIC' : 0x0f, | |
84 'LANG_IGBO' : 0x70, | |
85 'LANG_INDONESIAN' : 0x21, | |
86 'LANG_INUKTITUT' : 0x5d, | |
87 'LANG_IRISH' : 0x3c, | |
88 'LANG_ITALIAN' : 0x10, | |
89 'LANG_JAPANESE' : 0x11, | |
90 'LANG_KANNADA' : 0x4b, | |
91 'LANG_KASHMIRI' : 0x60, | |
92 'LANG_KAZAK' : 0x3f, | |
93 'LANG_KHMER' : 0x53, | |
94 'LANG_KICHE' : 0x86, | |
95 'LANG_KINYARWANDA' : 0x87, | |
96 'LANG_KONKANI' : 0x57, | |
97 'LANG_KOREAN' : 0x12, | |
98 'LANG_KYRGYZ' : 0x40, | |
99 'LANG_LAO' : 0x54, | |
100 'LANG_LATVIAN' : 0x26, | |
101 'LANG_LITHUANIAN' : 0x27, | |
102 'LANG_LOWER_SORBIAN' : 0x2e, | |
103 'LANG_LUXEMBOURGISH' : 0x6e, | |
104 'LANG_MACEDONIAN' : 0x2f, | |
105 'LANG_MALAY' : 0x3e, | |
106 'LANG_MALAYALAM' : 0x4c, | |
107 'LANG_MALTESE' : 0x3a, | |
108 'LANG_MANIPURI' : 0x58, | |
109 'LANG_MAORI' : 0x81, | |
110 'LANG_MAPUDUNGUN' : 0x7a, | |
111 'LANG_MARATHI' : 0x4e, | |
112 'LANG_MOHAWK' : 0x7c, | |
113 'LANG_MONGOLIAN' : 0x50, | |
114 'LANG_NEPALI' : 0x61, | |
115 'LANG_NORWEGIAN' : 0x14, | |
116 'LANG_OCCITAN' : 0x82, | |
117 'LANG_ORIYA' : 0x48, | |
118 'LANG_PASHTO' : 0x63, | |
119 'LANG_PERSIAN' : 0x29, | |
120 'LANG_POLISH' : 0x15, | |
121 'LANG_PORTUGUESE' : 0x16, | |
122 'LANG_PUNJABI' : 0x46, | |
123 'LANG_QUECHUA' : 0x6b, | |
124 'LANG_ROMANIAN' : 0x18, | |
125 'LANG_ROMANSH' : 0x17, | |
126 'LANG_RUSSIAN' : 0x19, | |
127 'LANG_SAMI' : 0x3b, | |
128 'LANG_SANSKRIT' : 0x4f, | |
129 'LANG_SCOTTISH_GAELIC' : 0x91, | |
130 'LANG_SERBIAN' : 0x1a, | |
131 'LANG_SINDHI' : 0x59, | |
132 'LANG_SINHALESE' : 0x5b, | |
133 'LANG_SLOVAK' : 0x1b, | |
134 'LANG_SLOVENIAN' : 0x24, | |
135 'LANG_SOTHO' : 0x6c, | |
136 'LANG_SPANISH' : 0x0a, | |
137 'LANG_SWAHILI' : 0x41, | |
138 'LANG_SWEDISH' : 0x1d, | |
139 'LANG_SYRIAC' : 0x5a, | |
140 'LANG_TAJIK' : 0x28, | |
141 'LANG_TAMAZIGHT' : 0x5f, | |
142 'LANG_TAMIL' : 0x49, | |
143 'LANG_TATAR' : 0x44, | |
144 'LANG_TELUGU' : 0x4a, | |
145 'LANG_THAI' : 0x1e, | |
146 'LANG_TIBETAN' : 0x51, | |
147 'LANG_TIGRIGNA' : 0x73, | |
148 'LANG_TSWANA' : 0x32, | |
149 'LANG_TURKISH' : 0x1f, | |
150 'LANG_TURKMEN' : 0x42, | |
151 'LANG_UIGHUR' : 0x80, | |
152 'LANG_UKRAINIAN' : 0x22, | |
153 'LANG_UPPER_SORBIAN' : 0x2e, | |
154 'LANG_URDU' : 0x20, | |
155 'LANG_UZBEK' : 0x43, | |
156 'LANG_VIETNAMESE' : 0x2a, | |
157 'LANG_WELSH' : 0x52, | |
158 'LANG_WOLOF' : 0x88, | |
159 'LANG_XHOSA' : 0x34, | |
160 'LANG_YAKUT' : 0x85, | |
161 'LANG_YI' : 0x78, | |
162 'LANG_YORUBA' : 0x6a, | |
163 'LANG_ZULU' : 0x35, | |
164 } | |
165 | |
166 | |
167 # Win32 sublanguage IDs. | |
168 _LANGUAGE_SUB = { | |
169 'SUBLANG_NEUTRAL' : 0x00, | |
170 'SUBLANG_DEFAULT' : 0x01, | |
171 'SUBLANG_SYS_DEFAULT' : 0x02, | |
172 'SUBLANG_CUSTOM_DEFAULT' : 0x03, | |
173 'SUBLANG_CUSTOM_UNSPECIFIED' : 0x04, | |
174 'SUBLANG_UI_CUSTOM_DEFAULT' : 0x05, | |
175 'SUBLANG_AFRIKAANS_SOUTH_AFRICA' : 0x01, | |
176 'SUBLANG_ALBANIAN_ALBANIA' : 0x01, | |
177 'SUBLANG_ALSATIAN_FRANCE' : 0x01, | |
178 'SUBLANG_AMHARIC_ETHIOPIA' : 0x01, | |
179 'SUBLANG_ARABIC_SAUDI_ARABIA' : 0x01, | |
180 'SUBLANG_ARABIC_IRAQ' : 0x02, | |
181 'SUBLANG_ARABIC_EGYPT' : 0x03, | |
182 'SUBLANG_ARABIC_LIBYA' : 0x04, | |
183 'SUBLANG_ARABIC_ALGERIA' : 0x05, | |
184 'SUBLANG_ARABIC_MOROCCO' : 0x06, | |
185 'SUBLANG_ARABIC_TUNISIA' : 0x07, | |
186 'SUBLANG_ARABIC_OMAN' : 0x08, | |
187 'SUBLANG_ARABIC_YEMEN' : 0x09, | |
188 'SUBLANG_ARABIC_SYRIA' : 0x0a, | |
189 'SUBLANG_ARABIC_JORDAN' : 0x0b, | |
190 'SUBLANG_ARABIC_LEBANON' : 0x0c, | |
191 'SUBLANG_ARABIC_KUWAIT' : 0x0d, | |
192 'SUBLANG_ARABIC_UAE' : 0x0e, | |
193 'SUBLANG_ARABIC_BAHRAIN' : 0x0f, | |
194 'SUBLANG_ARABIC_QATAR' : 0x10, | |
195 'SUBLANG_ARMENIAN_ARMENIA' : 0x01, | |
196 'SUBLANG_ASSAMESE_INDIA' : 0x01, | |
197 'SUBLANG_AZERI_LATIN' : 0x01, | |
198 'SUBLANG_AZERI_CYRILLIC' : 0x02, | |
199 'SUBLANG_BASHKIR_RUSSIA' : 0x01, | |
200 'SUBLANG_BASQUE_BASQUE' : 0x01, | |
201 'SUBLANG_BELARUSIAN_BELARUS' : 0x01, | |
202 'SUBLANG_BENGALI_INDIA' : 0x01, | |
203 'SUBLANG_BENGALI_BANGLADESH' : 0x02, | |
204 'SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN' : 0x05, | |
205 'SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC' : 0x08, | |
206 'SUBLANG_BRETON_FRANCE' : 0x01, | |
207 'SUBLANG_BULGARIAN_BULGARIA' : 0x01, | |
208 'SUBLANG_CATALAN_CATALAN' : 0x01, | |
209 'SUBLANG_CHINESE_TRADITIONAL' : 0x01, | |
210 'SUBLANG_CHINESE_SIMPLIFIED' : 0x02, | |
211 'SUBLANG_CHINESE_HONGKONG' : 0x03, | |
212 'SUBLANG_CHINESE_SINGAPORE' : 0x04, | |
213 'SUBLANG_CHINESE_MACAU' : 0x05, | |
214 'SUBLANG_CORSICAN_FRANCE' : 0x01, | |
215 'SUBLANG_CZECH_CZECH_REPUBLIC' : 0x01, | |
216 'SUBLANG_CROATIAN_CROATIA' : 0x01, | |
217 'SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN' : 0x04, | |
218 'SUBLANG_DANISH_DENMARK' : 0x01, | |
219 'SUBLANG_DARI_AFGHANISTAN' : 0x01, | |
220 'SUBLANG_DIVEHI_MALDIVES' : 0x01, | |
221 'SUBLANG_DUTCH' : 0x01, | |
222 'SUBLANG_DUTCH_BELGIAN' : 0x02, | |
223 'SUBLANG_ENGLISH_US' : 0x01, | |
224 'SUBLANG_ENGLISH_UK' : 0x02, | |
225 'SUBLANG_ENGLISH_AUS' : 0x03, | |
226 'SUBLANG_ENGLISH_CAN' : 0x04, | |
227 'SUBLANG_ENGLISH_NZ' : 0x05, | |
228 'SUBLANG_ENGLISH_EIRE' : 0x06, | |
229 'SUBLANG_ENGLISH_SOUTH_AFRICA' : 0x07, | |
230 'SUBLANG_ENGLISH_JAMAICA' : 0x08, | |
231 'SUBLANG_ENGLISH_CARIBBEAN' : 0x09, | |
232 'SUBLANG_ENGLISH_BELIZE' : 0x0a, | |
233 'SUBLANG_ENGLISH_TRINIDAD' : 0x0b, | |
234 'SUBLANG_ENGLISH_ZIMBABWE' : 0x0c, | |
235 'SUBLANG_ENGLISH_PHILIPPINES' : 0x0d, | |
236 'SUBLANG_ENGLISH_INDIA' : 0x10, | |
237 'SUBLANG_ENGLISH_MALAYSIA' : 0x11, | |
238 'SUBLANG_ENGLISH_SINGAPORE' : 0x12, | |
239 'SUBLANG_ESTONIAN_ESTONIA' : 0x01, | |
240 'SUBLANG_FAEROESE_FAROE_ISLANDS' : 0x01, | |
241 'SUBLANG_FILIPINO_PHILIPPINES' : 0x01, | |
242 'SUBLANG_FINNISH_FINLAND' : 0x01, | |
243 'SUBLANG_FRENCH' : 0x01, | |
244 'SUBLANG_FRENCH_BELGIAN' : 0x02, | |
245 'SUBLANG_FRENCH_CANADIAN' : 0x03, | |
246 'SUBLANG_FRENCH_SWISS' : 0x04, | |
247 'SUBLANG_FRENCH_LUXEMBOURG' : 0x05, | |
248 'SUBLANG_FRENCH_MONACO' : 0x06, | |
249 'SUBLANG_FRISIAN_NETHERLANDS' : 0x01, | |
250 'SUBLANG_GALICIAN_GALICIAN' : 0x01, | |
251 'SUBLANG_GEORGIAN_GEORGIA' : 0x01, | |
252 'SUBLANG_GERMAN' : 0x01, | |
253 'SUBLANG_GERMAN_SWISS' : 0x02, | |
254 'SUBLANG_GERMAN_AUSTRIAN' : 0x03, | |
255 'SUBLANG_GERMAN_LUXEMBOURG' : 0x04, | |
256 'SUBLANG_GERMAN_LIECHTENSTEIN' : 0x05, | |
257 'SUBLANG_GREEK_GREECE' : 0x01, | |
258 'SUBLANG_GREENLANDIC_GREENLAND' : 0x01, | |
259 'SUBLANG_GUJARATI_INDIA' : 0x01, | |
260 'SUBLANG_HAUSA_NIGERIA_LATIN' : 0x01, | |
261 'SUBLANG_HEBREW_ISRAEL' : 0x01, | |
262 'SUBLANG_HINDI_INDIA' : 0x01, | |
263 'SUBLANG_HUNGARIAN_HUNGARY' : 0x01, | |
264 'SUBLANG_ICELANDIC_ICELAND' : 0x01, | |
265 'SUBLANG_IGBO_NIGERIA' : 0x01, | |
266 'SUBLANG_INDONESIAN_INDONESIA' : 0x01, | |
267 'SUBLANG_INUKTITUT_CANADA' : 0x01, | |
268 'SUBLANG_INUKTITUT_CANADA_LATIN' : 0x02, | |
269 'SUBLANG_IRISH_IRELAND' : 0x02, | |
270 'SUBLANG_ITALIAN' : 0x01, | |
271 'SUBLANG_ITALIAN_SWISS' : 0x02, | |
272 'SUBLANG_JAPANESE_JAPAN' : 0x01, | |
273 'SUBLANG_KANNADA_INDIA' : 0x01, | |
274 'SUBLANG_KASHMIRI_SASIA' : 0x02, | |
275 'SUBLANG_KASHMIRI_INDIA' : 0x02, | |
276 'SUBLANG_KAZAK_KAZAKHSTAN' : 0x01, | |
277 'SUBLANG_KHMER_CAMBODIA' : 0x01, | |
278 'SUBLANG_KICHE_GUATEMALA' : 0x01, | |
279 'SUBLANG_KINYARWANDA_RWANDA' : 0x01, | |
280 'SUBLANG_KONKANI_INDIA' : 0x01, | |
281 'SUBLANG_KOREAN' : 0x01, | |
282 'SUBLANG_KYRGYZ_KYRGYZSTAN' : 0x01, | |
283 'SUBLANG_LAO_LAO' : 0x01, | |
284 'SUBLANG_LATVIAN_LATVIA' : 0x01, | |
285 'SUBLANG_LITHUANIAN' : 0x01, | |
286 'SUBLANG_LOWER_SORBIAN_GERMANY' : 0x02, | |
287 'SUBLANG_LUXEMBOURGISH_LUXEMBOURG' : 0x01, | |
288 'SUBLANG_MACEDONIAN_MACEDONIA' : 0x01, | |
289 'SUBLANG_MALAY_MALAYSIA' : 0x01, | |
290 'SUBLANG_MALAY_BRUNEI_DARUSSALAM' : 0x02, | |
291 'SUBLANG_MALAYALAM_INDIA' : 0x01, | |
292 'SUBLANG_MALTESE_MALTA' : 0x01, | |
293 'SUBLANG_MAORI_NEW_ZEALAND' : 0x01, | |
294 'SUBLANG_MAPUDUNGUN_CHILE' : 0x01, | |
295 'SUBLANG_MARATHI_INDIA' : 0x01, | |
296 'SUBLANG_MOHAWK_MOHAWK' : 0x01, | |
297 'SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA' : 0x01, | |
298 'SUBLANG_MONGOLIAN_PRC' : 0x02, | |
299 'SUBLANG_NEPALI_INDIA' : 0x02, | |
300 'SUBLANG_NEPALI_NEPAL' : 0x01, | |
301 'SUBLANG_NORWEGIAN_BOKMAL' : 0x01, | |
302 'SUBLANG_NORWEGIAN_NYNORSK' : 0x02, | |
303 'SUBLANG_OCCITAN_FRANCE' : 0x01, | |
304 'SUBLANG_ORIYA_INDIA' : 0x01, | |
305 'SUBLANG_PASHTO_AFGHANISTAN' : 0x01, | |
306 'SUBLANG_PERSIAN_IRAN' : 0x01, | |
307 'SUBLANG_POLISH_POLAND' : 0x01, | |
308 'SUBLANG_PORTUGUESE' : 0x02, | |
309 'SUBLANG_PORTUGUESE_BRAZILIAN' : 0x01, | |
310 'SUBLANG_PUNJABI_INDIA' : 0x01, | |
311 'SUBLANG_QUECHUA_BOLIVIA' : 0x01, | |
312 'SUBLANG_QUECHUA_ECUADOR' : 0x02, | |
313 'SUBLANG_QUECHUA_PERU' : 0x03, | |
314 'SUBLANG_ROMANIAN_ROMANIA' : 0x01, | |
315 'SUBLANG_ROMANSH_SWITZERLAND' : 0x01, | |
316 'SUBLANG_RUSSIAN_RUSSIA' : 0x01, | |
317 'SUBLANG_SAMI_NORTHERN_NORWAY' : 0x01, | |
318 'SUBLANG_SAMI_NORTHERN_SWEDEN' : 0x02, | |
319 'SUBLANG_SAMI_NORTHERN_FINLAND' : 0x03, | |
320 'SUBLANG_SAMI_LULE_NORWAY' : 0x04, | |
321 'SUBLANG_SAMI_LULE_SWEDEN' : 0x05, | |
322 'SUBLANG_SAMI_SOUTHERN_NORWAY' : 0x06, | |
323 'SUBLANG_SAMI_SOUTHERN_SWEDEN' : 0x07, | |
324 'SUBLANG_SAMI_SKOLT_FINLAND' : 0x08, | |
325 'SUBLANG_SAMI_INARI_FINLAND' : 0x09, | |
326 'SUBLANG_SANSKRIT_INDIA' : 0x01, | |
327 'SUBLANG_SCOTTISH_GAELIC' : 0x01, | |
328 'SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN' : 0x06, | |
329 'SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC' : 0x07, | |
330 'SUBLANG_SERBIAN_MONTENEGRO_LATIN' : 0x0b, | |
331 'SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC' : 0x0c, | |
332 'SUBLANG_SERBIAN_SERBIA_LATIN' : 0x09, | |
333 'SUBLANG_SERBIAN_SERBIA_CYRILLIC' : 0x0a, | |
334 'SUBLANG_SERBIAN_CROATIA' : 0x01, | |
335 'SUBLANG_SERBIAN_LATIN' : 0x02, | |
336 'SUBLANG_SERBIAN_CYRILLIC' : 0x03, | |
337 'SUBLANG_SINDHI_INDIA' : 0x01, | |
338 'SUBLANG_SINDHI_PAKISTAN' : 0x02, | |
339 'SUBLANG_SINDHI_AFGHANISTAN' : 0x02, | |
340 'SUBLANG_SINHALESE_SRI_LANKA' : 0x01, | |
341 'SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA' : 0x01, | |
342 'SUBLANG_SLOVAK_SLOVAKIA' : 0x01, | |
343 'SUBLANG_SLOVENIAN_SLOVENIA' : 0x01, | |
344 'SUBLANG_SPANISH' : 0x01, | |
345 'SUBLANG_SPANISH_MEXICAN' : 0x02, | |
346 'SUBLANG_SPANISH_MODERN' : 0x03, | |
347 'SUBLANG_SPANISH_GUATEMALA' : 0x04, | |
348 'SUBLANG_SPANISH_COSTA_RICA' : 0x05, | |
349 'SUBLANG_SPANISH_PANAMA' : 0x06, | |
350 'SUBLANG_SPANISH_DOMINICAN_REPUBLIC' : 0x07, | |
351 'SUBLANG_SPANISH_VENEZUELA' : 0x08, | |
352 'SUBLANG_SPANISH_COLOMBIA' : 0x09, | |
353 'SUBLANG_SPANISH_PERU' : 0x0a, | |
354 'SUBLANG_SPANISH_ARGENTINA' : 0x0b, | |
355 'SUBLANG_SPANISH_ECUADOR' : 0x0c, | |
356 'SUBLANG_SPANISH_CHILE' : 0x0d, | |
357 'SUBLANG_SPANISH_URUGUAY' : 0x0e, | |
358 'SUBLANG_SPANISH_PARAGUAY' : 0x0f, | |
359 'SUBLANG_SPANISH_BOLIVIA' : 0x10, | |
360 'SUBLANG_SPANISH_EL_SALVADOR' : 0x11, | |
361 'SUBLANG_SPANISH_HONDURAS' : 0x12, | |
362 'SUBLANG_SPANISH_NICARAGUA' : 0x13, | |
363 'SUBLANG_SPANISH_PUERTO_RICO' : 0x14, | |
364 'SUBLANG_SPANISH_US' : 0x15, | |
365 'SUBLANG_SWAHILI_KENYA' : 0x01, | |
366 'SUBLANG_SWEDISH' : 0x01, | |
367 'SUBLANG_SWEDISH_FINLAND' : 0x02, | |
368 'SUBLANG_SYRIAC_SYRIA' : 0x01, | |
369 'SUBLANG_TAJIK_TAJIKISTAN' : 0x01, | |
370 'SUBLANG_TAMAZIGHT_ALGERIA_LATIN' : 0x02, | |
371 'SUBLANG_TAMIL_INDIA' : 0x01, | |
372 'SUBLANG_TATAR_RUSSIA' : 0x01, | |
373 'SUBLANG_TELUGU_INDIA' : 0x01, | |
374 'SUBLANG_THAI_THAILAND' : 0x01, | |
375 'SUBLANG_TIBETAN_PRC' : 0x01, | |
376 'SUBLANG_TIGRIGNA_ERITREA' : 0x02, | |
377 'SUBLANG_TSWANA_SOUTH_AFRICA' : 0x01, | |
378 'SUBLANG_TURKISH_TURKEY' : 0x01, | |
379 'SUBLANG_TURKMEN_TURKMENISTAN' : 0x01, | |
380 'SUBLANG_UIGHUR_PRC' : 0x01, | |
381 'SUBLANG_UKRAINIAN_UKRAINE' : 0x01, | |
382 'SUBLANG_UPPER_SORBIAN_GERMANY' : 0x01, | |
383 'SUBLANG_URDU_PAKISTAN' : 0x01, | |
384 'SUBLANG_URDU_INDIA' : 0x02, | |
385 'SUBLANG_UZBEK_LATIN' : 0x01, | |
386 'SUBLANG_UZBEK_CYRILLIC' : 0x02, | |
387 'SUBLANG_VIETNAMESE_VIETNAM' : 0x01, | |
388 'SUBLANG_WELSH_UNITED_KINGDOM' : 0x01, | |
389 'SUBLANG_WOLOF_SENEGAL' : 0x01, | |
390 'SUBLANG_XHOSA_SOUTH_AFRICA' : 0x01, | |
391 'SUBLANG_YAKUT_RUSSIA' : 0x01, | |
392 'SUBLANG_YI_PRC' : 0x01, | |
393 'SUBLANG_YORUBA_NIGERIA' : 0x01, | |
394 'SUBLANG_ZULU_SOUTH_AFRICA' : 0x01, | |
395 } | |
396 | |
397 | |
398 ''' | |
399 This dictionary defines the language lookup table. The key is the language ISO | |
400 country code, and the value specifies the corresponding code page, primary | |
401 language and sublanguage. | |
402 | |
403 LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx | |
404 Codepage resource: http://www.science.co.il/language/locale-codes.asp | |
405 Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx | |
406 | |
407 There is no appropriate sublang for Spanish (Latin America) [es-419], so we | |
408 use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other | |
409 Latin American countries, Mexican Spanish is supported by VERSIONINFO: | |
410 http://msdn.microsoft.com/en-us/library/aa381058.aspx | |
411 | |
412 ''' | |
413 _LANGUAGE_MAP = { | |
414 # Language neutral LCID, unicode(1200) code page. | |
415 'neutral' : [ 1200, 'LANG_NEUTRAL', 'SUBLANG_NEUTRAL' ], | |
416 # LANG_USER_DEFAULT LCID, unicode(1200) code page. | |
417 'userdefault' : [ 1200, 'LANG_NEUTRAL', 'SUBLANG_DEFAULT' ], | |
418 'fake-bidi' : [ 1255, 'LANG_HEBREW', 'SUBLANG_DEFAULT' ], | |
419 'af' : [ 1252, 'LANG_AFRIKAANS', 'SUBLANG_DEFAULT' ], | |
420 'am' : [ 1200, 'LANG_AMHARIC', 'SUBLANG_DEFAULT' ], | |
421 'ar' : [ 1256, 'LANG_ARABIC', 'SUBLANG_DEFAULT' ], | |
422 'bg' : [ 1251, 'LANG_BULGARIAN', 'SUBLANG_DEFAULT' ], | |
423 'bn' : [ 1200, 'LANG_BENGALI', 'SUBLANG_DEFAULT' ], | |
424 'ca' : [ 1252, 'LANG_CATALAN', 'SUBLANG_DEFAULT' ], | |
425 'cs' : [ 1250, 'LANG_CZECH', 'SUBLANG_DEFAULT' ], | |
426 'da' : [ 1252, 'LANG_DANISH', 'SUBLANG_DEFAULT' ], | |
427 'de' : [ 1252, 'LANG_GERMAN', 'SUBLANG_GERMAN' ], | |
428 'el' : [ 1253, 'LANG_GREEK', 'SUBLANG_DEFAULT' ], | |
429 'en' : [ 1200, 'LANG_ENGLISH', 'SUBLANG_ENGLISH_US' ], | |
430 'en-GB' : [ 1038, 'LANG_ENGLISH', 'SUBLANG_ENGLISH_UK' ], | |
431 'es' : [ 1252, 'LANG_SPANISH', 'SUBLANG_SPANISH_MODERN' ], | |
432 # LCID for Mexico; Windows does not support L.A. LCID. | |
433 'es-419' : [ 1252, 'LANG_SPANISH', 'SUBLANG_SPANISH_MEXICAN' ], | |
434 'et' : [ 1257, 'LANG_ESTONIAN', 'SUBLANG_DEFAULT' ], | |
435 'eu' : [ 1252, 'LANG_BASQUE', 'SUBLANG_DEFAULT' ], | |
436 'fa' : [ 1256, 'LANG_PERSIAN', 'SUBLANG_DEFAULT' ], | |
437 'fi' : [ 1252, 'LANG_FINNISH', 'SUBLANG_DEFAULT' ], | |
438 'fil' : [ 1252, 'LANG_FILIPINO', 'SUBLANG_DEFAULT' ], | |
439 'fr' : [ 1252, 'LANG_FRENCH', 'SUBLANG_FRENCH' ], | |
440 'fr-CA' : [ 1252, 'LANG_FRENCH', 'SUBLANG_FRENCH_CANADIAN' ], | |
441 'gl' : [ 1252, 'LANG_GALICIAN', 'SUBLANG_DEFAULT' ], | |
442 'gu' : [ 1200, 'LANG_GUJARATI', 'SUBLANG_DEFAULT' ], | |
443 'he' : [ 1255, 'LANG_HEBREW', 'SUBLANG_DEFAULT' ], | |
444 'hi' : [ 1200, 'LANG_HINDI', 'SUBLANG_DEFAULT' ], | |
445 'hr' : [ 1252, 'LANG_CROATIAN', 'SUBLANG_DEFAULT' ], | |
446 'hu' : [ 1250, 'LANG_HUNGARIAN', 'SUBLANG_DEFAULT' ], | |
447 'id' : [ 1252, 'LANG_INDONESIAN', 'SUBLANG_DEFAULT' ], | |
448 'is' : [ 1252, 'LANG_ICELANDIC', 'SUBLANG_DEFAULT' ], | |
449 'it' : [ 1252, 'LANG_ITALIAN', 'SUBLANG_DEFAULT' ], | |
450 'iw' : [ 1255, 'LANG_HEBREW', 'SUBLANG_DEFAULT' ], | |
451 'ja' : [ 932, 'LANG_JAPANESE', 'SUBLANG_DEFAULT' ], | |
452 'kn' : [ 1200, 'LANG_KANNADA', 'SUBLANG_DEFAULT' ], | |
453 'ko' : [ 949, 'LANG_KOREAN', 'SUBLANG_KOREAN' ], | |
454 'lt' : [ 1257, 'LANG_LITHUANIAN', 'SUBLANG_LITHUANIAN' ], | |
455 'lv' : [ 1257, 'LANG_LATVIAN', 'SUBLANG_DEFAULT' ], | |
456 'ml' : [ 1200, 'LANG_MALAYALAM', 'SUBLANG_DEFAULT' ], | |
457 'mr' : [ 1200, 'LANG_MARATHI', 'SUBLANG_DEFAULT' ], | |
458 # Malay (Malaysia) [ms-MY] | |
459 'ms' : [ 1252, 'LANG_MALAY', 'SUBLANG_DEFAULT' ], | |
460 'nb' : [ 1252, 'LANG_NORWEGIAN', 'SUBLANG_NORWEGIAN_BOKMAL' ], | |
461 'ne' : [ 1200, 'LANG_NEPALI', 'SUBLANG_NEPALI_NEPAL' ], | |
462 'nl' : [ 1252, 'LANG_DUTCH', 'SUBLANG_DEFAULT' ], | |
463 'nn' : [ 1252, 'LANG_NORWEGIAN', 'SUBLANG_NORWEGIAN_NYNORSK' ], | |
464 'no' : [ 1252, 'LANG_NORWEGIAN', 'SUBLANG_DEFAULT' ], | |
465 'or' : [ 1200, 'LANG_ORIYA', 'SUBLANG_DEFAULT' ], | |
466 'pa' : [ 1200, 'LANG_PUNJABI', 'SUBLANG_PUNJABI_INDIA' ], | |
467 'pl' : [ 1250, 'LANG_POLISH', 'SUBLANG_DEFAULT' ], | |
468 'pt-BR' : [ 1252, 'LANG_PORTUGUESE', 'SUBLANG_DEFAULT' ], | |
469 'pt-PT' : [ 1252, 'LANG_PORTUGUESE', 'SUBLANG_PORTUGUESE' ], | |
470 'ro' : [ 1250, 'LANG_ROMANIAN', 'SUBLANG_DEFAULT' ], | |
471 'ru' : [ 1251, 'LANG_RUSSIAN', 'SUBLANG_DEFAULT' ], | |
472 'sa' : [ 1200, 'LANG_SANSKRIT', 'SUBLANG_SANSKRIT_INDIA' ], | |
473 'si' : [ 1200, 'LANG_SINHALESE', 'SUBLANG_SINHALESE_SRI_LANKA' ], | |
474 'sk' : [ 1250, 'LANG_SLOVAK', 'SUBLANG_DEFAULT' ], | |
475 'sl' : [ 1250, 'LANG_SLOVENIAN', 'SUBLANG_DEFAULT' ], | |
476 'sr' : [ 1250, 'LANG_SERBIAN', 'SUBLANG_SERBIAN_LATIN' ], | |
477 'sv' : [ 1252, 'LANG_SWEDISH', 'SUBLANG_SWEDISH' ], | |
478 'sw' : [ 1252, 'LANG_SWAHILI', 'SUBLANG_DEFAULT' ], | |
479 'ta' : [ 1200, 'LANG_TAMIL', 'SUBLANG_DEFAULT' ], | |
480 'te' : [ 1200, 'LANG_TELUGU', 'SUBLANG_DEFAULT' ], | |
481 'th' : [ 874, 'LANG_THAI', 'SUBLANG_DEFAULT' ], | |
482 'ti' : [ 1200, 'LANG_TIGRIGNA', 'SUBLANG_TIGRIGNA_ERITREA' ], | |
483 'tr' : [ 1254, 'LANG_TURKISH', 'SUBLANG_DEFAULT' ], | |
484 'uk' : [ 1251, 'LANG_UKRAINIAN', 'SUBLANG_DEFAULT' ], | |
485 'ur' : [ 1200, 'LANG_URDU', 'SUBLANG_DEFAULT' ], | |
486 'vi' : [ 1258, 'LANG_VIETNAMESE', 'SUBLANG_DEFAULT' ], | |
487 'zh-CN' : [ 936, 'LANG_CHINESE', 'SUBLANG_CHINESE_SIMPLIFIED' ], | |
488 'zh-HK' : [ 950, 'LANG_CHINESE', 'SUBLANG_CHINESE_HONGKONG' ], | |
489 'zh-TW' : [ 950, 'LANG_CHINESE', 'SUBLANG_CHINESE_TRADITIONAL' ], | |
490 'zu' : [ 1200, 'LANG_ZULU', 'SUBLANG_DEFAULT' ], | |
491 } | |
492 | |
493 | |
494 # Right-To-Left languages | |
495 _RTL_LANGUAGES = ( | |
496 'ar', # Arabic | |
497 'fa', # Farsi | |
498 'iw', # Hebrew | |
499 'ks', # Kashmiri | |
500 'ku', # Kurdish | |
501 'ps', # Pashto | |
502 'ur', # Urdu | |
503 'yi', # Yiddish | |
504 ) | |
505 | |
506 | |
507 def GetCodepage(language): | |
508 """ Returns the codepage for the given |language|. """ | |
509 lang = _LANGUAGE_MAP[language] | |
510 return "%04x" % lang[0] | |
511 | |
512 | |
513 def GetCodepageDecimal(language): | |
514 """ Returns the codepage for the given |language| as a decimal value. """ | |
515 lang = _LANGUAGE_MAP[language] | |
516 return "%d" % lang[0] | |
517 | |
518 | |
519 def GetLangId(language): | |
520 """ Returns the language id for the given |language|. """ | |
521 lang = _LANGUAGE_MAP[language] | |
522 return "%04x" % (_LANGUAGE_PRIMARY[lang[1]] | (_LANGUAGE_SUB[lang[2]] << 10)) | |
523 | |
524 | |
525 def GetPrimaryLanguage(language): | |
526 """ Returns the primary language ID for the given |language|. """ | |
527 lang = _LANGUAGE_MAP[language] | |
528 return _LANGUAGE_PRIMARY[lang[1]] | |
529 | |
530 | |
531 def GetSublanguage(language): | |
532 """ Returns the sublanguage ID for the given |language|. """ | |
533 lang = _LANGUAGE_MAP[language] | |
534 return _LANGUAGE_SUB[lang[2]] | |
535 | |
536 | |
537 def IsRtlLanguage(language): | |
538 return language in _RTL_LANGUAGES; | |
539 | |
540 | |
541 def NormalizeLanguageCode(language): | |
542 return language.replace('_', '-', 1) | |
543 | |
544 | |
545 def ReadValuesFromFile(values_dict, file_name): | |
546 """ | |
547 Reads KEYWORD=VALUE settings from the specified file. | |
548 | |
549 Everything to the left of the first '=' is the keyword, | |
550 everything to the right is the value. No stripping of | |
551 white space, so beware. | |
552 | |
553 The file must exist, otherwise you get the Python exception from open(). | |
554 """ | |
555 for line in open(file_name, 'r').readlines(): | |
556 key, val = line.rstrip('\r\n').split('=', 1) | |
557 values_dict[key] = val | |
558 | |
559 | |
560 def ReadMessagesFromFile(file_name): | |
561 """ | |
562 Reads messages from a 'chrome_messages_json' file. | |
563 | |
564 The file must exist, otherwise you get the Python exception from open(). | |
565 """ | |
566 messages_file = io.open(file_name, encoding='utf-8-sig') | |
567 messages = json.load(messages_file) | |
568 messages_file.close() | |
569 | |
570 values = {} | |
571 for key in messages.keys(): | |
572 values[key] = unicode(messages[key]['message']); | |
573 return values | |
574 | |
575 | |
576 def WriteIfChanged(file_name, contents, encoding='utf-16'): | |
577 """ | |
578 Writes the specified contents to the specified file_name | |
579 iff the contents are different than the current contents. | |
580 """ | |
581 try: | |
582 target = io.open(file_name, 'r') | |
583 old_contents = target.read() | |
584 except EnvironmentError: | |
585 pass | |
586 except UnicodeDecodeError: | |
587 target.close() | |
588 os.unlink(file_name) | |
589 else: | |
590 if contents == old_contents: | |
591 return | |
592 target.close() | |
593 os.unlink(file_name) | |
594 io.open(file_name, 'w', encoding=encoding).write(contents) | |
595 | |
596 | |
597 class MessageMap: | |
598 """ Provides a dictionary of localized messages for each language.""" | |
599 def __init__(self, languages, messages_path): | |
600 self.language = None | |
601 self.message_map = {} | |
602 | |
603 # Populate the message map | |
604 if messages_path: | |
605 for language in languages: | |
606 file_name = os.path.join(messages_path, | |
607 language.replace('-', '_', 1), | |
608 'messages.json') | |
609 self.message_map[language] = ReadMessagesFromFile(file_name) | |
610 | |
611 def GetText(self, message): | |
612 """ Returns a localized message for the current language. """ | |
613 return self.message_map[self.language][message] | |
614 | |
615 def SelectLanguage(self, language): | |
616 """ Selects the language to be used when retrieving localized messages. """ | |
617 self.language = language | |
618 | |
619 def MakeSelectLanguage(self): | |
620 """ Returns a function that can be used to select the current language. """ | |
621 return lambda language: self.SelectLanguage(language) | |
622 | |
623 def MakeGetText(self): | |
624 """ Returns a function that can be used to retrieve a localized message. """ | |
625 return lambda message: self.GetText(message) | |
626 | |
627 | |
628 def Localize(source, target, options): | |
629 # Load jinja2 library. | |
630 if options.jinja2: | |
631 jinja2_path = os.path.normpath(options.jinja2) | |
632 else: | |
633 jinja2_path = os.path.normpath(os.path.join(os.path.abspath(__file__), | |
634 '../../../third_party/jinja2')) | |
635 sys.path.append(os.path.split(jinja2_path)[0]) | |
636 from jinja2 import Environment, FileSystemLoader | |
637 | |
638 # Create jinja2 environment. | |
639 (template_path, template_name) = os.path.split(source) | |
640 env = Environment(loader=FileSystemLoader(template_path), | |
641 extensions=['jinja2.ext.do', 'jinja2.ext.i18n']) | |
642 | |
643 # Register custom filters. | |
644 env.filters['GetCodepage'] = GetCodepage | |
645 env.filters['GetCodepageDecimal'] = GetCodepageDecimal | |
646 env.filters['GetLangId'] = GetLangId | |
647 env.filters['GetPrimaryLanguage'] = GetPrimaryLanguage | |
648 env.filters['GetSublanguage'] = GetSublanguage | |
649 | |
650 # Set the list of languages to use | |
651 languages = map(NormalizeLanguageCode, options.languages) | |
652 context = { 'languages' : languages } | |
653 env.globals['IsRtlLanguage'] = IsRtlLanguage | |
654 | |
655 # Load the localized messages and register the message map with jinja2.i18n | |
656 # extension. | |
657 message_map = MessageMap(languages, options.messages_path) | |
658 env.globals['SelectLanguage'] = message_map.MakeSelectLanguage() | |
659 env.install_gettext_callables(message_map.MakeGetText(), | |
660 message_map.MakeGetText()); | |
661 | |
662 # Add OFFICIAL_BUILD variable the same way chrome/tools/build/version.py | |
663 # does. | |
664 if os.environ.get('CHROME_BUILD_TYPE') == '_official': | |
665 context['official_build'] = '1' | |
666 else: | |
667 context['official_build'] = '0' | |
668 | |
669 # Add all variables defined in the command line. | |
670 if options.define: | |
671 for define in options.define: | |
672 context.update(dict([define.split('=', 1)])); | |
673 | |
674 # Read KEYWORD=VALUE variables from file. | |
675 if options.input: | |
676 for file_name in options.input: | |
677 ReadValuesFromFile(context, file_name) | |
678 | |
679 template = env.get_template(template_name) | |
680 WriteIfChanged(target, template.render(context), options.encoding); | |
681 return 0; | |
682 | |
683 | |
684 def main(): | |
685 usage = "Usage: localize [options] <input> <output>" | |
686 parser = OptionParser(usage=usage) | |
687 parser.add_option( | |
688 '-d', '--define', dest='define', action='append', type='string', | |
689 help='define a variable (VAR=VALUE).') | |
690 parser.add_option( | |
691 '-i', '--input', dest='input', action='append', type='string', | |
692 help='read variables from INPUT.') | |
693 parser.add_option( | |
694 '-l', '--language', dest='languages', action='append', type='string', | |
695 help='add LANGUAGE to the list of languages to use.') | |
696 parser.add_option( | |
697 '--encoding', dest='encoding', type='string', default='utf-16', | |
698 help="set the encoding of <output>. 'utf-16' is the default.") | |
699 parser.add_option( | |
700 '--jinja2', dest='jinja2', type='string', | |
701 help="specifies path to the jinja2 library.") | |
702 parser.add_option( | |
703 '--messages_path', dest='messages_path', type='string', | |
704 help="set path to localized messages.") | |
705 | |
706 options, args = parser.parse_args() | |
707 if len(args) != 2: | |
708 parser.error('Two positional arguments (<input> and <output>) are expected') | |
709 if not options.languages: | |
710 parser.error('At least one language must be specified') | |
711 if not options.messages_path: | |
712 parser.error('--messages_path is required') | |
713 | |
714 return Localize(args[0], args[1], options) | |
715 | |
716 if __name__ == '__main__': | |
717 sys.exit(main()) | |
718 | |
OLD | NEW |