##// END OF EJS Templates
i18n: cache translated messages per encoding...
Yuya Nishihara -
r34661:d00ec62d default
parent child Browse files
Show More
@@ -1,109 +1,110
1 1 # i18n.py - internationalization support for mercurial
2 2 #
3 3 # Copyright 2005, 2006 Matt Mackall <mpm@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 from __future__ import absolute_import
9 9
10 10 import gettext as gettextmod
11 11 import locale
12 12 import os
13 13 import sys
14 14
15 15 from . import (
16 16 encoding,
17 17 pycompat,
18 18 )
19 19
20 20 # modelled after templater.templatepath:
21 21 if getattr(sys, 'frozen', None) is not None:
22 22 module = pycompat.sysexecutable
23 23 else:
24 24 module = pycompat.fsencode(__file__)
25 25
26 26 try:
27 27 unicode
28 28 except NameError:
29 29 unicode = str
30 30
31 31 _languages = None
32 32 if (pycompat.iswindows
33 33 and 'LANGUAGE' not in encoding.environ
34 34 and 'LC_ALL' not in encoding.environ
35 35 and 'LC_MESSAGES' not in encoding.environ
36 36 and 'LANG' not in encoding.environ):
37 37 # Try to detect UI language by "User Interface Language Management" API
38 38 # if no locale variables are set. Note that locale.getdefaultlocale()
39 39 # uses GetLocaleInfo(), which may be different from UI language.
40 40 # (See http://msdn.microsoft.com/en-us/library/dd374098(v=VS.85).aspx )
41 41 try:
42 42 import ctypes
43 43 langid = ctypes.windll.kernel32.GetUserDefaultUILanguage()
44 44 _languages = [locale.windows_locale[langid]]
45 45 except (ImportError, AttributeError, KeyError):
46 46 # ctypes not found or unknown langid
47 47 pass
48 48
49 49 _ugettext = None
50 50
51 51 def setdatapath(datapath):
52 52 datapath = pycompat.fsdecode(datapath)
53 53 localedir = os.path.join(datapath, pycompat.sysstr('locale'))
54 54 t = gettextmod.translation('hg', localedir, _languages, fallback=True)
55 55 global _ugettext
56 56 try:
57 57 _ugettext = t.ugettext
58 58 except AttributeError:
59 59 _ugettext = t.gettext
60 60
61 _msgcache = {}
61 _msgcache = {} # encoding: {message: translation}
62 62
63 63 def gettext(message):
64 64 """Translate message.
65 65
66 66 The message is looked up in the catalog to get a Unicode string,
67 67 which is encoded in the local encoding before being returned.
68 68
69 69 Important: message is restricted to characters in the encoding
70 70 given by sys.getdefaultencoding() which is most likely 'ascii'.
71 71 """
72 72 # If message is None, t.ugettext will return u'None' as the
73 73 # translation whereas our callers expect us to return None.
74 74 if message is None or not _ugettext:
75 75 return message
76 76
77 if message not in _msgcache:
77 cache = _msgcache.setdefault(encoding.encoding, {})
78 if message not in cache:
78 79 if type(message) is unicode:
79 80 # goofy unicode docstrings in test
80 81 paragraphs = message.split(u'\n\n')
81 82 else:
82 83 paragraphs = [p.decode("ascii") for p in message.split('\n\n')]
83 84 # Be careful not to translate the empty string -- it holds the
84 85 # meta data of the .po file.
85 86 u = u'\n\n'.join([p and _ugettext(p) or u'' for p in paragraphs])
86 87 try:
87 88 # encoding.tolocal cannot be used since it will first try to
88 89 # decode the Unicode string. Calling u.decode(enc) really
89 90 # means u.encode(sys.getdefaultencoding()).decode(enc). Since
90 91 # the Python encoding defaults to 'ascii', this fails if the
91 92 # translated string use non-ASCII characters.
92 93 encodingstr = pycompat.sysstr(encoding.encoding)
93 _msgcache[message] = u.encode(encodingstr, "replace")
94 cache[message] = u.encode(encodingstr, "replace")
94 95 except LookupError:
95 96 # An unknown encoding results in a LookupError.
96 _msgcache[message] = message
97 return _msgcache[message]
97 cache[message] = message
98 return cache[message]
98 99
99 100 def _plain():
100 101 if ('HGPLAIN' not in encoding.environ
101 102 and 'HGPLAINEXCEPT' not in encoding.environ):
102 103 return False
103 104 exceptions = encoding.environ.get('HGPLAINEXCEPT', '').strip().split(',')
104 105 return 'i18n' not in exceptions
105 106
106 107 if _plain():
107 108 _ = lambda message: message
108 109 else:
109 110 _ = gettext
@@ -1,50 +1,70
1 1 (Translations are optional)
2 2
3 3 #if gettext no-outer-repo
4 4
5 5 Test that translations are compiled and installed correctly.
6 6
7 7 Default encoding in tests is "ascii" and the translation is encoded
8 8 using the "replace" error handler:
9 9
10 10 $ LANGUAGE=pt_BR hg tip
11 11 abortado: n?o foi encontrado um reposit?rio em '$TESTTMP' (.hg n?o encontrado)!
12 12 [255]
13 13
14 14 Using a more accommodating encoding:
15 15
16 16 $ HGENCODING=UTF-8 LANGUAGE=pt_BR hg tip
17 17 abortado: n\xc3\xa3o foi encontrado um reposit\xc3\xb3rio em '$TESTTMP' (.hg n\xc3\xa3o encontrado)! (esc)
18 18 [255]
19 19
20 20 Different encoding:
21 21
22 22 $ HGENCODING=Latin-1 LANGUAGE=pt_BR hg tip
23 23 abortado: n\xe3o foi encontrado um reposit\xf3rio em '$TESTTMP' (.hg n\xe3o encontrado)! (esc)
24 24 [255]
25 25
26 26 #endif
27 27
28 28 #if gettext
29 29
30 30 Test keyword search in translated help text:
31 31
32 32 $ HGENCODING=UTF-8 LANGUAGE=de hg help -k Aktualisiert
33 33 Themen:
34 34
35 35 subrepos Unterarchive
36 36
37 37 Befehle:
38 38
39 39 pull Ruft \xc3\x84nderungen von der angegebenen Quelle ab (esc)
40 40 update Aktualisiert das Arbeitsverzeichnis (oder wechselt die Version)
41 41
42 42 #endif
43 43
44 44 Check Mercurial specific translation problems in each *.po files, and
45 45 tool itself by doctest
46 46
47 47 $ cd "$TESTDIR"/../i18n
48 48 $ $PYTHON check-translation.py *.po
49 49 $ $PYTHON check-translation.py --doctest
50 50 $ cd $TESTTMP
51
52 Check i18n cache isn't reused after encoding change:
53
54 $ cat > $TESTTMP/encodingchange.py << EOF
55 > from mercurial import encoding, registrar
56 > from mercurial.i18n import _
57 > cmdtable = {}
58 > command = registrar.command(cmdtable)
59 > @command(b'encodingchange', norepo=True)
60 > def encodingchange(ui):
61 > for encode in (b'ascii', b'UTF-8', b'ascii', b'UTF-8'):
62 > encoding.encoding = encode
63 > ui.write(b'%s\n' % _(b'(EXPERIMENTAL)'))
64 > EOF
65
66 $ LANGUAGE=ja hg --config extensions.encodingchange=$TESTTMP/encodingchange.py encodingchange
67 (?????)
68 (\xe5\xae\x9f\xe9\xa8\x93\xe7\x9a\x84\xe5\xae\x9f\xe8\xa3\x85) (esc)
69 (?????)
70 (\xe5\xae\x9f\xe9\xa8\x93\xe7\x9a\x84\xe5\xae\x9f\xe8\xa3\x85) (esc)
General Comments 0
You need to be logged in to leave comments. Login now