1
0

__init__.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # $Id: __init__.py 9030 2022-03-05 23:28:32Z milde $
  2. # Author: David Goodger <goodger@python.org>
  3. # Copyright: This module has been placed in the public domain.
  4. # Internationalization details are documented in
  5. # <https://docutils.sourceforge.io/docs/howto/i18n.html>.
  6. """
  7. This package contains modules for language-dependent features of Docutils.
  8. """
  9. __docformat__ = 'reStructuredText'
  10. from importlib import import_module
  11. from docutils.utils import normalize_language_tag
  12. class LanguageImporter:
  13. """Import language modules.
  14. When called with a BCP 47 language tag, instances return a module
  15. with localisations from `docutils.languages` or the PYTHONPATH.
  16. If there is no matching module, warn (if a `reporter` is passed)
  17. and fall back to English.
  18. """
  19. packages = ('docutils.languages.', '')
  20. warn_msg = ('Language "%s" not supported: '
  21. 'Docutils-generated text will be in English.')
  22. fallback = 'en'
  23. # TODO: use a dummy module returning empty strings?, configurable?
  24. def __init__(self):
  25. self.cache = {}
  26. def import_from_packages(self, name, reporter=None):
  27. """Try loading module `name` from `self.packages`."""
  28. module = None
  29. for package in self.packages:
  30. try:
  31. module = import_module(package+name)
  32. self.check_content(module)
  33. except (ImportError, AttributeError):
  34. if reporter and module:
  35. reporter.info(f'{module} is no complete '
  36. 'Docutils language module.')
  37. elif reporter:
  38. reporter.info(f'Module "{package+name}" not found.')
  39. continue
  40. break
  41. return module
  42. def check_content(self, module):
  43. """Check if we got a Docutils language module."""
  44. if not (isinstance(module.labels, dict)
  45. and isinstance(module.bibliographic_fields, dict)
  46. and isinstance(module.author_separators, list)):
  47. raise ImportError
  48. def __call__(self, language_code, reporter=None):
  49. try:
  50. return self.cache[language_code]
  51. except KeyError:
  52. pass
  53. for tag in normalize_language_tag(language_code):
  54. tag = tag.replace('-', '_') # '-' not valid in module names
  55. module = self.import_from_packages(tag, reporter)
  56. if module is not None:
  57. break
  58. else:
  59. if reporter:
  60. reporter.warning(self.warn_msg % language_code)
  61. if self.fallback:
  62. module = self.import_from_packages(self.fallback)
  63. if reporter and (language_code != 'en'):
  64. reporter.info('Using %s for language "%s".'
  65. % (module, language_code))
  66. self.cache[language_code] = module
  67. return module
  68. get_language = LanguageImporter()