"Fossies" - the Fresh Open Source Software Archive

Member "roundup-2.0.0/roundup/i18n.py" (29 Feb 2020, 7764 Bytes) of package /linux/www/roundup-2.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "i18n.py": 1.6.1_vs_2.0.0.

    1 #
    2 # Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
    3 # This module is free software, and you may redistribute it and/or modify
    4 # under the same terms as Python, so long as this copyright message and
    5 # disclaimer are retained in their original form.
    6 #
    7 # IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
    8 # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
    9 # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
   10 # POSSIBILITY OF SUCH DAMAGE.
   11 #
   12 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
   13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   14 # FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
   15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
   16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
   17 #
   18 """
   19 RoundUp Internationalization (I18N)
   20 
   21 To use this module, the following code should be used::
   22 
   23     from roundup.i18n import _
   24     ...
   25     print _("Some text that can be translated")
   26 
   27 Note that to enable re-ordering of inserted texts in formatting strings
   28 (which can easily happen if a sentence has to be re-ordered due to
   29 grammatical changes), translatable formats should use named format specs::
   30 
   31     ... _('Index of %(classname)s') % {'classname': cn} ...
   32 
   33 Also, this eases the job of translators since they have some context what
   34 the dynamic portion of a message really means.
   35 """
   36 __docformat__ = 'restructuredtext'
   37 
   38 import gettext as gettext_module
   39 import os
   40 
   41 from roundup import msgfmt
   42 from roundup.anypy.strings import is_us
   43 
   44 # List of directories for mo file search (see SF bug 1219689)
   45 LOCALE_DIRS = [
   46     gettext_module._default_localedir,
   47 ]
   48 # compute mo location relative to roundup installation directory
   49 # (prefix/lib/python/site-packages/roundup/msgfmt.py on posix systems,
   50 # prefix/lib/site-packages/roundup/msgfmt.py on windows).
   51 # locale root is prefix/share/locale.
   52 if os.name == "nt":
   53     _mo_path = [".."] * 4 + ["share", "locale"]
   54 else:
   55     _mo_path = [".."] * 5 + ["share", "locale"]
   56 _mo_path = os.path.normpath(os.path.join(msgfmt.__file__, *_mo_path))
   57 if _mo_path not in LOCALE_DIRS:
   58     LOCALE_DIRS.append(_mo_path)
   59 del _mo_path
   60 
   61 # Roundup text domain
   62 DOMAIN = "roundup"
   63 
   64 RoundupNullTranslations = gettext_module.NullTranslations
   65 RoundupTranslations = gettext_module.GNUTranslations
   66 
   67 
   68 def find_locales(language=None):
   69     """Return normalized list of locale names to try for given language
   70 
   71     Argument 'language' may be a single language code or a list of codes.
   72     If 'language' is omitted or None, use locale settings in OS environment.
   73 
   74     """
   75     # body of this function is borrowed from gettext_module.find()
   76     if language is None:
   77         languages = []
   78         for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
   79             val = os.environ.get(envar)
   80             if val:
   81                 languages = val.split(':')
   82                 break
   83     elif is_us(language):
   84         languages = [language]
   85     else:
   86         # 'language' must be iterable
   87         languages = language
   88     # now normalize and expand the languages
   89     nelangs = []
   90     for lang in languages:
   91         for nelang in gettext_module._expand_lang(lang):
   92             if nelang not in nelangs:
   93                 nelangs.append(nelang)
   94     return nelangs
   95 
   96 
   97 def get_mofile(languages, localedir, domain=None):
   98     """Return the first of .mo files found in localedir for languages
   99 
  100     Parameters:
  101         languages:
  102             list of locale names to try
  103         localedir:
  104             path to directory containing locale files.
  105             Usually this is either gettext_module._default_localedir
  106             or 'locale' subdirectory in the tracker home.
  107         domain:
  108             optional name of messages domain.
  109             If omitted or None, work with simplified
  110             locale directory, as used in tracker homes:
  111             message catalogs are kept in files locale.po
  112             instead of locale/LC_MESSAGES/domain.po
  113 
  114     Return the path of the first .mo file found.
  115     If nothing found, return None.
  116 
  117     Automatically compile .po files if necessary.
  118 
  119     """
  120     for locale in languages:
  121         if locale == "C":
  122             break
  123         if domain:
  124             basename = os.path.join(localedir, locale, "LC_MESSAGES", domain)
  125         else:
  126             basename = os.path.join(localedir, locale)
  127         # look for message catalog files, check timestamps
  128         mofile = basename + ".mo"
  129         if os.path.isfile(mofile):
  130             motime = os.path.getmtime(mofile)
  131         else:
  132             motime = 0
  133         pofile = basename + ".po"
  134         if os.path.isfile(pofile):
  135             potime = os.path.getmtime(pofile)
  136         else:
  137             potime = 0
  138         # see what we've found
  139         if motime < potime:
  140             # compile
  141             mo = msgfmt.Msgfmt(pofile).get()
  142             open(mofile, 'wb').write(mo)
  143         elif motime == 0:
  144             # no files found - proceed to the next locale name
  145             continue
  146         # .mo file found or made
  147         return mofile
  148     return None
  149 
  150 
  151 def get_translation(language=None, tracker_home=None,
  152                     translation_class=RoundupTranslations,
  153                     null_translation_class=RoundupNullTranslations):
  154     """Return Translation object for given language and domain
  155 
  156     Argument 'language' may be a single language code or a list of codes.
  157     If 'language' is omitted or None, use locale settings in OS environment.
  158 
  159     Arguments 'translation_class' and 'null_translation_class'
  160     specify the classes that are instantiated for existing
  161     and non-existing translations, respectively.
  162 
  163     """
  164     mofiles = []
  165     # locale directory paths
  166     if tracker_home is None:
  167         tracker_locale = None
  168     else:
  169         tracker_locale = os.path.join(tracker_home, "locale")
  170     # get the list of locales
  171     locales = find_locales(language)
  172     # add mofiles found in the tracker, then in the system locale directory
  173     if tracker_locale:
  174         mofiles.append(get_mofile(locales, tracker_locale))
  175     for system_locale in LOCALE_DIRS:
  176         mofiles.append(get_mofile(locales, system_locale, DOMAIN))
  177     # we want to fall back to english unless english is selected language
  178     if "en" not in locales:
  179         locales = find_locales("en")
  180         # add mofiles found in the tracker, then in the system locale directory
  181         if tracker_locale:
  182             mofiles.append(get_mofile(locales, tracker_locale))
  183         for system_locale in LOCALE_DIRS:
  184             mofiles.append(get_mofile(locales, system_locale, DOMAIN))
  185     # filter out elements that are not found
  186     mofiles = filter(None, mofiles)
  187     translator = None
  188     for mofile in mofiles:
  189         try:
  190             mo = open(mofile, "rb")
  191             if translator is None:
  192                 translator = translation_class(mo)
  193             else:
  194                 # note: current implementation of gettext_module
  195                 #   always adds fallback to the end of the fallback chain.
  196                 translator.add_fallback(translation_class(mo))
  197         except IOError:
  198             # ignore unreadable .mo files
  199             pass
  200     if translator is None:
  201         translator = null_translation_class()
  202     return translator
  203 
  204 
  205 # static translations object
  206 translation = get_translation()
  207 # static translation functions
  208 _ = gettext = translation.gettext
  209 try:
  210     # Python 2.
  211     ugettext = translation.ugettext
  212 except AttributeError:
  213     # Python 3.
  214     ugettext = translation.gettext
  215 ngettext = translation.ngettext
  216 try:
  217     # Python 2.
  218     ungettext = translation.ungettext
  219 except AttributeError:
  220     # Python 3.
  221     ungettext = translation.ngettext
  222 
  223 # vim: set filetype=python sts=4 sw=4 et si :