mercurial/i18n.py
author Martin von Zweigbergk <martinvonz@gmail.com>
Sun, 12 Oct 2014 00:00:13 -0700
changeset 23238 39eb9f78f968
parent 23031 3c0983cc279e
child 25955 2c07c6884394
permissions -rw-r--r--
context.status: move manifest caching trick to _buildstatus() In basectx._buildstatus(), we read the manifests for the two revisions being compared. For "caching reasons" unknown to me, it is better to read the earlier manifest first, which basectx._prestatus() takes care of. However, if the 'self' context is a committablectx and the 'other' context is the parent of the working directory (as in the very common case of plain "hg status"), there is no need to read any manifests at all -- all that's needed is the dirstate status. To avoid reading the manifests, _prestatus() is overridden in committablectx and avoids calling its super method, and _buildstatus() calls its super method only if the 'other' context is not the parent of the working directory. It seems easier to follow what's happening if we move the pre-fetching to _buildstatus() just before the place where the manifests are fetched. We just need to add an extra check that the revision is not None to handle the case that was previously handled by subclass overriding. That also makes it safe for committablectx._prestatus() to call its parent, although the latter now becomes empty, so we won't bother.

# i18n.py - internationalization support for mercurial
#
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

import encoding
import gettext as gettextmod, sys, os, locale

# modelled after templater.templatepath:
if getattr(sys, 'frozen', None) is not None:
    module = sys.executable
else:
    module = __file__


_languages = None
if (os.name == 'nt'
    and 'LANGUAGE' not in os.environ
    and 'LC_ALL' not in os.environ
    and 'LC_MESSAGES' not in os.environ
    and 'LANG' not in os.environ):
    # Try to detect UI language by "User Interface Language Management" API
    # if no locale variables are set. Note that locale.getdefaultlocale()
    # uses GetLocaleInfo(), which may be different from UI language.
    # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx )
    try:
        import ctypes
        langid = ctypes.windll.kernel32.GetUserDefaultUILanguage()
        _languages = [locale.windows_locale[langid]]
    except (ImportError, AttributeError, KeyError):
        # ctypes not found or unknown langid
        pass

_ugettext = None

def setdatapath(datapath):
    localedir = os.path.join(datapath, 'locale')
    t = gettextmod.translation('hg', localedir, _languages, fallback=True)
    global _ugettext
    _ugettext = t.ugettext

_msgcache = {}

def gettext(message):
    """Translate message.

    The message is looked up in the catalog to get a Unicode string,
    which is encoded in the local encoding before being returned.

    Important: message is restricted to characters in the encoding
    given by sys.getdefaultencoding() which is most likely 'ascii'.
    """
    # If message is None, t.ugettext will return u'None' as the
    # translation whereas our callers expect us to return None.
    if message is None or not _ugettext:
        return message

    if message not in _msgcache:
        if type(message) is unicode:
            # goofy unicode docstrings in test
            paragraphs = message.split(u'\n\n')
        else:
            paragraphs = [p.decode("ascii") for p in message.split('\n\n')]
        # Be careful not to translate the empty string -- it holds the
        # meta data of the .po file.
        u = u'\n\n'.join([p and _ugettext(p) or '' for p in paragraphs])
        try:
            # encoding.tolocal cannot be used since it will first try to
            # decode the Unicode string. Calling u.decode(enc) really
            # means u.encode(sys.getdefaultencoding()).decode(enc). Since
            # the Python encoding defaults to 'ascii', this fails if the
            # translated string use non-ASCII characters.
            _msgcache[message] = u.encode(encoding.encoding, "replace")
        except LookupError:
            # An unknown encoding results in a LookupError.
            _msgcache[message] = message
    return _msgcache[message]

def _plain():
    if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
        return False
    exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
    return 'i18n' not in exceptions

if _plain():
    _ = lambda message: message
else:
    _ = gettext