codekingpro/portable-devtools
114k
1"""Locale support module.2 3The module provides low-level access to the C lib's locale APIs and adds high4level number formatting APIs as well as a locale aliasing engine to complement5these.6 7The aliasing engine includes support for many commonly used locale names and8maps them to values suitable for passing to the C lib's setlocale() function. It9also includes default encodings for all supported locale names.10 11"""12 13import sys14import encodings15import encodings.aliases16import _collections_abc17from builtins import str as _builtin_str18import functools19 20# Try importing the _locale module.21#22# If this fails, fall back on a basic 'C' locale emulation.23 24# Yuck: LC_MESSAGES is non-standard: can't tell whether it exists before25# trying the import. So __all__ is also fiddled at the end of the file.26__all__ = ["getlocale", "getdefaultlocale", "getpreferredencoding", "Error",27 "setlocale", "localeconv", "strcoll", "strxfrm",28 "str", "atof", "atoi", "format_string", "currency",29 "normalize", "LC_CTYPE", "LC_COLLATE", "LC_TIME", "LC_MONETARY",30 "LC_NUMERIC", "LC_ALL", "CHAR_MAX", "getencoding"]31 32def _strcoll(a,b):33 """ strcoll(string,string) -> int.34 Compares two strings according to the locale.35 """36 return (a > b) - (a < b)37 38def _strxfrm(s):39 """ strxfrm(string) -> string.40 Returns a string that behaves for cmp locale-aware.41 """42 return s43 44try:45 46 from _locale import *47 48except ImportError:49 50 # Locale emulation51 52 CHAR_MAX = 12753 LC_ALL = 654 LC_COLLATE = 355 LC_CTYPE = 056 LC_MESSAGES = 557 LC_MONETARY = 458 LC_NUMERIC = 159 LC_TIME = 260 Error = ValueError61 62 def localeconv():63 """ localeconv() -> dict.64 Returns numeric and monetary locale-specific parameters.65 """66 # 'C' locale default values67 return {'grouping': [127],68 'currency_symbol': '',69 'n_sign_posn': 127,70 'p_cs_precedes': 127,71 'n_cs_precedes': 127,72 'mon_grouping': [],73 'n_sep_by_space': 127,74 'decimal_point': '.',75 'negative_sign': '',76 'positive_sign': '',77 'p_sep_by_space': 127,78 'int_curr_symbol': '',79 'p_sign_posn': 127,80 'thousands_sep': '',81 'mon_thousands_sep': '',82 'frac_digits': 127,83 'mon_decimal_point': '',84 'int_frac_digits': 127}85 86 def setlocale(category, value=None):87 """ setlocale(integer,string=None) -> string.88 Activates/queries locale processing.89 """90 if value not in (None, '', 'C'):91 raise Error('_locale emulation only supports "C" locale')92 return 'C'93 94# These may or may not exist in _locale, so be sure to set them.95if 'strxfrm' not in globals():96 strxfrm = _strxfrm97if 'strcoll' not in globals():98 strcoll = _strcoll99 100 101_localeconv = localeconv102 103# With this dict, you can override some items of localeconv's return value.104# This is useful for testing purposes.105_override_localeconv = {}106 107@functools.wraps(_localeconv)108def localeconv():109 d = _localeconv()110 if _override_localeconv:111 d.update(_override_localeconv)112 return d113 114 115### Number formatting APIs116 117# Author: Martin von Loewis118# improved by Georg Brandl119 120# Iterate over grouping intervals121def _grouping_intervals(grouping):122 last_interval = None123 for interval in grouping:124 # if grouping is -1, we are done125 if interval == CHAR_MAX:126 return127 # 0: re-use last group ad infinitum128 if interval == 0:129 if last_interval is None:130 raise ValueError("invalid grouping")131 while True:132 yield last_interval133 yield interval134 last_interval = interval135 136#perform the grouping from right to left137def _group(s, monetary=False):138 conv = localeconv()139 thousands_sep = conv[monetary and 'mon_thousands_sep' or 'thousands_sep']140 grouping = conv[monetary and 'mon_grouping' or 'grouping']141 if not grouping:142 return (s, 0)143 if s[-1] == ' ':144 stripped = s.rstrip()145 right_spaces = s[len(stripped):]146 s = stripped147 else:148 right_spaces = ''149 left_spaces = ''150 groups = []151 for interval in _grouping_intervals(grouping):152 if not s or s[-1] not in "0123456789":153 # only non-digit characters remain (sign, spaces)154 left_spaces = s155 s = ''156 break157 groups.append(s[-interval:])158 s = s[:-interval]159 if s:160 groups.append(s)161 groups.reverse()162 return (163 left_spaces + thousands_sep.join(groups) + right_spaces,164 len(thousands_sep) * (len(groups) - 1)165 )166 167# Strip a given amount of excess padding from the given string168def _strip_padding(s, amount):169 lpos = 0170 while amount and s[lpos] == ' ':171 lpos += 1172 amount -= 1173 rpos = len(s) - 1174 while amount and s[rpos] == ' ':175 rpos -= 1176 amount -= 1177 return s[lpos:rpos+1]178 179_percent_re = None180 181def _format(percent, value, grouping=False, monetary=False, *additional):182 if additional:183 formatted = percent % ((value,) + additional)184 else:185 formatted = percent % value186 if percent[-1] in 'eEfFgGdiu':187 formatted = _localize(formatted, grouping, monetary)188 return formatted189 190# Transform formatted as locale number according to the locale settings191def _localize(formatted, grouping=False, monetary=False):192 # floats and decimal ints need special action!193 if '.' in formatted:194 seps = 0195 parts = formatted.split('.')196 if grouping:197 parts[0], seps = _group(parts[0], monetary=monetary)198 decimal_point = localeconv()[monetary and 'mon_decimal_point'199 or 'decimal_point']200 formatted = decimal_point.join(parts)201 if seps:202 formatted = _strip_padding(formatted, seps)203 else:204 seps = 0205 if grouping:206 formatted, seps = _group(formatted, monetary=monetary)207 if seps:208 formatted = _strip_padding(formatted, seps)209 return formatted210 211def format_string(f, val, grouping=False, monetary=False):212 """Formats a string in the same way that the % formatting would use,213 but takes the current locale into account.214 215 Grouping is applied if the third parameter is true.216 Conversion uses monetary thousands separator and grouping strings if217 forth parameter monetary is true."""218 global _percent_re219 if _percent_re is None:220 import re221 222 _percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?(?P<modifiers'223 r'>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')224 225 percents = list(_percent_re.finditer(f))226 new_f = _percent_re.sub('%s', f)227 228 if isinstance(val, _collections_abc.Mapping):229 new_val = []230 for perc in percents:231 if perc.group()[-1]=='%':232 new_val.append('%')233 else:234 new_val.append(_format(perc.group(), val, grouping, monetary))235 else:236 if not isinstance(val, tuple):237 val = (val,)238 new_val = []239 i = 0240 for perc in percents:241 if perc.group()[-1]=='%':242 new_val.append('%')243 else:244 starcount = perc.group('modifiers').count('*')245 new_val.append(_format(perc.group(),246 val[i],247 grouping,248 monetary,249 *val[i+1:i+1+starcount]))250 i += (1 + starcount)251 val = tuple(new_val)252 253 return new_f % val254 255def currency(val, symbol=True, grouping=False, international=False):256 """Formats val according to the currency settings257 in the current locale."""258 conv = localeconv()259 260 # check for illegal values261 digits = conv[international and 'int_frac_digits' or 'frac_digits']262 if digits == 127:263 raise ValueError("Currency formatting is not possible using "264 "the 'C' locale.")265 266 s = _localize(f'{abs(val):.{digits}f}', grouping, monetary=True)267 # '<' and '>' are markers if the sign must be inserted between symbol and value268 s = '<' + s + '>'269 270 if symbol:271 smb = conv[international and 'int_curr_symbol' or 'currency_symbol']272 precedes = conv[val<0 and 'n_cs_precedes' or 'p_cs_precedes']273 separated = conv[val<0 and 'n_sep_by_space' or 'p_sep_by_space']274 275 if precedes:276 s = smb + (separated and ' ' or '') + s277 else:278 if international and smb[-1] == ' ':279 smb = smb[:-1]280 s = s + (separated and ' ' or '') + smb281 282 sign_pos = conv[val<0 and 'n_sign_posn' or 'p_sign_posn']283 sign = conv[val<0 and 'negative_sign' or 'positive_sign']284 285 if sign_pos == 0:286 s = '(' + s + ')'287 elif sign_pos == 1:288 s = sign + s289 elif sign_pos == 2:290 s = s + sign291 elif sign_pos == 3:292 s = s.replace('<', sign)293 elif sign_pos == 4:294 s = s.replace('>', sign)295 else:296 # the default if nothing specified;297 # this should be the most fitting sign position298 s = sign + s299 300 return s.replace('<', '').replace('>', '')301 302def str(val):303 """Convert float to string, taking the locale into account."""304 return _format("%.12g", val)305 306def delocalize(string):307 "Parses a string as a normalized number according to the locale settings."308 309 conv = localeconv()310 311 #First, get rid of the grouping312 ts = conv['thousands_sep']313 if ts:314 string = string.replace(ts, '')315 316 #next, replace the decimal point with a dot317 dd = conv['decimal_point']318 if dd:319 string = string.replace(dd, '.')320 return string321 322def localize(string, grouping=False, monetary=False):323 """Parses a string as locale number according to the locale settings."""324 return _localize(string, grouping, monetary)325 326def atof(string, func=float):327 "Parses a string as a float according to the locale settings."328 return func(delocalize(string))329 330def atoi(string):331 "Converts a string to an integer according to the locale settings."332 return int(delocalize(string))333 334def _test():335 setlocale(LC_ALL, "")336 #do grouping337 s1 = format_string("%d", 123456789,1)338 print(s1, "is", atoi(s1))339 #standard formatting340 s1 = str(3.14)341 print(s1, "is", atof(s1))342 343### Locale name aliasing engine344 345# Author: Marc-Andre Lemburg, mal@lemburg.com346# Various tweaks by Fredrik Lundh <fredrik@pythonware.com>347 348# store away the low-level version of setlocale (it's349# overridden below)350_setlocale = setlocale351 352def _replace_encoding(code, encoding):353 if '.' in code:354 langname = code[:code.index('.')]355 else:356 langname = code357 # Convert the encoding to a C lib compatible encoding string358 norm_encoding = encodings.normalize_encoding(encoding)359 #print('norm encoding: %r' % norm_encoding)360 norm_encoding = encodings.aliases.aliases.get(norm_encoding.lower(),361 norm_encoding)362 #print('aliased encoding: %r' % norm_encoding)363 encoding = norm_encoding364 norm_encoding = norm_encoding.lower()365 if norm_encoding in locale_encoding_alias:366 encoding = locale_encoding_alias[norm_encoding]367 else:368 norm_encoding = norm_encoding.replace('_', '')369 norm_encoding = norm_encoding.replace('-', '')370 if norm_encoding in locale_encoding_alias:371 encoding = locale_encoding_alias[norm_encoding]372 #print('found encoding %r' % encoding)373 return langname + '.' + encoding374 375def _append_modifier(code, modifier):376 if modifier == 'euro':377 if '.' not in code:378 return code + '.ISO8859-15'379 _, _, encoding = code.partition('.')380 if encoding in ('ISO8859-15', 'UTF-8'):381 return code382 if encoding == 'ISO8859-1':383 return _replace_encoding(code, 'ISO8859-15')384 return code + '@' + modifier385 386def normalize(localename):387 388 """ Returns a normalized locale code for the given locale389 name.390 391 The returned locale code is formatted for use with392 setlocale().393 394 If normalization fails, the original name is returned395 unchanged.396 397 If the given encoding is not known, the function defaults to398 the default encoding for the locale code just like setlocale()399 does.400 401 """402 # Normalize the locale name and extract the encoding and modifier403 code = localename.lower()404 if ':' in code:405 # ':' is sometimes used as encoding delimiter.406 code = code.replace(':', '.')407 if '@' in code:408 code, modifier = code.split('@', 1)409 else:410 modifier = ''411 if '.' in code:412 langname, encoding = code.split('.')[:2]413 else:414 langname = code415 encoding = ''416 417 # First lookup: fullname (possibly with encoding and modifier)418 lang_enc = langname419 if encoding:420 norm_encoding = encoding.replace('-', '')421 norm_encoding = norm_encoding.replace('_', '')422 lang_enc += '.' + norm_encoding423 lookup_name = lang_enc424 if modifier:425 lookup_name += '@' + modifier426 code = locale_alias.get(lookup_name, None)427 if code is not None:428 return code429 #print('first lookup failed')430 431 if modifier:432 # Second try: fullname without modifier (possibly with encoding)433 code = locale_alias.get(lang_enc, None)434 if code is not None:435 #print('lookup without modifier succeeded')436 if '@' not in code:437 return _append_modifier(code, modifier)438 if code.split('@', 1)[1].lower() == modifier:439 return code440 #print('second lookup failed')441 442 if encoding:443 # Third try: langname (without encoding, possibly with modifier)444 lookup_name = langname445 if modifier:446 lookup_name += '@' + modifier447 code = locale_alias.get(lookup_name, None)448 if code is not None:449 #print('lookup without encoding succeeded')450 if '@' not in code:451 return _replace_encoding(code, encoding)452 code, modifier = code.split('@', 1)453 return _replace_encoding(code, encoding) + '@' + modifier454 455 if modifier:456 # Fourth try: langname (without encoding and modifier)457 code = locale_alias.get(langname, None)458 if code is not None:459 #print('lookup without modifier and encoding succeeded')460 if '@' not in code:461 code = _replace_encoding(code, encoding)462 return _append_modifier(code, modifier)463 code, defmod = code.split('@', 1)464 if defmod.lower() == modifier:465 return _replace_encoding(code, encoding) + '@' + defmod466 467 return localename468 469def _parse_localename(localename):470 471 """ Parses the locale code for localename and returns the472 result as tuple (language code, encoding).473 474 The localename is normalized and passed through the locale475 alias engine. A ValueError is raised in case the locale name476 cannot be parsed.477 478 The language code corresponds to RFC 1766. code and encoding479 can be None in case the values cannot be determined or are480 unknown to this implementation.481 482 """483 code = normalize(localename)484 if '@' in code:485 # Deal with locale modifiers486 code, modifier = code.split('@', 1)487 if modifier == 'euro' and '.' not in code:488 # Assume Latin-9 for @euro locales. This is bogus,489 # since some systems may use other encodings for these490 # locales. Also, we ignore other modifiers.491 return code, 'iso-8859-15'492 493 if '.' in code:494 return tuple(code.split('.')[:2])495 elif code == 'C':496 return None, None497 elif code == 'UTF-8':498 # On macOS "LC_CTYPE=UTF-8" is a valid locale setting499 # for getting UTF-8 handling for text.500 return None, 'UTF-8'501 raise ValueError('unknown locale: %s' % localename)502 503def _build_localename(localetuple):504 505 """ Builds a locale code from the given tuple (language code,506 encoding).507 508 No aliasing or normalizing takes place.509 510 """511 try:512 language, encoding = localetuple513 514 if language is None:515 language = 'C'516 if encoding is None:517 return language518 else:519 return language + '.' + encoding520 except (TypeError, ValueError):521 raise TypeError('Locale must be None, a string, or an iterable of '522 'two strings -- language code, encoding.') from None523 524def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')):525 526 """ Tries to determine the default locale settings and returns527 them as tuple (language code, encoding).528 529 According to POSIX, a program which has not called530 setlocale(LC_ALL, "") runs using the portable 'C' locale.531 Calling setlocale(LC_ALL, "") lets it use the default locale as532 defined by the LANG variable. Since we don't want to interfere533 with the current locale setting we thus emulate the behavior534 in the way described above.535 536 To maintain compatibility with other platforms, not only the537 LANG variable is tested, but a list of variables given as538 envvars parameter. The first found to be defined will be539 used. envvars defaults to the search path used in GNU gettext;540 it must always contain the variable name 'LANG'.541 542 Except for the code 'C', the language code corresponds to RFC543 1766. code and encoding can be None in case the values cannot544 be determined.545 546 """547 548 import warnings549 warnings._deprecated(550 "locale.getdefaultlocale",551 "{name!r} is deprecated and slated for removal in Python {remove}. "552 "Use setlocale(), getencoding() and getlocale() instead.",553 remove=(3, 15))554 return _getdefaultlocale(envvars)555 556 557def _getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')):558 try:559 # check if it's supported by the _locale module560 import _locale561 code, encoding = _locale._getdefaultlocale()562 except (ImportError, AttributeError):563 pass564 else:565 # make sure the code/encoding values are valid566 if sys.platform == "win32" and code and code[:2] == "0x":567 # map windows language identifier to language name568 code = windows_locale.get(int(code, 0))569 # ...add other platform-specific processing here, if570 # necessary...571 return code, encoding572 573 # fall back on POSIX behaviour574 import os575 lookup = os.environ.get576 for variable in envvars:577 localename = lookup(variable,None)578 if localename:579 if variable == 'LANGUAGE':580 localename = localename.split(':')[0]581 break582 else:583 localename = 'C'584 return _parse_localename(localename)585 586 587def getlocale(category=LC_CTYPE):588 589 """ Returns the current setting for the given locale category as590 tuple (language code, encoding).591 592 category may be one of the LC_* value except LC_ALL. It593 defaults to LC_CTYPE.594 595 Except for the code 'C', the language code corresponds to RFC596 1766. code and encoding can be None in case the values cannot597 be determined.598 599 """600 localename = _setlocale(category)601 if category == LC_ALL and ';' in localename:602 raise TypeError('category LC_ALL is not supported')603 return _parse_localename(localename)604 605def setlocale(category, locale=None):606 607 """ Set the locale for the given category. The locale can be608 a string, an iterable of two strings (language code and encoding),609 or None.610 611 Iterables are converted to strings using the locale aliasing612 engine. Locale strings are passed directly to the C lib.613 614 category may be given as one of the LC_* values.615 616 """617 if locale and not isinstance(locale, _builtin_str):618 # convert to string619 locale = normalize(_build_localename(locale))620 return _setlocale(category, locale)621 622 623try:624 from _locale import getencoding625except ImportError:626 # When _locale.getencoding() is missing, locale.getencoding() uses the627 # Python filesystem encoding.628 def getencoding():629 return sys.getfilesystemencoding()630 631 632try:633 CODESET634except NameError:635 def getpreferredencoding(do_setlocale=True):636 """Return the charset that the user is likely using."""637 if sys.flags.warn_default_encoding:638 import warnings639 warnings.warn(640 "UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.",641 EncodingWarning, 2)642 if sys.flags.utf8_mode:643 return 'utf-8'644 return getencoding()645else:646 # On Unix, if CODESET is available, use that.647 def getpreferredencoding(do_setlocale=True):648 """Return the charset that the user is likely using,649 according to the system configuration."""650 651 if sys.flags.warn_default_encoding:652 import warnings653 warnings.warn(654 "UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.",655 EncodingWarning, 2)656 if sys.flags.utf8_mode:657 return 'utf-8'658 659 if not do_setlocale:660 return getencoding()661 662 old_loc = setlocale(LC_CTYPE)663 try:664 try:665 setlocale(LC_CTYPE, "")666 except Error:667 pass668 return getencoding()669 finally:670 setlocale(LC_CTYPE, old_loc)671 672 673### Database674#675# The following data was extracted from the locale.alias file which676# comes with X11 and then hand edited removing the explicit encoding677# definitions and adding some more aliases. The file is usually678# available as /usr/lib/X11/locale/locale.alias.679#680 681#682# The local_encoding_alias table maps lowercase encoding alias names683# to C locale encoding names (case-sensitive). Note that normalize()684# first looks up the encoding in the encodings.aliases dictionary and685# then applies this mapping to find the correct C lib name for the686# encoding.687#688locale_encoding_alias = {689 690 # Mappings for non-standard encoding names used in locale names691 '437': 'C',692 'c': 'C',693 'en': 'ISO8859-1',694 'jis': 'JIS7',695 'jis7': 'JIS7',696 'ajec': 'eucJP',697 'koi8c': 'KOI8-C',698 'microsoftcp1251': 'CP1251',699 'microsoftcp1255': 'CP1255',700 'microsoftcp1256': 'CP1256',701 '88591': 'ISO8859-1',702 '88592': 'ISO8859-2',703 '88595': 'ISO8859-5',704 '885915': 'ISO8859-15',705 706 # Mappings from Python codec names to C lib encoding names707 'ascii': 'ISO8859-1',708 'latin_1': 'ISO8859-1',709 'iso8859_1': 'ISO8859-1',710 'iso8859_10': 'ISO8859-10',711 'iso8859_11': 'ISO8859-11',712 'iso8859_13': 'ISO8859-13',713 'iso8859_14': 'ISO8859-14',714 'iso8859_15': 'ISO8859-15',715 'iso8859_16': 'ISO8859-16',716 'iso8859_2': 'ISO8859-2',717 'iso8859_3': 'ISO8859-3',718 'iso8859_4': 'ISO8859-4',719 'iso8859_5': 'ISO8859-5',720 'iso8859_6': 'ISO8859-6',721 'iso8859_7': 'ISO8859-7',722 'iso8859_8': 'ISO8859-8',723 'iso8859_9': 'ISO8859-9',724 'iso2022_jp': 'JIS7',725 'shift_jis': 'SJIS',726 'tactis': 'TACTIS',727 'euc_jp': 'eucJP',728 'euc_kr': 'eucKR',729 'utf_8': 'UTF-8',730 'koi8_r': 'KOI8-R',731 'koi8_t': 'KOI8-T',732 'koi8_u': 'KOI8-U',733 'kz1048': 'RK1048',734 'cp1251': 'CP1251',735 'cp1255': 'CP1255',736 'cp1256': 'CP1256',737 738 # XXX This list is still incomplete. If you know more739 # mappings, please file a bug report. Thanks.740}741 742for k, v in sorted(locale_encoding_alias.items()):743 k = k.replace('_', '')744 locale_encoding_alias.setdefault(k, v)745del k, v746 747#748# The locale_alias table maps lowercase alias names to C locale names749# (case-sensitive). Encodings are always separated from the locale750# name using a dot ('.'); they should only be given in case the751# language name is needed to interpret the given encoding alias752# correctly (CJK codes often have this need).753#754# Note that the normalize() function which uses this tables755# removes '_' and '-' characters from the encoding part of the756# locale name before doing the lookup. This saves a lot of757# space in the table.758#759# MAL 2004-12-10:760# Updated alias mapping to most recent locale.alias file761# from X.org distribution using makelocalealias.py.762#763# These are the differences compared to the old mapping (Python 2.4764# and older):765#766# updated 'bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251'767# updated 'bg_bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251'768# updated 'bulgarian' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251'769# updated 'cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2'770# updated 'cz_cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2'771# updated 'czech' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2'772# updated 'dutch' -> 'nl_BE.ISO8859-1' to 'nl_NL.ISO8859-1'773# updated 'et' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15'774# updated 'et_ee' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15'775# updated 'fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15'776# updated 'fi_fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15'777# updated 'iw' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8'778# updated 'iw_il' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8'779# updated 'japanese' -> 'ja_JP.SJIS' to 'ja_JP.eucJP'780# updated 'lt' -> 'lt_LT.ISO8859-4' to 'lt_LT.ISO8859-13'781# updated 'lv' -> 'lv_LV.ISO8859-4' to 'lv_LV.ISO8859-13'782# updated 'sl' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2'783# updated 'slovene' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2'784# updated 'th_th' -> 'th_TH.TACTIS' to 'th_TH.ISO8859-11'785# updated 'zh_cn' -> 'zh_CN.eucCN' to 'zh_CN.gb2312'786# updated 'zh_cn.big5' -> 'zh_TW.eucTW' to 'zh_TW.big5'787# updated 'zh_tw' -> 'zh_TW.eucTW' to 'zh_TW.big5'788#789# MAL 2008-05-30:790# Updated alias mapping to most recent locale.alias file791# from X.org distribution using makelocalealias.py.792#793# These are the differences compared to the old mapping (Python 2.5794# and older):795#796# updated 'cs_cs.iso88592' -> 'cs_CZ.ISO8859-2' to 'cs_CS.ISO8859-2'797# updated 'serbocroatian' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'798# updated 'sh' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'799# updated 'sh_hr.iso88592' -> 'sh_HR.ISO8859-2' to 'hr_HR.ISO8859-2'800# updated 'sh_sp' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'801# updated 'sh_yu' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2'802# updated 'sp' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5'803# updated 'sp_yu' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5'804# updated 'sr' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'805# updated 'sr@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'806# updated 'sr_sp' -> 'sr_SP.ISO8859-2' to 'sr_CS.ISO8859-2'807# updated 'sr_yu' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'808# updated 'sr_yu.cp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251'809# updated 'sr_yu.iso88592' -> 'sr_YU.ISO8859-2' to 'sr_CS.ISO8859-2'810# updated 'sr_yu.iso88595' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'811# updated 'sr_yu.iso88595@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'812# updated 'sr_yu.microsoftcp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251'813# updated 'sr_yu.utf8@cyrillic' -> 'sr_YU.UTF-8' to 'sr_CS.UTF-8'814# updated 'sr_yu@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5'815#816# AP 2010-04-12:817# Updated alias mapping to most recent locale.alias file818# from X.org distribution using makelocalealias.py.819#820# These are the differences compared to the old mapping (Python 2.6.5821# and older):822#823# updated 'ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8'824# updated 'ru_ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8'825# updated 'serbocroatian' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'826# updated 'sh' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'827# updated 'sh_yu' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'828# updated 'sr' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8'829# updated 'sr@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8'830# updated 'sr@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'831# updated 'sr_cs.utf8@latn' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8@latin'832# updated 'sr_cs@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin'833# updated 'sr_yu' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8@latin'834# updated 'sr_yu.utf8@cyrillic' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8'835# updated 'sr_yu@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8'836#837# SS 2013-12-20:838# Updated alias mapping to most recent locale.alias file839# from X.org distribution using makelocalealias.py.840#841# These are the differences compared to the old mapping (Python 3.3.3842# and older):843#844# updated 'a3' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C'845# updated 'a3_az' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C'846# updated 'a3_az.koi8c' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C'847# updated 'cs_cs.iso88592' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2'848# updated 'hebrew' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8'849# updated 'hebrew.iso88598' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8'850# updated 'sd' -> 'sd_IN@devanagari.UTF-8' to 'sd_IN.UTF-8'851# updated 'sr@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin'852# updated 'sr_cs' -> 'sr_RS.UTF-8' to 'sr_CS.UTF-8'853# updated 'sr_cs.utf8@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin'854# updated 'sr_cs@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin'855#856# SS 2014-10-01:857# Updated alias mapping with glibc 2.19 supported locales.858#859# SS 2018-05-05:860# Updated alias mapping with glibc 2.27 supported locales.861#862# These are the differences compared to the old mapping (Python 3.6.5863# and older):864#865# updated 'ca_es@valencia' -> 'ca_ES.ISO8859-15@valencia' to 'ca_ES.UTF-8@valencia'866# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154'867# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R'868#869# SS 2025-02-04:870# Updated alias mapping with glibc 2.41 supported locales and the latest871# X lib alias mapping.872#873# These are the differences compared to the old mapping (Python 3.13.1874# and older):875#876# updated 'c.utf8' -> 'C.UTF-8' to 'en_US.UTF-8'877# updated 'de_it' -> 'de_IT.ISO8859-1' to 'de_IT.UTF-8'878# removed 'de_li.utf8'879# updated 'en_il' -> 'en_IL.UTF-8' to 'en_IL.ISO8859-1'880# removed 'english.iso88591'881# updated 'es_cu' -> 'es_CU.UTF-8' to 'es_CU.ISO8859-1'882# updated 'russian' -> 'ru_RU.KOI8-R' to 'ru_RU.ISO8859-5'883# updated 'sr@latn' -> 'sr_CS.UTF-8@latin' to 'sr_RS.UTF-8@latin'884# removed 'univ'885# removed 'universal'886#887# SS 2025-06-10:888# Remove 'c.utf8' -> 'en_US.UTF-8' because 'en_US.UTF-8' does not exist889# on all platforms.890 891locale_alias = {892 'a3': 'az_AZ.KOI8-C',893 'a3_az': 'az_AZ.KOI8-C',894 'a3_az.koic': 'az_AZ.KOI8-C',895 'aa_dj': 'aa_DJ.ISO8859-1',896 'aa_er': 'aa_ER.UTF-8',897 'aa_et': 'aa_ET.UTF-8',898 'af': 'af_ZA.ISO8859-1',899 'af_za': 'af_ZA.ISO8859-1',900 'agr_pe': 'agr_PE.UTF-8',901 'ak_gh': 'ak_GH.UTF-8',902 'am': 'am_ET.UTF-8',903 'am_et': 'am_ET.UTF-8',904 'american': 'en_US.ISO8859-1',905 'an_es': 'an_ES.ISO8859-15',906 'anp_in': 'anp_IN.UTF-8',907 'ar': 'ar_AA.ISO8859-6',908 'ar_aa': 'ar_AA.ISO8859-6',909 'ar_ae': 'ar_AE.ISO8859-6',910 'ar_bh': 'ar_BH.ISO8859-6',911 'ar_dz': 'ar_DZ.ISO8859-6',912 'ar_eg': 'ar_EG.ISO8859-6',913 'ar_in': 'ar_IN.UTF-8',914 'ar_iq': 'ar_IQ.ISO8859-6',915 'ar_jo': 'ar_JO.ISO8859-6',916 'ar_kw': 'ar_KW.ISO8859-6',917 'ar_lb': 'ar_LB.ISO8859-6',918 'ar_ly': 'ar_LY.ISO8859-6',919 'ar_ma': 'ar_MA.ISO8859-6',920 'ar_om': 'ar_OM.ISO8859-6',921 'ar_qa': 'ar_QA.ISO8859-6',922 'ar_sa': 'ar_SA.ISO8859-6',923 'ar_sd': 'ar_SD.ISO8859-6',924 'ar_ss': 'ar_SS.UTF-8',925 'ar_sy': 'ar_SY.ISO8859-6',926 'ar_tn': 'ar_TN.ISO8859-6',927 'ar_ye': 'ar_YE.ISO8859-6',928 'arabic': 'ar_AA.ISO8859-6',929 'as': 'as_IN.UTF-8',930 'as_in': 'as_IN.UTF-8',931 'ast_es': 'ast_ES.ISO8859-15',932 'ayc_pe': 'ayc_PE.UTF-8',933 'az': 'az_AZ.ISO8859-9E',934 'az_az': 'az_AZ.ISO8859-9E',935 'az_az.iso88599e': 'az_AZ.ISO8859-9E',936 'az_ir': 'az_IR.UTF-8',937 'be': 'be_BY.CP1251',938 'be@latin': 'be_BY.UTF-8@latin',939 'be_bg.utf8': 'bg_BG.UTF-8',940 'be_by': 'be_BY.CP1251',941 'be_by@latin': 'be_BY.UTF-8@latin',942 'bem_zm': 'bem_ZM.UTF-8',943 'ber_dz': 'ber_DZ.UTF-8',944 'ber_ma': 'ber_MA.UTF-8',945 'bg': 'bg_BG.CP1251',946 'bg_bg': 'bg_BG.CP1251',947 'bhb_in.utf8': 'bhb_IN.UTF-8',948 'bho_in': 'bho_IN.UTF-8',949 'bho_np': 'bho_NP.UTF-8',950 'bi_vu': 'bi_VU.UTF-8',951 'bn_bd': 'bn_BD.UTF-8',952 'bn_in': 'bn_IN.UTF-8',953 'bo_cn': 'bo_CN.UTF-8',954 'bo_in': 'bo_IN.UTF-8',955 'bokmal': 'nb_NO.ISO8859-1',956 'bokm\xe5l': 'nb_NO.ISO8859-1',957 'br': 'br_FR.ISO8859-1',958 'br_fr': 'br_FR.ISO8859-1',959 'brx_in': 'brx_IN.UTF-8',960 'bs': 'bs_BA.ISO8859-2',961 'bs_ba': 'bs_BA.ISO8859-2',962 'bulgarian': 'bg_BG.CP1251',963 'byn_er': 'byn_ER.UTF-8',964 'c': 'C',965 'c-french': 'fr_CA.ISO8859-1',966 'c.ascii': 'C',967 'c.en': 'C',968 'c.iso88591': 'en_US.ISO8859-1',969 'c_c': 'C',970 'c_c.c': 'C',971 'ca': 'ca_ES.ISO8859-1',972 'ca_ad': 'ca_AD.ISO8859-1',973 'ca_es': 'ca_ES.ISO8859-1',974 'ca_es@valencia': 'ca_ES.UTF-8@valencia',975 'ca_fr': 'ca_FR.ISO8859-1',976 'ca_it': 'ca_IT.ISO8859-1',977 'catalan': 'ca_ES.ISO8859-1',978 'ce_ru': 'ce_RU.UTF-8',979 'cextend': 'en_US.ISO8859-1',980 'chinese-s': 'zh_CN.eucCN',981 'chinese-t': 'zh_TW.eucTW',982 'chr_us': 'chr_US.UTF-8',983 'ckb_iq': 'ckb_IQ.UTF-8',984 'cmn_tw': 'cmn_TW.UTF-8',985 'crh_ru': 'crh_RU.UTF-8',986 'crh_ua': 'crh_UA.UTF-8',987 'croatian': 'hr_HR.ISO8859-2',988 'cs': 'cs_CZ.ISO8859-2',989 'cs_cs': 'cs_CZ.ISO8859-2',990 'cs_cz': 'cs_CZ.ISO8859-2',991 'csb_pl': 'csb_PL.UTF-8',992 'cv_ru': 'cv_RU.UTF-8',993 'cy': 'cy_GB.ISO8859-1',994 'cy_gb': 'cy_GB.ISO8859-1',995 'cz': 'cs_CZ.ISO8859-2',996 'cz_cz': 'cs_CZ.ISO8859-2',997 'czech': 'cs_CZ.ISO8859-2',998 'da': 'da_DK.ISO8859-1',999 'da_dk': 'da_DK.ISO8859-1',1000 'danish': 'da_DK.ISO8859-1',1001 'dansk': 'da_DK.ISO8859-1',1002 'de': 'de_DE.ISO8859-1',1003 'de_at': 'de_AT.ISO8859-1',1004 'de_be': 'de_BE.ISO8859-1',1005 'de_ch': 'de_CH.ISO8859-1',1006 'de_de': 'de_DE.ISO8859-1',1007 'de_it': 'de_IT.UTF-8',1008 'de_li': 'de_LI.ISO8859-1',1009 'de_lu': 'de_LU.ISO8859-1',1010 'deutsch': 'de_DE.ISO8859-1',1011 'doi_in': 'doi_IN.UTF-8',1012 'dsb_de': 'dsb_DE.UTF-8',1013 'dutch': 'nl_NL.ISO8859-1',1014 'dutch.iso88591': 'nl_BE.ISO8859-1',1015 'dv_mv': 'dv_MV.UTF-8',1016 'dz_bt': 'dz_BT.UTF-8',1017 'ee': 'ee_EE.ISO8859-4',1018 'ee_ee': 'ee_EE.ISO8859-4',1019 'eesti': 'et_EE.ISO8859-1',1020 'el': 'el_GR.ISO8859-7',1021 'el_cy': 'el_CY.ISO8859-7',1022 'el_gr': 'el_GR.ISO8859-7',1023 'el_gr@euro': 'el_GR.ISO8859-15',1024 'en': 'en_US.ISO8859-1',1025 'en_ag': 'en_AG.UTF-8',1026 'en_au': 'en_AU.ISO8859-1',1027 'en_be': 'en_BE.ISO8859-1',1028 'en_bw': 'en_BW.ISO8859-1',1029 'en_ca': 'en_CA.ISO8859-1',1030 'en_dk': 'en_DK.ISO8859-1',1031 'en_dl.utf8': 'en_DL.UTF-8',1032 'en_gb': 'en_GB.ISO8859-1',1033 'en_hk': 'en_HK.ISO8859-1',1034 'en_ie': 'en_IE.ISO8859-1',1035 'en_il': 'en_IL.ISO8859-1',1036 'en_in': 'en_IN.ISO8859-1',1037 'en_ng': 'en_NG.UTF-8',1038 'en_nz': 'en_NZ.ISO8859-1',1039 'en_ph': 'en_PH.ISO8859-1',1040 'en_sc.utf8': 'en_SC.UTF-8',1041 'en_sg': 'en_SG.ISO8859-1',1042 'en_uk': 'en_GB.ISO8859-1',1043 'en_us': 'en_US.ISO8859-1',1044 'en_us@euro@euro': 'en_US.ISO8859-15',1045 'en_za': 'en_ZA.ISO8859-1',1046 'en_zm': 'en_ZM.UTF-8',1047 'en_zw': 'en_ZW.ISO8859-1',1048 'en_zw.utf8': 'en_ZS.UTF-8',1049 'eng_gb': 'en_GB.ISO8859-1',1050 'english': 'en_EN.ISO8859-1',1051 'english_uk': 'en_GB.ISO8859-1',1052 'english_united-states': 'en_US.ISO8859-1',1053 'english_united-states.437': 'C',1054 'english_us': 'en_US.ISO8859-1',1055 'eo': 'eo_XX.ISO8859-3',1056 'eo.utf8': 'eo.UTF-8',1057 'eo_eo': 'eo_EO.ISO8859-3',1058 'eo_us.utf8': 'eo_US.UTF-8',1059 'eo_xx': 'eo_XX.ISO8859-3',1060 'es': 'es_ES.ISO8859-1',1061 'es_ar': 'es_AR.ISO8859-1',1062 'es_bo': 'es_BO.ISO8859-1',1063 'es_cl': 'es_CL.ISO8859-1',1064 'es_co': 'es_CO.ISO8859-1',1065 'es_cr': 'es_CR.ISO8859-1',1066 'es_cu': 'es_CU.ISO8859-1',1067 'es_do': 'es_DO.ISO8859-1',1068 'es_ec': 'es_EC.ISO8859-1',1069 'es_es': 'es_ES.ISO8859-1',1070 'es_gt': 'es_GT.ISO8859-1',1071 'es_hn': 'es_HN.ISO8859-1',1072 'es_mx': 'es_MX.ISO8859-1',1073 'es_ni': 'es_NI.ISO8859-1',1074 'es_pa': 'es_PA.ISO8859-1',1075 'es_pe': 'es_PE.ISO8859-1',1076 'es_pr': 'es_PR.ISO8859-1',1077 'es_py': 'es_PY.ISO8859-1',1078 'es_sv': 'es_SV.ISO8859-1',1079 'es_us': 'es_US.ISO8859-1',1080 'es_uy': 'es_UY.ISO8859-1',1081 'es_ve': 'es_VE.ISO8859-1',1082 'estonian': 'et_EE.ISO8859-1',1083 'et': 'et_EE.ISO8859-15',1084 'et_ee': 'et_EE.ISO8859-15',1085 'eu': 'eu_ES.ISO8859-1',1086 'eu_es': 'eu_ES.ISO8859-1',1087 'eu_fr': 'eu_FR.ISO8859-1',1088 'fa': 'fa_IR.UTF-8',1089 'fa_ir': 'fa_IR.UTF-8',1090 'fa_ir.isiri3342': 'fa_IR.ISIRI-3342',1091 'ff_sn': 'ff_SN.UTF-8',1092 'fi': 'fi_FI.ISO8859-15',1093 'fi_fi': 'fi_FI.ISO8859-15',1094 'fil_ph': 'fil_PH.UTF-8',1095 'finnish': 'fi_FI.ISO8859-1',1096 'fo': 'fo_FO.ISO8859-1',1097 'fo_fo': 'fo_FO.ISO8859-1',1098 'fr': 'fr_FR.ISO8859-1',1099 'fr_be': 'fr_BE.ISO8859-1',1100 'fr_ca': 'fr_CA.ISO8859-1',1101 'fr_ch': 'fr_CH.ISO8859-1',1102 'fr_fr': 'fr_FR.ISO8859-1',1103 'fr_lu': 'fr_LU.ISO8859-1',1104 'fran\xe7ais': 'fr_FR.ISO8859-1',1105 'fre_fr': 'fr_FR.ISO8859-1',1106 'french': 'fr_FR.ISO8859-1',1107 'french.iso88591': 'fr_CH.ISO8859-1',1108 'french_france': 'fr_FR.ISO8859-1',1109 'fur_it': 'fur_IT.UTF-8',1110 'fy_de': 'fy_DE.UTF-8',1111 'fy_nl': 'fy_NL.UTF-8',1112 'ga': 'ga_IE.ISO8859-1',1113 'ga_ie': 'ga_IE.ISO8859-1',1114 'galego': 'gl_ES.ISO8859-1',1115 'galician': 'gl_ES.ISO8859-1',1116 'gbm_in': 'gbm_IN.UTF-8',1117 'gd': 'gd_GB.ISO8859-1',1118 'gd_gb': 'gd_GB.ISO8859-1',1119 'ger_de': 'de_DE.ISO8859-1',1120 'german': 'de_DE.ISO8859-1',1121 'german.iso88591': 'de_CH.ISO8859-1',1122 'german_germany': 'de_DE.ISO8859-1',1123 'gez_er': 'gez_ER.UTF-8',1124 'gez_et': 'gez_ET.UTF-8',1125 'gl': 'gl_ES.ISO8859-1',1126 'gl_es': 'gl_ES.ISO8859-1',1127 'greek': 'el_GR.ISO8859-7',1128 'gu_in': 'gu_IN.UTF-8',1129 'gv': 'gv_GB.ISO8859-1',1130 'gv_gb': 'gv_GB.ISO8859-1',1131 'ha_ng': 'ha_NG.UTF-8',1132 'hak_tw': 'hak_TW.UTF-8',1133 'he': 'he_IL.ISO8859-8',1134 'he_il': 'he_IL.ISO8859-8',1135 'hebrew': 'he_IL.ISO8859-8',1136 'hi': 'hi_IN.ISCII-DEV',1137 'hi_in': 'hi_IN.ISCII-DEV',1138 'hi_in.isciidev': 'hi_IN.ISCII-DEV',1139 'hif_fj': 'hif_FJ.UTF-8',1140 'hne': 'hne_IN.UTF-8',1141 'hne_in': 'hne_IN.UTF-8',1142 'hr': 'hr_HR.ISO8859-2',1143 'hr_hr': 'hr_HR.ISO8859-2',1144 'hrvatski': 'hr_HR.ISO8859-2',1145 'hsb_de': 'hsb_DE.ISO8859-2',1146 'ht_ht': 'ht_HT.UTF-8',1147 'hu': 'hu_HU.ISO8859-2',1148 'hu_hu': 'hu_HU.ISO8859-2',1149 'hungarian': 'hu_HU.ISO8859-2',1150 'hy_am': 'hy_AM.UTF-8',1151 'hy_am.armscii8': 'hy_AM.ARMSCII_8',1152 'ia': 'ia.UTF-8',1153 'ia_fr': 'ia_FR.UTF-8',1154 'icelandic': 'is_IS.ISO8859-1',1155 'id': 'id_ID.ISO8859-1',1156 'id_id': 'id_ID.ISO8859-1',1157 'ie': 'ie.UTF-8',1158 'ig_ng': 'ig_NG.UTF-8',1159 'ik_ca': 'ik_CA.UTF-8',1160 'in': 'id_ID.ISO8859-1',1161 'in_id': 'id_ID.ISO8859-1',1162 'is': 'is_IS.ISO8859-1',1163 'is_is': 'is_IS.ISO8859-1',1164 'iso-8859-1': 'en_US.ISO8859-1',1165 'iso-8859-15': 'en_US.ISO8859-15',1166 'iso8859-1': 'en_US.ISO8859-1',1167 'iso8859-15': 'en_US.ISO8859-15',1168 'iso_8859_1': 'en_US.ISO8859-1',1169 'iso_8859_15': 'en_US.ISO8859-15',1170 'it': 'it_IT.ISO8859-1',1171 'it_ch': 'it_CH.ISO8859-1',1172 'it_it': 'it_IT.ISO8859-1',1173 'italian': 'it_IT.ISO8859-1',1174 'iu': 'iu_CA.NUNACOM-8',1175 'iu_ca': 'iu_CA.NUNACOM-8',1176 'iu_ca.nunacom8': 'iu_CA.NUNACOM-8',1177 'iw': 'he_IL.ISO8859-8',1178 'iw_il': 'he_IL.ISO8859-8',1179 'iw_il.utf8': 'iw_IL.UTF-8',1180 'ja': 'ja_JP.eucJP',1181 'ja_jp': 'ja_JP.eucJP',1182 'ja_jp.euc': 'ja_JP.eucJP',1183 'ja_jp.mscode': 'ja_JP.SJIS',1184 'ja_jp.pck': 'ja_JP.SJIS',1185 'japan': 'ja_JP.eucJP',1186 'japanese': 'ja_JP.eucJP',1187 'japanese-euc': 'ja_JP.eucJP',1188 'japanese.euc': 'ja_JP.eucJP',1189 'jp_jp': 'ja_JP.eucJP',1190 'ka': 'ka_GE.GEORGIAN-ACADEMY',1191 'ka_ge': 'ka_GE.GEORGIAN-ACADEMY',1192 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY',1193 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS',1194 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY',1195 'kab_dz': 'kab_DZ.UTF-8',1196 'kk_kz': 'kk_KZ.ptcp154',1197 'kl': 'kl_GL.ISO8859-1',1198 'kl_gl': 'kl_GL.ISO8859-1',1199 'km_kh': 'km_KH.UTF-8',1200 'kn': 'kn_IN.UTF-8',