123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- # MODULE: grass
- #
- # AUTHOR(S): Vaclav Petras <wenzeslaus gmail com>
- #
- # PURPOSE: Top level file of the grass package and its initialization
- #
- # COPYRIGHT: (C) 2021 Vaclav Petras, and by the GRASS Development Team
- #
- # This program is free software under the GNU General Public
- # License (>=v2). Read the file COPYING that comes with GRASS
- # for details.
- """Top-level GRASS GIS Python package
- Importing the package (or any subpackage) initializes translation functions
- so that the function ``_`` appears in the global namespace (as an additional build-in).
- """
- import builtins as _builtins
- import os
- # Setup translations
- #
- # The translations in the GRASS GIS Python package grass, GRASS Python modules
- # (scripts), and the wxPython GUI (wxGUI) are handled as application translations,
- # rather than Python module or package translations. This means that that translation
- # function called `_` (underscore) is added to buildins namespace. When the grass
- # package or any subpackage (or an object from there) is imported, the `_` function
- # becomes available globally (i.e. for all Python code in the same process). This is
- # the good part.
- # Unfortunately, creating `_` in the global namespace has unitended consequences such
- # as issues in interactive shells, with doctests, and it is conflicting with a common
- # practice of using `_` for unused variables. This is the same behavior as with the
- # common function `gettext.install()` which also adds `_` into the global namespace.
- # The solution to this is to use the module translations approach instead of
- # application translation approach. Without changing the overall approach, the current
- # code can be modified to allow for using imports of translation functions instead of
- # relying on the buildins when desired as a transitional state before removing the
- # modification of buildins.
- #
- # The current code mitigates two other issues associated with `gettext.install()`
- # approach: First, it delays initialization of translations to the time when they are
- # needed instead of doing it during import time (and possibly failing when
- # environmental variables pointing to the source file are not set properly). Second,
- # it adds multiple domains as fallback unlike `gettext.install()` which simply uses
- # the last used domain.
- #
- # For more info, please check the following links:
- # - https://docs.python.org/3/library/gettext.html#gettext.translation
- # - https://github.com/python/cpython/blob/main/Lib/gettext.py (esp. install function)
- # - https://pymotw.com/3//gettext/index.html#application-vs-module-localization
- # - https://www.wefearchange.org/2012/06/the-right-way-to-internationalize-your.html
- def _translate(text):
- """Get translated version of text
- The first call to this function initializes translations, i.e., simply importing
- the package does not require the translations to be availabe. However, a first
- call to translate a message will do the initialization first before translating
- the message.
- """
- if _translate.translation is None:
- # Initialize translations if needed. This should happen (only) during the
- # the first call of the function.
- try:
- import gettext # pylint: disable=import-outside-toplevel
- gisbase = os.environ["GISBASE"]
- locale_dir = os.path.join(gisbase, "locale")
- # With fallback set to True, not finding the translations files for
- # a language or domain results in a use of null translation, so this
- # does not raise an exception even if the locale settings is broken
- # or the translation files were not installed.
- fallback = True
- translation = gettext.translation(
- "grasslibs", locale_dir, fallback=fallback
- )
- # Add other domains as fallback.
- translation.add_fallback(
- gettext.translation("grassmods", locale_dir, fallback=fallback)
- )
- translation.add_fallback(
- gettext.translation("grasswxpy", locale_dir, fallback=fallback)
- )
- # Store the resulting translation object.
- _translate.translation = translation
- except (KeyError, ImportError):
- # If the environmental variable is not set or there is no gettext,
- # use null translation as an ultimate fallback.
- _translate.translation = gettext.NullTranslations()
- return _translate.translation.gettext(text)
- # Initialize the translation attribute of the translate function to indicate
- # that the translations are not initialized.
- _translate.translation = None
- _builtins.__dict__["_"] = _translate
- __all__ = ["script", "temporal"]
- if os.path.exists(os.path.join(os.path.dirname(__file__), "lib", "__init__.py")):
- __all__.append("lib")
|