mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
fix: keep reference if link refname was translated. refs #1193
case1::
Keep link to ExternalSite_.
It will translated with ``\`SomeOtherString\`_``.
.. _ExternalSite: http://example.com
case2::
Keep link to `title string`_ before appearing.
title string
=============
case3::
Keep link to glossary 'term string'.
.. glossary::
term string
description...
This commit is contained in:
@@ -205,12 +205,13 @@ class OptionXRefRole(XRefRole):
|
||||
return title, target
|
||||
|
||||
|
||||
def make_termnodes_from_paragraph_node(env, node):
|
||||
def make_termnodes_from_paragraph_node(env, node, new_id=None):
|
||||
gloss_entries = env.temp_data.setdefault('gloss_entries', set())
|
||||
objects = env.domaindata['std']['objects']
|
||||
|
||||
termtext = node.astext()
|
||||
new_id = 'term-' + nodes.make_id(termtext)
|
||||
if new_id is None:
|
||||
new_id = 'term-' + nodes.make_id(termtext)
|
||||
if new_id in gloss_entries:
|
||||
new_id = 'term-' + str(len(gloss_entries))
|
||||
gloss_entries.add(new_id)
|
||||
|
||||
@@ -177,6 +177,7 @@ class Locale(Transform):
|
||||
|
||||
parser = RSTParser()
|
||||
|
||||
#phase1: replace reference ids with translated names
|
||||
for node, msg in extract_messages(self.document):
|
||||
msgstr = catalog.gettext(msg)
|
||||
# XXX add marker to untranslated parts
|
||||
@@ -199,6 +200,8 @@ class Locale(Transform):
|
||||
if not isinstance(patch, nodes.paragraph):
|
||||
continue # skip for now
|
||||
|
||||
processed = False # skip flag
|
||||
|
||||
# update title(section) target name-id mapping
|
||||
if isinstance(node, nodes.title):
|
||||
section_node = node.parent
|
||||
@@ -217,6 +220,60 @@ class Locale(Transform):
|
||||
_type = self.document.nametypes.pop(old_name, None)
|
||||
self.document.set_name_id_map(
|
||||
section_node, _id, section_node, explicit=_type)
|
||||
processed = True
|
||||
|
||||
# glossary terms update refid
|
||||
if isinstance(node, nodes.term):
|
||||
gloss_entries = env.temp_data.setdefault('gloss_entries', set())
|
||||
ids = []
|
||||
termnodes = []
|
||||
for _id in node['names']:
|
||||
if _id in gloss_entries:
|
||||
gloss_entries.remove(_id)
|
||||
_id, _, new_termnodes = \
|
||||
make_termnodes_from_paragraph_node(env, patch, _id)
|
||||
ids.append(_id)
|
||||
termnodes.extend(new_termnodes)
|
||||
|
||||
if termnodes and ids:
|
||||
patch = make_term_from_paragraph_node(termnodes, ids)
|
||||
node['ids'] = patch['ids']
|
||||
node['names'] = patch['names']
|
||||
processed = True
|
||||
|
||||
# update leaves with processed nodes
|
||||
if processed:
|
||||
for child in patch.children:
|
||||
child.parent = node
|
||||
node.children = patch.children
|
||||
node['translated'] = True
|
||||
|
||||
|
||||
#phase2: translation
|
||||
for node, msg in extract_messages(self.document):
|
||||
if node.get('translated', False):
|
||||
continue
|
||||
|
||||
msgstr = catalog.gettext(msg)
|
||||
# XXX add marker to untranslated parts
|
||||
if not msgstr or msgstr == msg: # as-of-yet untranslated
|
||||
continue
|
||||
|
||||
# Avoid "Literal block expected; none found." warnings.
|
||||
# If msgstr ends with '::' then it cause warning message at
|
||||
# parser.parse() processing.
|
||||
# literal-block-warning is only appear in avobe case.
|
||||
if msgstr.strip().endswith('::'):
|
||||
msgstr += '\n\n dummy literal'
|
||||
# dummy literal node will discard by 'patch = patch[0]'
|
||||
|
||||
patch = new_document(source, settings)
|
||||
CustomLocaleReporter(node.source, node.line).set_reporter(patch)
|
||||
parser.parse(msgstr, patch)
|
||||
patch = patch[0]
|
||||
# XXX doctest and other block markup
|
||||
if not isinstance(patch, nodes.paragraph):
|
||||
continue # skip for now
|
||||
|
||||
# auto-numbered foot note reference should use original 'ids'.
|
||||
def is_autonumber_footnote_ref(node):
|
||||
@@ -246,7 +303,20 @@ class Locale(Transform):
|
||||
if len(old_refs) != len(new_refs):
|
||||
env.warn_node('inconsistent references in '
|
||||
'translated message', node)
|
||||
old_ref_names = [r['refname'] for r in old_refs]
|
||||
new_ref_names = [r['refname'] for r in new_refs]
|
||||
orphans = list(set(old_ref_names) - set(new_ref_names))
|
||||
for new in new_refs:
|
||||
if not self.document.has_name(new['refname']):
|
||||
# Maybe refname is translated but target is not translated.
|
||||
# Note: multiple translated refnames break link ordering.
|
||||
if orphans:
|
||||
new['refname'] = orphans.pop(0)
|
||||
else:
|
||||
# orphan refnames is already empty!
|
||||
# reference number is same in new_refs and old_refs.
|
||||
pass
|
||||
|
||||
self.document.note_refname(new)
|
||||
|
||||
# refnamed footnote and citation should use original 'ids'.
|
||||
@@ -268,16 +338,6 @@ class Locale(Transform):
|
||||
if refname in refname_ids_map:
|
||||
new["ids"] = refname_ids_map[refname]
|
||||
|
||||
# glossary terms update refid
|
||||
if isinstance(node, nodes.term):
|
||||
new_id, _, termnodes = \
|
||||
make_termnodes_from_paragraph_node(env, patch)
|
||||
term = make_term_from_paragraph_node(
|
||||
termnodes, [new_id])
|
||||
patch = term
|
||||
node['ids'] = patch['ids']
|
||||
node['names'] = patch['names']
|
||||
|
||||
# Original pending_xref['reftarget'] contain not-translated
|
||||
# target name, new pending_xref must use original one.
|
||||
# This code restricts to change ref-targets in the translation.
|
||||
@@ -310,6 +370,7 @@ class Locale(Transform):
|
||||
for child in patch.children:
|
||||
child.parent = node
|
||||
node.children = patch.children
|
||||
node['translated'] = True
|
||||
|
||||
# Extract and translate messages for index entries.
|
||||
for node, entries in traverse_translatable_index(self.document):
|
||||
|
||||
@@ -346,14 +346,14 @@ def test_i18n_role_xref(app):
|
||||
'SOME NEW TERM', '.'],
|
||||
['i18n-role-xref',
|
||||
'contents',
|
||||
'glossary_terms#term-some-new-term'])
|
||||
'glossary_terms#term-some-term'])
|
||||
|
||||
para2 = sec2.findall('paragraph')
|
||||
assert_elem_text_refs(
|
||||
para2[0],
|
||||
['LINK TO', 'SOME OTHER NEW TERM', 'AND', 'SOME NEW TERM', '.'],
|
||||
['glossary_terms#term-some-other-new-term',
|
||||
'glossary_terms#term-some-new-term'])
|
||||
['glossary_terms#term-some-other-term',
|
||||
'glossary_terms#term-some-term'])
|
||||
assert_elem_text_refs(
|
||||
para2[1],
|
||||
['LINK TO', 'SAME TYPE LINKS', 'AND', "I18N ROCK'N ROLE XREF", '.'],
|
||||
|
||||
Reference in New Issue
Block a user