Mercurial > hg
annotate mercurial/i18n.py @ 35616:706aa203b396
fileset: add a lightweight file filtering language
This patch was inspired by one that Jun Wu authored for the fb-experimental
repo, to avoid using matcher for efficiency[1]. We want a way to specify what
files will be converted to LFS at commit time. And per discussion, we also want
to specify what files to skip, text diff, or merge in another config option.
The current `lfs.threshold` config option could not satisfy complex needs. I'm
putting it in a core package because Augie floated the idea of also using it for
narrow and sparse.
Yuya suggested farming out to fileset.parse(), which added support for more
symbols. The only fileset element not supported here is 'negate'. (List isn't
supported by filesets either.) I also changed the 'always' token to the 'all()'
predicate for consistency, and introduced 'none()' to improve readability in a
future tracked file based config. The extension operator was changed from '.'
to '**', to match how recursive path globs are specified. Finally, I changed
the path matcher from '/' to 'path:' at Yuya's suggestion, for consistency with
matcher. Unfortunately, ':' is currently reserved in filesets, so this has to
be quoted to be processed as a string instead of a symbol[2]. We should
probably revisit that, because it's seriously ugly. But it's only used by an
experimental extension, and I think using a file based config for LFS may drive
some more tweaks, so I'm settling for this for now.
I reserved all of the glob characters in fileset except '.' and '_' for the
extension test because those are likely valid extension characters.
Sample filter settings:
all() # everything
size(">20MB") # larger than 20MB
!**.txt # except for .txt files
**.zip | **.tar.gz | **.7z # some types of compressed files
"path:bin" # files under "bin" in the project root
[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-December/109387.html
[2] https://www.mercurial-scm.org/pipermail/mercurial-devel/2018-January/109729.html
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Wed, 10 Jan 2018 22:23:34 -0500 |
parents | d00ec62d156f |
children | aeaf9c7f7528 |
rev | line source |
---|---|
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 | 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 |
25955
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
8 from __future__ import absolute_import |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
9 |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
10 import gettext as gettextmod |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
11 import locale |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
12 import os |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
13 import sys |
2c07c6884394
i18n: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
23031
diff
changeset
|
14 |
30050
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
15 from . import ( |
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
16 encoding, |
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
17 pycompat, |
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
18 ) |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
19 |
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
20 # modelled after templater.templatepath: |
14975
b64538363dbe
i18n: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents:
13849
diff
changeset
|
21 if getattr(sys, 'frozen', None) is not None: |
30669
10b17ed9b591
py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30639
diff
changeset
|
22 module = pycompat.sysexecutable |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
23 else: |
31074
2912b06905dc
py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30669
diff
changeset
|
24 module = pycompat.fsencode(__file__) |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
25 |
28674
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
26 try: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
27 unicode |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
28 except NameError: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
29 unicode = str |
7650
85ae7aaf08e9
i18n: lookup .mo files in private locale/ directory
Martin Geisler <mg@daimi.au.dk>
parents:
3888
diff
changeset
|
30 |
21987
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
31 _languages = None |
34645 | 32 if (pycompat.iswindows |
30035
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
33 and 'LANGUAGE' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
34 and 'LC_ALL' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
35 and 'LC_MESSAGES' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
36 and 'LANG' not in encoding.environ): |
21987
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
37 # 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
|
38 # 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
|
39 # 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
|
40 # (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
|
41 try: |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
42 import ctypes |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
43 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
|
44 _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
|
45 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
|
46 # 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
|
47 pass |
4953cd193e84
i18n: detect UI language without POSIX-style locale variable on Windows (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
21746
diff
changeset
|
48 |
22638
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
49 _ugettext = None |
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
50 |
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
51 def setdatapath(datapath): |
30301
8321b083a83d
py3: make util.datapath a bytes variable
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30085
diff
changeset
|
52 datapath = pycompat.fsdecode(datapath) |
30085
2bde971474d2
i18n: make the locale directory name the same string type as the datapath
Augie Fackler <augie@google.com>
parents:
30050
diff
changeset
|
53 localedir = os.path.join(datapath, pycompat.sysstr('locale')) |
22638
0d0350cfc7ab
i18n: use datapath for i18n like for templates and help
Mads Kiilerich <madski@unity3d.com>
parents:
21987
diff
changeset
|
54 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
|
55 global _ugettext |
28674
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
56 try: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
57 _ugettext = t.ugettext |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
58 except AttributeError: |
03d1ecbbd81e
py3: handle ugettext + unicode in i18n
timeless <timeless@mozdev.org>
parents:
25955
diff
changeset
|
59 _ugettext = t.gettext |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
60 |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
61 _msgcache = {} # encoding: {message: translation} |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
62 |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
63 def gettext(message): |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
64 """Translate message. |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
65 |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
66 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
|
67 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
|
68 |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
69 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
|
70 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
|
71 """ |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
72 # 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
|
73 # 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
|
74 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
|
75 return message |
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
76 |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
77 cache = _msgcache.setdefault(encoding.encoding, {}) |
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
78 if message not in cache: |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
79 if type(message) is unicode: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
80 # goofy unicode docstrings in test |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
81 paragraphs = message.split(u'\n\n') |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
82 else: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
83 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
|
84 # 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
|
85 # meta data of the .po file. |
29415
47fb4beb992b
i18n: use unicode literal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28674
diff
changeset
|
86 u = u'\n\n'.join([p and _ugettext(p) or u'' for p in paragraphs]) |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
87 try: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
88 # 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
|
89 # 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
|
90 # 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
|
91 # 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
|
92 # translated string use non-ASCII characters. |
30050
d229be12e256
py3: convert to unicode to pass into encode()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30035
diff
changeset
|
93 encodingstr = pycompat.sysstr(encoding.encoding) |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
94 cache[message] = u.encode(encodingstr, "replace") |
23031
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
95 except LookupError: |
3c0983cc279e
i18n: cache the result of every gettext call
Augie Fackler <raf@durin42.com>
parents:
22638
diff
changeset
|
96 # An unknown encoding results in a LookupError. |
34660
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
97 cache[message] = message |
d00ec62d156f
i18n: cache translated messages per encoding
Yuya Nishihara <yuya@tcha.org>
parents:
34645
diff
changeset
|
98 return cache[message] |
7651
5b5036ef847a
i18n: encode output in user's local encoding
Martin Geisler <mg@daimi.au.dk>
parents:
7650
diff
changeset
|
99 |
13849
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
100 def _plain(): |
30035
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
101 if ('HGPLAIN' not in encoding.environ |
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
102 and 'HGPLAINEXCEPT' not in encoding.environ): |
13849
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
103 return False |
30035
02328b5d775d
py3: make i18n use encoding.environ
Yuya Nishihara <yuya@tcha.org>
parents:
29415
diff
changeset
|
104 exceptions = encoding.environ.get('HGPLAINEXCEPT', '').strip().split(',') |
13849
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
105 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
|
106 |
9f97de157aad
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT
Brodie Rao <brodie@bitheap.org>
parents:
11403
diff
changeset
|
107 if _plain(): |
10455
40dfd46d098f
ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents:
10263
diff
changeset
|
108 _ = lambda message: message |
40dfd46d098f
ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents:
10263
diff
changeset
|
109 else: |
40dfd46d098f
ui: add HGPLAIN environment variable for easier scripting
Brodie Rao <me+hg@dackz.net>
parents:
10263
diff
changeset
|
110 _ = gettext |