|
44 | 44 | LCID_NONE = 0 # 0 used instead of None for backwards compatibility. |
45 | 45 |
|
46 | 46 | LANGS_WITHOUT_TRANSLATIONS: FrozenSet[str] = frozenset(("en",)) |
47 | | -installedTranslation: Optional[weakref.ReferenceType] = None |
48 | 47 | """Saved copy of the installed translation for ease of wrapping. |
49 | 48 | """ |
50 | 49 |
|
| 50 | +LCIDS_TO_TRANSLATED_LOCALES = { |
| 51 | + # Windows maps this to "ku-Arab-IQ", however a translation is added for |
| 52 | + # Central Kurdish in localesData.LANG_NAMES_TO_LOCALIZED_DESCS["ckb"] |
| 53 | + # and NVDA may drop "Arab-IQ" from this locale to get the language. |
| 54 | + 1170: 'ckb' |
| 55 | +} |
| 56 | +""" |
| 57 | +Map Windows locale identifiers to language codes. |
| 58 | +These are Windows LCIDs that are used in NVDA but are not found in locale.windows_locale. |
| 59 | +These have been added when new locales have been introduced to the translation system and |
| 60 | +we cannot use the results from the Windows function LCIDToLocaleName. |
| 61 | +installedTranslation: Optional[weakref.ReferenceType] = None |
| 62 | +""" |
| 63 | + |
51 | 64 |
|
52 | 65 | class LOCALE(enum.IntEnum): |
53 | 66 | # Represents NLS constants which can be used with `GetLocaleInfoEx` or `GetLocaleInfoW` |
@@ -110,16 +123,22 @@ def localeNameToWindowsLCID(localeName: str) -> int: |
110 | 123 |
|
111 | 124 | def windowsLCIDToLocaleName(lcid: int) -> Optional[str]: |
112 | 125 | """ |
113 | | - gets a normalized locale from a lcid |
| 126 | + Gets a normalized locale from a Windows LCID. |
| 127 | +
|
| 128 | + NVDA should avoid relying on LCIDs in future, as they have been deprecated by MS: |
| 129 | + https://docs.microsoft.com/en-us/globalization/locale/locale-names |
114 | 130 | """ |
115 | | - # Look up a full locale name (language + country) |
116 | | - try: |
117 | | - lang = locale.windows_locale[lcid] |
118 | | - except KeyError: |
119 | | - # Or at least just a language-only locale name |
120 | | - lang=windowsPrimaryLCIDsToLocaleNames[lcid] |
121 | | - if lang: |
122 | | - return normalizeLanguage(lang) |
| 131 | + # From the locale.windows_locale in-line code documentation: (#4203) |
| 132 | + # This list has been updated to include every locale up to Windows Vista. |
| 133 | + # NOTE: this mapping is incomplete. |
| 134 | + localeName = locale.windows_locale.get(lcid) |
| 135 | + # Check a manual mapping before using Windows to look up the correct LCID locale name. |
| 136 | + if not localeName: |
| 137 | + localeName = LCIDS_TO_TRANSLATED_LOCALES.get(lcid) |
| 138 | + if not localeName: |
| 139 | + localeName = winKernel.LCIDToLocaleName(lcid) |
| 140 | + if localeName: |
| 141 | + return normalizeLanguage(localeName) |
123 | 142 |
|
124 | 143 |
|
125 | 144 | def getLanguageDescription(language: str) -> Optional[str]: |
@@ -315,22 +334,10 @@ def getWindowsLanguage(): |
315 | 334 | """ |
316 | 335 | windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage() |
317 | 336 | localeName = windowsLCIDToLocaleName(windowsLCID) |
318 | | - if not localeName: |
319 | | - # #4203: some locale identifiers from Windows 8 do not exist in Python's list. |
320 | | - # Therefore use windows' own function to get the locale name. |
321 | | - # Eventually this should probably be used all the time. |
322 | | - bufSize=32 |
323 | | - buf=ctypes.create_unicode_buffer(bufSize) |
324 | | - dwFlags=0 |
325 | | - try: |
326 | | - ctypes.windll.kernel32.LCIDToLocaleName(windowsLCID,buf,bufSize,dwFlags) |
327 | | - except AttributeError: |
328 | | - pass |
329 | | - localeName=buf.value |
330 | | - if localeName: |
331 | | - localeName=normalizeLanguage(localeName) |
332 | | - else: |
333 | | - localeName="en" |
| 337 | + if localeName: |
| 338 | + localeName = normalizeLanguage(localeName) |
| 339 | + else: |
| 340 | + localeName = "en" |
334 | 341 | return localeName |
335 | 342 |
|
336 | 343 |
|
@@ -493,126 +500,3 @@ def useImperialMeasurements() -> bool: |
493 | 500 | return buf.value == '1' |
494 | 501 |
|
495 | 502 |
|
496 | | -# Map Windows primary locale identifiers to locale names |
497 | | -# Note these are only primary language codes (I.e. no country information) |
498 | | -# For full locale identifiers we use Python's own locale.windows_locale. |
499 | | -# Generated from: {x&0x3ff:y.split('_')[0] for x,y in locale.windows_locale.iteritems()} |
500 | | -windowsPrimaryLCIDsToLocaleNames={ |
501 | | - 1:'ar', |
502 | | - 2:'bg', |
503 | | - 3:'ca', |
504 | | - 4:'zh', |
505 | | - 5:'cs', |
506 | | - 6:'da', |
507 | | - 7:'de', |
508 | | - 8:'el', |
509 | | - 9:'en', |
510 | | - 10:'es', |
511 | | - 11:'fi', |
512 | | - 12:'fr', |
513 | | - 13:'he', |
514 | | - 14:'hu', |
515 | | - 15:'is', |
516 | | - 16:'it', |
517 | | - 17:'ja', |
518 | | - 18:'ko', |
519 | | - 19:'nl', |
520 | | - 20:'nb', |
521 | | - 21:'pl', |
522 | | - 22:'pt', |
523 | | - 23:'rm', |
524 | | - 24:'ro', |
525 | | - 25:'ru', |
526 | | - 26:'sr', |
527 | | - 27:'sk', |
528 | | - 28:'sq', |
529 | | - 29:'sv', |
530 | | - 30:'th', |
531 | | - 31:'tr', |
532 | | - 32:'ur', |
533 | | - 33:'id', |
534 | | - 34:'uk', |
535 | | - 35:'be', |
536 | | - 36:'sl', |
537 | | - 37:'et', |
538 | | - 38:'lv', |
539 | | - 39:'lt', |
540 | | - 40:'tg', |
541 | | - 41:'fa', |
542 | | - 42:'vi', |
543 | | - 43:'hy', |
544 | | - 44:'az', |
545 | | - 45:'eu', |
546 | | - 46:'wen', |
547 | | - 47:'mk', |
548 | | - 50:'tn', |
549 | | - 52:'xh', |
550 | | - 53:'zu', |
551 | | - 54:'af', |
552 | | - 55:'ka', |
553 | | - 56:'fo', |
554 | | - 57:'hi', |
555 | | - 58:'mt', |
556 | | - 59:'sms', |
557 | | - 60:'ga', |
558 | | - 62:'ms', |
559 | | - 63:'kk', |
560 | | - 64:'ky', |
561 | | - 65:'sw', |
562 | | - 66:'tk', |
563 | | - 67:'uz', |
564 | | - 68:'tt', |
565 | | - 69:'bn', |
566 | | - 70:'pa', |
567 | | - 71:'gu', |
568 | | - 72:'or', |
569 | | - 73:'ta', |
570 | | - 74:'te', |
571 | | - 75:'kn', |
572 | | - 76:'ml', |
573 | | - 77:'as', |
574 | | - 78:'mr', |
575 | | - 79:'sa', |
576 | | - 80:'mn', |
577 | | - 81:'bo', |
578 | | - 82:'cy', |
579 | | - 83:'kh', |
580 | | - 84:'lo', |
581 | | - 86:'gl', |
582 | | - 87:'kok', |
583 | | - 90:'syr', |
584 | | - 91:'si', |
585 | | - 93:'iu', |
586 | | - 94:'am', |
587 | | - 95:'tmz', |
588 | | - 97:'ne', |
589 | | - 98:'fy', |
590 | | - 99:'ps', |
591 | | - 100:'fil', |
592 | | - 101:'div', |
593 | | - 104:'ha', |
594 | | - 106:'yo', |
595 | | - 107:'quz', |
596 | | - 108:'ns', |
597 | | - 109:'ba', |
598 | | - 110:'lb', |
599 | | - 111:'kl', |
600 | | - 120:'ii', |
601 | | - 122:'arn', |
602 | | - 124:'moh', |
603 | | - 126:'br', |
604 | | - 128:'ug', |
605 | | - 129:'mi', |
606 | | - 130:'oc', |
607 | | - 131:'co', |
608 | | - 132:'gsw', |
609 | | - 133:'sah', |
610 | | - 134:'qut', |
611 | | - 135:'rw', |
612 | | - 136:'wo', |
613 | | - 140: 'gbz', |
614 | | - 1170: 'ckb', |
615 | | - 1109: 'my', |
616 | | - 1143: 'so', |
617 | | - 9242: 'sr', |
618 | | -} |
0 commit comments