mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Mark idempotent translations as 'translated' (#11580)
This commit is contained in:
parent
c19f0ac8e9
commit
2ef9728b6e
@ -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)
|
||||
|
@ -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,
|
||||
|
||||
.. 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 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.
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user