Skip to content

Commit aa845af

Browse files
authored
gh-130057: Pygettext: Support translator comments (GH-130061)
1 parent 6669905 commit aa845af

File tree

5 files changed

+335
-20
lines changed

5 files changed

+335
-20
lines changed
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# SOME DESCRIPTIVE TITLE.
2+
# Copyright (C) YEAR ORGANIZATION
3+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: PACKAGE VERSION\n"
8+
"POT-Creation-Date: 2000-01-01 00:00+0000\n"
9+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
10+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
11+
"Language-Team: LANGUAGE <[email protected]>\n"
12+
"MIME-Version: 1.0\n"
13+
"Content-Type: text/plain; charset=UTF-8\n"
14+
"Content-Transfer-Encoding: 8bit\n"
15+
"Generated-By: pygettext.py 1.5\n"
16+
17+
18+
#: comments.py:4
19+
msgid "foo"
20+
msgstr ""
21+
22+
#. i18n: This is a translator comment
23+
#: comments.py:7
24+
msgid "bar"
25+
msgstr ""
26+
27+
#. i18n: This is a translator comment
28+
#. i18n: This is another translator comment
29+
#: comments.py:11
30+
msgid "baz"
31+
msgstr ""
32+
33+
#. i18n: This is a translator comment
34+
#. with multiple
35+
#. lines
36+
#: comments.py:16
37+
msgid "qux"
38+
msgstr ""
39+
40+
#. i18n: This is a translator comment
41+
#: comments.py:21
42+
msgid "quux"
43+
msgstr ""
44+
45+
#. i18n: This is a translator comment
46+
#. with multiple lines
47+
#. i18n: This is another translator comment
48+
#. with multiple lines
49+
#: comments.py:27
50+
msgid "corge"
51+
msgstr ""
52+
53+
#: comments.py:31
54+
msgid "grault"
55+
msgstr ""
56+
57+
#. i18n: This is another translator comment
58+
#: comments.py:36
59+
msgid "garply"
60+
msgstr ""
61+
62+
#: comments.py:40
63+
msgid "george"
64+
msgstr ""
65+
66+
#. i18n: This is another translator comment
67+
#: comments.py:45
68+
msgid "waldo"
69+
msgstr ""
70+
71+
#. i18n: This is a translator comment
72+
#. i18n: This is also a translator comment
73+
#. i18n: This is another translator comment
74+
#: comments.py:50
75+
msgid "waldo2"
76+
msgstr ""
77+
78+
#. i18n: This is a translator comment
79+
#. i18n: This is another translator comment
80+
#. i18n: This is yet another translator comment
81+
#. i18n: This is a translator comment
82+
#. with multiple lines
83+
#: comments.py:53 comments.py:56 comments.py:59 comments.py:63
84+
msgid "fred"
85+
msgstr ""
86+
87+
#: comments.py:65
88+
msgid "plugh"
89+
msgstr ""
90+
91+
#: comments.py:67
92+
msgid "foobar"
93+
msgstr ""
94+
95+
#. i18n: This is a translator comment
96+
#: comments.py:71
97+
msgid "xyzzy"
98+
msgstr ""
99+
100+
#: comments.py:72
101+
msgid "thud"
102+
msgstr ""
103+
104+
#. i18n: This is a translator comment
105+
#. i18n: This is another translator comment
106+
#. i18n: This is yet another translator comment
107+
#: comments.py:78
108+
msgid "foos"
109+
msgstr ""
110+
+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from gettext import gettext as _
2+
3+
# Not a translator comment
4+
_('foo')
5+
6+
# i18n: This is a translator comment
7+
_('bar')
8+
9+
# i18n: This is a translator comment
10+
# i18n: This is another translator comment
11+
_('baz')
12+
13+
# i18n: This is a translator comment
14+
# with multiple
15+
# lines
16+
_('qux')
17+
18+
# This comment should not be included because
19+
# it does not start with the prefix
20+
# i18n: This is a translator comment
21+
_('quux')
22+
23+
# i18n: This is a translator comment
24+
# with multiple lines
25+
# i18n: This is another translator comment
26+
# with multiple lines
27+
_('corge')
28+
29+
# i18n: This comment should be ignored
30+
31+
_('grault')
32+
33+
# i18n: This comment should be ignored
34+
35+
# i18n: This is another translator comment
36+
_('garply')
37+
38+
# i18n: comment should be ignored
39+
x = 1
40+
_('george')
41+
42+
# i18n: This comment should be ignored
43+
x = 1
44+
# i18n: This is another translator comment
45+
_('waldo')
46+
47+
# i18n: This is a translator comment
48+
x = 1 # i18n: This is also a translator comment
49+
# i18n: This is another translator comment
50+
_('waldo2')
51+
52+
# i18n: This is a translator comment
53+
_('fred')
54+
55+
# i18n: This is another translator comment
56+
_('fred')
57+
58+
# i18n: This is yet another translator comment
59+
_('fred')
60+
61+
# i18n: This is a translator comment
62+
# with multiple lines
63+
_('fred')
64+
65+
_('plugh') # i18n: This comment should be ignored
66+
67+
_('foo' # i18n: This comment should be ignored
68+
'bar') # i18n: This comment should be ignored
69+
70+
# i18n: This is a translator comment
71+
_('xyzzy')
72+
_('thud')
73+
74+
75+
## i18n: This is a translator comment
76+
# # i18n: This is another translator comment
77+
### ### i18n: This is yet another translator comment
78+
_('foos')

