summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshimizukawa <shimizukawa@gmail.com>2013-10-04 05:07:09 +0900
committershimizukawa <shimizukawa@gmail.com>2013-10-04 05:07:09 +0900
commitc3e34e0e59f9f1e16a7eed958685c854c666b96e (patch)
tree0c0e2d2a71ef4854b60deb4113cbb78f41243af0
parentc0ec30bb423782d83b55e7cd1590fb20d396901a (diff)
downloadsphinx-c3e34e0e59f9f1e16a7eed958685c854c666b96e.tar.gz
Now gettext translates label target name. Fix i18n: crash when using a indirect target and translating a target section name. Closes #1265
-rw-r--r--CHANGES19
-rw-r--r--sphinx/builders/gettext.py9
-rw-r--r--sphinx/transforms.py44
-rw-r--r--sphinx/util/nodes.py7
-rw-r--r--tests/roots/test-intl/label_target.po21
-rw-r--r--tests/roots/test-intl/label_target.txt4
-rw-r--r--tests/test_intl.py15
7 files changed, 95 insertions, 24 deletions
diff --git a/CHANGES b/CHANGES
index cb80bd7d..ea6b6a7d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,22 @@
+Release 1.2 (in development)
+============================
+
+Features added
+--------------
+
+* i18n: gettext translates label target name.
+
+Incompatible changes
+--------------------
+
+
+Bugs fixed
+----------
+
+* #1265: Fix i18n: crash when using a indirect target and translating a target
+ section name.
+
+
Release 1.2 beta3 (released Oct 3, 2013)
========================================
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index 50d5163b..5d358665 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -18,7 +18,11 @@ from uuid import uuid4
from sphinx.builders import Builder
from sphinx.util import split_index_msg
-from sphinx.util.nodes import extract_messages, traverse_translatable_index
+from sphinx.util.nodes import (
+ extract_messages,
+ traverse_translatable_target,
+ traverse_translatable_index,
+)
from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog, SEP
from sphinx.util.console import darkgreen, purple, bold
from sphinx.locale import pairindextypes
@@ -97,6 +101,9 @@ class I18nBuilder(Builder):
for node, msg in extract_messages(doctree):
catalog.add(msg, node)
+ for node, msg in traverse_translatable_target(doctree):
+ catalog.add(msg, node)
+
# Extract translatable messages from index entries.
for node, entries in traverse_translatable_index(doctree):
for typ, msg, tid, main in entries:
diff --git a/sphinx/transforms.py b/sphinx/transforms.py
index 338d4739..37952dd6 100644
--- a/sphinx/transforms.py
+++ b/sphinx/transforms.py
@@ -20,7 +20,11 @@ from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes
from sphinx.locale import _, init as init_locale
from sphinx.util import split_index_msg
-from sphinx.util.nodes import traverse_translatable_index, extract_messages
+from sphinx.util.nodes import (
+ traverse_translatable_target,
+ traverse_translatable_index,
+ extract_messages,
+)
from sphinx.util.osutil import ustrftime, find_catalog
from sphinx.util.compat import docutils_version
from sphinx.util.pycompat import all
@@ -178,6 +182,34 @@ class Locale(Transform):
parser = RSTParser()
#phase1: replace reference ids with translated names
+ for node, msg in traverse_translatable_target(self.document):
+ msgstr = catalog.gettext(msg)
+ # XXX add marker to untranslated parts
+ if not msgstr or msgstr == msg or not msgstr.strip():
+ # as-of-yet untranslated
+ continue
+
+ 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
+
+ old_name = msg
+ new_name = nodes.fully_normalize_name(patch.astext())
+
+ if old_name in self.document.nameids:
+ self.document.nameids[new_name] = (
+ self.document.nameids[old_name])
+ self.document.nametypes[new_name] = (
+ self.document.nametypes[old_name])
+ self.document.refnames[new_name] = (
+ self.document.refnames[old_name])
+
+ #phase2: replace reference ids with translated names
for node, msg in extract_messages(self.document):
msgstr = catalog.gettext(msg)
# XXX add marker to untranslated parts
@@ -234,9 +266,9 @@ class Locale(Transform):
# _id was not duplicated.
# remove old_name entry from document ids database
# to reuse original _id.
- self.document.nameids.pop(old_name, None)
- self.document.nametypes.pop(old_name, None)
- self.document.ids.pop(_id, None)
+ self.document.nameids.pop(old_name, None) #supplemental
+ self.document.nametypes.pop(old_name, None) #supplemental
+ self.document.ids.pop(_id, None) # must remove
# re-entry with new named section node.
self.document.note_implicit_target(
@@ -278,7 +310,7 @@ class Locale(Transform):
node['translated'] = True
- #phase2: translation
+ #phase3: translation
for node, msg in extract_messages(self.document):
if node.get('translated', False):
continue
@@ -422,7 +454,7 @@ class Locale(Transform):
node.children = patch.children
node['translated'] = True
- # Extract and translate messages for index entries.
+ #phase4: Extract and translate messages for index entries.
for node, entries in traverse_translatable_index(self.document):
new_entries = []
for type, msg, tid, main in entries:
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index a8395f60..2690cf3a 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -77,6 +77,13 @@ def extract_messages(doctree):
yield node, msg
+def traverse_translatable_target(doctree):
+ """Extract translatable target from a document tree."""
+ for node in doctree.traverse(nodes.target):
+ if 'names' in node and node['names']:
+ yield node, node['names'][0]
+
+
def traverse_translatable_index(doctree):
"""Traverse translatable index node from a document tree."""
def is_block_index(node):
diff --git a/tests/roots/test-intl/label_target.po b/tests/roots/test-intl/label_target.po
index 60d7c3e5..7255dd98 100644
--- a/tests/roots/test-intl/label_target.po
+++ b/tests/roots/test-intl/label_target.po
@@ -31,10 +31,10 @@ msgstr "X EXPLICIT-TARGET"
msgid ""
":ref:`explicit-target` point to ``explicit-target`` and `explicit-target`_"
-" point to duplicated id like ``id1``."
+" point to ``explicit-target`` too."
msgstr ""
":ref:`explicit-target` POINT TO ``explicit-target`` AND `X EXPLICIT-TARGET`_"
-" POINT TO DUPLICATED ID LIKE ``id1``."
+" POINT TO ``explicit-target`` TOO."
msgid "implicit section name"
msgstr "X IMPLICIT SECTION NAME"
@@ -53,14 +53,21 @@ msgstr ""
msgid "label bridged target section"
msgstr "X LABEL BRIDGED TARGET SECTION"
-msgid "`bridge label`_ is not translatable but linked to translated section title."
-msgstr "X `bridge label`_ IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED SECTION TITLE."
+msgid "`bridge label`_ is also translatable and linked to translated section title."
+msgstr "X `Y BRIDGE LABEL`_ IS ALSO TRANSLATABLE AND LINKED TO TRANSLATED SECTION TITLE."
msgid ""
"`bridge label2`_ point to ``section and label`` and `bridge label`_ point to "
"``label bridged target section``. The second appeared `bridge label2`_ point "
"to correct target."
msgstr ""
-"X `bridge label`_ POINT TO ``LABEL BRIDGED TARGET SECTION`` AND "
-"`bridge label2`_ POINT TO ``SECTION AND LABEL``. THE SECOND APPEARED "
-"`bridge label2`_ POINT TO CORRECT TARGET."
+"X `Y BRIDGE LABEL`_ POINT TO ``LABEL BRIDGED TARGET SECTION`` AND "
+"`Z BRIDGE LABEL2`_ POINT TO ``SECTION AND LABEL``. THE SECOND APPEARED "
+"`Z BRIDGE LABEL2`_ POINT TO CORRECT TARGET."
+
+msgid "bridge label"
+msgstr "Y BRIDGE LABEL"
+
+msgid "bridge label2"
+msgstr "Z BRIDGE LABEL2"
+
diff --git a/tests/roots/test-intl/label_target.txt b/tests/roots/test-intl/label_target.txt
index ac000849..93378d36 100644
--- a/tests/roots/test-intl/label_target.txt
+++ b/tests/roots/test-intl/label_target.txt
@@ -21,7 +21,7 @@ explicit-target
.. This case, a duplicated target id is generated by docutils.
:ref:`explicit-target` point to ``explicit-target`` and
-`explicit-target`_ point to duplicated id like ``id1``.
+`explicit-target`_ point to ``explicit-target`` too.
implicit section name
@@ -61,7 +61,7 @@ label bridged target section
.. This section is targeted through label definition.
-`bridge label`_ is not translatable but linked to translated section title.
+`bridge label`_ is also translatable and linked to translated section title.
`bridge label2`_ point to ``section and label`` and `bridge label`_ point to ``label bridged target section``. The second appeared `bridge label2`_ point to correct target.
diff --git a/tests/test_intl.py b/tests/test_intl.py
index 744e1679..1fb2ae1d 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -436,9 +436,8 @@ def test_i18n_label_target(app):
assert_elem(
para1[0],
texts=['X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'AND',
- 'X EXPLICIT-TARGET', 'POINT TO DUPLICATED ID LIKE', 'id1',
- '.'],
- refs=['explicit-target', 'id1'])
+ 'X EXPLICIT-TARGET', 'POINT TO', 'explicit-target', 'TOO.'],
+ refs=['explicit-target', 'explicit-target'])
para2 = secs[2].findall('paragraph')
assert_elem(
@@ -458,16 +457,16 @@ def test_i18n_label_target(app):
para3 = secs[3].findall('paragraph')
assert_elem(
para3[0],
- texts=['X', 'bridge label',
- 'IS NOT TRANSLATABLE BUT LINKED TO TRANSLATED ' +
+ texts=['X', 'Y BRIDGE LABEL',
+ 'IS ALSO TRANSLATABLE AND LINKED TO TRANSLATED ' +
'SECTION TITLE.'],
refs=['label-bridged-target-section'])
assert_elem(
para3[1],
- texts=['X', 'bridge label', 'POINT TO',
- 'LABEL BRIDGED TARGET SECTION', 'AND', 'bridge label2',
+ texts=['X', 'Y BRIDGE LABEL', 'POINT TO',
+ 'LABEL BRIDGED TARGET SECTION', 'AND', 'Z BRIDGE LABEL2',
'POINT TO', 'SECTION AND LABEL', '. THE SECOND APPEARED',
- 'bridge label2', 'POINT TO CORRECT TARGET.'],
+ 'Z BRIDGE LABEL2', 'POINT TO CORRECT TARGET.'],
refs=['label-bridged-target-section',
'section-and-label',
'section-and-label'])