makelocalealias.py 4.7 KB

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