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