mercurial/i18n.py
author Matt Mackall <mpm@selenic.com>
Thu, 16 Apr 2015 20:57:51 -0500
branchstable
changeset 24803 e89f909edffa
parent 23031 3c0983cc279e
child 25955 2c07c6884394
permissions -rw-r--r--
merge default into stable for 3.4 freeze
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     1
# i18n.py - internationalization support for mercurial
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     2
#
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     3
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     4
#
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9538
diff changeset
     6
# GNU General Public License version 2 or any later version.
1400
cf9a1233738a i18n first part: make '_' available for files who need it
Benoit Boissinot <benoit.boissinot@ens-lyon.org
parents:
diff changeset
     7
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8226
diff changeset
     8
import encoding
22638
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
     9
import gettext as gettextmod, sys, os, locale
7650
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    10
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    11
# modelled after templater.templatepath:
14975
b64538363dbe i18n: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 13849
diff changeset
    12
if getattr(sys, 'frozen', None) is not None:
7650
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    13
    module = sys.executable
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    14
else:
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    15
    module = __file__
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    16
85ae7aaf08e9 i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents: 3888
diff changeset
    17
21987
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    18
_languages = None
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    19
if (os.name == 'nt'
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    20
    and 'LANGUAGE' not in os.environ
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    21
    and 'LC_ALL' not in os.environ
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    22
    and 'LC_MESSAGES' not in os.environ
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    23
    and 'LANG' not in os.environ):
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    24
    # Try to detect UI language by "User Interface Language Management" API
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    25
    # if no locale variables are set. Note that locale.getdefaultlocale()
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    26
    # uses GetLocaleInfo(), which may be different from UI language.
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    27
    # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx )
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    28
    try:
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    29
        import ctypes
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    30
        langid = ctypes.windll.kernel32.GetUserDefaultUILanguage()
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    31
        _languages = [locale.windows_locale[langid]]
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    32
    except (ImportError, AttributeError, KeyError):
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    33
        # ctypes not found or unknown langid
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    34
        pass
4953cd193e84 i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents: 21746
diff changeset
    35
22638
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    36
_ugettext = None
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    37
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    38
def setdatapath(datapath):
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    39
    localedir = os.path.join(datapath, 'locale')
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    40
    t = gettextmod.translation('hg', localedir, _languages, fallback=True)
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    41
    global _ugettext
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    42
    _ugettext = t.ugettext
7651
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    43
23031
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    44
_msgcache = {}
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    45
7651
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    46
def gettext(message):
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    47
    """Translate message.
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    48
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    49
    The message is looked up in the catalog to get a Unicode string,
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    50
    which is encoded in the local encoding before being returned.
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    51
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    52
    Important: message is restricted to characters in the encoding
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    53
    given by sys.getdefaultencoding() which is most likely 'ascii'.
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    54
    """
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    55
    # If message is None, t.ugettext will return u'None' as the
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    56
    # translation whereas our callers expect us to return None.
22638
0d0350cfc7ab i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents: 21987
diff changeset
    57
    if message is None or not _ugettext:
7651
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    58
        return message
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    59
23031
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    60
    if message not in _msgcache:
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    61
        if type(message) is unicode:
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    62
            # goofy unicode docstrings in test
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    63
            paragraphs = message.split(u'\n\n')
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    64
        else:
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    65
            paragraphs = [p.decode("ascii") for p in message.split('\n\n')]
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    66
        # Be careful not to translate the empty string -- it holds the
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    67
        # meta data of the .po file.
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    68
        u = u'\n\n'.join([p and _ugettext(p) or '' for p in paragraphs])
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    69
        try:
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    70
            # encoding.tolocal cannot be used since it will first try to
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    71
            # decode the Unicode string. Calling u.decode(enc) really
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    72
            # means u.encode(sys.getdefaultencoding()).decode(enc). Since
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    73
            # the Python encoding defaults to 'ascii', this fails if the
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    74
            # translated string use non-ASCII characters.
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    75
            _msgcache[message] = u.encode(encoding.encoding, "replace")
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    76
        except LookupError:
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    77
            # An unknown encoding results in a LookupError.
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    78
            _msgcache[message] = message
3c0983cc279e i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents: 22638
diff changeset
    79
    return _msgcache[message]
7651
5b5036ef847a i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents: 7650
diff changeset
    80
13849
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    81
def _plain():
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    82
    if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    83
        return False
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    84
    exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    85
    return 'i18n' not in exceptions
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    86
9f97de157aad HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents: 11403
diff changeset
    87
if _plain():
10455
40dfd46d098f ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
    88
    _ = lambda message: message
40dfd46d098f ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
    89
else:
40dfd46d098f ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
    90
    _ = gettext