Skip to content

Commit

Permalink
Mark idempotent translations as 'translated' (#11580)
Browse files Browse the repository at this point in the history
  • Loading branch information
AA-Turner committed Aug 12, 2023
1 parent c19f0ac commit 2ef9728
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 19 deletions.
19 changes: 15 additions & 4 deletions sphinx/transforms/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,16 @@ def apply(self, **kwargs: Any) -> None:
if not has_catalog:
return

catalogues = [getattr(catalog, '_catalog', None)]
while (catalog := catalog._fallback) is not None: # type: ignore[attr-defined]
catalogues.append(getattr(catalog, '_catalog', None))
merged: dict[str, str] = {}
for catalogue in filter(None, reversed(catalogues)): # type: dict[str, str]
merged |= catalogue

# phase1: replace reference ids with translated names
for node, msg in extract_messages(self.document):
msgstr = catalog.gettext(msg)
msgstr = merged.get(msg, '')

# There is no point in having #noqa on literal blocks because
# they cannot contain references. Recognizing it would just
Expand All @@ -364,10 +371,14 @@ def apply(self, **kwargs: Any) -> None:
if not isinstance(node, LITERAL_TYPE_NODES):
msgstr, _ = parse_noqa(msgstr)

if not msgstr or msgstr == msg or not msgstr.strip():
if msgstr.strip() == '':
# as-of-yet untranslated
node['translated'] = False
continue
if msgstr == msg:
# identical source and translated messages
node['translated'] = True
continue

# Avoid "Literal block expected; none found." warnings.
# If msgstr ends with '::' then it cause warning message at
Expand Down Expand Up @@ -416,7 +427,7 @@ def apply(self, **kwargs: Any) -> None:
if node.setdefault('translated', False): # to avoid double translation
continue # skip if the node is already translated by phase1

msgstr = catalog.gettext(msg)
msgstr = merged.get(msg, '')
noqa = False

# See above.
Expand Down Expand Up @@ -510,7 +521,7 @@ def apply(self, **kwargs: Any) -> None:
msg_parts = split_index_msg(entry_type, value)
msgstr_parts = []
for part in msg_parts:
msgstr = catalog.gettext(part)
msgstr = merged.get(part, '')
if not msgstr:
msgstr = part
msgstr_parts.append(msgstr)
Expand Down
8 changes: 6 additions & 2 deletions tests/roots/test-intl/translation_progress.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ Desiring this man’s art and that man’s scope,

With what I most enjoy contented least;

.. idempotent translations (2 out of 14 lines):

Yet in these thoughts myself almost despising,

Haply I think on thee, and then my state,

Like to the lark at break of day arising
.. untranslated (2 out of 14 lines):

.. untranslated (3 out of 14 lines):
Like to the lark at break of day arising

From sullen earth, sings hymns at heaven’s gate;

.. translation missing (2 out of 14 lines):

For thy sweet love remember’d such wealth brings

That then I scorn to change my state with kings.
Expand Down
15 changes: 12 additions & 3 deletions tests/roots/test-intl/xx/LC_MESSAGES/translation_progress.po
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,20 @@ msgstr "DESIRING THIS MAN’S ART AND THAT MAN’S SCOPE,"
msgid "With what I most enjoy contented least;"
msgstr "WITH WHAT I MOST ENJOY CONTENTED LEAST;"

# idempotent translations (2 out of 14 lines):

msgid "Yet in these thoughts myself almost despising,"
msgstr "YET IN THESE THOUGHTS MYSELF ALMOST DESPISING,"
msgstr "Yet in these thoughts myself almost despising,"

msgid "Haply I think on thee, and then my state,"
msgstr "HAPLY I THINK ON THEE, AND THEN MY STATE,"
msgstr "Haply I think on thee, and then my state,"

# untranslated (2 out of 14 lines):

msgid "Like to the lark at break of day arising"
msgstr "LIKE TO THE LARK AT BREAK OF DAY ARISING"
msgstr ""

msgid "From sullen earth, sings hymns at heaven’s gate;"
msgstr ""

# translation missing (2 out of 14 lines):
33 changes: 23 additions & 10 deletions tests/test_intl.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,24 +612,24 @@ def test_gettext_buildr_ignores_only_directive(app):

@sphinx_intl
def test_node_translated_attribute(app):
app.build()
app.builder.build_specific([app.srcdir / 'translation_progress.txt'])

doctree = app.env.get_doctree('translation_progress')

translated_nodes = sum(1 for _ in doctree.findall(NodeMatcher(translated=True)))
assert translated_nodes == 11 + 1 # 11 lines + title
assert translated_nodes == 10 + 1 # 10 lines + title

untranslated_nodes = sum(1 for _ in doctree.findall(NodeMatcher(translated=False)))
assert untranslated_nodes == 3 + 1 # 3 lines + substitution reference
assert untranslated_nodes == 2 + 2 + 1 # 2 lines + 2 lines + substitution reference


@sphinx_intl
def test_translation_progress_substitution(app):
app.build()
app.builder.build_specific([app.srcdir / 'translation_progress.txt'])

doctree = app.env.get_doctree('translation_progress')

assert doctree[0][17][0] == '75.00%' # 12 out of 16 lines are translated
assert doctree[0][19][0] == '68.75%' # 11 out of 16 lines are translated


@pytest.mark.sphinx(testroot='intl', freshenv=True, confoverrides={
Expand All @@ -638,11 +638,14 @@ def test_translation_progress_substitution(app):
'translation_progress_classes': True,
})
def test_translation_progress_classes_true(app):
app.build()
app.builder.build_specific([app.srcdir / 'translation_progress.txt'])

doctree = app.env.get_doctree('translation_progress')

# title
assert 'translated' in doctree[0][0]['classes']

# translated lines
assert 'translated' in doctree[0][1]['classes']
assert 'translated' in doctree[0][2]['classes']
assert 'translated' in doctree[0][3]['classes']
Expand All @@ -651,21 +654,31 @@ def test_translation_progress_classes_true(app):
assert 'translated' in doctree[0][6]['classes']
assert 'translated' in doctree[0][7]['classes']
assert 'translated' in doctree[0][8]['classes']
assert 'translated' in doctree[0][9]['classes']

assert doctree[0][9]['classes'] == [] # comment node

# idempotent
assert 'translated' in doctree[0][10]['classes']
assert 'translated' in doctree[0][11]['classes']

assert doctree[0][12]['classes'] == [] # comment node

# untranslated
assert 'untranslated' in doctree[0][13]['classes']
assert 'untranslated' in doctree[0][14]['classes']
assert 'untranslated' in doctree[0][15]['classes']

assert doctree[0][16]['classes'] == [] # comment node
assert doctree[0][15]['classes'] == [] # comment node

# missing
assert 'untranslated' in doctree[0][16]['classes']
assert 'untranslated' in doctree[0][17]['classes']

assert len(doctree[0]) == 18
assert doctree[0][18]['classes'] == [] # comment node

# substitution reference
assert 'untranslated' in doctree[0][19]['classes']

assert len(doctree[0]) == 20


@sphinx_intl
Expand Down

0 comments on commit 2ef9728

Please sign in to comment.