Lib/test/test_tools/test_i18n.py

+55-6
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def assert_POT_equal(self, expected, actual):
8787
self.maxDiff = None
8888
self.assertEqual(normalize_POT_file(expected), normalize_POT_file(actual))
8989

90-
def extract_from_str(self, module_content, *, args=(), strict=True, with_stderr=False):
90+
def extract_from_str(self, module_content, *, args=(), strict=True,
91+
with_stderr=False, raw=False):
9192
"""Return all msgids extracted from module_content."""
9293
filename = 'test.py'
9394
with temp_cwd(None):
@@ -98,10 +99,11 @@ def extract_from_str(self, module_content, *, args=(), strict=True, with_stderr=
9899
self.assertEqual(res.err, b'')
99100
with open('messages.pot', encoding='utf-8') as fp:
100101
data = fp.read()
101-
msgids = self.get_msgids(data)
102+
if not raw:
103+
data = self.get_msgids(data)
102104
if not with_stderr:
103-
return msgids
104-
return msgids, res.err
105+
return data
106+
return data, res.err
105107

106108
def extract_docstrings_from_str(self, module_content):
107109
"""Return all docstrings extracted from module_content."""
@@ -381,7 +383,8 @@ def test_pygettext_output(self):
381383
contents = input_file.read_text(encoding='utf-8')
382384
with temp_cwd(None):
383385
Path(input_file.name).write_text(contents)
384-
assert_python_ok('-Xutf8', self.script, '--docstrings', input_file.name)
386+
assert_python_ok('-Xutf8', self.script, '--docstrings',
387+
'--add-comments=i18n:', input_file.name)
385388
output = Path('messages.pot').read_text(encoding='utf-8')
386389

387390
expected = output_file.read_text(encoding='utf-8')
@@ -437,14 +440,60 @@ def test_error_messages(self):
437440
"*** test.py:3: Variable positional arguments are not allowed in gettext calls\n"
438441
)
439442

443+
def test_extract_all_comments(self):
444+
"""
445+
Test that the --add-comments option without an
446+
explicit tag extracts all translator comments.
447+
"""
448+
for arg in ('--add-comments', '-c'):
449+
with self.subTest(arg=arg):
450+
data = self.extract_from_str(dedent('''\
451+
# Translator comment
452+
_("foo")
453+
'''), args=(arg,), raw=True)
454+
self.assertIn('#. Translator comment', data)
455+
456+
def test_comments_with_multiple_tags(self):
457+
"""
458+
Test that multiple --add-comments tags can be specified.
459+
"""
460+
for arg in ('--add-comments={}', '-c{}'):
461+
with self.subTest(arg=arg):
462+
args = (arg.format('foo:'), arg.format('bar:'))
463+
data = self.extract_from_str(dedent('''\
464+
# foo: comment
465+
_("foo")
466+
467+
# bar: comment
468+
_("bar")
469+
470+
# baz: comment
471+
_("baz")
472+
'''), args=args, raw=True)
473+
self.assertIn('#. foo: comment', data)
474+
self.assertIn('#. bar: comment', data)
475+
self.assertNotIn('#. baz: comment', data)
476+
477+
def test_comments_not_extracted_without_tags(self):
478+
"""
479+
Test that translator comments are not extracted without
480+
specifying --add-comments.
481+
"""
482+
data = self.extract_from_str(dedent('''\
483+
# Translator comment
484+
_("foo")
485+
'''), raw=True)
486+
self.assertNotIn('#.', data)
487+
440488

441489
def update_POT_snapshots():
442490
for input_file in DATA_DIR.glob('*.py'):
443491
output_file = input_file.with_suffix('.pot')
444492
contents = input_file.read_bytes()
445493
with temp_cwd(None):
446494
Path(input_file.name).write_bytes(contents)
447-
assert_python_ok('-Xutf8', Test_pygettext.script, '--docstrings', input_file.name)
495+
assert_python_ok('-Xutf8', Test_pygettext.script, '--docstrings',
496+
'--add-comments=i18n:', input_file.name)
448497
output = Path('messages.pot').read_text(encoding='utf-8')
449498

450499
output = normalize_POT_file(output)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for translator comments in :program:`pygettext.py`.

0 commit comments

Comments
 (0)