update_locales.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #!/usr/bin/env python
  2. # SPDX-License-Identifier: AGPL-3.0-or-later
  3. """Update locale names in :origin:`searx/data/locales.json` used by
  4. :ref:`searx.locales`
  5. - :py:obj:`searx.locales.RTL_LOCALES`
  6. - :py:obj:`searx.locales.LOCALE_NAMES`
  7. """
  8. from __future__ import annotations
  9. from typing import Set
  10. import json
  11. from pathlib import Path
  12. import os
  13. import babel
  14. import babel.languages
  15. import babel.core
  16. from searx import searx_dir
  17. from searx.locales import (
  18. ADDITIONAL_TRANSLATIONS,
  19. LOCALE_BEST_MATCH,
  20. get_translation_locales,
  21. )
  22. LOCALE_DATA_FILE = Path(searx_dir) / 'data' / 'locales.json'
  23. TRANSLATOINS_FOLDER = Path(searx_dir) / 'translations'
  24. def main():
  25. LOCALE_NAMES = {}
  26. RTL_LOCALES: Set[str] = set()
  27. for tag, descr in ADDITIONAL_TRANSLATIONS.items():
  28. locale = babel.Locale.parse(LOCALE_BEST_MATCH[tag], sep='-')
  29. LOCALE_NAMES[tag] = descr
  30. if locale.text_direction == 'rtl':
  31. RTL_LOCALES.add(tag)
  32. for tag in LOCALE_BEST_MATCH:
  33. descr = LOCALE_NAMES.get(tag)
  34. if not descr:
  35. locale = babel.Locale.parse(tag, sep='-')
  36. LOCALE_NAMES[tag] = get_locale_descr(locale, tag.replace('-', '_'))
  37. if locale.text_direction == 'rtl':
  38. RTL_LOCALES.add(tag)
  39. for tr_locale in get_translation_locales():
  40. sxng_tag = tr_locale.replace('_', '-')
  41. descr = LOCALE_NAMES.get(sxng_tag)
  42. if not descr:
  43. locale = babel.Locale.parse(tr_locale)
  44. LOCALE_NAMES[sxng_tag] = get_locale_descr(locale, tr_locale)
  45. if locale.text_direction == 'rtl':
  46. RTL_LOCALES.add(sxng_tag)
  47. content = {
  48. "LOCALE_NAMES": LOCALE_NAMES,
  49. "RTL_LOCALES": sorted(RTL_LOCALES),
  50. }
  51. with open(LOCALE_DATA_FILE, 'w', encoding='utf-8') as f:
  52. json.dump(content, f, indent=2, sort_keys=True, ensure_ascii=False)
  53. def get_locale_descr(locale: babel.Locale, tr_locale):
  54. """Get locale name e.g. 'Français - fr' or 'Português (Brasil) - pt-BR'
  55. :param locale: instance of :py:class:`Locale`
  56. :param tr_locale: name e.g. 'fr' or 'pt_BR' (delimiter is *underscore*)
  57. """
  58. native_language, native_territory = _get_locale_descr(locale, tr_locale)
  59. english_language, english_territory = _get_locale_descr(locale, 'en')
  60. if native_territory == english_territory:
  61. english_territory = None
  62. if not native_territory and not english_territory:
  63. # none territory name
  64. if native_language == english_language:
  65. return native_language
  66. return native_language + ' (' + english_language + ')'
  67. else:
  68. result = native_language + ', ' + native_territory + ' (' + english_language
  69. if english_territory:
  70. return result + ', ' + english_territory + ')'
  71. return result + ')'
  72. def _get_locale_descr(locale: babel.Locale, tr_locale: str) -> tuple[str, str]:
  73. language_name = locale.get_language_name(tr_locale).capitalize() # type: ignore
  74. if language_name and ('a' <= language_name[0] <= 'z'):
  75. language_name = language_name.capitalize()
  76. territory_name: str = locale.get_territory_name(tr_locale) # type: ignore
  77. return language_name, territory_name
  78. if __name__ == "__main__":
  79. main()