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