Mark idempotent translations as 'translated' (#11580)

This commit is contained in:
Adam Turner 2023-08-12 04:51:52 +01:00 committed by GitHub
parent c19f0ac8e9
commit 2ef9728b6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 19 deletions

View File

@ -353,9 +353,16 @@ class Locale(SphinxTransform):
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
@ -364,10 +371,14 @@ class Locale(SphinxTransform):
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
@ -416,7 +427,7 @@ class Locale(SphinxTransform):
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.
@ -510,7 +521,7 @@ class Locale(SphinxTransform):
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)

View File

@ -17,16 +17,20 @@ Desiring this mans art and that mans 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,
.. untranslated (2 out of 14 lines):
Like to the lark at break of day arising
.. untranslated (3 out of 14 lines):
From sullen earth, sings hymns at heavens gate;
.. translation missing (2 out of 14 lines):
For thy sweet love rememberd such wealth brings
That then I scorn to change my state with kings.

View File

@ -38,11 +38,20 @@ msgstr "DESIRING THIS MANS ART AND THAT MANS 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 heavens gate;"
msgstr ""
# translation missing (2 out of 14 lines):

View File

@ -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={
@ -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']
@ -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