diff --git a/CHANGES b/CHANGES index d1a075373ad..502e621f643 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,7 @@ Bugs fixed * #5419: incompatible math_block node has been generated * #5548: Fix ensuredir() in case of pre-existing file * #5549: graphviz Correctly deal with non-existing static dir +* #3002: i18n: same node_id is assigned to multiple footnote_references Testing -------- diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py index f49e27df3d2..d7350812844 100644 --- a/sphinx/transforms/i18n.py +++ b/sphinx/transforms/i18n.py @@ -373,11 +373,11 @@ def is_refnamed_footnote_ref(node): .format(old_foot_ref_rawsources, new_foot_ref_rawsources), location=node) for old in old_foot_refs: - refname_ids_map[old["refname"]] = old["ids"] + refname_ids_map.setdefault(old["refname"], []).append(old["ids"]) for new in new_foot_refs: refname = new["refname"] - if refname in refname_ids_map: - new["ids"] = refname_ids_map[refname] + if refname_ids_map.get(refname): + new["ids"] = refname_ids_map[refname].pop(0) # citation should use original 'ids'. def is_citation_ref(node): @@ -395,11 +395,11 @@ def is_citation_ref(node): .format(old_cite_ref_rawsources, new_cite_ref_rawsources), location=node) for old in old_cite_refs: - refname_ids_map[old["refname"]] = old["ids"] + refname_ids_map.setdefault(old["refname"], []).append(old["ids"]) for new in new_cite_refs: refname = new["refname"] - if refname in refname_ids_map: - new["ids"] = refname_ids_map[refname] + if refname_ids_map.get(refname): + new["ids"] = refname_ids_map[refname].pop() # Original pending_xref['reftarget'] contain not-translated # target name, new pending_xref must use original one. diff --git a/tests/roots/test-intl/footnote.po b/tests/roots/test-intl/footnote.po index 1dd6b93a7ca..869bf62fe69 100644 --- a/tests/roots/test-intl/footnote.po +++ b/tests/roots/test-intl/footnote.po @@ -19,8 +19,10 @@ msgstr "" msgid "i18n with Footnote" msgstr "I18N WITH FOOTNOTE" -msgid "[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_ [*]_." -msgstr "`I18N WITH FOOTNOTE`_ INCLUDE THIS CONTENTS [#named]_ [ref]_ [#]_ [100]_ [*]_." +msgid "[100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_ [*]_. " +"second footnote_ref [100]_." +msgstr "`I18N WITH FOOTNOTE`_ INCLUDE THIS CONTENTS [#named]_ [ref]_ [#]_ [100]_ [*]_. " +"SECOND FOOTNOTE_REF [100]_." msgid "This is a auto numbered footnote." msgstr "THIS IS A AUTO NUMBERED FOOTNOTE." diff --git a/tests/roots/test-intl/footnote.txt b/tests/roots/test-intl/footnote.txt index 04639fa0144..0bbed914595 100644 --- a/tests/roots/test-intl/footnote.txt +++ b/tests/roots/test-intl/footnote.txt @@ -5,6 +5,7 @@ i18n with Footnote .. #955 cant-build-html-with-footnotes-when-using [100]_ Contents [#]_ for `i18n with Footnote`_ [ref]_ [#named]_ [*]_. +second footnote_ref [100]_. .. [#] This is a auto numbered footnote. .. [ref] This is a named footnote. diff --git a/tests/test_intl.py b/tests/test_intl.py index c8f90e41c38..aed323eed0f 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -794,9 +794,13 @@ def test_xml_footnotes(app, warning): assert_elem( para0[0], ['I18N WITH FOOTNOTE', 'INCLUDE THIS CONTENTS', - '2', '[ref]', '1', '100', '*', '.'], + '2', '[ref]', '1', '100', '*', '. SECOND FOOTNOTE_REF', '100', '.'], ['i18n-with-footnote', 'ref']) + # check node_id for footnote_references which refer same footnote (refs: #3002) + assert para0[0][4].text == para0[0][6].text == '100' + assert para0[0][4].attrib['ids'] != para0[0][6].attrib['ids'] + footnote0 = secs[0].findall('footnote') assert_elem( footnote0[0], @@ -848,8 +852,8 @@ def test_xml_footnote_backlinks(app): footnote0 = secs[0].findall('footnote') for footnote in footnote0: ids = footnote.attrib.get('ids') - backrefs = footnote.attrib.get('backrefs') - assert refid2id[ids] == backrefs + backrefs = footnote.attrib.get('backrefs').split() + assert refid2id[ids] in backrefs @sphinx_intl