|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "mozilla/ArrayUtils.h" |
|
7 |
|
8 #include "nscore.h" |
|
9 #include "nsString.h" |
|
10 #include "nsXPCOMStrings.h" |
|
11 #include "nsReadableUtils.h" |
|
12 #include "nsWin32Locale.h" |
|
13 #include "prprf.h" |
|
14 #include <windows.h> |
|
15 #include "nsCRT.h" |
|
16 |
|
17 using namespace mozilla; |
|
18 |
|
19 struct iso_pair |
|
20 { |
|
21 const char* iso_code; |
|
22 DWORD win_code; |
|
23 }; |
|
24 |
|
25 struct iso_map |
|
26 { |
|
27 const char* iso_code; |
|
28 DWORD win_code; |
|
29 iso_pair sublang_list[20]; |
|
30 }; |
|
31 |
|
32 nsWin32Locale::LocaleNameToLCIDPtr nsWin32Locale::localeNameToLCID = nullptr; |
|
33 nsWin32Locale::LCIDToLocaleNamePtr nsWin32Locale::lcidToLocaleName = nullptr; |
|
34 |
|
35 // Older versions of VC++ and Win32 SDK and mingw don't have |
|
36 // macros for languages and sublanguages recently added to Win32. |
|
37 // see http://www.tug.org/ftp/tex/texinfo/intl/localename.c |
|
38 |
|
39 #ifndef LANG_URDU |
|
40 #define LANG_URDU 0x20 |
|
41 #endif |
|
42 #ifndef LANG_ARMENIAN |
|
43 #define LANG_ARMENIAN 0x2b |
|
44 #endif |
|
45 #ifndef LANG_AZERI |
|
46 #define LANG_AZERI 0x2c |
|
47 #endif |
|
48 #ifndef LANG_MACEDONIAN |
|
49 #define LANG_MACEDONIAN 0x2f |
|
50 #endif |
|
51 #ifndef LANG_GEORGIAN |
|
52 #define LANG_GEORGIAN 0x37 |
|
53 #endif |
|
54 #ifndef LANG_HINDI |
|
55 #define LANG_HINDI 0x39 |
|
56 #endif |
|
57 #ifndef LANG_MALAY |
|
58 #define LANG_MALAY 0x3e |
|
59 #endif |
|
60 #ifndef LANG_KAZAK |
|
61 #define LANG_KAZAK 0x3f |
|
62 #endif |
|
63 #ifndef LANG_KYRGYZ |
|
64 #define LANG_KYRGYZ 0x40 |
|
65 #endif |
|
66 #ifndef LANG_SWAHILI |
|
67 #define LANG_SWAHILI 0x41 |
|
68 #endif |
|
69 #ifndef LANG_UZBEK |
|
70 #define LANG_UZBEK 0x43 |
|
71 #endif |
|
72 #ifndef LANG_TATAR |
|
73 #define LANG_TATAR 0x44 |
|
74 #endif |
|
75 #ifndef LANG_PUNJABI |
|
76 #define LANG_PUNJABI 0x46 |
|
77 #endif |
|
78 #ifndef LANG_GUJARAT |
|
79 #define LANG_GUJARAT 0x47 |
|
80 #endif |
|
81 #ifndef LANG_TAMIL |
|
82 #define LANG_TAMIL 0x49 |
|
83 #endif |
|
84 #ifndef LANG_TELUGU |
|
85 #define LANG_TELUGU 0x4a |
|
86 #endif |
|
87 #ifndef LANG_KANNADA |
|
88 #define LANG_KANNADA 0x4b |
|
89 #endif |
|
90 #ifndef LANG_MARATHI |
|
91 #define LANG_MARATHI 0x4e |
|
92 #endif |
|
93 #ifndef LANG_SANSKRIT |
|
94 #define LANG_SANSKRIT 0x4f |
|
95 #endif |
|
96 #ifndef LANG_MONGOLIAN |
|
97 #define LANG_MONGOLIAN 0x50 |
|
98 #endif |
|
99 #ifndef LANG_GALICIAN |
|
100 #define LANG_GALICIAN 0x56 |
|
101 #endif |
|
102 #ifndef LANG_KONKANI |
|
103 #define LANG_KONKANI 0x57 |
|
104 #endif |
|
105 #ifndef LANG_DIVEHI |
|
106 #define LANG_DIVEHI 0x65 |
|
107 #endif |
|
108 |
|
109 #ifndef SUBLANG_MALAY_MALAYSIA |
|
110 #define SUBLANG_MALAY_MALAYSIA 0x01 |
|
111 #endif |
|
112 #ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM |
|
113 #define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 |
|
114 #endif |
|
115 #ifndef SUBLANG_CHINESE_MACAU |
|
116 #define SUBLANG_CHINESE_MACAU 0x05 |
|
117 #endif |
|
118 #ifndef SUBLANG_FRENCH_MONACO |
|
119 #define SUBLANG_FRENCH_MONACO 0x06 |
|
120 #endif |
|
121 #ifndef SUBLANG_ENGLISH_ZIMBABWE |
|
122 #define SUBLANG_ENGLISH_ZIMBABWE 0x0c |
|
123 #endif |
|
124 #ifndef SUBLANG_ENGLISH_PHILIPPINES |
|
125 #define SUBLANG_ENGLISH_PHILIPPINES 0x0d |
|
126 #endif |
|
127 |
|
128 |
|
129 // |
|
130 // This list is used to map between ISO language |
|
131 // References : |
|
132 // http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html |
|
133 // http://www.loc.gov/standards/iso639-2/ |
|
134 // http://www.ethnologue.com/ |
|
135 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_19ir.asp |
|
136 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_61df.asp |
|
137 |
|
138 static const |
|
139 iso_map iso_list[] = |
|
140 { |
|
141 {"af", LANG_AFRIKAANS, { |
|
142 { "ZA", SUBLANG_DEFAULT }, |
|
143 { "",0}} |
|
144 }, |
|
145 { "ar", LANG_ARABIC, { |
|
146 { "SA", SUBLANG_ARABIC_SAUDI_ARABIA }, |
|
147 { "IQ", SUBLANG_ARABIC_IRAQ }, |
|
148 { "EG", SUBLANG_ARABIC_EGYPT }, |
|
149 { "LY", SUBLANG_ARABIC_LIBYA }, |
|
150 { "DZ", SUBLANG_ARABIC_ALGERIA }, |
|
151 { "MA", SUBLANG_ARABIC_MOROCCO }, |
|
152 { "TN", SUBLANG_ARABIC_TUNISIA }, |
|
153 { "OM", SUBLANG_ARABIC_OMAN }, |
|
154 { "YE", SUBLANG_ARABIC_YEMEN }, |
|
155 { "SY", SUBLANG_ARABIC_SYRIA }, |
|
156 { "JO", SUBLANG_ARABIC_JORDAN }, |
|
157 { "LB", SUBLANG_ARABIC_LEBANON }, |
|
158 { "KW", SUBLANG_ARABIC_KUWAIT }, |
|
159 { "AE", SUBLANG_ARABIC_UAE }, |
|
160 { "BH", SUBLANG_ARABIC_BAHRAIN }, |
|
161 { "QA", SUBLANG_ARABIC_QATAR }, |
|
162 {"",0}} |
|
163 }, |
|
164 {"az", LANG_AZERI, { |
|
165 { "AZ",SUBLANG_DEFAULT }, // XXX Latin vs Cyrillic vs Arabic |
|
166 { "",0}} |
|
167 }, |
|
168 {"be", LANG_BELARUSIAN, { |
|
169 { "BY",SUBLANG_DEFAULT }, |
|
170 { "",0}} |
|
171 }, |
|
172 {"bg", LANG_BULGARIAN, { |
|
173 { "BG", SUBLANG_DEFAULT }, |
|
174 { "",0}} |
|
175 }, |
|
176 {"ca", LANG_CATALAN, { |
|
177 { "ES", SUBLANG_DEFAULT}, |
|
178 { "",0}} |
|
179 }, |
|
180 {"cs", LANG_CZECH, { |
|
181 { "CZ", SUBLANG_DEFAULT}, |
|
182 {"",0}} |
|
183 }, |
|
184 { "da", LANG_DANISH, { |
|
185 { "DK", SUBLANG_DEFAULT }, |
|
186 { "",0}} |
|
187 }, |
|
188 { "de", LANG_GERMAN, { |
|
189 { "DE", SUBLANG_GERMAN }, |
|
190 { "CH", SUBLANG_GERMAN_SWISS }, |
|
191 { "AT", SUBLANG_GERMAN_AUSTRIAN }, |
|
192 { "LU", SUBLANG_GERMAN_LUXEMBOURG }, |
|
193 { "LI", SUBLANG_GERMAN_LIECHTENSTEIN }, |
|
194 { "" , 0}} |
|
195 }, |
|
196 {"dv", LANG_DIVEHI, { |
|
197 { "MV", SUBLANG_DEFAULT}, |
|
198 { "", 0}} |
|
199 }, |
|
200 {"el", LANG_GREEK, { |
|
201 { "GR", SUBLANG_DEFAULT}, |
|
202 { "", 0}} |
|
203 }, |
|
204 { "en", LANG_ENGLISH, { |
|
205 { "US", SUBLANG_ENGLISH_US }, |
|
206 { "GB", SUBLANG_ENGLISH_UK }, |
|
207 { "AU", SUBLANG_ENGLISH_AUS }, |
|
208 { "CA", SUBLANG_ENGLISH_CAN }, |
|
209 { "NZ", SUBLANG_ENGLISH_NZ }, |
|
210 { "IE", SUBLANG_ENGLISH_EIRE }, |
|
211 { "ZA", SUBLANG_ENGLISH_SOUTH_AFRICA }, |
|
212 { "JM", SUBLANG_ENGLISH_JAMAICA }, |
|
213 { "BZ", SUBLANG_ENGLISH_BELIZE }, |
|
214 { "TT", SUBLANG_ENGLISH_TRINIDAD }, |
|
215 { "ZW", SUBLANG_ENGLISH_ZIMBABWE }, |
|
216 { "PH", SUBLANG_ENGLISH_PHILIPPINES }, |
|
217 { "",0}} |
|
218 }, |
|
219 { "es", LANG_SPANISH, { // XXX : SUBLANG_SPANISH_MODERN |
|
220 { "ES", SUBLANG_SPANISH }, |
|
221 { "MX", SUBLANG_SPANISH_MEXICAN }, |
|
222 { "GT", SUBLANG_SPANISH_GUATEMALA }, |
|
223 { "CR", SUBLANG_SPANISH_COSTA_RICA }, |
|
224 { "PA", SUBLANG_SPANISH_PANAMA }, |
|
225 { "DO", SUBLANG_SPANISH_DOMINICAN_REPUBLIC }, |
|
226 { "VE", SUBLANG_SPANISH_VENEZUELA }, |
|
227 { "CO", SUBLANG_SPANISH_COLOMBIA }, |
|
228 { "PE", SUBLANG_SPANISH_PERU }, |
|
229 { "AR", SUBLANG_SPANISH_ARGENTINA }, |
|
230 { "EC", SUBLANG_SPANISH_ECUADOR }, |
|
231 { "CL", SUBLANG_SPANISH_CHILE }, |
|
232 { "UY", SUBLANG_SPANISH_URUGUAY }, |
|
233 { "PY", SUBLANG_SPANISH_PARAGUAY }, |
|
234 { "BO", SUBLANG_SPANISH_BOLIVIA }, |
|
235 { "SV", SUBLANG_SPANISH_EL_SALVADOR }, |
|
236 { "HN", SUBLANG_SPANISH_HONDURAS }, |
|
237 { "NI", SUBLANG_SPANISH_NICARAGUA }, |
|
238 { "PR", SUBLANG_SPANISH_PUERTO_RICO }, |
|
239 { "", 0 }} |
|
240 }, |
|
241 {"et", LANG_ESTONIAN, { |
|
242 { "EE", SUBLANG_DEFAULT }, |
|
243 { "", 0}} |
|
244 }, |
|
245 {"eu", LANG_BASQUE, { |
|
246 { "ES" , SUBLANG_DEFAULT }, |
|
247 { "" , 0 }} |
|
248 }, |
|
249 {"fa", LANG_FARSI, { |
|
250 { "IR", SUBLANG_DEFAULT}, |
|
251 { "", 0}} |
|
252 }, |
|
253 {"fi", LANG_FINNISH, { |
|
254 { "FI", SUBLANG_DEFAULT }, |
|
255 { "",0}} |
|
256 }, |
|
257 {"fo", LANG_FAEROESE, { |
|
258 { "FO", SUBLANG_DEFAULT }, |
|
259 { "", 0}} |
|
260 }, |
|
261 { "fr", LANG_FRENCH, { |
|
262 { "FR", SUBLANG_FRENCH }, |
|
263 { "BE", SUBLANG_FRENCH_BELGIAN }, |
|
264 { "CA", SUBLANG_FRENCH_CANADIAN }, |
|
265 { "CH", SUBLANG_FRENCH_SWISS }, |
|
266 { "LU", SUBLANG_FRENCH_LUXEMBOURG }, |
|
267 { "MC", SUBLANG_FRENCH_MONACO }, |
|
268 {"",0}} |
|
269 }, |
|
270 { "gl", LANG_GALICIAN, { |
|
271 { "ES", SUBLANG_DEFAULT }, |
|
272 { "", 0}} |
|
273 }, |
|
274 { "gu", LANG_GUJARATI, { |
|
275 { "IN", SUBLANG_DEFAULT }, |
|
276 { "", 0}} |
|
277 }, |
|
278 {"he", LANG_HEBREW, { |
|
279 { "IL", SUBLANG_DEFAULT}, |
|
280 { "", 0}} |
|
281 }, |
|
282 {"hi", LANG_HINDI, { |
|
283 { "IN", SUBLANG_DEFAULT }, |
|
284 { "", 0}} |
|
285 }, |
|
286 /* Duplicate the SUBLANG codes for Croatian and Serbian, because the Windows |
|
287 LANG code is the same for both */ |
|
288 {"hr", LANG_CROATIAN, { |
|
289 { "CS", SUBLANG_SERBIAN_LATIN }, |
|
290 { "SP", SUBLANG_SERBIAN_CYRILLIC }, |
|
291 { "HR", SUBLANG_DEFAULT}, |
|
292 { "" ,0 }} |
|
293 }, |
|
294 {"hu", LANG_HUNGARIAN, { |
|
295 { "HU", SUBLANG_DEFAULT }, |
|
296 { "" , 0 }} |
|
297 }, |
|
298 {"hy", LANG_ARMENIAN, { |
|
299 { "AM", SUBLANG_DEFAULT}, |
|
300 { "" ,0 }} |
|
301 }, |
|
302 {"id", LANG_INDONESIAN, { |
|
303 { "ID", SUBLANG_DEFAULT }, |
|
304 {"", 0}} |
|
305 }, |
|
306 {"is", LANG_ICELANDIC, { |
|
307 { "IS", SUBLANG_DEFAULT }, |
|
308 { "", 0}} |
|
309 }, |
|
310 { "it", LANG_ITALIAN, { |
|
311 { "IT", SUBLANG_ITALIAN }, |
|
312 { "CH", SUBLANG_ITALIAN_SWISS }, |
|
313 { "", 0}} |
|
314 }, |
|
315 {"iw", LANG_HEBREW, { |
|
316 { "IL", SUBLANG_DEFAULT}, |
|
317 { "", 0}} |
|
318 }, |
|
319 {"ja", LANG_JAPANESE, { |
|
320 { "JP", SUBLANG_DEFAULT }, |
|
321 { "", 0}} |
|
322 }, |
|
323 { "ka", LANG_GEORGIAN, { |
|
324 { "GE", SUBLANG_DEFAULT }, |
|
325 { "", 0}} |
|
326 }, |
|
327 { "kk", LANG_KAZAK, { |
|
328 { "KZ", SUBLANG_DEFAULT }, // KAZAKHSTAN |
|
329 { "", 0}} |
|
330 }, |
|
331 { "kn", LANG_KANNADA, { |
|
332 { "IN", SUBLANG_DEFAULT }, |
|
333 { "", 0}} |
|
334 }, |
|
335 { "ko", LANG_KOREAN, { |
|
336 { "KR", SUBLANG_KOREAN }, |
|
337 { "", 0}} |
|
338 }, |
|
339 { "kok", LANG_KONKANI, { |
|
340 { "IN", SUBLANG_DEFAULT }, |
|
341 { "", 0}} |
|
342 }, |
|
343 { "ky", LANG_KYRGYZ, { |
|
344 { "KG", SUBLANG_DEFAULT }, // Kygyzstan |
|
345 { "", 0}} |
|
346 }, |
|
347 {"lt", LANG_LITHUANIAN, { |
|
348 { "LT", SUBLANG_DEFAULT }, |
|
349 { "" ,0 }} |
|
350 }, |
|
351 {"lv", LANG_LATVIAN, { |
|
352 { "LV", SUBLANG_DEFAULT}, |
|
353 { "", 0}} |
|
354 }, |
|
355 {"mk", LANG_MACEDONIAN, { |
|
356 { "MK", SUBLANG_DEFAULT }, |
|
357 { "", 0 }} |
|
358 }, |
|
359 { "mn", LANG_MONGOLIAN, { |
|
360 { "MN", SUBLANG_DEFAULT }, |
|
361 { "", 0}} |
|
362 }, |
|
363 { "mr", LANG_MARATHI, { |
|
364 { "IN", SUBLANG_DEFAULT }, |
|
365 { "", 0}} |
|
366 }, |
|
367 {"ms", LANG_MALAY, { |
|
368 { "MY", SUBLANG_MALAY_MALAYSIA }, |
|
369 { "BN", SUBLANG_MALAY_BRUNEI_DARUSSALAM }, // XXX |
|
370 { "", 0}} |
|
371 }, |
|
372 {"nb", LANG_NORWEGIAN, { |
|
373 { "NO", SUBLANG_NORWEGIAN_BOKMAL }, |
|
374 { "", SUBLANG_NORWEGIAN_BOKMAL}} |
|
375 }, |
|
376 {"nl", LANG_DUTCH, { |
|
377 {"NL", SUBLANG_DUTCH }, |
|
378 {"BE", SUBLANG_DUTCH_BELGIAN }, |
|
379 { "", 0}} |
|
380 }, |
|
381 {"nn", LANG_NORWEGIAN, { |
|
382 { "NO", SUBLANG_NORWEGIAN_NYNORSK }, |
|
383 { "", SUBLANG_NORWEGIAN_NYNORSK}} |
|
384 }, |
|
385 {"no", LANG_NORWEGIAN, { |
|
386 { "NO", SUBLANG_DEFAULT }, |
|
387 { "", 0}} |
|
388 }, |
|
389 { "pa", LANG_PUNJABI, { |
|
390 { "IN", SUBLANG_DEFAULT }, |
|
391 { "", 0}} |
|
392 }, |
|
393 {"pl", LANG_POLISH, { |
|
394 { "PL", SUBLANG_DEFAULT }, |
|
395 { "", 0}} |
|
396 }, |
|
397 { "pt", LANG_PORTUGUESE, { |
|
398 { "PT", SUBLANG_PORTUGUESE }, |
|
399 { "BR", SUBLANG_PORTUGUESE_BRAZILIAN }, |
|
400 {"",0}} |
|
401 }, |
|
402 {"ro", LANG_ROMANIAN, { |
|
403 { "RO", SUBLANG_DEFAULT }, |
|
404 { "", 0}} |
|
405 }, |
|
406 {"ru", LANG_RUSSIAN, { |
|
407 { "RU", SUBLANG_DEFAULT }, |
|
408 { "", 0 }} |
|
409 }, |
|
410 { "sa", LANG_SANSKRIT, { |
|
411 { "IN", SUBLANG_DEFAULT }, |
|
412 { "", 0}} |
|
413 }, |
|
414 {"sk", LANG_SLOVAK, { |
|
415 { "SK", SUBLANG_DEFAULT }, |
|
416 { "", 0}} |
|
417 }, |
|
418 {"sl", LANG_SLOVENIAN, { |
|
419 { "SI", SUBLANG_DEFAULT }, |
|
420 { "", 0}} |
|
421 }, |
|
422 {"sq", LANG_ALBANIAN, { |
|
423 { "AL", SUBLANG_DEFAULT }, |
|
424 { "", 0}} |
|
425 }, |
|
426 /* Duplicate the SUBLANG codes for Croatian and Serbian, because the Windows |
|
427 LANG code is the same for both */ |
|
428 {"sr", LANG_SERBIAN, { |
|
429 { "CS", SUBLANG_SERBIAN_LATIN }, |
|
430 { "SP", SUBLANG_SERBIAN_CYRILLIC }, |
|
431 { "HR", SUBLANG_DEFAULT }, |
|
432 { "", 0}} |
|
433 }, |
|
434 { "sv", LANG_SWEDISH, { |
|
435 { "SE", SUBLANG_SWEDISH }, |
|
436 { "FI", SUBLANG_SWEDISH_FINLAND }, |
|
437 { "", 0 }} |
|
438 }, |
|
439 {"sw", LANG_SWAHILI, { |
|
440 { "KE", SUBLANG_DEFAULT }, |
|
441 { "", 0}} |
|
442 }, |
|
443 { "ta", LANG_TAMIL, { |
|
444 { "IN", SUBLANG_DEFAULT }, |
|
445 { "", 0}} |
|
446 }, |
|
447 { "te", LANG_TELUGU, { |
|
448 { "IN", SUBLANG_DEFAULT }, |
|
449 { "", 0}} |
|
450 }, |
|
451 {"th", LANG_THAI, { |
|
452 {"TH", SUBLANG_DEFAULT}, |
|
453 {"",0}} |
|
454 }, |
|
455 {"tr", LANG_TURKISH, { |
|
456 { "TR", SUBLANG_DEFAULT }, |
|
457 { "", 0}} |
|
458 }, |
|
459 { "tt", LANG_TATAR, { |
|
460 { "RU", SUBLANG_DEFAULT }, |
|
461 { "", 0}} |
|
462 }, |
|
463 {"uk", LANG_UKRAINIAN, { |
|
464 { "UA", SUBLANG_DEFAULT }, |
|
465 { "", 0}} |
|
466 }, |
|
467 {"ur", LANG_URDU, { |
|
468 { "PK", SUBLANG_URDU_PAKISTAN }, |
|
469 { "IN", SUBLANG_URDU_INDIA }, |
|
470 { "", 0}} |
|
471 }, |
|
472 {"uz", LANG_UZBEK, { // XXX : Cyrillic, Latin |
|
473 { "UZ", SUBLANG_DEFAULT }, |
|
474 { "", 0}} |
|
475 }, |
|
476 {"vi", LANG_VIETNAMESE, { |
|
477 { "VN", SUBLANG_DEFAULT }, |
|
478 { "", 0}} |
|
479 }, |
|
480 { "zh", LANG_CHINESE, { |
|
481 { "TW", SUBLANG_CHINESE_TRADITIONAL }, |
|
482 { "CN", SUBLANG_CHINESE_SIMPLIFIED }, |
|
483 { "HK", SUBLANG_CHINESE_HONGKONG }, |
|
484 { "SG", SUBLANG_CHINESE_SINGAPORE }, |
|
485 { "MO", SUBLANG_CHINESE_MACAU }, |
|
486 { "",0}} |
|
487 } |
|
488 }; |
|
489 |
|
490 #define LENGTH_MAPPING_LIST ArrayLength(iso_list) |
|
491 |
|
492 // |
|
493 // This list maps ISO 2 digit country codes to Win32 country codes. |
|
494 // This list must be kept in alphabetic (by iso code) order and synchronized |
|
495 // with the list above. This is only used in debug builds to check the consistentcy |
|
496 // of the internal tables. |
|
497 // |
|
498 #ifdef DEBUG |
|
499 static const |
|
500 iso_pair dbg_list[] = |
|
501 { |
|
502 {"af", LANG_AFRIKAANS}, |
|
503 {"ar", LANG_ARABIC}, |
|
504 {"az", LANG_AZERI}, |
|
505 {"be", LANG_BELARUSIAN}, |
|
506 {"bg", LANG_BULGARIAN}, |
|
507 {"ca", LANG_CATALAN}, |
|
508 {"cs", LANG_CZECH}, |
|
509 {"da", LANG_DANISH}, |
|
510 {"de", LANG_GERMAN}, |
|
511 {"dv", LANG_DIVEHI}, |
|
512 {"el", LANG_GREEK}, |
|
513 {"en", LANG_ENGLISH}, |
|
514 {"es", LANG_SPANISH}, |
|
515 {"et", LANG_ESTONIAN}, |
|
516 {"eu", LANG_BASQUE}, |
|
517 {"fa", LANG_FARSI}, |
|
518 {"fi", LANG_FINNISH}, |
|
519 {"fo", LANG_FAEROESE}, |
|
520 {"fr", LANG_FRENCH}, |
|
521 {"gl", LANG_GALICIAN}, |
|
522 {"gu", LANG_GUJARATI}, |
|
523 {"he", LANG_HEBREW}, |
|
524 {"hi", LANG_HINDI}, |
|
525 {"hr", LANG_CROATIAN}, |
|
526 {"hu", LANG_HUNGARIAN}, |
|
527 {"hy", LANG_ARMENIAN}, |
|
528 {"id", LANG_INDONESIAN}, |
|
529 {"in", LANG_INDONESIAN}, |
|
530 {"is", LANG_ICELANDIC}, |
|
531 {"it", LANG_ITALIAN}, |
|
532 {"iw", LANG_HEBREW}, |
|
533 {"ja", LANG_JAPANESE}, |
|
534 {"ka", LANG_GEORGIAN}, |
|
535 {"kn", LANG_KANNADA}, |
|
536 {"ko", LANG_KOREAN}, |
|
537 {"kok", LANG_KONKANI}, |
|
538 {"lt", LANG_LITHUANIAN}, |
|
539 {"lv", LANG_LATVIAN}, |
|
540 {"mk", LANG_MACEDONIAN}, |
|
541 {"mn", LANG_MONGOLIAN}, |
|
542 {"mr", LANG_MARATHI}, |
|
543 {"ms", LANG_MALAY}, |
|
544 {"nb", LANG_NORWEGIAN}, |
|
545 {"nl", LANG_DUTCH}, |
|
546 {"nn", LANG_NORWEGIAN}, |
|
547 {"no", LANG_NORWEGIAN}, |
|
548 {"pa", LANG_PUNJABI}, |
|
549 {"pl", LANG_POLISH}, |
|
550 {"pt", LANG_PORTUGUESE}, |
|
551 {"ro", LANG_ROMANIAN}, |
|
552 {"ru", LANG_RUSSIAN}, |
|
553 {"sa", LANG_SANSKRIT}, |
|
554 {"sk", LANG_SLOVAK}, |
|
555 {"sl", LANG_SLOVENIAN}, |
|
556 {"sq", LANG_ALBANIAN}, |
|
557 {"sr", LANG_SERBIAN}, |
|
558 {"sv", LANG_SWEDISH}, |
|
559 {"sw", LANG_SWAHILI}, |
|
560 {"ta", LANG_TAMIL}, |
|
561 {"te", LANG_TELUGU}, |
|
562 {"th", LANG_THAI}, |
|
563 {"tr", LANG_TURKISH}, |
|
564 {"tt", LANG_TATAR}, |
|
565 {"uk", LANG_UKRAINIAN}, |
|
566 {"ur", LANG_URDU}, |
|
567 {"uz", LANG_UZBEK}, |
|
568 {"vi", LANG_VIETNAMESE}, |
|
569 {"zh", LANG_CHINESE}, |
|
570 {"",0} |
|
571 }; |
|
572 #endif |
|
573 |
|
574 #define CROATIAN_ISO_CODE "hr" |
|
575 #define SERBIAN_ISO_CODE "sr" |
|
576 |
|
577 void |
|
578 nsWin32Locale::initFunctionPointers(void) |
|
579 { |
|
580 static bool sInitialized = false; |
|
581 // We use the Vista and above functions if we have them |
|
582 if (!sInitialized) { |
|
583 HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll"); |
|
584 if (kernelDLL) { |
|
585 localeNameToLCID = (LocaleNameToLCIDPtr) GetProcAddress(kernelDLL, "LocaleNameToLCID"); |
|
586 lcidToLocaleName = (LCIDToLocaleNamePtr) GetProcAddress(kernelDLL, "LCIDToLocaleName"); |
|
587 } |
|
588 sInitialized = true; |
|
589 } |
|
590 } |
|
591 |
|
592 // |
|
593 // the mapping routines are a first approximation to get us going on |
|
594 // the tier-1 languages. we are making an assumption that we can map |
|
595 // language and country codes separately on Windows, which isn't true |
|
596 // |
|
597 nsresult |
|
598 nsWin32Locale::GetPlatformLocale(const nsAString& locale, LCID* winLCID) |
|
599 { |
|
600 initFunctionPointers (); |
|
601 |
|
602 if (localeNameToLCID) { |
|
603 nsAutoString locale_autostr(locale); |
|
604 LCID lcid = localeNameToLCID(locale_autostr.get(), 0); |
|
605 // The function returning 0 means that the locale name couldn't be matched, |
|
606 // so we fallback to the old function |
|
607 if (lcid != 0) |
|
608 { |
|
609 *winLCID = lcid; |
|
610 return NS_OK; |
|
611 } |
|
612 } |
|
613 |
|
614 char locale_string[9] = {'\0','\0','\0','\0','\0','\0','\0','\0','\0'}; |
|
615 char* language_code; |
|
616 char* country_code; |
|
617 size_t i, j; |
|
618 |
|
619 // parse the locale |
|
620 const char16_t* data; |
|
621 j = NS_StringGetData(locale, &data); |
|
622 for (i = 0; i < 7 && i < j; i++) { |
|
623 locale_string[i] = data[i] == '-' ? '\0' : data[i]; |
|
624 } |
|
625 |
|
626 language_code = locale_string; |
|
627 country_code = locale_string + strlen(locale_string) + 1; |
|
628 |
|
629 // convert parsed locale to Windows LCID |
|
630 for(i=0;i<LENGTH_MAPPING_LIST;i++) { |
|
631 if (strcmp(language_code,iso_list[i].iso_code)==0) { |
|
632 for(j=0;iso_list[i].sublang_list[j].win_code;j++) { |
|
633 if (strcmp(country_code,iso_list[i].sublang_list[j].iso_code)==0) { |
|
634 *winLCID = MAKELCID(MAKELANGID(iso_list[i].win_code,iso_list[i].sublang_list[j].win_code),SORT_DEFAULT); |
|
635 return NS_OK; |
|
636 } |
|
637 } |
|
638 // here we have a language match but no country match |
|
639 *winLCID = MAKELCID(MAKELANGID(iso_list[i].win_code,SUBLANG_DEFAULT),SORT_DEFAULT); |
|
640 return NS_OK; |
|
641 } |
|
642 } |
|
643 |
|
644 return NS_ERROR_FAILURE; |
|
645 } |
|
646 |
|
647 #ifndef LOCALE_NAME_MAX_LENGTH |
|
648 #define LOCALE_NAME_MAX_LENGTH 85 |
|
649 #endif |
|
650 |
|
651 void |
|
652 nsWin32Locale::GetXPLocale(LCID winLCID, nsAString& locale) |
|
653 { |
|
654 initFunctionPointers (); |
|
655 |
|
656 if (lcidToLocaleName) |
|
657 { |
|
658 WCHAR ret_locale[LOCALE_NAME_MAX_LENGTH]; |
|
659 int rv = lcidToLocaleName(winLCID, ret_locale, LOCALE_NAME_MAX_LENGTH, 0); |
|
660 // rv 0 means that the function failed to match up the LCID, so we fallback |
|
661 // to the old function |
|
662 if (rv != 0) |
|
663 { |
|
664 locale.Assign(ret_locale); |
|
665 return; |
|
666 } |
|
667 } |
|
668 |
|
669 DWORD lang_id, sublang_id; |
|
670 size_t i, j; |
|
671 |
|
672 lang_id = PRIMARYLANGID(LANGIDFROMLCID(winLCID)); |
|
673 sublang_id = SUBLANGID(LANGIDFROMLCID(winLCID)); |
|
674 |
|
675 /* Special-case Norwegian Bokmal and Norwegian Nynorsk, which have the same |
|
676 LANG_ID on Windows, but have separate ISO-639-2 codes */ |
|
677 if (lang_id == LANG_NORWEGIAN) { |
|
678 if (sublang_id == SUBLANG_NORWEGIAN_BOKMAL) { |
|
679 locale.AssignASCII("nb-NO"); |
|
680 } else if (sublang_id == SUBLANG_NORWEGIAN_NYNORSK) { |
|
681 locale.AssignASCII("nn-NO"); |
|
682 } else { |
|
683 locale.AssignASCII("no-NO"); |
|
684 } |
|
685 return; |
|
686 } |
|
687 |
|
688 for(i=0;i<LENGTH_MAPPING_LIST;i++) { |
|
689 if (lang_id==iso_list[i].win_code) { |
|
690 /* Special-case Croatian and Serbian, which have the same LANG_ID on |
|
691 Windows, but have been split into separate ISO-639-2 codes */ |
|
692 if (lang_id == LANG_CROATIAN) { |
|
693 if (sublang_id == SUBLANG_DEFAULT) { |
|
694 locale.AssignLiteral(CROATIAN_ISO_CODE); |
|
695 } else { |
|
696 locale.AssignLiteral(SERBIAN_ISO_CODE); |
|
697 } |
|
698 } else { |
|
699 locale.AssignASCII(iso_list[i].iso_code); |
|
700 } |
|
701 for(j=0;iso_list[i].sublang_list[j].win_code;j++) { |
|
702 if (sublang_id == iso_list[i].sublang_list[j].win_code) { |
|
703 locale.Append(char16_t('-')); |
|
704 locale.AppendASCII(iso_list[i].sublang_list[j].iso_code); |
|
705 break; |
|
706 } |
|
707 } |
|
708 return; |
|
709 } |
|
710 } |
|
711 |
|
712 // |
|
713 // didn't find any match. fall back to en-US, which is better |
|
714 // than unusable buttons without 'OK', 'Cancel', etc (bug 224546) |
|
715 // |
|
716 locale.AssignLiteral("en-US"); |
|
717 return; |
|
718 } |
|
719 |
|
720 #ifdef DEBUG |
|
721 void |
|
722 test_internal_tables(void) |
|
723 { |
|
724 size_t i; |
|
725 |
|
726 for(i=1;i<LENGTH_MAPPING_LIST;i++) { |
|
727 if (strcmp(dbg_list[i-1].iso_code,dbg_list[i].iso_code)>=0) |
|
728 fprintf(stderr,"nsLocale: language_list %s and %s are not ordered\n",dbg_list[i-1].iso_code,dbg_list[i].iso_code); |
|
729 } |
|
730 |
|
731 i=0; |
|
732 while(strlen(dbg_list[i].iso_code)!=0) { |
|
733 i++; |
|
734 } |
|
735 if (i!=LENGTH_MAPPING_LIST) |
|
736 fprintf(stderr,"nsLocale: language_list length is %d, reported length is %d\n",i,LENGTH_MAPPING_LIST); |
|
737 |
|
738 for(i=0;i<LENGTH_MAPPING_LIST;i++) { |
|
739 if (strcmp(iso_list[i].iso_code,dbg_list[i].iso_code)!=0) { |
|
740 fprintf(stderr,"nsLocale: iso_list and dbg_list differet at item: %d\n",i); |
|
741 } |
|
742 } |
|
743 } |
|
744 |
|
745 #endif |
|
746 |