nsWin32Locale.cpp 18 KB

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