##// END OF EJS Templates
typing: add type hints to `i18n._msgcache`...
Matt Harbison -
r52610:f841de63 default
parent child Browse files
Show More
@@ -1,123 +1,126 b''
1 1 # i18n.py - internationalization support for mercurial
2 2 #
3 3 # Copyright 2005, 2006 Olivia Mackall <olivia@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8
9 9 import gettext as gettextmod
10 10 import locale
11 11 import os
12 12 import sys
13 13
14 14 from typing import (
15 Dict,
15 16 List,
16 17 )
17 18
18 19 from .utils import resourceutil
19 20 from . import (
20 21 encoding,
21 22 pycompat,
22 23 )
23 24
24 25 # modelled after templater.templatepath:
25 26 if getattr(sys, 'frozen', None) is not None:
26 27 module = pycompat.sysexecutable
27 28 else:
28 29 module = pycompat.fsencode(__file__)
29 30
30 31 _languages = None
31 32 if (
32 33 pycompat.iswindows
33 34 and b'LANGUAGE' not in encoding.environ
34 35 and b'LC_ALL' not in encoding.environ
35 36 and b'LC_MESSAGES' not in encoding.environ
36 37 and b'LANG' not in encoding.environ
37 38 ):
38 39 # Try to detect UI language by "User Interface Language Management" API
39 40 # if no locale variables are set. Note that locale.getdefaultlocale()
40 41 # uses GetLocaleInfo(), which may be different from UI language.
41 42 # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx )
42 43 try:
43 44 import ctypes
44 45
45 46 # pytype: disable=module-attr
46 47 langid = ctypes.windll.kernel32.GetUserDefaultUILanguage()
47 48 # pytype: enable=module-attr
48 49
49 50 _languages = [locale.windows_locale[langid]]
50 51 except (ImportError, AttributeError, KeyError):
51 52 # ctypes not found or unknown langid
52 53 pass
53 54
54 55
55 56 datapath = pycompat.fsdecode(resourceutil.datapath)
56 57 localedir = os.path.join(datapath, 'locale')
57 58 t = gettextmod.translation('hg', localedir, _languages, fallback=True)
58 59 try:
59 60 _ugettext = t.ugettext # pytype: disable=attribute-error
60 61 except AttributeError:
61 62 _ugettext = t.gettext
62 63
63 64
64 _msgcache = {} # encoding: {message: translation}
65 _msgcache: Dict[
66 bytes, Dict[bytes, bytes]
67 ] = {} # encoding: {message: translation}
65 68
66 69
67 70 def gettext(message: bytes) -> bytes:
68 71 """Translate message.
69 72
70 73 The message is looked up in the catalog to get a Unicode string,
71 74 which is encoded in the local encoding before being returned.
72 75
73 76 Important: message is restricted to characters in the encoding
74 77 given by sys.getdefaultencoding() which is most likely 'ascii'.
75 78 """
76 79 # If message is None, t.ugettext will return u'None' as the
77 80 # translation whereas our callers expect us to return None.
78 81 if message is None or not _ugettext:
79 82 return message
80 83
81 84 cache = _msgcache.setdefault(encoding.encoding, {})
82 85 if message not in cache:
83 86 if type(message) is str:
84 87 # goofy unicode docstrings in test
85 88 paragraphs: List[str] = message.split(u'\n\n')
86 89 else:
87 90 # should be ascii, but we have unicode docstrings in test, which
88 91 # are converted to utf-8 bytes on Python 3.
89 92 paragraphs = [p.decode("utf-8") for p in message.split(b'\n\n')]
90 93 # Be careful not to translate the empty string -- it holds the
91 94 # meta data of the .po file.
92 95 u = u'\n\n'.join([p and _ugettext(p) or u'' for p in paragraphs])
93 96 try:
94 97 # encoding.tolocal cannot be used since it will first try to
95 98 # decode the Unicode string. Calling u.decode(enc) really
96 99 # means u.encode(sys.getdefaultencoding()).decode(enc). Since
97 100 # the Python encoding defaults to 'ascii', this fails if the
98 101 # translated string use non-ASCII characters.
99 102 encodingstr = pycompat.sysstr(encoding.encoding)
100 103 cache[message] = u.encode(encodingstr, "replace")
101 104 except LookupError:
102 105 # An unknown encoding results in a LookupError.
103 106 cache[message] = message
104 107 return cache[message]
105 108
106 109
107 110 def _plain():
108 111 if (
109 112 b'HGPLAIN' not in encoding.environ
110 113 and b'HGPLAINEXCEPT' not in encoding.environ
111 114 ):
112 115 return False
113 116 exceptions = encoding.environ.get(b'HGPLAINEXCEPT', b'').strip().split(b',')
114 117 return b'i18n' not in exceptions
115 118
116 119
117 120 if _plain():
118 121
119 122 def _(message: bytes) -> bytes:
120 123 return message
121 124
122 125 else:
123 126 _ = gettext
General Comments 0
You need to be logged in to leave comments. Login now