Line data Source code
1 : /* Determine name of the currently selected locale. 2 : Copyright (C) 1995-2020 Free Software Foundation, Inc. 3 : 4 : This program is free software: you can redistribute it and/or modify 5 : it under the terms of the GNU General Public License as published by 6 : the Free Software Foundation; either version 3 of the License, or 7 : (at your option) any later version. 8 : 9 : This program is distributed in the hope that it will be useful, 10 : but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : GNU General Public License for more details. 13 : 14 : You should have received a copy of the GNU General Public License 15 : along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 : 17 : /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */ 18 : /* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */ 19 : /* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */ 20 : 21 : #include <config.h> 22 : 23 : /* Specification. */ 24 : #ifdef IN_LIBINTL 25 : # include "gettextP.h" 26 : #else 27 : # include "localename.h" 28 : #endif 29 : 30 : #include <limits.h> 31 : #include <stddef.h> 32 : #include <stdlib.h> 33 : #include <locale.h> 34 : #include <string.h> 35 : 36 : #include "flexmember.h" 37 : #include "setlocale_null.h" 38 : 39 : /* We cannot support uselocale() on platforms where the locale_t type is fake. 40 : See intl-thread-locale.m4 for details. */ 41 : #if HAVE_WORKING_USELOCALE && !HAVE_FAKE_LOCALES 42 : # define HAVE_GOOD_USELOCALE 1 43 : #endif 44 : 45 : #if HAVE_GOOD_USELOCALE 46 : /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */ 47 : # if defined __APPLE__ && defined __MACH__ 48 : # include <xlocale.h> 49 : # endif 50 : # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__ 51 : # include <langinfo.h> 52 : # endif 53 : # if !defined IN_LIBINTL 54 : # include "glthread/lock.h" 55 : # endif 56 : # if defined __sun 57 : # if HAVE_GETLOCALENAME_L 58 : /* Solaris >= 12. */ 59 : extern char * getlocalename_l(int, locale_t); 60 : # elif HAVE_SOLARIS114_LOCALES 61 : # include <sys/localedef.h> 62 : # endif 63 : # endif 64 : # if HAVE_NAMELESS_LOCALES 65 : # include <errno.h> 66 : # include "localename-table.h" 67 : # endif 68 : #endif 69 : 70 : #if HAVE_CFPREFERENCESCOPYAPPVALUE 71 : # include <CoreFoundation/CFString.h> 72 : # include <CoreFoundation/CFPreferences.h> 73 : #endif 74 : 75 : #if defined _WIN32 && !defined __CYGWIN__ 76 : # define WINDOWS_NATIVE 77 : # if !defined IN_LIBINTL 78 : # include "glthread/lock.h" 79 : # endif 80 : #endif 81 : 82 : #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */ 83 : # define WIN32_LEAN_AND_MEAN 84 : # include <windows.h> 85 : # include <winnls.h> 86 : /* List of language codes, sorted by value: 87 : 0x01 LANG_ARABIC 88 : 0x02 LANG_BULGARIAN 89 : 0x03 LANG_CATALAN 90 : 0x04 LANG_CHINESE 91 : 0x05 LANG_CZECH 92 : 0x06 LANG_DANISH 93 : 0x07 LANG_GERMAN 94 : 0x08 LANG_GREEK 95 : 0x09 LANG_ENGLISH 96 : 0x0a LANG_SPANISH 97 : 0x0b LANG_FINNISH 98 : 0x0c LANG_FRENCH 99 : 0x0d LANG_HEBREW 100 : 0x0e LANG_HUNGARIAN 101 : 0x0f LANG_ICELANDIC 102 : 0x10 LANG_ITALIAN 103 : 0x11 LANG_JAPANESE 104 : 0x12 LANG_KOREAN 105 : 0x13 LANG_DUTCH 106 : 0x14 LANG_NORWEGIAN 107 : 0x15 LANG_POLISH 108 : 0x16 LANG_PORTUGUESE 109 : 0x17 LANG_ROMANSH 110 : 0x18 LANG_ROMANIAN 111 : 0x19 LANG_RUSSIAN 112 : 0x1a LANG_CROATIAN == LANG_SERBIAN 113 : 0x1b LANG_SLOVAK 114 : 0x1c LANG_ALBANIAN 115 : 0x1d LANG_SWEDISH 116 : 0x1e LANG_THAI 117 : 0x1f LANG_TURKISH 118 : 0x20 LANG_URDU 119 : 0x21 LANG_INDONESIAN 120 : 0x22 LANG_UKRAINIAN 121 : 0x23 LANG_BELARUSIAN 122 : 0x24 LANG_SLOVENIAN 123 : 0x25 LANG_ESTONIAN 124 : 0x26 LANG_LATVIAN 125 : 0x27 LANG_LITHUANIAN 126 : 0x28 LANG_TAJIK 127 : 0x29 LANG_FARSI 128 : 0x2a LANG_VIETNAMESE 129 : 0x2b LANG_ARMENIAN 130 : 0x2c LANG_AZERI 131 : 0x2d LANG_BASQUE 132 : 0x2e LANG_SORBIAN 133 : 0x2f LANG_MACEDONIAN 134 : 0x30 LANG_SUTU 135 : 0x31 LANG_TSONGA 136 : 0x32 LANG_TSWANA 137 : 0x33 LANG_VENDA 138 : 0x34 LANG_XHOSA 139 : 0x35 LANG_ZULU 140 : 0x36 LANG_AFRIKAANS 141 : 0x37 LANG_GEORGIAN 142 : 0x38 LANG_FAEROESE 143 : 0x39 LANG_HINDI 144 : 0x3a LANG_MALTESE 145 : 0x3b LANG_SAMI 146 : 0x3c LANG_GAELIC 147 : 0x3d LANG_YIDDISH 148 : 0x3e LANG_MALAY 149 : 0x3f LANG_KAZAK 150 : 0x40 LANG_KYRGYZ 151 : 0x41 LANG_SWAHILI 152 : 0x42 LANG_TURKMEN 153 : 0x43 LANG_UZBEK 154 : 0x44 LANG_TATAR 155 : 0x45 LANG_BENGALI 156 : 0x46 LANG_PUNJABI 157 : 0x47 LANG_GUJARATI 158 : 0x48 LANG_ORIYA 159 : 0x49 LANG_TAMIL 160 : 0x4a LANG_TELUGU 161 : 0x4b LANG_KANNADA 162 : 0x4c LANG_MALAYALAM 163 : 0x4d LANG_ASSAMESE 164 : 0x4e LANG_MARATHI 165 : 0x4f LANG_SANSKRIT 166 : 0x50 LANG_MONGOLIAN 167 : 0x51 LANG_TIBETAN 168 : 0x52 LANG_WELSH 169 : 0x53 LANG_CAMBODIAN 170 : 0x54 LANG_LAO 171 : 0x55 LANG_BURMESE 172 : 0x56 LANG_GALICIAN 173 : 0x57 LANG_KONKANI 174 : 0x58 LANG_MANIPURI 175 : 0x59 LANG_SINDHI 176 : 0x5a LANG_SYRIAC 177 : 0x5b LANG_SINHALESE 178 : 0x5c LANG_CHEROKEE 179 : 0x5d LANG_INUKTITUT 180 : 0x5e LANG_AMHARIC 181 : 0x5f LANG_TAMAZIGHT 182 : 0x60 LANG_KASHMIRI 183 : 0x61 LANG_NEPALI 184 : 0x62 LANG_FRISIAN 185 : 0x63 LANG_PASHTO 186 : 0x64 LANG_TAGALOG 187 : 0x65 LANG_DIVEHI 188 : 0x66 LANG_EDO 189 : 0x67 LANG_FULFULDE 190 : 0x68 LANG_HAUSA 191 : 0x69 LANG_IBIBIO 192 : 0x6a LANG_YORUBA 193 : 0x6d LANG_BASHKIR 194 : 0x6e LANG_LUXEMBOURGISH 195 : 0x6f LANG_GREENLANDIC 196 : 0x70 LANG_IGBO 197 : 0x71 LANG_KANURI 198 : 0x72 LANG_OROMO 199 : 0x73 LANG_TIGRINYA 200 : 0x74 LANG_GUARANI 201 : 0x75 LANG_HAWAIIAN 202 : 0x76 LANG_LATIN 203 : 0x77 LANG_SOMALI 204 : 0x78 LANG_YI 205 : 0x79 LANG_PAPIAMENTU 206 : 0x7a LANG_MAPUDUNGUN 207 : 0x7c LANG_MOHAWK 208 : 0x7e LANG_BRETON 209 : 0x82 LANG_OCCITAN 210 : 0x83 LANG_CORSICAN 211 : 0x84 LANG_ALSATIAN 212 : 0x85 LANG_YAKUT 213 : 0x86 LANG_KICHE 214 : 0x87 LANG_KINYARWANDA 215 : 0x88 LANG_WOLOF 216 : 0x8c LANG_DARI 217 : 0x91 LANG_SCOTTISH_GAELIC 218 : */ 219 : /* Mingw headers don't have latest language and sublanguage codes. */ 220 : # ifndef LANG_AFRIKAANS 221 : # define LANG_AFRIKAANS 0x36 222 : # endif 223 : # ifndef LANG_ALBANIAN 224 : # define LANG_ALBANIAN 0x1c 225 : # endif 226 : # ifndef LANG_ALSATIAN 227 : # define LANG_ALSATIAN 0x84 228 : # endif 229 : # ifndef LANG_AMHARIC 230 : # define LANG_AMHARIC 0x5e 231 : # endif 232 : # ifndef LANG_ARABIC 233 : # define LANG_ARABIC 0x01 234 : # endif 235 : # ifndef LANG_ARMENIAN 236 : # define LANG_ARMENIAN 0x2b 237 : # endif 238 : # ifndef LANG_ASSAMESE 239 : # define LANG_ASSAMESE 0x4d 240 : # endif 241 : # ifndef LANG_AZERI 242 : # define LANG_AZERI 0x2c 243 : # endif 244 : # ifndef LANG_BASHKIR 245 : # define LANG_BASHKIR 0x6d 246 : # endif 247 : # ifndef LANG_BASQUE 248 : # define LANG_BASQUE 0x2d 249 : # endif 250 : # ifndef LANG_BELARUSIAN 251 : # define LANG_BELARUSIAN 0x23 252 : # endif 253 : # ifndef LANG_BENGALI 254 : # define LANG_BENGALI 0x45 255 : # endif 256 : # ifndef LANG_BRETON 257 : # define LANG_BRETON 0x7e 258 : # endif 259 : # ifndef LANG_BURMESE 260 : # define LANG_BURMESE 0x55 261 : # endif 262 : # ifndef LANG_CAMBODIAN 263 : # define LANG_CAMBODIAN 0x53 264 : # endif 265 : # ifndef LANG_CATALAN 266 : # define LANG_CATALAN 0x03 267 : # endif 268 : # ifndef LANG_CHEROKEE 269 : # define LANG_CHEROKEE 0x5c 270 : # endif 271 : # ifndef LANG_CORSICAN 272 : # define LANG_CORSICAN 0x83 273 : # endif 274 : # ifndef LANG_DARI 275 : # define LANG_DARI 0x8c 276 : # endif 277 : # ifndef LANG_DIVEHI 278 : # define LANG_DIVEHI 0x65 279 : # endif 280 : # ifndef LANG_EDO 281 : # define LANG_EDO 0x66 282 : # endif 283 : # ifndef LANG_ESTONIAN 284 : # define LANG_ESTONIAN 0x25 285 : # endif 286 : # ifndef LANG_FAEROESE 287 : # define LANG_FAEROESE 0x38 288 : # endif 289 : # ifndef LANG_FARSI 290 : # define LANG_FARSI 0x29 291 : # endif 292 : # ifndef LANG_FRISIAN 293 : # define LANG_FRISIAN 0x62 294 : # endif 295 : # ifndef LANG_FULFULDE 296 : # define LANG_FULFULDE 0x67 297 : # endif 298 : # ifndef LANG_GAELIC 299 : # define LANG_GAELIC 0x3c 300 : # endif 301 : # ifndef LANG_GALICIAN 302 : # define LANG_GALICIAN 0x56 303 : # endif 304 : # ifndef LANG_GEORGIAN 305 : # define LANG_GEORGIAN 0x37 306 : # endif 307 : # ifndef LANG_GREENLANDIC 308 : # define LANG_GREENLANDIC 0x6f 309 : # endif 310 : # ifndef LANG_GUARANI 311 : # define LANG_GUARANI 0x74 312 : # endif 313 : # ifndef LANG_GUJARATI 314 : # define LANG_GUJARATI 0x47 315 : # endif 316 : # ifndef LANG_HAUSA 317 : # define LANG_HAUSA 0x68 318 : # endif 319 : # ifndef LANG_HAWAIIAN 320 : # define LANG_HAWAIIAN 0x75 321 : # endif 322 : # ifndef LANG_HEBREW 323 : # define LANG_HEBREW 0x0d 324 : # endif 325 : # ifndef LANG_HINDI 326 : # define LANG_HINDI 0x39 327 : # endif 328 : # ifndef LANG_IBIBIO 329 : # define LANG_IBIBIO 0x69 330 : # endif 331 : # ifndef LANG_IGBO 332 : # define LANG_IGBO 0x70 333 : # endif 334 : # ifndef LANG_INDONESIAN 335 : # define LANG_INDONESIAN 0x21 336 : # endif 337 : # ifndef LANG_INUKTITUT 338 : # define LANG_INUKTITUT 0x5d 339 : # endif 340 : # ifndef LANG_KANNADA 341 : # define LANG_KANNADA 0x4b 342 : # endif 343 : # ifndef LANG_KANURI 344 : # define LANG_KANURI 0x71 345 : # endif 346 : # ifndef LANG_KASHMIRI 347 : # define LANG_KASHMIRI 0x60 348 : # endif 349 : # ifndef LANG_KAZAK 350 : # define LANG_KAZAK 0x3f 351 : # endif 352 : # ifndef LANG_KICHE 353 : # define LANG_KICHE 0x86 354 : # endif 355 : # ifndef LANG_KINYARWANDA 356 : # define LANG_KINYARWANDA 0x87 357 : # endif 358 : # ifndef LANG_KONKANI 359 : # define LANG_KONKANI 0x57 360 : # endif 361 : # ifndef LANG_KYRGYZ 362 : # define LANG_KYRGYZ 0x40 363 : # endif 364 : # ifndef LANG_LAO 365 : # define LANG_LAO 0x54 366 : # endif 367 : # ifndef LANG_LATIN 368 : # define LANG_LATIN 0x76 369 : # endif 370 : # ifndef LANG_LATVIAN 371 : # define LANG_LATVIAN 0x26 372 : # endif 373 : # ifndef LANG_LITHUANIAN 374 : # define LANG_LITHUANIAN 0x27 375 : # endif 376 : # ifndef LANG_LUXEMBOURGISH 377 : # define LANG_LUXEMBOURGISH 0x6e 378 : # endif 379 : # ifndef LANG_MACEDONIAN 380 : # define LANG_MACEDONIAN 0x2f 381 : # endif 382 : # ifndef LANG_MALAY 383 : # define LANG_MALAY 0x3e 384 : # endif 385 : # ifndef LANG_MALAYALAM 386 : # define LANG_MALAYALAM 0x4c 387 : # endif 388 : # ifndef LANG_MALTESE 389 : # define LANG_MALTESE 0x3a 390 : # endif 391 : # ifndef LANG_MANIPURI 392 : # define LANG_MANIPURI 0x58 393 : # endif 394 : # ifndef LANG_MAORI 395 : # define LANG_MAORI 0x81 396 : # endif 397 : # ifndef LANG_MAPUDUNGUN 398 : # define LANG_MAPUDUNGUN 0x7a 399 : # endif 400 : # ifndef LANG_MARATHI 401 : # define LANG_MARATHI 0x4e 402 : # endif 403 : # ifndef LANG_MOHAWK 404 : # define LANG_MOHAWK 0x7c 405 : # endif 406 : # ifndef LANG_MONGOLIAN 407 : # define LANG_MONGOLIAN 0x50 408 : # endif 409 : # ifndef LANG_NEPALI 410 : # define LANG_NEPALI 0x61 411 : # endif 412 : # ifndef LANG_OCCITAN 413 : # define LANG_OCCITAN 0x82 414 : # endif 415 : # ifndef LANG_ORIYA 416 : # define LANG_ORIYA 0x48 417 : # endif 418 : # ifndef LANG_OROMO 419 : # define LANG_OROMO 0x72 420 : # endif 421 : # ifndef LANG_PAPIAMENTU 422 : # define LANG_PAPIAMENTU 0x79 423 : # endif 424 : # ifndef LANG_PASHTO 425 : # define LANG_PASHTO 0x63 426 : # endif 427 : # ifndef LANG_PUNJABI 428 : # define LANG_PUNJABI 0x46 429 : # endif 430 : # ifndef LANG_QUECHUA 431 : # define LANG_QUECHUA 0x6b 432 : # endif 433 : # ifndef LANG_ROMANSH 434 : # define LANG_ROMANSH 0x17 435 : # endif 436 : # ifndef LANG_SAMI 437 : # define LANG_SAMI 0x3b 438 : # endif 439 : # ifndef LANG_SANSKRIT 440 : # define LANG_SANSKRIT 0x4f 441 : # endif 442 : # ifndef LANG_SCOTTISH_GAELIC 443 : # define LANG_SCOTTISH_GAELIC 0x91 444 : # endif 445 : # ifndef LANG_SERBIAN 446 : # define LANG_SERBIAN 0x1a 447 : # endif 448 : # ifndef LANG_SINDHI 449 : # define LANG_SINDHI 0x59 450 : # endif 451 : # ifndef LANG_SINHALESE 452 : # define LANG_SINHALESE 0x5b 453 : # endif 454 : # ifndef LANG_SLOVAK 455 : # define LANG_SLOVAK 0x1b 456 : # endif 457 : # ifndef LANG_SOMALI 458 : # define LANG_SOMALI 0x77 459 : # endif 460 : # ifndef LANG_SORBIAN 461 : # define LANG_SORBIAN 0x2e 462 : # endif 463 : # ifndef LANG_SOTHO 464 : # define LANG_SOTHO 0x6c 465 : # endif 466 : # ifndef LANG_SUTU 467 : # define LANG_SUTU 0x30 468 : # endif 469 : # ifndef LANG_SWAHILI 470 : # define LANG_SWAHILI 0x41 471 : # endif 472 : # ifndef LANG_SYRIAC 473 : # define LANG_SYRIAC 0x5a 474 : # endif 475 : # ifndef LANG_TAGALOG 476 : # define LANG_TAGALOG 0x64 477 : # endif 478 : # ifndef LANG_TAJIK 479 : # define LANG_TAJIK 0x28 480 : # endif 481 : # ifndef LANG_TAMAZIGHT 482 : # define LANG_TAMAZIGHT 0x5f 483 : # endif 484 : # ifndef LANG_TAMIL 485 : # define LANG_TAMIL 0x49 486 : # endif 487 : # ifndef LANG_TATAR 488 : # define LANG_TATAR 0x44 489 : # endif 490 : # ifndef LANG_TELUGU 491 : # define LANG_TELUGU 0x4a 492 : # endif 493 : # ifndef LANG_THAI 494 : # define LANG_THAI 0x1e 495 : # endif 496 : # ifndef LANG_TIBETAN 497 : # define LANG_TIBETAN 0x51 498 : # endif 499 : # ifndef LANG_TIGRINYA 500 : # define LANG_TIGRINYA 0x73 501 : # endif 502 : # ifndef LANG_TSONGA 503 : # define LANG_TSONGA 0x31 504 : # endif 505 : # ifndef LANG_TSWANA 506 : # define LANG_TSWANA 0x32 507 : # endif 508 : # ifndef LANG_TURKMEN 509 : # define LANG_TURKMEN 0x42 510 : # endif 511 : # ifndef LANG_UIGHUR 512 : # define LANG_UIGHUR 0x80 513 : # endif 514 : # ifndef LANG_UKRAINIAN 515 : # define LANG_UKRAINIAN 0x22 516 : # endif 517 : # ifndef LANG_URDU 518 : # define LANG_URDU 0x20 519 : # endif 520 : # ifndef LANG_UZBEK 521 : # define LANG_UZBEK 0x43 522 : # endif 523 : # ifndef LANG_VENDA 524 : # define LANG_VENDA 0x33 525 : # endif 526 : # ifndef LANG_VIETNAMESE 527 : # define LANG_VIETNAMESE 0x2a 528 : # endif 529 : # ifndef LANG_WELSH 530 : # define LANG_WELSH 0x52 531 : # endif 532 : # ifndef LANG_WOLOF 533 : # define LANG_WOLOF 0x88 534 : # endif 535 : # ifndef LANG_XHOSA 536 : # define LANG_XHOSA 0x34 537 : # endif 538 : # ifndef LANG_YAKUT 539 : # define LANG_YAKUT 0x85 540 : # endif 541 : # ifndef LANG_YI 542 : # define LANG_YI 0x78 543 : # endif 544 : # ifndef LANG_YIDDISH 545 : # define LANG_YIDDISH 0x3d 546 : # endif 547 : # ifndef LANG_YORUBA 548 : # define LANG_YORUBA 0x6a 549 : # endif 550 : # ifndef LANG_ZULU 551 : # define LANG_ZULU 0x35 552 : # endif 553 : # ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA 554 : # define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01 555 : # endif 556 : # ifndef SUBLANG_ALBANIAN_ALBANIA 557 : # define SUBLANG_ALBANIAN_ALBANIA 0x01 558 : # endif 559 : # ifndef SUBLANG_ALSATIAN_FRANCE 560 : # define SUBLANG_ALSATIAN_FRANCE 0x01 561 : # endif 562 : # ifndef SUBLANG_AMHARIC_ETHIOPIA 563 : # define SUBLANG_AMHARIC_ETHIOPIA 0x01 564 : # endif 565 : # ifndef SUBLANG_ARABIC_SAUDI_ARABIA 566 : # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 567 : # endif 568 : # ifndef SUBLANG_ARABIC_IRAQ 569 : # define SUBLANG_ARABIC_IRAQ 0x02 570 : # endif 571 : # ifndef SUBLANG_ARABIC_EGYPT 572 : # define SUBLANG_ARABIC_EGYPT 0x03 573 : # endif 574 : # ifndef SUBLANG_ARABIC_LIBYA 575 : # define SUBLANG_ARABIC_LIBYA 0x04 576 : # endif 577 : # ifndef SUBLANG_ARABIC_ALGERIA 578 : # define SUBLANG_ARABIC_ALGERIA 0x05 579 : # endif 580 : # ifndef SUBLANG_ARABIC_MOROCCO 581 : # define SUBLANG_ARABIC_MOROCCO 0x06 582 : # endif 583 : # ifndef SUBLANG_ARABIC_TUNISIA 584 : # define SUBLANG_ARABIC_TUNISIA 0x07 585 : # endif 586 : # ifndef SUBLANG_ARABIC_OMAN 587 : # define SUBLANG_ARABIC_OMAN 0x08 588 : # endif 589 : # ifndef SUBLANG_ARABIC_YEMEN 590 : # define SUBLANG_ARABIC_YEMEN 0x09 591 : # endif 592 : # ifndef SUBLANG_ARABIC_SYRIA 593 : # define SUBLANG_ARABIC_SYRIA 0x0a 594 : # endif 595 : # ifndef SUBLANG_ARABIC_JORDAN 596 : # define SUBLANG_ARABIC_JORDAN 0x0b 597 : # endif 598 : # ifndef SUBLANG_ARABIC_LEBANON 599 : # define SUBLANG_ARABIC_LEBANON 0x0c 600 : # endif 601 : # ifndef SUBLANG_ARABIC_KUWAIT 602 : # define SUBLANG_ARABIC_KUWAIT 0x0d 603 : # endif 604 : # ifndef SUBLANG_ARABIC_UAE 605 : # define SUBLANG_ARABIC_UAE 0x0e 606 : # endif 607 : # ifndef SUBLANG_ARABIC_BAHRAIN 608 : # define SUBLANG_ARABIC_BAHRAIN 0x0f 609 : # endif 610 : # ifndef SUBLANG_ARABIC_QATAR 611 : # define SUBLANG_ARABIC_QATAR 0x10 612 : # endif 613 : # ifndef SUBLANG_ARMENIAN_ARMENIA 614 : # define SUBLANG_ARMENIAN_ARMENIA 0x01 615 : # endif 616 : # ifndef SUBLANG_ASSAMESE_INDIA 617 : # define SUBLANG_ASSAMESE_INDIA 0x01 618 : # endif 619 : # ifndef SUBLANG_AZERI_LATIN 620 : # define SUBLANG_AZERI_LATIN 0x01 621 : # endif 622 : # ifndef SUBLANG_AZERI_CYRILLIC 623 : # define SUBLANG_AZERI_CYRILLIC 0x02 624 : # endif 625 : # ifndef SUBLANG_BASHKIR_RUSSIA 626 : # define SUBLANG_BASHKIR_RUSSIA 0x01 627 : # endif 628 : # ifndef SUBLANG_BASQUE_BASQUE 629 : # define SUBLANG_BASQUE_BASQUE 0x01 630 : # endif 631 : # ifndef SUBLANG_BELARUSIAN_BELARUS 632 : # define SUBLANG_BELARUSIAN_BELARUS 0x01 633 : # endif 634 : # ifndef SUBLANG_BENGALI_INDIA 635 : # define SUBLANG_BENGALI_INDIA 0x01 636 : # endif 637 : # ifndef SUBLANG_BENGALI_BANGLADESH 638 : # define SUBLANG_BENGALI_BANGLADESH 0x02 639 : # endif 640 : # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 641 : # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05 642 : # endif 643 : # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 644 : # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08 645 : # endif 646 : # ifndef SUBLANG_BRETON_FRANCE 647 : # define SUBLANG_BRETON_FRANCE 0x01 648 : # endif 649 : # ifndef SUBLANG_BULGARIAN_BULGARIA 650 : # define SUBLANG_BULGARIAN_BULGARIA 0x01 651 : # endif 652 : # ifndef SUBLANG_CAMBODIAN_CAMBODIA 653 : # define SUBLANG_CAMBODIAN_CAMBODIA 0x01 654 : # endif 655 : # ifndef SUBLANG_CATALAN_SPAIN 656 : # define SUBLANG_CATALAN_SPAIN 0x01 657 : # endif 658 : # ifndef SUBLANG_CORSICAN_FRANCE 659 : # define SUBLANG_CORSICAN_FRANCE 0x01 660 : # endif 661 : # ifndef SUBLANG_CROATIAN_CROATIA 662 : # define SUBLANG_CROATIAN_CROATIA 0x01 663 : # endif 664 : # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 665 : # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04 666 : # endif 667 : # ifndef SUBLANG_CHINESE_MACAU 668 : # define SUBLANG_CHINESE_MACAU 0x05 669 : # endif 670 : # ifndef SUBLANG_CZECH_CZECH_REPUBLIC 671 : # define SUBLANG_CZECH_CZECH_REPUBLIC 0x01 672 : # endif 673 : # ifndef SUBLANG_DANISH_DENMARK 674 : # define SUBLANG_DANISH_DENMARK 0x01 675 : # endif 676 : # ifndef SUBLANG_DARI_AFGHANISTAN 677 : # define SUBLANG_DARI_AFGHANISTAN 0x01 678 : # endif 679 : # ifndef SUBLANG_DIVEHI_MALDIVES 680 : # define SUBLANG_DIVEHI_MALDIVES 0x01 681 : # endif 682 : # ifndef SUBLANG_DUTCH_SURINAM 683 : # define SUBLANG_DUTCH_SURINAM 0x03 684 : # endif 685 : # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA 686 : # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 687 : # endif 688 : # ifndef SUBLANG_ENGLISH_JAMAICA 689 : # define SUBLANG_ENGLISH_JAMAICA 0x08 690 : # endif 691 : # ifndef SUBLANG_ENGLISH_CARIBBEAN 692 : # define SUBLANG_ENGLISH_CARIBBEAN 0x09 693 : # endif 694 : # ifndef SUBLANG_ENGLISH_BELIZE 695 : # define SUBLANG_ENGLISH_BELIZE 0x0a 696 : # endif 697 : # ifndef SUBLANG_ENGLISH_TRINIDAD 698 : # define SUBLANG_ENGLISH_TRINIDAD 0x0b 699 : # endif 700 : # ifndef SUBLANG_ENGLISH_ZIMBABWE 701 : # define SUBLANG_ENGLISH_ZIMBABWE 0x0c 702 : # endif 703 : # ifndef SUBLANG_ENGLISH_PHILIPPINES 704 : # define SUBLANG_ENGLISH_PHILIPPINES 0x0d 705 : # endif 706 : # ifndef SUBLANG_ENGLISH_INDONESIA 707 : # define SUBLANG_ENGLISH_INDONESIA 0x0e 708 : # endif 709 : # ifndef SUBLANG_ENGLISH_HONGKONG 710 : # define SUBLANG_ENGLISH_HONGKONG 0x0f 711 : # endif 712 : # ifndef SUBLANG_ENGLISH_INDIA 713 : # define SUBLANG_ENGLISH_INDIA 0x10 714 : # endif 715 : # ifndef SUBLANG_ENGLISH_MALAYSIA 716 : # define SUBLANG_ENGLISH_MALAYSIA 0x11 717 : # endif 718 : # ifndef SUBLANG_ENGLISH_SINGAPORE 719 : # define SUBLANG_ENGLISH_SINGAPORE 0x12 720 : # endif 721 : # ifndef SUBLANG_ESTONIAN_ESTONIA 722 : # define SUBLANG_ESTONIAN_ESTONIA 0x01 723 : # endif 724 : # ifndef SUBLANG_FAEROESE_FAROE_ISLANDS 725 : # define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01 726 : # endif 727 : # ifndef SUBLANG_FARSI_IRAN 728 : # define SUBLANG_FARSI_IRAN 0x01 729 : # endif 730 : # ifndef SUBLANG_FINNISH_FINLAND 731 : # define SUBLANG_FINNISH_FINLAND 0x01 732 : # endif 733 : # ifndef SUBLANG_FRENCH_LUXEMBOURG 734 : # define SUBLANG_FRENCH_LUXEMBOURG 0x05 735 : # endif 736 : # ifndef SUBLANG_FRENCH_MONACO 737 : # define SUBLANG_FRENCH_MONACO 0x06 738 : # endif 739 : # ifndef SUBLANG_FRENCH_WESTINDIES 740 : # define SUBLANG_FRENCH_WESTINDIES 0x07 741 : # endif 742 : # ifndef SUBLANG_FRENCH_REUNION 743 : # define SUBLANG_FRENCH_REUNION 0x08 744 : # endif 745 : # ifndef SUBLANG_FRENCH_CONGO 746 : # define SUBLANG_FRENCH_CONGO 0x09 747 : # endif 748 : # ifndef SUBLANG_FRENCH_SENEGAL 749 : # define SUBLANG_FRENCH_SENEGAL 0x0a 750 : # endif 751 : # ifndef SUBLANG_FRENCH_CAMEROON 752 : # define SUBLANG_FRENCH_CAMEROON 0x0b 753 : # endif 754 : # ifndef SUBLANG_FRENCH_COTEDIVOIRE 755 : # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c 756 : # endif 757 : # ifndef SUBLANG_FRENCH_MALI 758 : # define SUBLANG_FRENCH_MALI 0x0d 759 : # endif 760 : # ifndef SUBLANG_FRENCH_MOROCCO 761 : # define SUBLANG_FRENCH_MOROCCO 0x0e 762 : # endif 763 : # ifndef SUBLANG_FRENCH_HAITI 764 : # define SUBLANG_FRENCH_HAITI 0x0f 765 : # endif 766 : # ifndef SUBLANG_FRISIAN_NETHERLANDS 767 : # define SUBLANG_FRISIAN_NETHERLANDS 0x01 768 : # endif 769 : # ifndef SUBLANG_GALICIAN_SPAIN 770 : # define SUBLANG_GALICIAN_SPAIN 0x01 771 : # endif 772 : # ifndef SUBLANG_GEORGIAN_GEORGIA 773 : # define SUBLANG_GEORGIAN_GEORGIA 0x01 774 : # endif 775 : # ifndef SUBLANG_GERMAN_LUXEMBOURG 776 : # define SUBLANG_GERMAN_LUXEMBOURG 0x04 777 : # endif 778 : # ifndef SUBLANG_GERMAN_LIECHTENSTEIN 779 : # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 780 : # endif 781 : # ifndef SUBLANG_GREEK_GREECE 782 : # define SUBLANG_GREEK_GREECE 0x01 783 : # endif 784 : # ifndef SUBLANG_GREENLANDIC_GREENLAND 785 : # define SUBLANG_GREENLANDIC_GREENLAND 0x01 786 : # endif 787 : # ifndef SUBLANG_GUJARATI_INDIA 788 : # define SUBLANG_GUJARATI_INDIA 0x01 789 : # endif 790 : # ifndef SUBLANG_HAUSA_NIGERIA_LATIN 791 : # define SUBLANG_HAUSA_NIGERIA_LATIN 0x01 792 : # endif 793 : # ifndef SUBLANG_HEBREW_ISRAEL 794 : # define SUBLANG_HEBREW_ISRAEL 0x01 795 : # endif 796 : # ifndef SUBLANG_HINDI_INDIA 797 : # define SUBLANG_HINDI_INDIA 0x01 798 : # endif 799 : # ifndef SUBLANG_HUNGARIAN_HUNGARY 800 : # define SUBLANG_HUNGARIAN_HUNGARY 0x01 801 : # endif 802 : # ifndef SUBLANG_ICELANDIC_ICELAND 803 : # define SUBLANG_ICELANDIC_ICELAND 0x01 804 : # endif 805 : # ifndef SUBLANG_IGBO_NIGERIA 806 : # define SUBLANG_IGBO_NIGERIA 0x01 807 : # endif 808 : # ifndef SUBLANG_INDONESIAN_INDONESIA 809 : # define SUBLANG_INDONESIAN_INDONESIA 0x01 810 : # endif 811 : # ifndef SUBLANG_INUKTITUT_CANADA 812 : # define SUBLANG_INUKTITUT_CANADA 0x01 813 : # endif 814 : # undef SUBLANG_INUKTITUT_CANADA_LATIN 815 : # define SUBLANG_INUKTITUT_CANADA_LATIN 0x02 816 : # undef SUBLANG_IRISH_IRELAND 817 : # define SUBLANG_IRISH_IRELAND 0x02 818 : # ifndef SUBLANG_JAPANESE_JAPAN 819 : # define SUBLANG_JAPANESE_JAPAN 0x01 820 : # endif 821 : # ifndef SUBLANG_KANNADA_INDIA 822 : # define SUBLANG_KANNADA_INDIA 0x01 823 : # endif 824 : # ifndef SUBLANG_KASHMIRI_INDIA 825 : # define SUBLANG_KASHMIRI_INDIA 0x02 826 : # endif 827 : # ifndef SUBLANG_KAZAK_KAZAKHSTAN 828 : # define SUBLANG_KAZAK_KAZAKHSTAN 0x01 829 : # endif 830 : # ifndef SUBLANG_KICHE_GUATEMALA 831 : # define SUBLANG_KICHE_GUATEMALA 0x01 832 : # endif 833 : # ifndef SUBLANG_KINYARWANDA_RWANDA 834 : # define SUBLANG_KINYARWANDA_RWANDA 0x01 835 : # endif 836 : # ifndef SUBLANG_KONKANI_INDIA 837 : # define SUBLANG_KONKANI_INDIA 0x01 838 : # endif 839 : # ifndef SUBLANG_KYRGYZ_KYRGYZSTAN 840 : # define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01 841 : # endif 842 : # ifndef SUBLANG_LAO_LAOS 843 : # define SUBLANG_LAO_LAOS 0x01 844 : # endif 845 : # ifndef SUBLANG_LATVIAN_LATVIA 846 : # define SUBLANG_LATVIAN_LATVIA 0x01 847 : # endif 848 : # ifndef SUBLANG_LITHUANIAN_LITHUANIA 849 : # define SUBLANG_LITHUANIAN_LITHUANIA 0x01 850 : # endif 851 : # undef SUBLANG_LOWER_SORBIAN_GERMANY 852 : # define SUBLANG_LOWER_SORBIAN_GERMANY 0x02 853 : # ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG 854 : # define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01 855 : # endif 856 : # ifndef SUBLANG_MACEDONIAN_MACEDONIA 857 : # define SUBLANG_MACEDONIAN_MACEDONIA 0x01 858 : # endif 859 : # ifndef SUBLANG_MALAY_MALAYSIA 860 : # define SUBLANG_MALAY_MALAYSIA 0x01 861 : # endif 862 : # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM 863 : # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 864 : # endif 865 : # ifndef SUBLANG_MALAYALAM_INDIA 866 : # define SUBLANG_MALAYALAM_INDIA 0x01 867 : # endif 868 : # ifndef SUBLANG_MALTESE_MALTA 869 : # define SUBLANG_MALTESE_MALTA 0x01 870 : # endif 871 : # ifndef SUBLANG_MAORI_NEW_ZEALAND 872 : # define SUBLANG_MAORI_NEW_ZEALAND 0x01 873 : # endif 874 : # ifndef SUBLANG_MAPUDUNGUN_CHILE 875 : # define SUBLANG_MAPUDUNGUN_CHILE 0x01 876 : # endif 877 : # ifndef SUBLANG_MARATHI_INDIA 878 : # define SUBLANG_MARATHI_INDIA 0x01 879 : # endif 880 : # ifndef SUBLANG_MOHAWK_CANADA 881 : # define SUBLANG_MOHAWK_CANADA 0x01 882 : # endif 883 : # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 884 : # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01 885 : # endif 886 : # ifndef SUBLANG_MONGOLIAN_PRC 887 : # define SUBLANG_MONGOLIAN_PRC 0x02 888 : # endif 889 : # ifndef SUBLANG_NEPALI_NEPAL 890 : # define SUBLANG_NEPALI_NEPAL 0x01 891 : # endif 892 : # ifndef SUBLANG_NEPALI_INDIA 893 : # define SUBLANG_NEPALI_INDIA 0x02 894 : # endif 895 : # ifndef SUBLANG_OCCITAN_FRANCE 896 : # define SUBLANG_OCCITAN_FRANCE 0x01 897 : # endif 898 : # ifndef SUBLANG_ORIYA_INDIA 899 : # define SUBLANG_ORIYA_INDIA 0x01 900 : # endif 901 : # ifndef SUBLANG_PASHTO_AFGHANISTAN 902 : # define SUBLANG_PASHTO_AFGHANISTAN 0x01 903 : # endif 904 : # ifndef SUBLANG_POLISH_POLAND 905 : # define SUBLANG_POLISH_POLAND 0x01 906 : # endif 907 : # ifndef SUBLANG_PUNJABI_INDIA 908 : # define SUBLANG_PUNJABI_INDIA 0x01 909 : # endif 910 : # ifndef SUBLANG_PUNJABI_PAKISTAN 911 : # define SUBLANG_PUNJABI_PAKISTAN 0x02 912 : # endif 913 : # ifndef SUBLANG_QUECHUA_BOLIVIA 914 : # define SUBLANG_QUECHUA_BOLIVIA 0x01 915 : # endif 916 : # ifndef SUBLANG_QUECHUA_ECUADOR 917 : # define SUBLANG_QUECHUA_ECUADOR 0x02 918 : # endif 919 : # ifndef SUBLANG_QUECHUA_PERU 920 : # define SUBLANG_QUECHUA_PERU 0x03 921 : # endif 922 : # ifndef SUBLANG_ROMANIAN_ROMANIA 923 : # define SUBLANG_ROMANIAN_ROMANIA 0x01 924 : # endif 925 : # ifndef SUBLANG_ROMANIAN_MOLDOVA 926 : # define SUBLANG_ROMANIAN_MOLDOVA 0x02 927 : # endif 928 : # ifndef SUBLANG_ROMANSH_SWITZERLAND 929 : # define SUBLANG_ROMANSH_SWITZERLAND 0x01 930 : # endif 931 : # ifndef SUBLANG_RUSSIAN_RUSSIA 932 : # define SUBLANG_RUSSIAN_RUSSIA 0x01 933 : # endif 934 : # ifndef SUBLANG_RUSSIAN_MOLDAVIA 935 : # define SUBLANG_RUSSIAN_MOLDAVIA 0x02 936 : # endif 937 : # ifndef SUBLANG_SAMI_NORTHERN_NORWAY 938 : # define SUBLANG_SAMI_NORTHERN_NORWAY 0x01 939 : # endif 940 : # ifndef SUBLANG_SAMI_NORTHERN_SWEDEN 941 : # define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02 942 : # endif 943 : # ifndef SUBLANG_SAMI_NORTHERN_FINLAND 944 : # define SUBLANG_SAMI_NORTHERN_FINLAND 0x03 945 : # endif 946 : # ifndef SUBLANG_SAMI_LULE_NORWAY 947 : # define SUBLANG_SAMI_LULE_NORWAY 0x04 948 : # endif 949 : # ifndef SUBLANG_SAMI_LULE_SWEDEN 950 : # define SUBLANG_SAMI_LULE_SWEDEN 0x05 951 : # endif 952 : # ifndef SUBLANG_SAMI_SOUTHERN_NORWAY 953 : # define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06 954 : # endif 955 : # ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN 956 : # define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07 957 : # endif 958 : # undef SUBLANG_SAMI_SKOLT_FINLAND 959 : # define SUBLANG_SAMI_SKOLT_FINLAND 0x08 960 : # undef SUBLANG_SAMI_INARI_FINLAND 961 : # define SUBLANG_SAMI_INARI_FINLAND 0x09 962 : # ifndef SUBLANG_SANSKRIT_INDIA 963 : # define SUBLANG_SANSKRIT_INDIA 0x01 964 : # endif 965 : # ifndef SUBLANG_SERBIAN_LATIN 966 : # define SUBLANG_SERBIAN_LATIN 0x02 967 : # endif 968 : # ifndef SUBLANG_SERBIAN_CYRILLIC 969 : # define SUBLANG_SERBIAN_CYRILLIC 0x03 970 : # endif 971 : # ifndef SUBLANG_SINDHI_INDIA 972 : # define SUBLANG_SINDHI_INDIA 0x01 973 : # endif 974 : # undef SUBLANG_SINDHI_PAKISTAN 975 : # define SUBLANG_SINDHI_PAKISTAN 0x02 976 : # ifndef SUBLANG_SINDHI_AFGHANISTAN 977 : # define SUBLANG_SINDHI_AFGHANISTAN 0x02 978 : # endif 979 : # ifndef SUBLANG_SINHALESE_SRI_LANKA 980 : # define SUBLANG_SINHALESE_SRI_LANKA 0x01 981 : # endif 982 : # ifndef SUBLANG_SLOVAK_SLOVAKIA 983 : # define SUBLANG_SLOVAK_SLOVAKIA 0x01 984 : # endif 985 : # ifndef SUBLANG_SLOVENIAN_SLOVENIA 986 : # define SUBLANG_SLOVENIAN_SLOVENIA 0x01 987 : # endif 988 : # ifndef SUBLANG_SOTHO_SOUTH_AFRICA 989 : # define SUBLANG_SOTHO_SOUTH_AFRICA 0x01 990 : # endif 991 : # ifndef SUBLANG_SPANISH_GUATEMALA 992 : # define SUBLANG_SPANISH_GUATEMALA 0x04 993 : # endif 994 : # ifndef SUBLANG_SPANISH_COSTA_RICA 995 : # define SUBLANG_SPANISH_COSTA_RICA 0x05 996 : # endif 997 : # ifndef SUBLANG_SPANISH_PANAMA 998 : # define SUBLANG_SPANISH_PANAMA 0x06 999 : # endif 1000 : # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC 1001 : # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 1002 : # endif 1003 : # ifndef SUBLANG_SPANISH_VENEZUELA 1004 : # define SUBLANG_SPANISH_VENEZUELA 0x08 1005 : # endif 1006 : # ifndef SUBLANG_SPANISH_COLOMBIA 1007 : # define SUBLANG_SPANISH_COLOMBIA 0x09 1008 : # endif 1009 : # ifndef SUBLANG_SPANISH_PERU 1010 : # define SUBLANG_SPANISH_PERU 0x0a 1011 : # endif 1012 : # ifndef SUBLANG_SPANISH_ARGENTINA 1013 : # define SUBLANG_SPANISH_ARGENTINA 0x0b 1014 : # endif 1015 : # ifndef SUBLANG_SPANISH_ECUADOR 1016 : # define SUBLANG_SPANISH_ECUADOR 0x0c 1017 : # endif 1018 : # ifndef SUBLANG_SPANISH_CHILE 1019 : # define SUBLANG_SPANISH_CHILE 0x0d 1020 : # endif 1021 : # ifndef SUBLANG_SPANISH_URUGUAY 1022 : # define SUBLANG_SPANISH_URUGUAY 0x0e 1023 : # endif 1024 : # ifndef SUBLANG_SPANISH_PARAGUAY 1025 : # define SUBLANG_SPANISH_PARAGUAY 0x0f 1026 : # endif 1027 : # ifndef SUBLANG_SPANISH_BOLIVIA 1028 : # define SUBLANG_SPANISH_BOLIVIA 0x10 1029 : # endif 1030 : # ifndef SUBLANG_SPANISH_EL_SALVADOR 1031 : # define SUBLANG_SPANISH_EL_SALVADOR 0x11 1032 : # endif 1033 : # ifndef SUBLANG_SPANISH_HONDURAS 1034 : # define SUBLANG_SPANISH_HONDURAS 0x12 1035 : # endif 1036 : # ifndef SUBLANG_SPANISH_NICARAGUA 1037 : # define SUBLANG_SPANISH_NICARAGUA 0x13 1038 : # endif 1039 : # ifndef SUBLANG_SPANISH_PUERTO_RICO 1040 : # define SUBLANG_SPANISH_PUERTO_RICO 0x14 1041 : # endif 1042 : # ifndef SUBLANG_SPANISH_US 1043 : # define SUBLANG_SPANISH_US 0x15 1044 : # endif 1045 : # ifndef SUBLANG_SWAHILI_KENYA 1046 : # define SUBLANG_SWAHILI_KENYA 0x01 1047 : # endif 1048 : # ifndef SUBLANG_SWEDISH_SWEDEN 1049 : # define SUBLANG_SWEDISH_SWEDEN 0x01 1050 : # endif 1051 : # ifndef SUBLANG_SWEDISH_FINLAND 1052 : # define SUBLANG_SWEDISH_FINLAND 0x02 1053 : # endif 1054 : # ifndef SUBLANG_SYRIAC_SYRIA 1055 : # define SUBLANG_SYRIAC_SYRIA 0x01 1056 : # endif 1057 : # ifndef SUBLANG_TAGALOG_PHILIPPINES 1058 : # define SUBLANG_TAGALOG_PHILIPPINES 0x01 1059 : # endif 1060 : # ifndef SUBLANG_TAJIK_TAJIKISTAN 1061 : # define SUBLANG_TAJIK_TAJIKISTAN 0x01 1062 : # endif 1063 : # ifndef SUBLANG_TAMAZIGHT_ARABIC 1064 : # define SUBLANG_TAMAZIGHT_ARABIC 0x01 1065 : # endif 1066 : # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN 1067 : # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02 1068 : # endif 1069 : # ifndef SUBLANG_TAMIL_INDIA 1070 : # define SUBLANG_TAMIL_INDIA 0x01 1071 : # endif 1072 : # ifndef SUBLANG_TATAR_RUSSIA 1073 : # define SUBLANG_TATAR_RUSSIA 0x01 1074 : # endif 1075 : # ifndef SUBLANG_TELUGU_INDIA 1076 : # define SUBLANG_TELUGU_INDIA 0x01 1077 : # endif 1078 : # ifndef SUBLANG_THAI_THAILAND 1079 : # define SUBLANG_THAI_THAILAND 0x01 1080 : # endif 1081 : # ifndef SUBLANG_TIBETAN_PRC 1082 : # define SUBLANG_TIBETAN_PRC 0x01 1083 : # endif 1084 : # undef SUBLANG_TIBETAN_BHUTAN 1085 : # define SUBLANG_TIBETAN_BHUTAN 0x02 1086 : # ifndef SUBLANG_TIGRINYA_ETHIOPIA 1087 : # define SUBLANG_TIGRINYA_ETHIOPIA 0x01 1088 : # endif 1089 : # ifndef SUBLANG_TIGRINYA_ERITREA 1090 : # define SUBLANG_TIGRINYA_ERITREA 0x02 1091 : # endif 1092 : # ifndef SUBLANG_TSWANA_SOUTH_AFRICA 1093 : # define SUBLANG_TSWANA_SOUTH_AFRICA 0x01 1094 : # endif 1095 : # ifndef SUBLANG_TURKISH_TURKEY 1096 : # define SUBLANG_TURKISH_TURKEY 0x01 1097 : # endif 1098 : # ifndef SUBLANG_TURKMEN_TURKMENISTAN 1099 : # define SUBLANG_TURKMEN_TURKMENISTAN 0x01 1100 : # endif 1101 : # ifndef SUBLANG_UIGHUR_PRC 1102 : # define SUBLANG_UIGHUR_PRC 0x01 1103 : # endif 1104 : # ifndef SUBLANG_UKRAINIAN_UKRAINE 1105 : # define SUBLANG_UKRAINIAN_UKRAINE 0x01 1106 : # endif 1107 : # ifndef SUBLANG_UPPER_SORBIAN_GERMANY 1108 : # define SUBLANG_UPPER_SORBIAN_GERMANY 0x01 1109 : # endif 1110 : # ifndef SUBLANG_URDU_PAKISTAN 1111 : # define SUBLANG_URDU_PAKISTAN 0x01 1112 : # endif 1113 : # ifndef SUBLANG_URDU_INDIA 1114 : # define SUBLANG_URDU_INDIA 0x02 1115 : # endif 1116 : # ifndef SUBLANG_UZBEK_LATIN 1117 : # define SUBLANG_UZBEK_LATIN 0x01 1118 : # endif 1119 : # ifndef SUBLANG_UZBEK_CYRILLIC 1120 : # define SUBLANG_UZBEK_CYRILLIC 0x02 1121 : # endif 1122 : # ifndef SUBLANG_VIETNAMESE_VIETNAM 1123 : # define SUBLANG_VIETNAMESE_VIETNAM 0x01 1124 : # endif 1125 : # ifndef SUBLANG_WELSH_UNITED_KINGDOM 1126 : # define SUBLANG_WELSH_UNITED_KINGDOM 0x01 1127 : # endif 1128 : # ifndef SUBLANG_WOLOF_SENEGAL 1129 : # define SUBLANG_WOLOF_SENEGAL 0x01 1130 : # endif 1131 : # ifndef SUBLANG_XHOSA_SOUTH_AFRICA 1132 : # define SUBLANG_XHOSA_SOUTH_AFRICA 0x01 1133 : # endif 1134 : # ifndef SUBLANG_YAKUT_RUSSIA 1135 : # define SUBLANG_YAKUT_RUSSIA 0x01 1136 : # endif 1137 : # ifndef SUBLANG_YI_PRC 1138 : # define SUBLANG_YI_PRC 0x01 1139 : # endif 1140 : # ifndef SUBLANG_YORUBA_NIGERIA 1141 : # define SUBLANG_YORUBA_NIGERIA 0x01 1142 : # endif 1143 : # ifndef SUBLANG_ZULU_SOUTH_AFRICA 1144 : # define SUBLANG_ZULU_SOUTH_AFRICA 0x01 1145 : # endif 1146 : /* GetLocaleInfoA operations. */ 1147 : # ifndef LOCALE_SNAME 1148 : # define LOCALE_SNAME 0x5c 1149 : # endif 1150 : # ifndef LOCALE_NAME_MAX_LENGTH 1151 : # define LOCALE_NAME_MAX_LENGTH 85 1152 : # endif 1153 : /* Don't assume that UNICODE is not defined. */ 1154 : # undef GetLocaleInfo 1155 : # define GetLocaleInfo GetLocaleInfoA 1156 : # undef EnumSystemLocales 1157 : # define EnumSystemLocales EnumSystemLocalesA 1158 : #endif 1159 : 1160 : /* We want to use the system's setlocale() function here, not the gnulib 1161 : override. */ 1162 : #undef setlocale 1163 : 1164 : 1165 : #if HAVE_CFPREFERENCESCOPYAPPVALUE 1166 : /* Mac OS X 10.4 or newer */ 1167 : 1168 : /* Canonicalize a Mac OS X locale name to a Unix locale name. 1169 : NAME is a sufficiently large buffer. 1170 : On input, it contains the Mac OS X locale name. 1171 : On output, it contains the Unix locale name. */ 1172 : # if !defined IN_LIBINTL 1173 : static 1174 : # endif 1175 : void 1176 : gl_locale_name_canonicalize (char *name) 1177 : { 1178 : /* This conversion is based on a posting by 1179 : Deborah GoldSmith <goldsmit@apple.com> on 2005年03月08日, 1180 : https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */ 1181 : 1182 : /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and 1183 : ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this. 1184 : Therefore we do it ourselves, using a table based on the results of the 1185 : Mac OS X 10.3.8 function 1186 : CFLocaleCreateCanonicalLocaleIdentifierFromString(). */ 1187 : typedef struct { const char legacy[21+1]; const char unixy[5+1]; } 1188 : legacy_entry; 1189 : static const legacy_entry legacy_table[] = { 1190 : { "Afrikaans", "af" }, 1191 : { "Albanian", "sq" }, 1192 : { "Amharic", "am" }, 1193 : { "Arabic", "ar" }, 1194 : { "Armenian", "hy" }, 1195 : { "Assamese", "as" }, 1196 : { "Aymara", "ay" }, 1197 : { "Azerbaijani", "az" }, 1198 : { "Basque", "eu" }, 1199 : { "Belarusian", "be" }, 1200 : { "Belorussian", "be" }, 1201 : { "Bengali", "bn" }, 1202 : { "Brazilian Portugese", "pt_BR" }, 1203 : { "Brazilian Portuguese", "pt_BR" }, 1204 : { "Breton", "br" }, 1205 : { "Bulgarian", "bg" }, 1206 : { "Burmese", "my" }, 1207 : { "Byelorussian", "be" }, 1208 : { "Catalan", "ca" }, 1209 : { "Chewa", "ny" }, 1210 : { "Chichewa", "ny" }, 1211 : { "Chinese", "zh" }, 1212 : { "Chinese, Simplified", "zh_CN" }, 1213 : { "Chinese, Traditional", "zh_TW" }, 1214 : { "Chinese, Tradtional", "zh_TW" }, 1215 : { "Croatian", "hr" }, 1216 : { "Czech", "cs" }, 1217 : { "Danish", "da" }, 1218 : { "Dutch", "nl" }, 1219 : { "Dzongkha", "dz" }, 1220 : { "English", "en" }, 1221 : { "Esperanto", "eo" }, 1222 : { "Estonian", "et" }, 1223 : { "Faroese", "fo" }, 1224 : { "Farsi", "fa" }, 1225 : { "Finnish", "fi" }, 1226 : { "Flemish", "nl_BE" }, 1227 : { "French", "fr" }, 1228 : { "Galician", "gl" }, 1229 : { "Gallegan", "gl" }, 1230 : { "Georgian", "ka" }, 1231 : { "German", "de" }, 1232 : { "Greek", "el" }, 1233 : { "Greenlandic", "kl" }, 1234 : { "Guarani", "gn" }, 1235 : { "Gujarati", "gu" }, 1236 : { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */ 1237 : { "Hebrew", "he" }, 1238 : { "Hindi", "hi" }, 1239 : { "Hungarian", "hu" }, 1240 : { "Icelandic", "is" }, 1241 : { "Indonesian", "id" }, 1242 : { "Inuktitut", "iu" }, 1243 : { "Irish", "ga" }, 1244 : { "Italian", "it" }, 1245 : { "Japanese", "ja" }, 1246 : { "Javanese", "jv" }, 1247 : { "Kalaallisut", "kl" }, 1248 : { "Kannada", "kn" }, 1249 : { "Kashmiri", "ks" }, 1250 : { "Kazakh", "kk" }, 1251 : { "Khmer", "km" }, 1252 : { "Kinyarwanda", "rw" }, 1253 : { "Kirghiz", "ky" }, 1254 : { "Korean", "ko" }, 1255 : { "Kurdish", "ku" }, 1256 : { "Latin", "la" }, 1257 : { "Latvian", "lv" }, 1258 : { "Lithuanian", "lt" }, 1259 : { "Macedonian", "mk" }, 1260 : { "Malagasy", "mg" }, 1261 : { "Malay", "ms" }, 1262 : { "Malayalam", "ml" }, 1263 : { "Maltese", "mt" }, 1264 : { "Manx", "gv" }, 1265 : { "Marathi", "mr" }, 1266 : { "Moldavian", "mo" }, 1267 : { "Mongolian", "mn" }, 1268 : { "Nepali", "ne" }, 1269 : { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */ 1270 : { "Nyanja", "ny" }, 1271 : { "Nynorsk", "nn" }, 1272 : { "Oriya", "or" }, 1273 : { "Oromo", "om" }, 1274 : { "Panjabi", "pa" }, 1275 : { "Pashto", "ps" }, 1276 : { "Persian", "fa" }, 1277 : { "Polish", "pl" }, 1278 : { "Portuguese", "pt" }, 1279 : { "Portuguese, Brazilian", "pt_BR" }, 1280 : { "Punjabi", "pa" }, 1281 : { "Pushto", "ps" }, 1282 : { "Quechua", "qu" }, 1283 : { "Romanian", "ro" }, 1284 : { "Ruanda", "rw" }, 1285 : { "Rundi", "rn" }, 1286 : { "Russian", "ru" }, 1287 : { "Sami", "se_NO" }, /* Not just "se". */ 1288 : { "Sanskrit", "sa" }, 1289 : { "Scottish", "gd" }, 1290 : { "Serbian", "sr" }, 1291 : { "Simplified Chinese", "zh_CN" }, 1292 : { "Sindhi", "sd" }, 1293 : { "Sinhalese", "si" }, 1294 : { "Slovak", "sk" }, 1295 : { "Slovenian", "sl" }, 1296 : { "Somali", "so" }, 1297 : { "Spanish", "es" }, 1298 : { "Sundanese", "su" }, 1299 : { "Swahili", "sw" }, 1300 : { "Swedish", "sv" }, 1301 : { "Tagalog", "tl" }, 1302 : { "Tajik", "tg" }, 1303 : { "Tajiki", "tg" }, 1304 : { "Tamil", "ta" }, 1305 : { "Tatar", "tt" }, 1306 : { "Telugu", "te" }, 1307 : { "Thai", "th" }, 1308 : { "Tibetan", "bo" }, 1309 : { "Tigrinya", "ti" }, 1310 : { "Tongan", "to" }, 1311 : { "Traditional Chinese", "zh_TW" }, 1312 : { "Turkish", "tr" }, 1313 : { "Turkmen", "tk" }, 1314 : { "Uighur", "ug" }, 1315 : { "Ukrainian", "uk" }, 1316 : { "Urdu", "ur" }, 1317 : { "Uzbek", "uz" }, 1318 : { "Vietnamese", "vi" }, 1319 : { "Welsh", "cy" }, 1320 : { "Yiddish", "yi" } 1321 : }; 1322 : 1323 : /* Convert new-style locale names with language tags (ISO 639 and ISO 15924) 1324 : to Unix (ISO 639 and ISO 3166) names. */ 1325 : typedef struct { const char langtag[7+1]; const char unixy[12+1]; } 1326 : langtag_entry; 1327 : static const langtag_entry langtag_table[] = { 1328 : /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn". 1329 : The default script for az on Unix is Latin. */ 1330 : { "az-Latn", "az" }, 1331 : /* Mac OS X has "bs-Cyrl", "bs-Latn". 1332 : The default script for bs on Unix is Latin. */ 1333 : { "bs-Latn", "bs" }, 1334 : /* Mac OS X has "ga-dots". Does not yet exist on Unix. */ 1335 : { "ga-dots", "ga" }, 1336 : /* Mac OS X has "kk-Cyrl". 1337 : The default script for kk on Unix is Cyrillic. */ 1338 : { "kk-Cyrl", "kk" }, 1339 : /* Mac OS X has "mn-Cyrl", "mn-Mong". 1340 : The default script for mn on Unix is Cyrillic. */ 1341 : { "mn-Cyrl", "mn" }, 1342 : /* Mac OS X has "ms-Arab", "ms-Latn". 1343 : The default script for ms on Unix is Latin. */ 1344 : { "ms-Latn", "ms" }, 1345 : /* Mac OS X has "pa-Arab", "pa-Guru". 1346 : Country codes are used to distinguish these on Unix. */ 1347 : { "pa-Arab", "pa_PK" }, 1348 : { "pa-Guru", "pa_IN" }, 1349 : /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */ 1350 : /* Mac OS X has "sr-Cyrl", "sr-Latn". 1351 : The default script for sr on Unix is Cyrillic. */ 1352 : { "sr-Cyrl", "sr" }, 1353 : /* Mac OS X has "tg-Cyrl". 1354 : The default script for tg on Unix is Cyrillic. */ 1355 : { "tg-Cyrl", "tg" }, 1356 : /* Mac OS X has "tk-Cyrl". 1357 : The default script for tk on Unix is Cyrillic. */ 1358 : { "tk-Cyrl", "tk" }, 1359 : /* Mac OS X has "tt-Cyrl". 1360 : The default script for tt on Unix is Cyrillic. */ 1361 : { "tt-Cyrl", "tt" }, 1362 : /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn". 1363 : The default script for uz on Unix is Latin. */ 1364 : { "uz-Latn", "uz" }, 1365 : /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */ 1366 : /* Mac OS X has "yue-Hans", "yue-Hant". 1367 : The default script for yue on Unix is Simplified Han. */ 1368 : { "yue-Hans", "yue" }, 1369 : /* Mac OS X has "zh-Hans", "zh-Hant". 1370 : Country codes are used to distinguish these on Unix. */ 1371 : { "zh-Hans", "zh_CN" }, 1372 : { "zh-Hant", "zh_TW" } 1373 : }; 1374 : 1375 : /* Convert script names (ISO 15924) to Unix conventions. 1376 : See https://www.unicode.org/iso15924/iso15924-codes.html */ 1377 : typedef struct { const char script[4+1]; const char unixy[9+1]; } 1378 : script_entry; 1379 : static const script_entry script_table[] = { 1380 : { "Arab", "arabic" }, 1381 : { "Cyrl", "cyrillic" }, 1382 : { "Latn", "latin" }, 1383 : { "Mong", "mongolian" } 1384 : }; 1385 : 1386 : /* Step 1: Convert using legacy_table. */ 1387 : if (name[0] >= 'A' && name[0] <= 'Z') 1388 : { 1389 : unsigned int i1, i2; 1390 : i1 = 0; 1391 : i2 = sizeof (legacy_table) / sizeof (legacy_entry); 1392 : while (i2 - i1 > 1) 1393 : { 1394 : /* At this point we know that if name occurs in legacy_table, 1395 : its index must be >= i1 and < i2. */ 1396 : unsigned int i = (i1 + i2) >> 1; 1397 : const legacy_entry *p = &legacy_table[i]; 1398 : if (strcmp (name, p->legacy) < 0) 1399 : i2 = i; 1400 : else 1401 : i1 = i; 1402 : } 1403 : if (strcmp (name, legacy_table[i1].legacy) == 0) 1404 : { 1405 : strcpy (name, legacy_table[i1].unixy); 1406 : return; 1407 : } 1408 : } 1409 : 1410 : /* Step 2: Convert using langtag_table and script_table. */ 1411 : if (strlen (name) == 7 && name[2] == '-') 1412 : { 1413 : unsigned int i1, i2; 1414 : i1 = 0; 1415 : i2 = sizeof (langtag_table) / sizeof (langtag_entry); 1416 : while (i2 - i1 > 1) 1417 : { 1418 : /* At this point we know that if name occurs in langtag_table, 1419 : its index must be >= i1 and < i2. */ 1420 : unsigned int i = (i1 + i2) >> 1; 1421 : const langtag_entry *p = &langtag_table[i]; 1422 : if (strcmp (name, p->langtag) < 0) 1423 : i2 = i; 1424 : else 1425 : i1 = i; 1426 : } 1427 : if (strcmp (name, langtag_table[i1].langtag) == 0) 1428 : { 1429 : strcpy (name, langtag_table[i1].unixy); 1430 : return; 1431 : } 1432 : 1433 : i1 = 0; 1434 : i2 = sizeof (script_table) / sizeof (script_entry); 1435 : while (i2 - i1 > 1) 1436 : { 1437 : /* At this point we know that if (name + 3) occurs in script_table, 1438 : its index must be >= i1 and < i2. */ 1439 : unsigned int i = (i1 + i2) >> 1; 1440 : const script_entry *p = &script_table[i]; 1441 : if (strcmp (name + 3, p->script) < 0) 1442 : i2 = i; 1443 : else 1444 : i1 = i; 1445 : } 1446 : if (strcmp (name + 3, script_table[i1].script) == 0) 1447 : { 1448 : name[2] = '@'; 1449 : strcpy (name + 3, script_table[i1].unixy); 1450 : return; 1451 : } 1452 : } 1453 : 1454 : /* Step 3: Convert new-style dash to Unix underscore. */ 1455 : { 1456 : char *p; 1457 : for (p = name; *p != '0円'; p++) 1458 : if (*p == '-') 1459 : *p = '_'; 1460 : } 1461 : } 1462 : 1463 : #endif 1464 : 1465 : 1466 : #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */ 1467 : 1468 : /* Canonicalize a Windows native locale name to a Unix locale name. 1469 : NAME is a sufficiently large buffer. 1470 : On input, it contains the Windows locale name. 1471 : On output, it contains the Unix locale name. */ 1472 : # if !defined IN_LIBINTL 1473 : static 1474 : # endif 1475 : void 1476 : gl_locale_name_canonicalize (char *name) 1477 : { 1478 : /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and 1479 : "zh-Hant". */ 1480 : char *p; 1481 : 1482 : for (p = name; *p != '0円'; p++) 1483 : if (*p == '-') 1484 : { 1485 : *p = '_'; 1486 : p++; 1487 : for (; *p != '0円'; p++) 1488 : { 1489 : if (*p >= 'a' && *p <= 'z') 1490 : *p += 'A' - 'a'; 1491 : if (*p == '-') 1492 : { 1493 : *p = '0円'; 1494 : return; 1495 : } 1496 : } 1497 : return; 1498 : } 1499 : } 1500 : 1501 : # if !defined IN_LIBINTL 1502 : static 1503 : # endif 1504 : const char * 1505 : gl_locale_name_from_win32_LANGID (LANGID langid) 1506 : { 1507 : /* Activate the new code only when the GETTEXT_MUI environment variable is 1508 : set, for the time being, since the new code is not well tested. */ 1509 : if (getenv ("GETTEXT_MUI") != NULL) 1510 : { 1511 : static char namebuf[256]; 1512 : 1513 : /* Query the system's notion of locale name. 1514 : On Windows95/98/ME, GetLocaleInfoA returns some incorrect results. 1515 : But we don't need to support systems that are so old. */ 1516 : if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME, 1517 : namebuf, sizeof (namebuf) - 1)) 1518 : { 1519 : /* Convert it to a Unix locale name. */ 1520 : gl_locale_name_canonicalize (namebuf); 1521 : return namebuf; 1522 : } 1523 : } 1524 : /* Internet Explorer has an LCID to RFC3066 name mapping stored in 1525 : HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that 1526 : since IE's i18n subsystem is known to be inconsistent with the native 1527 : Windows base (e.g. they have different character conversion facilities 1528 : that produce different results). */ 1529 : /* Use our own table. */ 1530 : { 1531 : int primary, sub; 1532 : 1533 : /* Split into language and territory part. */ 1534 : primary = PRIMARYLANGID (langid); 1535 : sub = SUBLANGID (langid); 1536 : 1537 : /* Dispatch on language. 1538 : See also https://www.unicode.org/unicode/onlinedat/languages.html . 1539 : For details about languages, see https://www.ethnologue.com/ . */ 1540 : switch (primary) 1541 : { 1542 : case LANG_AFRIKAANS: 1543 : switch (sub) 1544 : { 1545 : case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA"; 1546 : } 1547 : return "af"; 1548 : case LANG_ALBANIAN: 1549 : switch (sub) 1550 : { 1551 : case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL"; 1552 : } 1553 : return "sq"; 1554 : case LANG_ALSATIAN: 1555 : switch (sub) 1556 : { 1557 : case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR"; 1558 : } 1559 : return "gsw"; 1560 : case LANG_AMHARIC: 1561 : switch (sub) 1562 : { 1563 : case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET"; 1564 : } 1565 : return "am"; 1566 : case LANG_ARABIC: 1567 : switch (sub) 1568 : { 1569 : case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA"; 1570 : case SUBLANG_ARABIC_IRAQ: return "ar_IQ"; 1571 : case SUBLANG_ARABIC_EGYPT: return "ar_EG"; 1572 : case SUBLANG_ARABIC_LIBYA: return "ar_LY"; 1573 : case SUBLANG_ARABIC_ALGERIA: return "ar_DZ"; 1574 : case SUBLANG_ARABIC_MOROCCO: return "ar_MA"; 1575 : case SUBLANG_ARABIC_TUNISIA: return "ar_TN"; 1576 : case SUBLANG_ARABIC_OMAN: return "ar_OM"; 1577 : case SUBLANG_ARABIC_YEMEN: return "ar_YE"; 1578 : case SUBLANG_ARABIC_SYRIA: return "ar_SY"; 1579 : case SUBLANG_ARABIC_JORDAN: return "ar_JO"; 1580 : case SUBLANG_ARABIC_LEBANON: return "ar_LB"; 1581 : case SUBLANG_ARABIC_KUWAIT: return "ar_KW"; 1582 : case SUBLANG_ARABIC_UAE: return "ar_AE"; 1583 : case SUBLANG_ARABIC_BAHRAIN: return "ar_BH"; 1584 : case SUBLANG_ARABIC_QATAR: return "ar_QA"; 1585 : } 1586 : return "ar"; 1587 : case LANG_ARMENIAN: 1588 : switch (sub) 1589 : { 1590 : case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM"; 1591 : } 1592 : return "hy"; 1593 : case LANG_ASSAMESE: 1594 : switch (sub) 1595 : { 1596 : case SUBLANG_ASSAMESE_INDIA: return "as_IN"; 1597 : } 1598 : return "as"; 1599 : case LANG_AZERI: 1600 : switch (sub) 1601 : { 1602 : /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ 1603 : case 0x1e: return "az@latin"; 1604 : case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; 1605 : case 0x1d: return "az@cyrillic"; 1606 : case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; 1607 : } 1608 : return "az"; 1609 : case LANG_BASHKIR: 1610 : switch (sub) 1611 : { 1612 : case SUBLANG_BASHKIR_RUSSIA: return "ba_RU"; 1613 : } 1614 : return "ba"; 1615 : case LANG_BASQUE: 1616 : switch (sub) 1617 : { 1618 : case SUBLANG_BASQUE_BASQUE: return "eu_ES"; 1619 : } 1620 : return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ 1621 : case LANG_BELARUSIAN: 1622 : switch (sub) 1623 : { 1624 : case SUBLANG_BELARUSIAN_BELARUS: return "be_BY"; 1625 : } 1626 : return "be"; 1627 : case LANG_BENGALI: 1628 : switch (sub) 1629 : { 1630 : case SUBLANG_BENGALI_INDIA: return "bn_IN"; 1631 : case SUBLANG_BENGALI_BANGLADESH: return "bn_BD"; 1632 : } 1633 : return "bn"; 1634 : case LANG_BRETON: 1635 : switch (sub) 1636 : { 1637 : case SUBLANG_BRETON_FRANCE: return "br_FR"; 1638 : } 1639 : return "br"; 1640 : case LANG_BULGARIAN: 1641 : switch (sub) 1642 : { 1643 : case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG"; 1644 : } 1645 : return "bg"; 1646 : case LANG_BURMESE: 1647 : switch (sub) 1648 : { 1649 : case SUBLANG_DEFAULT: return "my_MM"; 1650 : } 1651 : return "my"; 1652 : case LANG_CAMBODIAN: 1653 : switch (sub) 1654 : { 1655 : case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH"; 1656 : } 1657 : return "km"; 1658 : case LANG_CATALAN: 1659 : switch (sub) 1660 : { 1661 : case SUBLANG_CATALAN_SPAIN: return "ca_ES"; 1662 : } 1663 : return "ca"; 1664 : case LANG_CHEROKEE: 1665 : switch (sub) 1666 : { 1667 : case SUBLANG_DEFAULT: return "chr_US"; 1668 : } 1669 : return "chr"; 1670 : case LANG_CHINESE: 1671 : switch (sub) 1672 : { 1673 : case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW"; 1674 : case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN"; 1675 : case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */ 1676 : case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */ 1677 : case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */ 1678 : } 1679 : return "zh"; 1680 : case LANG_CORSICAN: 1681 : switch (sub) 1682 : { 1683 : case SUBLANG_CORSICAN_FRANCE: return "co_FR"; 1684 : } 1685 : return "co"; 1686 : case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN 1687 : * What used to be called Serbo-Croatian 1688 : * should really now be two separate 1689 : * languages because of political reasons. 1690 : * (Says tml, who knows nothing about Serbian 1691 : * or Croatian.) 1692 : * (I can feel those flames coming already.) 1693 : */ 1694 : switch (sub) 1695 : { 1696 : /* Croatian */ 1697 : case 0x00: return "hr"; 1698 : case SUBLANG_CROATIAN_CROATIA: return "hr_HR"; 1699 : case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA"; 1700 : /* Serbian */ 1701 : case 0x1f: return "sr"; 1702 : case 0x1c: return "sr"; /* latin */ 1703 : case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */ 1704 : case 0x09: return "sr_RS"; /* latin */ 1705 : case 0x0b: return "sr_ME"; /* latin */ 1706 : case 0x06: return "sr_BA"; /* latin */ 1707 : case 0x1b: return "sr@cyrillic"; 1708 : case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic"; 1709 : case 0x0a: return "sr_RS@cyrillic"; 1710 : case 0x0c: return "sr_ME@cyrillic"; 1711 : case 0x07: return "sr_BA@cyrillic"; 1712 : /* Bosnian */ 1713 : case 0x1e: return "bs"; 1714 : case 0x1a: return "bs"; /* latin */ 1715 : case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */ 1716 : case 0x19: return "bs@cyrillic"; 1717 : case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic"; 1718 : } 1719 : return "hr"; 1720 : case LANG_CZECH: 1721 : switch (sub) 1722 : { 1723 : case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ"; 1724 : } 1725 : return "cs"; 1726 : case LANG_DANISH: 1727 : switch (sub) 1728 : { 1729 : case SUBLANG_DANISH_DENMARK: return "da_DK"; 1730 : } 1731 : return "da"; 1732 : case LANG_DARI: 1733 : /* FIXME: Adjust this when such locales appear on Unix. */ 1734 : switch (sub) 1735 : { 1736 : case SUBLANG_DARI_AFGHANISTAN: return "prs_AF"; 1737 : } 1738 : return "prs"; 1739 : case LANG_DIVEHI: 1740 : switch (sub) 1741 : { 1742 : case SUBLANG_DIVEHI_MALDIVES: return "dv_MV"; 1743 : } 1744 : return "dv"; 1745 : case LANG_DUTCH: 1746 : switch (sub) 1747 : { 1748 : case SUBLANG_DUTCH: return "nl_NL"; 1749 : case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; 1750 : case SUBLANG_DUTCH_SURINAM: return "nl_SR"; 1751 : } 1752 : return "nl"; 1753 : case LANG_EDO: 1754 : switch (sub) 1755 : { 1756 : case SUBLANG_DEFAULT: return "bin_NG"; 1757 : } 1758 : return "bin"; 1759 : case LANG_ENGLISH: 1760 : switch (sub) 1761 : { 1762 : /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought 1763 : * English was the language spoken in England. 1764 : * Oh well. 1765 : */ 1766 : case SUBLANG_ENGLISH_US: return "en_US"; 1767 : case SUBLANG_ENGLISH_UK: return "en_GB"; 1768 : case SUBLANG_ENGLISH_AUS: return "en_AU"; 1769 : case SUBLANG_ENGLISH_CAN: return "en_CA"; 1770 : case SUBLANG_ENGLISH_NZ: return "en_NZ"; 1771 : case SUBLANG_ENGLISH_EIRE: return "en_IE"; 1772 : case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA"; 1773 : case SUBLANG_ENGLISH_JAMAICA: return "en_JM"; 1774 : case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */ 1775 : case SUBLANG_ENGLISH_BELIZE: return "en_BZ"; 1776 : case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; 1777 : case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; 1778 : case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; 1779 : case SUBLANG_ENGLISH_INDONESIA: return "en_ID"; 1780 : case SUBLANG_ENGLISH_HONGKONG: return "en_HK"; 1781 : case SUBLANG_ENGLISH_INDIA: return "en_IN"; 1782 : case SUBLANG_ENGLISH_MALAYSIA: return "en_MY"; 1783 : case SUBLANG_ENGLISH_SINGAPORE: return "en_SG"; 1784 : } 1785 : return "en"; 1786 : case LANG_ESTONIAN: 1787 : switch (sub) 1788 : { 1789 : case SUBLANG_ESTONIAN_ESTONIA: return "et_EE"; 1790 : } 1791 : return "et"; 1792 : case LANG_FAEROESE: 1793 : switch (sub) 1794 : { 1795 : case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO"; 1796 : } 1797 : return "fo"; 1798 : case LANG_FARSI: 1799 : switch (sub) 1800 : { 1801 : case SUBLANG_FARSI_IRAN: return "fa_IR"; 1802 : } 1803 : return "fa"; 1804 : case LANG_FINNISH: 1805 : switch (sub) 1806 : { 1807 : case SUBLANG_FINNISH_FINLAND: return "fi_FI"; 1808 : } 1809 : return "fi"; 1810 : case LANG_FRENCH: 1811 : switch (sub) 1812 : { 1813 : case SUBLANG_FRENCH: return "fr_FR"; 1814 : case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE"; 1815 : case SUBLANG_FRENCH_CANADIAN: return "fr_CA"; 1816 : case SUBLANG_FRENCH_SWISS: return "fr_CH"; 1817 : case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; 1818 : case SUBLANG_FRENCH_MONACO: return "fr_MC"; 1819 : case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */ 1820 : case SUBLANG_FRENCH_REUNION: return "fr_RE"; 1821 : case SUBLANG_FRENCH_CONGO: return "fr_CG"; 1822 : case SUBLANG_FRENCH_SENEGAL: return "fr_SN"; 1823 : case SUBLANG_FRENCH_CAMEROON: return "fr_CM"; 1824 : case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI"; 1825 : case SUBLANG_FRENCH_MALI: return "fr_ML"; 1826 : case SUBLANG_FRENCH_MOROCCO: return "fr_MA"; 1827 : case SUBLANG_FRENCH_HAITI: return "fr_HT"; 1828 : } 1829 : return "fr"; 1830 : case LANG_FRISIAN: 1831 : switch (sub) 1832 : { 1833 : case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL"; 1834 : } 1835 : return "fy"; 1836 : case LANG_FULFULDE: 1837 : /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */ 1838 : switch (sub) 1839 : { 1840 : case SUBLANG_DEFAULT: return "ff_NG"; 1841 : } 1842 : return "ff"; 1843 : case LANG_GAELIC: 1844 : switch (sub) 1845 : { 1846 : case 0x01: /* SCOTTISH */ 1847 : /* old, superseded by LANG_SCOTTISH_GAELIC */ 1848 : return "gd_GB"; 1849 : case SUBLANG_IRISH_IRELAND: return "ga_IE"; 1850 : } 1851 : return "ga"; 1852 : case LANG_GALICIAN: 1853 : switch (sub) 1854 : { 1855 : case SUBLANG_GALICIAN_SPAIN: return "gl_ES"; 1856 : } 1857 : return "gl"; 1858 : case LANG_GEORGIAN: 1859 : switch (sub) 1860 : { 1861 : case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE"; 1862 : } 1863 : return "ka"; 1864 : case LANG_GERMAN: 1865 : switch (sub) 1866 : { 1867 : case SUBLANG_GERMAN: return "de_DE"; 1868 : case SUBLANG_GERMAN_SWISS: return "de_CH"; 1869 : case SUBLANG_GERMAN_AUSTRIAN: return "de_AT"; 1870 : case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU"; 1871 : case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI"; 1872 : } 1873 : return "de"; 1874 : case LANG_GREEK: 1875 : switch (sub) 1876 : { 1877 : case SUBLANG_GREEK_GREECE: return "el_GR"; 1878 : } 1879 : return "el"; 1880 : case LANG_GREENLANDIC: 1881 : switch (sub) 1882 : { 1883 : case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL"; 1884 : } 1885 : return "kl"; 1886 : case LANG_GUARANI: 1887 : switch (sub) 1888 : { 1889 : case SUBLANG_DEFAULT: return "gn_PY"; 1890 : } 1891 : return "gn"; 1892 : case LANG_GUJARATI: 1893 : switch (sub) 1894 : { 1895 : case SUBLANG_GUJARATI_INDIA: return "gu_IN"; 1896 : } 1897 : return "gu"; 1898 : case LANG_HAUSA: 1899 : switch (sub) 1900 : { 1901 : case 0x1f: return "ha"; 1902 : case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG"; 1903 : } 1904 : return "ha"; 1905 : case LANG_HAWAIIAN: 1906 : /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) 1907 : or Hawaii Creole English ("cpe_US", 600000 speakers)? */ 1908 : switch (sub) 1909 : { 1910 : case SUBLANG_DEFAULT: return "cpe_US"; 1911 : } 1912 : return "cpe"; 1913 : case LANG_HEBREW: 1914 : switch (sub) 1915 : { 1916 : case SUBLANG_HEBREW_ISRAEL: return "he_IL"; 1917 : } 1918 : return "he"; 1919 : case LANG_HINDI: 1920 : switch (sub) 1921 : { 1922 : case SUBLANG_HINDI_INDIA: return "hi_IN"; 1923 : } 1924 : return "hi"; 1925 : case LANG_HUNGARIAN: 1926 : switch (sub) 1927 : { 1928 : case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU"; 1929 : } 1930 : return "hu"; 1931 : case LANG_IBIBIO: 1932 : switch (sub) 1933 : { 1934 : case SUBLANG_DEFAULT: return "nic_NG"; 1935 : } 1936 : return "nic"; 1937 : case LANG_ICELANDIC: 1938 : switch (sub) 1939 : { 1940 : case SUBLANG_ICELANDIC_ICELAND: return "is_IS"; 1941 : } 1942 : return "is"; 1943 : case LANG_IGBO: 1944 : switch (sub) 1945 : { 1946 : case SUBLANG_IGBO_NIGERIA: return "ig_NG"; 1947 : } 1948 : return "ig"; 1949 : case LANG_INDONESIAN: 1950 : switch (sub) 1951 : { 1952 : case SUBLANG_INDONESIAN_INDONESIA: return "id_ID"; 1953 : } 1954 : return "id"; 1955 : case LANG_INUKTITUT: 1956 : switch (sub) 1957 : { 1958 : case 0x1e: return "iu"; /* syllabic */ 1959 : case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */ 1960 : case 0x1f: return "iu@latin"; 1961 : case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin"; 1962 : } 1963 : return "iu"; 1964 : case LANG_ITALIAN: 1965 : switch (sub) 1966 : { 1967 : case SUBLANG_ITALIAN: return "it_IT"; 1968 : case SUBLANG_ITALIAN_SWISS: return "it_CH"; 1969 : } 1970 : return "it"; 1971 : case LANG_JAPANESE: 1972 : switch (sub) 1973 : { 1974 : case SUBLANG_JAPANESE_JAPAN: return "ja_JP"; 1975 : } 1976 : return "ja"; 1977 : case LANG_KANNADA: 1978 : switch (sub) 1979 : { 1980 : case SUBLANG_KANNADA_INDIA: return "kn_IN"; 1981 : } 1982 : return "kn"; 1983 : case LANG_KANURI: 1984 : switch (sub) 1985 : { 1986 : case SUBLANG_DEFAULT: return "kr_NG"; 1987 : } 1988 : return "kr"; 1989 : case LANG_KASHMIRI: 1990 : switch (sub) 1991 : { 1992 : case SUBLANG_DEFAULT: return "ks_PK"; 1993 : case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; 1994 : } 1995 : return "ks"; 1996 : case LANG_KAZAK: 1997 : switch (sub) 1998 : { 1999 : case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ"; 2000 : } 2001 : return "kk"; 2002 : case LANG_KICHE: 2003 : /* FIXME: Adjust this when such locales appear on Unix. */ 2004 : switch (sub) 2005 : { 2006 : case SUBLANG_KICHE_GUATEMALA: return "qut_GT"; 2007 : } 2008 : return "qut"; 2009 : case LANG_KINYARWANDA: 2010 : switch (sub) 2011 : { 2012 : case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW"; 2013 : } 2014 : return "rw"; 2015 : case LANG_KONKANI: 2016 : /* FIXME: Adjust this when such locales appear on Unix. */ 2017 : switch (sub) 2018 : { 2019 : case SUBLANG_KONKANI_INDIA: return "kok_IN"; 2020 : } 2021 : return "kok"; 2022 : case LANG_KOREAN: 2023 : switch (sub) 2024 : { 2025 : case SUBLANG_DEFAULT: return "ko_KR"; 2026 : } 2027 : return "ko"; 2028 : case LANG_KYRGYZ: 2029 : switch (sub) 2030 : { 2031 : case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG"; 2032 : } 2033 : return "ky"; 2034 : case LANG_LAO: 2035 : switch (sub) 2036 : { 2037 : case SUBLANG_LAO_LAOS: return "lo_LA"; 2038 : } 2039 : return "lo"; 2040 : case LANG_LATIN: 2041 : switch (sub) 2042 : { 2043 : case SUBLANG_DEFAULT: return "la_VA"; 2044 : } 2045 : return "la"; 2046 : case LANG_LATVIAN: 2047 : switch (sub) 2048 : { 2049 : case SUBLANG_LATVIAN_LATVIA: return "lv_LV"; 2050 : } 2051 : return "lv"; 2052 : case LANG_LITHUANIAN: 2053 : switch (sub) 2054 : { 2055 : case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT"; 2056 : } 2057 : return "lt"; 2058 : case LANG_LUXEMBOURGISH: 2059 : switch (sub) 2060 : { 2061 : case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU"; 2062 : } 2063 : return "lb"; 2064 : case LANG_MACEDONIAN: 2065 : switch (sub) 2066 : { 2067 : case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK"; 2068 : } 2069 : return "mk"; 2070 : case LANG_MALAY: 2071 : switch (sub) 2072 : { 2073 : case SUBLANG_MALAY_MALAYSIA: return "ms_MY"; 2074 : case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN"; 2075 : } 2076 : return "ms"; 2077 : case LANG_MALAYALAM: 2078 : switch (sub) 2079 : { 2080 : case SUBLANG_MALAYALAM_INDIA: return "ml_IN"; 2081 : } 2082 : return "ml"; 2083 : case LANG_MALTESE: 2084 : switch (sub) 2085 : { 2086 : case SUBLANG_MALTESE_MALTA: return "mt_MT"; 2087 : } 2088 : return "mt"; 2089 : case LANG_MANIPURI: 2090 : /* FIXME: Adjust this when such locales appear on Unix. */ 2091 : switch (sub) 2092 : { 2093 : case SUBLANG_DEFAULT: return "mni_IN"; 2094 : } 2095 : return "mni"; 2096 : case LANG_MAORI: 2097 : switch (sub) 2098 : { 2099 : case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ"; 2100 : } 2101 : return "mi"; 2102 : case LANG_MAPUDUNGUN: 2103 : switch (sub) 2104 : { 2105 : case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL"; 2106 : } 2107 : return "arn"; 2108 : case LANG_MARATHI: 2109 : switch (sub) 2110 : { 2111 : case SUBLANG_MARATHI_INDIA: return "mr_IN"; 2112 : } 2113 : return "mr"; 2114 : case LANG_MOHAWK: 2115 : switch (sub) 2116 : { 2117 : case SUBLANG_MOHAWK_CANADA: return "moh_CA"; 2118 : } 2119 : return "moh"; 2120 : case LANG_MONGOLIAN: 2121 : switch (sub) 2122 : { 2123 : case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN"; 2124 : case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN"; 2125 : } 2126 : return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */ 2127 : case LANG_NEPALI: 2128 : switch (sub) 2129 : { 2130 : case SUBLANG_NEPALI_NEPAL: return "ne_NP"; 2131 : case SUBLANG_NEPALI_INDIA: return "ne_IN"; 2132 : } 2133 : return "ne"; 2134 : case LANG_NORWEGIAN: 2135 : switch (sub) 2136 : { 2137 : case 0x1f: return "nb"; 2138 : case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO"; 2139 : case 0x1e: return "nn"; 2140 : case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; 2141 : } 2142 : return "no"; 2143 : case LANG_OCCITAN: 2144 : switch (sub) 2145 : { 2146 : case SUBLANG_OCCITAN_FRANCE: return "oc_FR"; 2147 : } 2148 : return "oc"; 2149 : case LANG_ORIYA: 2150 : switch (sub) 2151 : { 2152 : case SUBLANG_ORIYA_INDIA: return "or_IN"; 2153 : } 2154 : return "or"; 2155 : case LANG_OROMO: 2156 : switch (sub) 2157 : { 2158 : case SUBLANG_DEFAULT: return "om_ET"; 2159 : } 2160 : return "om"; 2161 : case LANG_PAPIAMENTU: 2162 : switch (sub) 2163 : { 2164 : case SUBLANG_DEFAULT: return "pap_AN"; 2165 : } 2166 : return "pap"; 2167 : case LANG_PASHTO: 2168 : switch (sub) 2169 : { 2170 : case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF"; 2171 : } 2172 : return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ 2173 : case LANG_POLISH: 2174 : switch (sub) 2175 : { 2176 : case SUBLANG_POLISH_POLAND: return "pl_PL"; 2177 : } 2178 : return "pl"; 2179 : case LANG_PORTUGUESE: 2180 : switch (sub) 2181 : { 2182 : /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. 2183 : Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ 2184 : case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; 2185 : case SUBLANG_PORTUGUESE: return "pt_PT"; 2186 : } 2187 : return "pt"; 2188 : case LANG_PUNJABI: 2189 : switch (sub) 2190 : { 2191 : case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ 2192 : case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */ 2193 : } 2194 : return "pa"; 2195 : case LANG_QUECHUA: 2196 : /* Note: Microsoft uses the non-ISO language code "quz". */ 2197 : switch (sub) 2198 : { 2199 : case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO"; 2200 : case SUBLANG_QUECHUA_ECUADOR: return "qu_EC"; 2201 : case SUBLANG_QUECHUA_PERU: return "qu_PE"; 2202 : } 2203 : return "qu"; 2204 : case LANG_ROMANIAN: 2205 : switch (sub) 2206 : { 2207 : case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; 2208 : case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD"; 2209 : } 2210 : return "ro"; 2211 : case LANG_ROMANSH: 2212 : switch (sub) 2213 : { 2214 : case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH"; 2215 : } 2216 : return "rm"; 2217 : case LANG_RUSSIAN: 2218 : switch (sub) 2219 : { 2220 : case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU"; 2221 : case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD"; 2222 : } 2223 : return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */ 2224 : case LANG_SAMI: 2225 : switch (sub) 2226 : { 2227 : /* Northern Sami */ 2228 : case 0x00: return "se"; 2229 : case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO"; 2230 : case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE"; 2231 : case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI"; 2232 : /* Lule Sami */ 2233 : case 0x1f: return "smj"; 2234 : case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO"; 2235 : case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE"; 2236 : /* Southern Sami */ 2237 : case 0x1e: return "sma"; 2238 : case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO"; 2239 : case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE"; 2240 : /* Skolt Sami */ 2241 : case 0x1d: return "sms"; 2242 : case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI"; 2243 : /* Inari Sami */ 2244 : case 0x1c: return "smn"; 2245 : case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI"; 2246 : } 2247 : return "se"; /* or "smi"? */ 2248 : case LANG_SANSKRIT: 2249 : switch (sub) 2250 : { 2251 : case SUBLANG_SANSKRIT_INDIA: return "sa_IN"; 2252 : } 2253 : return "sa"; 2254 : case LANG_SCOTTISH_GAELIC: 2255 : switch (sub) 2256 : { 2257 : case SUBLANG_DEFAULT: return "gd_GB"; 2258 : } 2259 : return "gd"; 2260 : case LANG_SINDHI: 2261 : switch (sub) 2262 : { 2263 : case SUBLANG_SINDHI_INDIA: return "sd_IN"; 2264 : case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; 2265 : /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/ 2266 : } 2267 : return "sd"; 2268 : case LANG_SINHALESE: 2269 : switch (sub) 2270 : { 2271 : case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK"; 2272 : } 2273 : return "si"; 2274 : case LANG_SLOVAK: 2275 : switch (sub) 2276 : { 2277 : case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK"; 2278 : } 2279 : return "sk"; 2280 : case LANG_SLOVENIAN: 2281 : switch (sub) 2282 : { 2283 : case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI"; 2284 : } 2285 : return "sl"; 2286 : case LANG_SOMALI: 2287 : switch (sub) 2288 : { 2289 : case SUBLANG_DEFAULT: return "so_SO"; 2290 : } 2291 : return "so"; 2292 : case LANG_SORBIAN: 2293 : /* FIXME: Adjust this when such locales appear on Unix. */ 2294 : switch (sub) 2295 : { 2296 : /* Upper Sorbian */ 2297 : case 0x00: return "hsb"; 2298 : case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE"; 2299 : /* Lower Sorbian */ 2300 : case 0x1f: return "dsb"; 2301 : case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE"; 2302 : } 2303 : return "wen"; 2304 : case LANG_SOTHO: 2305 : /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings> 2306 : calls it "Sesotho sa Leboa"; according to 2307 : <https://www.ethnologue.com/show_language.asp?code=nso> 2308 : <https://www.ethnologue.com/show_language.asp?code=sot> 2309 : it's the same as Northern Sotho. */ 2310 : switch (sub) 2311 : { 2312 : case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA"; 2313 : } 2314 : return "nso"; 2315 : case LANG_SPANISH: 2316 : switch (sub) 2317 : { 2318 : case SUBLANG_SPANISH: return "es_ES"; 2319 : case SUBLANG_SPANISH_MEXICAN: return "es_MX"; 2320 : case SUBLANG_SPANISH_MODERN: 2321 : return "es_ES@modern"; /* not seen on Unix */ 2322 : case SUBLANG_SPANISH_GUATEMALA: return "es_GT"; 2323 : case SUBLANG_SPANISH_COSTA_RICA: return "es_CR"; 2324 : case SUBLANG_SPANISH_PANAMA: return "es_PA"; 2325 : case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO"; 2326 : case SUBLANG_SPANISH_VENEZUELA: return "es_VE"; 2327 : case SUBLANG_SPANISH_COLOMBIA: return "es_CO"; 2328 : case SUBLANG_SPANISH_PERU: return "es_PE"; 2329 : case SUBLANG_SPANISH_ARGENTINA: return "es_AR"; 2330 : case SUBLANG_SPANISH_ECUADOR: return "es_EC"; 2331 : case SUBLANG_SPANISH_CHILE: return "es_CL"; 2332 : case SUBLANG_SPANISH_URUGUAY: return "es_UY"; 2333 : case SUBLANG_SPANISH_PARAGUAY: return "es_PY"; 2334 : case SUBLANG_SPANISH_BOLIVIA: return "es_BO"; 2335 : case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV"; 2336 : case SUBLANG_SPANISH_HONDURAS: return "es_HN"; 2337 : case SUBLANG_SPANISH_NICARAGUA: return "es_NI"; 2338 : case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; 2339 : case SUBLANG_SPANISH_US: return "es_US"; 2340 : } 2341 : return "es"; 2342 : case LANG_SUTU: 2343 : switch (sub) 2344 : { 2345 : case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */ 2346 : } 2347 : return "bnt"; 2348 : case LANG_SWAHILI: 2349 : switch (sub) 2350 : { 2351 : case SUBLANG_SWAHILI_KENYA: return "sw_KE"; 2352 : } 2353 : return "sw"; 2354 : case LANG_SWEDISH: 2355 : switch (sub) 2356 : { 2357 : case SUBLANG_SWEDISH_SWEDEN: return "sv_SE"; 2358 : case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; 2359 : } 2360 : return "sv"; 2361 : case LANG_SYRIAC: 2362 : switch (sub) 2363 : { 2364 : case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */ 2365 : } 2366 : return "syr"; 2367 : case LANG_TAGALOG: 2368 : switch (sub) 2369 : { 2370 : case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */ 2371 : } 2372 : return "tl"; /* or "fil"? */ 2373 : case LANG_TAJIK: 2374 : switch (sub) 2375 : { 2376 : case 0x1f: return "tg"; 2377 : case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ"; 2378 : } 2379 : return "tg"; 2380 : case LANG_TAMAZIGHT: 2381 : /* Note: Microsoft uses the non-ISO language code "tmz". */ 2382 : switch (sub) 2383 : { 2384 : /* FIXME: Adjust this when Tamazight locales appear on Unix. */ 2385 : case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; 2386 : case 0x1f: return "ber@latin"; 2387 : case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin"; 2388 : } 2389 : return "ber"; 2390 : case LANG_TAMIL: 2391 : switch (sub) 2392 : { 2393 : case SUBLANG_TAMIL_INDIA: return "ta_IN"; 2394 : } 2395 : return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ 2396 : case LANG_TATAR: 2397 : switch (sub) 2398 : { 2399 : case SUBLANG_TATAR_RUSSIA: return "tt_RU"; 2400 : } 2401 : return "tt"; 2402 : case LANG_TELUGU: 2403 : switch (sub) 2404 : { 2405 : case SUBLANG_TELUGU_INDIA: return "te_IN"; 2406 : } 2407 : return "te"; 2408 : case LANG_THAI: 2409 : switch (sub) 2410 : { 2411 : case SUBLANG_THAI_THAILAND: return "th_TH"; 2412 : } 2413 : return "th"; 2414 : case LANG_TIBETAN: 2415 : switch (sub) 2416 : { 2417 : case SUBLANG_TIBETAN_PRC: 2418 : /* Most Tibetans would not like "bo_CN". But Tibet does not yet 2419 : have a country code of its own. */ 2420 : return "bo"; 2421 : case SUBLANG_TIBETAN_BHUTAN: return "bo_BT"; 2422 : } 2423 : return "bo"; 2424 : case LANG_TIGRINYA: 2425 : switch (sub) 2426 : { 2427 : case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET"; 2428 : case SUBLANG_TIGRINYA_ERITREA: return "ti_ER"; 2429 : } 2430 : return "ti"; 2431 : case LANG_TSONGA: 2432 : switch (sub) 2433 : { 2434 : case SUBLANG_DEFAULT: return "ts_ZA"; 2435 : } 2436 : return "ts"; 2437 : case LANG_TSWANA: 2438 : /* Spoken in South Africa, Botswana. */ 2439 : switch (sub) 2440 : { 2441 : case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA"; 2442 : } 2443 : return "tn"; 2444 : case LANG_TURKISH: 2445 : switch (sub) 2446 : { 2447 : case SUBLANG_TURKISH_TURKEY: return "tr_TR"; 2448 : } 2449 : return "tr"; 2450 : case LANG_TURKMEN: 2451 : switch (sub) 2452 : { 2453 : case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM"; 2454 : } 2455 : return "tk"; 2456 : case LANG_UIGHUR: 2457 : switch (sub) 2458 : { 2459 : case SUBLANG_UIGHUR_PRC: return "ug_CN"; 2460 : } 2461 : return "ug"; 2462 : case LANG_UKRAINIAN: 2463 : switch (sub) 2464 : { 2465 : case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA"; 2466 : } 2467 : return "uk"; 2468 : case LANG_URDU: 2469 : switch (sub) 2470 : { 2471 : case SUBLANG_URDU_PAKISTAN: return "ur_PK"; 2472 : case SUBLANG_URDU_INDIA: return "ur_IN"; 2473 : } 2474 : return "ur"; 2475 : case LANG_UZBEK: 2476 : switch (sub) 2477 : { 2478 : case 0x1f: return "uz"; 2479 : case SUBLANG_UZBEK_LATIN: return "uz_UZ"; 2480 : case 0x1e: return "uz@cyrillic"; 2481 : case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; 2482 : } 2483 : return "uz"; 2484 : case LANG_VENDA: 2485 : switch (sub) 2486 : { 2487 : case SUBLANG_DEFAULT: return "ve_ZA"; 2488 : } 2489 : return "ve"; 2490 : case LANG_VIETNAMESE: 2491 : switch (sub) 2492 : { 2493 : case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN"; 2494 : } 2495 : return "vi"; 2496 : case LANG_WELSH: 2497 : switch (sub) 2498 : { 2499 : case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB"; 2500 : } 2501 : return "cy"; 2502 : case LANG_WOLOF: 2503 : switch (sub) 2504 : { 2505 : case SUBLANG_WOLOF_SENEGAL: return "wo_SN"; 2506 : } 2507 : return "wo"; 2508 : case LANG_XHOSA: 2509 : switch (sub) 2510 : { 2511 : case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA"; 2512 : } 2513 : return "xh"; 2514 : case LANG_YAKUT: 2515 : switch (sub) 2516 : { 2517 : case SUBLANG_YAKUT_RUSSIA: return "sah_RU"; 2518 : } 2519 : return "sah"; 2520 : case LANG_YI: 2521 : switch (sub) 2522 : { 2523 : case SUBLANG_YI_PRC: return "ii_CN"; 2524 : } 2525 : return "ii"; 2526 : case LANG_YIDDISH: 2527 : switch (sub) 2528 : { 2529 : case SUBLANG_DEFAULT: return "yi_IL"; 2530 : } 2531 : return "yi"; 2532 : case LANG_YORUBA: 2533 : switch (sub) 2534 : { 2535 : case SUBLANG_YORUBA_NIGERIA: return "yo_NG"; 2536 : } 2537 : return "yo"; 2538 : case LANG_ZULU: 2539 : switch (sub) 2540 : { 2541 : case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA"; 2542 : } 2543 : return "zu"; 2544 : default: return "C"; 2545 : } 2546 : } 2547 : } 2548 : 2549 : # if !defined IN_LIBINTL 2550 : static 2551 : # endif 2552 : const char * 2553 : gl_locale_name_from_win32_LCID (LCID lcid) 2554 : { 2555 : LANGID langid; 2556 : 2557 : /* Strip off the sorting rules, keep only the language part. */ 2558 : langid = LANGIDFROMLCID (lcid); 2559 : 2560 : return gl_locale_name_from_win32_LANGID (langid); 2561 : } 2562 : 2563 : # ifdef WINDOWS_NATIVE 2564 : 2565 : /* Two variables to interface between get_lcid and the EnumLocales 2566 : callback function below. */ 2567 : static LCID found_lcid; 2568 : static char lname[LC_MAX * (LOCALE_NAME_MAX_LENGTH + 1) + 1]; 2569 : 2570 : /* Callback function for EnumLocales. */ 2571 : static BOOL CALLBACK 2572 : enum_locales_fn (LPSTR locale_num_str) 2573 : { 2574 : char *endp; 2575 : char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1]; 2576 : LCID try_lcid = strtoul (locale_num_str, &endp, 16); 2577 : 2578 : if (GetLocaleInfo (try_lcid, LOCALE_SENGLANGUAGE, 2579 : locval, LOCALE_NAME_MAX_LENGTH)) 2580 : { 2581 : strcat (locval, "_"); 2582 : if (GetLocaleInfo (try_lcid, LOCALE_SENGCOUNTRY, 2583 : locval + strlen (locval), LOCALE_NAME_MAX_LENGTH)) 2584 : { 2585 : size_t locval_len = strlen (locval); 2586 : 2587 : if (strncmp (locval, lname, locval_len) == 0 2588 : && (lname[locval_len] == '.' 2589 : || lname[locval_len] == '0円')) 2590 : { 2591 : found_lcid = try_lcid; 2592 : return FALSE; 2593 : } 2594 : } 2595 : } 2596 : return TRUE; 2597 : } 2598 : 2599 : /* This lock protects the get_lcid against multiple simultaneous calls. */ 2600 : gl_lock_define_initialized(static, get_lcid_lock) 2601 : 2602 : /* Return the Locale ID (LCID) number given the locale's name, a 2603 : string, in LOCALE_NAME. This works by enumerating all the locales 2604 : supported by the system, until we find one whose name matches 2605 : LOCALE_NAME. */ 2606 : static LCID 2607 : get_lcid (const char *locale_name) 2608 : { 2609 : /* A simple cache. */ 2610 : static LCID last_lcid; 2611 : static char last_locale[1000]; 2612 : 2613 : /* Lock while looking for an LCID, to protect access to static 2614 : variables: last_lcid, last_locale, found_lcid, and lname. */ 2615 : gl_lock_lock (get_lcid_lock); 2616 : if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0) 2617 : { 2618 : gl_lock_unlock (get_lcid_lock); 2619 : return last_lcid; 2620 : } 2621 : strncpy (lname, locale_name, sizeof (lname) - 1); 2622 : lname[sizeof (lname) - 1] = '0円'; 2623 : found_lcid = 0; 2624 : EnumSystemLocales (enum_locales_fn, LCID_SUPPORTED); 2625 : if (found_lcid > 0) 2626 : { 2627 : last_lcid = found_lcid; 2628 : strcpy (last_locale, locale_name); 2629 : } 2630 : gl_lock_unlock (get_lcid_lock); 2631 : return found_lcid; 2632 : } 2633 : 2634 : # endif 2635 : #endif 2636 : 2637 : 2638 : #if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6, 2639 : Solaris 11 OpenIndiana, or Solaris >= 11.4 */ 2640 : 2641 : /* Simple hash set of strings. We don't want to drag in lots of hash table 2642 : code here. */ 2643 : 2644 : # define SIZE_BITS (sizeof (size_t) * CHAR_BIT) 2645 : 2646 : /* A hash function for NUL-terminated char* strings using 2647 : the method described by Bruno Haible. 2648 : See https://www.haible.de/bruno/hashfunc.html. */ 2649 : static size_t _GL_ATTRIBUTE_PURE 2650 72 : string_hash (const void *x) 2651 : { 2652 72 : const char *s = (const char *) x; 2653 72 : size_t h = 0; 2654 : 2655 384 : for (; *s; s++) 2656 312 : h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); 2657 : 2658 72 : return h; 2659 : } 2660 : 2661 : /* A hash table of fixed size. Multiple threads can access it read-only 2662 : simultaneously, but only one thread can insert into it at the same time. */ 2663 : 2664 : /* A node in a hash bucket collision list. */ 2665 : struct struniq_hash_node 2666 : { 2667 : struct struniq_hash_node * volatile next; 2668 : char contents[FLEXIBLE_ARRAY_MEMBER]; 2669 : }; 2670 : 2671 : # define STRUNIQ_HASH_TABLE_SIZE 257 2672 : static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE_SIZE] 2673 : /* = { NULL, ..., NULL } */; 2674 : 2675 : /* This lock protects the struniq_hash_table against multiple simultaneous 2676 : insertions. */ 2677 : gl_lock_define_initialized(static, struniq_lock) 2678 : 2679 : /* Store a copy of the given string in a string pool with indefinite extent. 2680 : Return a pointer to this copy. */ 2681 : static const char * 2682 72 : struniq (const char *string) 2683 : { 2684 72 : size_t hashcode = string_hash (string); 2685 72 : size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE; 2686 : size_t size; 2687 : struct struniq_hash_node *new_node; 2688 : struct struniq_hash_node *p; 2689 72 : for (p = struniq_hash_table[slot]; p != NULL; p = p->next) 2690 70 : if (strcmp (p->contents, string) == 0) 2691 70 : return p->contents; 2692 2 : size = strlen (string) + 1; 2693 : new_node = 2694 : (struct struniq_hash_node *) 2695 2 : malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size)); 2696 2 : if (new_node == NULL) 2697 : /* Out of memory. Return a statically allocated string. */ 2698 0 : return "C"; 2699 2 : memcpy (new_node->contents, string, size); 2700 : /* Lock while inserting new_node. */ 2701 2 : gl_lock_lock (struniq_lock); 2702 : /* Check whether another thread already added the string while we were 2703 : waiting on the lock. */ 2704 2 : for (p = struniq_hash_table[slot]; p != NULL; p = p->next) 2705 0 : if (strcmp (p->contents, string) == 0) 2706 : { 2707 0 : free (new_node); 2708 0 : new_node = p; 2709 0 : goto done; 2710 : } 2711 : /* Really insert new_node into the hash table. Fill new_node entirely first, 2712 : because other threads may be iterating over the linked list. */ 2713 2 : new_node->next = struniq_hash_table[slot]; 2714 2 : struniq_hash_table[slot] = new_node; 2715 2 : done: 2716 : /* Unlock after new_node is inserted. */ 2717 2 : gl_lock_unlock (struniq_lock); 2718 2 : return new_node->contents; 2719 : } 2720 : 2721 : #endif 2722 : 2723 : 2724 : #if HAVE_GOOD_USELOCALE && HAVE_NAMELESS_LOCALES 2725 : 2726 : /* The 'locale_t' object does not contain the names of the locale categories. 2727 : We have to associate them with the object through a hash table. 2728 : The hash table is defined in localename-table.[hc]. */ 2729 : 2730 : /* Returns the name of a given locale category in a given locale_t object, 2731 : allocated as a string with indefinite extent. */ 2732 : static const char * 2733 : get_locale_t_name (int category, locale_t locale) 2734 : { 2735 : if (locale == LC_GLOBAL_LOCALE) 2736 : { 2737 : /* Query the global locale. */ 2738 : const char *name = setlocale_null (category); 2739 : if (name != NULL) 2740 : return struniq (name); 2741 : else 2742 : /* Should normally not happen. */ 2743 : return ""; 2744 : } 2745 : else 2746 : { 2747 : /* Look up the names in the hash table. */ 2748 : size_t hashcode = locale_hash_function (locale); 2749 : size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; 2750 : /* If the locale was not found in the table, return "". This can 2751 : happen if the application uses the original newlocale()/duplocale() 2752 : functions instead of the overridden ones. */ 2753 : const char *name = ""; 2754 : struct locale_hash_node *p; 2755 : /* Lock while looking up the hash node. */ 2756 : gl_rwlock_rdlock (locale_lock); 2757 : for (p = locale_hash_table[slot]; p != NULL; p = p->next) 2758 : if (p->locale == locale) 2759 : { 2760 : name = p->names.category_name[category]; 2761 : break; 2762 : } 2763 : gl_rwlock_unlock (locale_lock); 2764 : return name; 2765 : } 2766 : } 2767 : 2768 : # if !(defined newlocale && defined duplocale && defined freelocale) 2769 : # error "newlocale, duplocale, freelocale not being replaced as expected!" 2770 : # endif 2771 : 2772 : /* newlocale() override. */ 2773 : locale_t 2774 : newlocale (int category_mask, const char *name, locale_t base) 2775 : #undef newlocale 2776 : { 2777 : struct locale_categories_names names; 2778 : struct locale_hash_node *node; 2779 : locale_t result; 2780 : 2781 : /* Make sure name has indefinite extent. */ 2782 : if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK 2783 : | LC_MONETARY_MASK | LC_MESSAGES_MASK) 2784 : & category_mask) != 0) 2785 : name = struniq (name); 2786 : 2787 : /* Determine the category names of the result. */ 2788 : if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK 2789 : | LC_MONETARY_MASK | LC_MESSAGES_MASK) 2790 : & ~category_mask) == 0) 2791 : { 2792 : /* Use name, ignore base. */ 2793 : int category; 2794 : 2795 : name = struniq (name); 2796 : for (category = 0; category < 6; category++) 2797 : names.category_name[category] = name; 2798 : } 2799 : else 2800 : { 2801 : /* Use base, possibly also name. */ 2802 : if (base == NULL) 2803 : { 2804 : int category; 2805 : 2806 : for (category = 0; category < 6; category++) 2807 : { 2808 : int mask; 2809 : 2810 : switch (category) 2811 : { 2812 : case LC_CTYPE: 2813 : mask = LC_CTYPE_MASK; 2814 : break; 2815 : case LC_NUMERIC: 2816 : mask = LC_NUMERIC_MASK; 2817 : break; 2818 : case LC_TIME: 2819 : mask = LC_TIME_MASK; 2820 : break; 2821 : case LC_COLLATE: 2822 : mask = LC_COLLATE_MASK; 2823 : break; 2824 : case LC_MONETARY: 2825 : mask = LC_MONETARY_MASK; 2826 : break; 2827 : case LC_MESSAGES: 2828 : mask = LC_MESSAGES_MASK; 2829 : break; 2830 : default: 2831 : abort (); 2832 : } 2833 : names.category_name[category] = 2834 : ((mask & category_mask) != 0 ? name : "C"); 2835 : } 2836 : } 2837 : else if (base == LC_GLOBAL_LOCALE) 2838 : { 2839 : int category; 2840 : 2841 : for (category = 0; category < 6; category++) 2842 : { 2843 : int mask; 2844 : 2845 : switch (category) 2846 : { 2847 : case LC_CTYPE: 2848 : mask = LC_CTYPE_MASK; 2849 : break; 2850 : case LC_NUMERIC: 2851 : mask = LC_NUMERIC_MASK; 2852 : break; 2853 : case LC_TIME: 2854 : mask = LC_TIME_MASK; 2855 : break; 2856 : case LC_COLLATE: 2857 : mask = LC_COLLATE_MASK; 2858 : break; 2859 : case LC_MONETARY: 2860 : mask = LC_MONETARY_MASK; 2861 : break; 2862 : case LC_MESSAGES: 2863 : mask = LC_MESSAGES_MASK; 2864 : break; 2865 : default: 2866 : abort (); 2867 : } 2868 : names.category_name[category] = 2869 : ((mask & category_mask) != 0 2870 : ? name 2871 : : get_locale_t_name (category, LC_GLOBAL_LOCALE)); 2872 : } 2873 : } 2874 : else 2875 : { 2876 : /* Look up the names of base in the hash table. Like multiple calls 2877 : of get_locale_t_name, but locking only once. */ 2878 : struct locale_hash_node *p; 2879 : int category; 2880 : 2881 : /* Lock while looking up the hash node. */ 2882 : gl_rwlock_rdlock (locale_lock); 2883 : for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE]; 2884 : p != NULL; 2885 : p = p->next) 2886 : if (p->locale == base) 2887 : break; 2888 : 2889 : for (category = 0; category < 6; category++) 2890 : { 2891 : int mask; 2892 : 2893 : switch (category) 2894 : { 2895 : case LC_CTYPE: 2896 : mask = LC_CTYPE_MASK; 2897 : break; 2898 : case LC_NUMERIC: 2899 : mask = LC_NUMERIC_MASK; 2900 : break; 2901 : case LC_TIME: 2902 : mask = LC_TIME_MASK; 2903 : break; 2904 : case LC_COLLATE: 2905 : mask = LC_COLLATE_MASK; 2906 : break; 2907 : case LC_MONETARY: 2908 : mask = LC_MONETARY_MASK; 2909 : break; 2910 : case LC_MESSAGES: 2911 : mask = LC_MESSAGES_MASK; 2912 : break; 2913 : default: 2914 : abort (); 2915 : } 2916 : names.category_name[category] = 2917 : ((mask & category_mask) != 0 2918 : ? name 2919 : : (p != NULL ? p->names.category_name[category] : "")); 2920 : } 2921 : 2922 : gl_rwlock_unlock (locale_lock); 2923 : } 2924 : } 2925 : 2926 : node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node)); 2927 : if (node == NULL) 2928 : /* errno is set to ENOMEM. */ 2929 : return NULL; 2930 : 2931 : result = newlocale (category_mask, name, base); 2932 : if (result == NULL) 2933 : { 2934 : int saved_errno = errno; 2935 : free (node); 2936 : errno = saved_errno; 2937 : return NULL; 2938 : } 2939 : 2940 : /* Fill the hash node. */ 2941 : node->locale = result; 2942 : node->names = names; 2943 : 2944 : /* Insert it in the hash table. */ 2945 : { 2946 : size_t hashcode = locale_hash_function (result); 2947 : size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; 2948 : struct locale_hash_node *p; 2949 : 2950 : /* Lock while inserting the new node. */ 2951 : gl_rwlock_wrlock (locale_lock); 2952 : for (p = locale_hash_table[slot]; p != NULL; p = p->next) 2953 : if (p->locale == result) 2954 : { 2955 : /* This can happen if the application uses the original freelocale() 2956 : function instead of the overridden one. */ 2957 : p->names = node->names; 2958 : break; 2959 : } 2960 : if (p == NULL) 2961 : { 2962 : node->next = locale_hash_table[slot]; 2963 : locale_hash_table[slot] = node; 2964 : } 2965 : 2966 : gl_rwlock_unlock (locale_lock); 2967 : 2968 : if (p != NULL) 2969 : free (node); 2970 : } 2971 : 2972 : return result; 2973 : } 2974 : 2975 : /* duplocale() override. */ 2976 : locale_t 2977 : duplocale (locale_t locale) 2978 : #undef duplocale 2979 : { 2980 : struct locale_hash_node *node; 2981 : locale_t result; 2982 : 2983 : if (locale == NULL) 2984 : /* Invalid argument. */ 2985 : abort (); 2986 : 2987 : node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node)); 2988 : if (node == NULL) 2989 : /* errno is set to ENOMEM. */ 2990 : return NULL; 2991 : 2992 : result = duplocale (locale); 2993 : if (result == NULL) 2994 : { 2995 : int saved_errno = errno; 2996 : free (node); 2997 : errno = saved_errno; 2998 : return NULL; 2999 : } 3000 : 3001 : /* Fill the hash node. */ 3002 : node->locale = result; 3003 : if (locale == LC_GLOBAL_LOCALE) 3004 : { 3005 : int category; 3006 : 3007 : for (category = 0; category < 6; category++) 3008 : node->names.category_name[category] = 3009 : get_locale_t_name (category, LC_GLOBAL_LOCALE); 3010 : 3011 : /* Lock before inserting the new node. */ 3012 : gl_rwlock_wrlock (locale_lock); 3013 : } 3014 : else 3015 : { 3016 : struct locale_hash_node *p; 3017 : 3018 : /* Lock once, for the lookup and the insertion. */ 3019 : gl_rwlock_wrlock (locale_lock); 3020 : 3021 : for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE]; 3022 : p != NULL; 3023 : p = p->next) 3024 : if (p->locale == locale) 3025 : break; 3026 : if (p != NULL) 3027 : node->names = p->names; 3028 : else 3029 : { 3030 : /* This can happen if the application uses the original 3031 : newlocale()/duplocale() functions instead of the overridden 3032 : ones. */ 3033 : int category; 3034 : 3035 : for (category = 0; category < 6; category++) 3036 : node->names.category_name[category] = ""; 3037 : } 3038 : } 3039 : 3040 : /* Insert it in the hash table. */ 3041 : { 3042 : size_t hashcode = locale_hash_function (result); 3043 : size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; 3044 : struct locale_hash_node *p; 3045 : 3046 : for (p = locale_hash_table[slot]; p != NULL; p = p->next) 3047 : if (p->locale == result) 3048 : { 3049 : /* This can happen if the application uses the original freelocale() 3050 : function instead of the overridden one. */ 3051 : p->names = node->names; 3052 : break; 3053 : } 3054 : if (p == NULL) 3055 : { 3056 : node->next = locale_hash_table[slot]; 3057 : locale_hash_table[slot] = node; 3058 : } 3059 : 3060 : gl_rwlock_unlock (locale_lock); 3061 : 3062 : if (p != NULL) 3063 : free (node); 3064 : } 3065 : 3066 : return result; 3067 : } 3068 : 3069 : /* freelocale() override. */ 3070 : void 3071 : freelocale (locale_t locale) 3072 : #undef freelocale 3073 : { 3074 : if (locale == NULL || locale == LC_GLOBAL_LOCALE) 3075 : /* Invalid argument. */ 3076 : abort (); 3077 : 3078 : { 3079 : size_t hashcode = locale_hash_function (locale); 3080 : size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; 3081 : struct locale_hash_node *found; 3082 : struct locale_hash_node **p; 3083 : 3084 : found = NULL; 3085 : /* Lock while removing the hash node. */ 3086 : gl_rwlock_wrlock (locale_lock); 3087 : for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next) 3088 : if ((*p)->locale == locale) 3089 : { 3090 : found = *p; 3091 : *p = (*p)->next; 3092 : break; 3093 : } 3094 : gl_rwlock_unlock (locale_lock); 3095 : free (found); 3096 : } 3097 : 3098 : freelocale (locale); 3099 : } 3100 : 3101 : #endif 3102 : 3103 : 3104 : #if defined IN_LIBINTL || HAVE_GOOD_USELOCALE 3105 : 3106 : /* Like gl_locale_name_thread, except that the result is not in storage of 3107 : indefinite extent. */ 3108 : # if !defined IN_LIBINTL 3109 : static 3110 : # endif 3111 : const char * 3112 84 : gl_locale_name_thread_unsafe (int category, const char *categoryname) 3113 : { 3114 : # if HAVE_GOOD_USELOCALE 3115 : { 3116 84 : locale_t thread_locale = uselocale (NULL); 3117 84 : if (thread_locale != LC_GLOBAL_LOCALE) 3118 : { 3119 : # if __GLIBC__ >= 2 && !defined __UCLIBC__ 3120 : /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in 3121 : glibc < 2.12. 3122 : See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */ 3123 : const char *name = 3124 72 : nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1))); 3125 72 : if (name[0] == '0円') 3126 : /* Fallback code for glibc < 2.4, which did not implement 3127 : nl_langinfo (_NL_LOCALE_NAME (category)). */ 3128 0 : name = thread_locale->__names[category]; 3129 72 : return name; 3130 : # elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME 3131 : /* musl libc */ 3132 : return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale); 3133 : # elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__) 3134 : /* FreeBSD, Mac OS X */ 3135 : int mask; 3136 : 3137 : switch (category) 3138 : { 3139 : case LC_CTYPE: 3140 : mask = LC_CTYPE_MASK; 3141 : break; 3142 : case LC_NUMERIC: 3143 : mask = LC_NUMERIC_MASK; 3144 : break; 3145 : case LC_TIME: 3146 : mask = LC_TIME_MASK; 3147 : break; 3148 : case LC_COLLATE: 3149 : mask = LC_COLLATE_MASK; 3150 : break; 3151 : case LC_MONETARY: 3152 : mask = LC_MONETARY_MASK; 3153 : break; 3154 : case LC_MESSAGES: 3155 : mask = LC_MESSAGES_MASK; 3156 : break; 3157 : default: /* We shouldn't get here. */ 3158 : return ""; 3159 : } 3160 : return querylocale (mask, thread_locale); 3161 : # elif defined __sun 3162 : # if HAVE_GETLOCALENAME_L 3163 : /* Solaris >= 12. */ 3164 : return getlocalename_l (category, thread_locale); 3165 : # elif HAVE_SOLARIS114_LOCALES 3166 : /* Solaris >= 11.4. */ 3167 : void *lcp = (*thread_locale)->core.data->lcp; 3168 : if (lcp != NULL) 3169 : switch (category) 3170 : { 3171 : case LC_CTYPE: 3172 : case LC_NUMERIC: 3173 : case LC_TIME: 3174 : case LC_COLLATE: 3175 : case LC_MONETARY: 3176 : case LC_MESSAGES: 3177 : return ((const char * const *) lcp)[category]; 3178 : default: /* We shouldn't get here. */ 3179 : return ""; 3180 : } 3181 : # elif HAVE_NAMELESS_LOCALES 3182 : return get_locale_t_name (category, thread_locale); 3183 : # else 3184 : /* Solaris 11 OpenIndiana. 3185 : For the internal structure of locale objects, see 3186 : https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */ 3187 : switch (category) 3188 : { 3189 : case LC_CTYPE: 3190 : case LC_NUMERIC: 3191 : case LC_TIME: 3192 : case LC_COLLATE: 3193 : case LC_MONETARY: 3194 : case LC_MESSAGES: 3195 : return ((const char * const *) thread_locale)[category]; 3196 : default: /* We shouldn't get here. */ 3197 : return ""; 3198 : } 3199 : # endif 3200 : # elif defined _AIX && HAVE_NAMELESS_LOCALES 3201 : return get_locale_t_name (category, thread_locale); 3202 : # elif defined __CYGWIN__ 3203 : /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether. 3204 : Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside 3205 : an opaque struct. */ 3206 : # ifdef NL_LOCALE_NAME 3207 : return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale); 3208 : # else 3209 : /* FIXME: Remove when we can assume new-enough Cygwin. */ 3210 : struct __locale_t { 3211 : char categories[7][32]; 3212 : }; 3213 : return ((struct __locale_t *) thread_locale)->categories[category]; 3214 : # endif 3215 : # elif defined __ANDROID__ 3216 : return MB_CUR_MAX == 4 ? "C.UTF-8" : "C"; 3217 : # endif 3218 : } 3219 : } 3220 : # endif 3221 12 : return NULL; 3222 : } 3223 : 3224 : #endif 3225 : 3226 : const char * 3227 84 : gl_locale_name_thread (int category, const char *categoryname) 3228 : { 3229 : #if HAVE_GOOD_USELOCALE 3230 84 : const char *name = gl_locale_name_thread_unsafe (category, categoryname); 3231 84 : if (name != NULL) 3232 72 : return struniq (name); 3233 : #endif 3234 : /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when 3235 : SetThreadLocale has not been called - which is a very frequent case - 3236 : the value of GetThreadLocale() ignores past calls to 'setlocale'. */ 3237 12 : return NULL; 3238 : } 3239 : 3240 : /* XPG3 defines the result of 'setlocale (category, NULL)' as: 3241 : "Directs 'setlocale()' to query 'category' and return the current 3242 : setting of 'local'." 3243 : However it does not specify the exact format. Neither do SUSV2 and 3244 : ISO C 99. So we can use this feature only on selected systems (e.g. 3245 : those using GNU C Library). */ 3246 : #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__) 3247 : # define HAVE_LOCALE_NULL 3248 : #endif 3249 : 3250 : const char * 3251 19 : gl_locale_name_posix (int category, const char *categoryname) 3252 : { 3253 : #if defined WINDOWS_NATIVE 3254 : if (LC_MIN <= category && category <= LC_MAX) 3255 : { 3256 : const char *locname = 3257 : /* setlocale_null (category) is identical to setlocale (category, NULL) 3258 : on this platform. */ 3259 : setlocale (category, NULL); 3260 : 3261 : /* Convert locale name to LCID. We don't want to use 3262 : LocaleNameToLCID because (a) it is only available since Vista, 3263 : and (b) it doesn't accept locale names returned by 'setlocale'. */ 3264 : LCID lcid = get_lcid (locname); 3265 : 3266 : if (lcid > 0) 3267 : return gl_locale_name_from_win32_LCID (lcid); 3268 : } 3269 : #endif 3270 : { 3271 : const char *locname; 3272 : 3273 : /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. 3274 : On some systems this can be done by the 'setlocale' function itself. */ 3275 : #if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL 3276 19 : locname = setlocale_null (category); 3277 : #else 3278 : /* On other systems we ignore what setlocale reports and instead look at the 3279 : environment variables directly. This is necessary 3280 : 1. on systems which have a facility for customizing the default locale 3281 : (Mac OS X, native Windows, Cygwin) and where the system's setlocale() 3282 : function ignores this default locale (Mac OS X, Cygwin), in two cases: 3283 : a. when the user missed to use the setlocale() override from libintl 3284 : (for example by not including <libintl.h>), 3285 : b. when setlocale supports only the "C" locale, such as on Cygwin 3286 : 1.5.x. In this case even the override from libintl cannot help. 3287 : 2. on all systems where setlocale supports only the "C" locale. */ 3288 : /* Strictly speaking, it is a POSIX violation to look at the environment 3289 : variables regardless whether setlocale has been called or not. POSIX 3290 : says: 3291 : "For C-language programs, the POSIX locale shall be the 3292 : default locale when the setlocale() function is not called." 3293 : But we assume that all programs that use internationalized APIs call 3294 : setlocale (LC_ALL, ""). */ 3295 : locname = gl_locale_name_environ (category, categoryname); 3296 : #endif 3297 : /* Convert the locale name from the format returned by setlocale() or found 3298 : in the environment variables to the XPG syntax. */ 3299 : #if defined WINDOWS_NATIVE 3300 : if (locname != NULL) 3301 : { 3302 : /* Convert locale name to LCID. We don't want to use 3303 : LocaleNameToLCID because (a) it is only available since Vista, 3304 : and (b) it doesn't accept locale names returned by 'setlocale'. */ 3305 : LCID lcid = get_lcid (locname); 3306 : 3307 : if (lcid > 0) 3308 : return gl_locale_name_from_win32_LCID (lcid); 3309 : } 3310 : #endif 3311 19 : return locname; 3312 : } 3313 : } 3314 : 3315 : const char * 3316 13 : gl_locale_name_environ (int category, const char *categoryname) 3317 : { 3318 : const char *retval; 3319 : 3320 : /* Setting of LC_ALL overrides all other. */ 3321 13 : retval = getenv ("LC_ALL"); 3322 13 : if (retval != NULL && retval[0] != '0円') 3323 1 : return retval; 3324 : /* Next comes the name of the desired category. */ 3325 12 : retval = getenv (categoryname); 3326 12 : if (retval != NULL && retval[0] != '0円') 3327 3 : return retval; 3328 : /* Last possibility is the LANG environment variable. */ 3329 9 : retval = getenv ("LANG"); 3330 9 : if (retval != NULL && retval[0] != '0円') 3331 : { 3332 : #if HAVE_CFPREFERENCESCOPYAPPVALUE 3333 : /* Mac OS X 10.2 or newer. 3334 : Ignore invalid LANG value set by the Terminal application. */ 3335 : if (strcmp (retval, "UTF-8") != 0) 3336 : #endif 3337 : #if defined __CYGWIN__ 3338 : /* Cygwin. 3339 : Ignore dummy LANG value set by ~/.profile. */ 3340 : if (strcmp (retval, "C.UTF-8") != 0) 3341 : #endif 3342 2 : return retval; 3343 : } 3344 : 3345 7 : return NULL; 3346 : } 3347 : 3348 : const char * 3349 13 : gl_locale_name_default (void) 3350 : { 3351 : /* POSIX:2001 says: 3352 : "All implementations shall define a locale as the default locale, to be 3353 : invoked when no environment variables are set, or set to the empty 3354 : string. This default locale can be the POSIX locale or any other 3355 : implementation-defined locale. Some implementations may provide 3356 : facilities for local installation administrators to set the default 3357 : locale, customizing it for each location. POSIX:2001 does not require 3358 : such a facility. 3359 : 3360 : The systems with such a facility are Mac OS X and Windows: They provide a 3361 : GUI that allows the user to choose a locale. 3362 : - On Mac OS X, by default, none of LC_* or LANG are set. Starting with 3363 : Mac OS X 10.4 or 10.5, LANG is set for processes launched by the 3364 : 'Terminal' application (but sometimes to an incorrect value "UTF-8"). 3365 : When no environment variable is set, setlocale (LC_ALL, "") uses the 3366 : "C" locale. 3367 : - On native Windows, by default, none of LC_* or LANG are set. 3368 : When no environment variable is set, setlocale (LC_ALL, "") uses the 3369 : locale chosen by the user. 3370 : - On Cygwin 1.5.x, by default, none of LC_* or LANG are set. 3371 : When no environment variable is set, setlocale (LC_ALL, "") uses the 3372 : "C" locale. 3373 : - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default 3374 : ~/.profile is executed. 3375 : When no environment variable is set, setlocale (LC_ALL, "") uses the 3376 : "C.UTF-8" locale, which operates in the same way as the "C" locale. 3377 : */ 3378 : 3379 : #if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__) 3380 : 3381 : /* The system does not have a way of setting the locale, other than the 3382 : POSIX specified environment variables. We use C as default locale. */ 3383 13 : return "C"; 3384 : 3385 : #else 3386 : 3387 : /* Return an XPG style locale name language[_territory][@modifier]. 3388 : Don't even bother determining the codeset; it's not useful in this 3389 : context, because message catalogs are not specific to a single 3390 : codeset. */ 3391 : 3392 : # if HAVE_CFPREFERENCESCOPYAPPVALUE 3393 : /* Mac OS X 10.4 or newer */ 3394 : /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent, 3395 : because in macOS 10.13.4 it has the following behaviour: 3396 : When two or more languages are specified in the 3397 : "System Preferences > Language & Region > Preferred Languages" panel, 3398 : it returns en_CC where CC is the territory (even when English is not among 3399 : the preferred languages!). What we want instead is what 3400 : CFLocaleCopyCurrent returned in earlier macOS releases and what 3401 : CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the 3402 : first among the preferred languages and CC is the territory. */ 3403 : { 3404 : /* Cache the locale name, since CoreFoundation calls are expensive. */ 3405 : static const char *cached_localename; 3406 : 3407 : if (cached_localename == NULL) 3408 : { 3409 : char namebuf[256]; 3410 : CFTypeRef value = 3411 : CFPreferencesCopyAppValue (CFSTR ("AppleLocale"), 3412 : kCFPreferencesCurrentApplication); 3413 : if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 3414 : { 3415 : CFStringRef name = (CFStringRef)value; 3416 : 3417 : if (CFStringGetCString (name, namebuf, sizeof (namebuf), 3418 : kCFStringEncodingASCII)) 3419 : { 3420 : gl_locale_name_canonicalize (namebuf); 3421 : cached_localename = strdup (namebuf); 3422 : } 3423 : } 3424 : if (cached_localename == NULL) 3425 : cached_localename = "C"; 3426 : } 3427 : return cached_localename; 3428 : } 3429 : 3430 : # endif 3431 : 3432 : # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */ 3433 : { 3434 : LCID lcid; 3435 : 3436 : /* Use native Windows API locale ID. */ 3437 : lcid = GetThreadLocale (); 3438 : 3439 : return gl_locale_name_from_win32_LCID (lcid); 3440 : } 3441 : # endif 3442 : #endif 3443 : } 3444 : 3445 : /* Determine the current locale's name, and canonicalize it into XPG syntax 3446 : language[_territory][.codeset][@modifier] 3447 : The codeset part in the result is not reliable; the locale_charset() 3448 : should be used for codeset information instead. 3449 : The result must not be freed; it is statically allocated. */ 3450 : 3451 : const char * 3452 10 : gl_locale_name (int category, const char *categoryname) 3453 : { 3454 : const char *retval; 3455 : 3456 10 : retval = gl_locale_name_thread (category, categoryname); 3457 10 : if (retval != NULL) 3458 0 : return retval; 3459 : 3460 10 : retval = gl_locale_name_posix (category, categoryname); 3461 10 : if (retval != NULL) 3462 10 : return retval; 3463 : 3464 0 : return gl_locale_name_default (); 3465 : }