1#!/usr/bin/env python3 2""" 3 Convert the X11 locale.alias file into a mapping dictionary suitable 4 for locale.py. 5 6 Written by Marc-Andre Lemburg <mal@genix.com>, 2004-12-10. 7 8""" 9import locale 10import sys 11_locale = locale 12 13# Location of the X11 alias file. 14LOCALE_ALIAS = '/usr/share/X11/locale/locale.alias' 15# Location of the glibc SUPPORTED locales file. 16SUPPORTED = '/usr/share/i18n/SUPPORTED' 17 18def parse(filename): 19 20 with open(filename, encoding='latin1') as f: 21 lines = list(f) 22 data = {} 23 for line in lines: 24 line = line.strip() 25 if not line: 26 continue 27 if line[:1] == '#': 28 continue 29 locale, alias = line.split() 30 # Fix non-standard locale names, e.g. ks_IN@devanagari.UTF-8 31 if '@' in alias: 32 alias_lang, _, alias_mod = alias.partition('@') 33 if '.' in alias_mod: 34 alias_mod, _, alias_enc = alias_mod.partition('.') 35 alias = alias_lang + '.' + alias_enc + '@' + alias_mod 36 # Strip ':' 37 if locale[-1] == ':': 38 locale = locale[:-1] 39 # Lower-case locale 40 locale = locale.lower() 41 # Ignore one letter locale mappings (except for 'c') 42 if len(locale) == 1 and locale != 'c': 43 continue 44 # Normalize encoding, if given 45 if '.' in locale: 46 lang, encoding = locale.split('.')[:2] 47 encoding = encoding.replace('-', '') 48 encoding = encoding.replace('_', '') 49 locale = lang + '.' + encoding 50 data[locale] = alias 51 return data 52 53def parse_glibc_supported(filename): 54 55 with open(filename, encoding='latin1') as f: 56 lines = list(f) 57 data = {} 58 for line in lines: 59 line = line.strip() 60 if not line: 61 continue 62 if line[:1] == '#': 63 continue 64 line = line.replace('/', ' ').strip() 65 line = line.rstrip('\\').rstrip() 66 words = line.split() 67 if len(words) != 2: 68 continue 69 alias, alias_encoding = words 70 # Lower-case locale 71 locale = alias.lower() 72 # Normalize encoding, if given 73 if '.' in locale: 74 lang, encoding = locale.split('.')[:2] 75 encoding = encoding.replace('-', '') 76 encoding = encoding.replace('_', '') 77 locale = lang + '.' + encoding 78 # Add an encoding to alias 79 alias, _, modifier = alias.partition('@') 80 alias = _locale._replace_encoding(alias, alias_encoding) 81 if modifier and not (modifier == 'euro' and alias_encoding == 'ISO-8859-15'): 82 alias += '@' + modifier 83 data[locale] = alias 84 return data 85 86def pprint(data): 87 items = sorted(data.items()) 88 for k, v in items: 89 print(' %-40s%a,' % ('%a:' % k, v)) 90 91def print_differences(data, olddata): 92 items = sorted(olddata.items()) 93 for k, v in items: 94 if k not in data: 95 print('# removed %a' % k) 96 elif olddata[k] != data[k]: 97 print('# updated %a -> %a to %a' % \ 98 (k, olddata[k], data[k])) 99 # Additions are not mentioned 100 101def optimize(data): 102 locale_alias = locale.locale_alias 103 locale.locale_alias = data.copy() 104 for k, v in data.items(): 105 del locale.locale_alias[k] 106 if locale.normalize(k) != v: 107 locale.locale_alias[k] = v 108 newdata = locale.locale_alias 109 errors = check(data) 110 locale.locale_alias = locale_alias 111 if errors: 112 sys.exit(1) 113 return newdata 114 115def check(data): 116 # Check that all alias definitions from the X11 file 117 # are actually mapped to the correct alias locales. 118 errors = 0 119 for k, v in data.items(): 120 if locale.normalize(k) != v: 121 print('ERROR: %a -> %a != %a' % (k, locale.normalize(k), v), 122 file=sys.stderr) 123 errors += 1 124 return errors 125 126if __name__ == '__main__': 127 import argparse 128 parser = argparse.ArgumentParser() 129 parser.add_argument('--locale-alias', default=LOCALE_ALIAS, 130 help='location of the X11 alias file ' 131 '(default: %a)' % LOCALE_ALIAS) 132 parser.add_argument('--glibc-supported', default=SUPPORTED, 133 help='location of the glibc SUPPORTED locales file ' 134 '(default: %a)' % SUPPORTED) 135 args = parser.parse_args() 136 137 data = locale.locale_alias.copy() 138 data.update(parse_glibc_supported(args.glibc_supported)) 139 data.update(parse(args.locale_alias)) 140 while True: 141 # Repeat optimization while the size is decreased. 142 n = len(data) 143 data = optimize(data) 144 if len(data) == n: 145 break 146 print_differences(data, locale.locale_alias) 147 print() 148 print('locale_alias = {') 149 pprint(data) 150 print('}') 151