Merge branch 'stable'

This commit is contained in:
shimizukawa 2015-09-13 09:47:38 +09:00
commit ef890a45d3
25 changed files with 382 additions and 66 deletions

16
CHANGES
View File

@ -18,11 +18,13 @@ Features added
Bugs fixed
----------
* #1976: Avoid "2.0" version of Babel because it doesn't work with Windows environment.
* Add a "default.css" stylesheet (which imports "classic.css") for compatibility.
* #1788: graphviz extension raises exception when caption option is present.
* #1789: ``:pyobject:`` option of ``literalinclude`` directive includes following
lines after class definitions.
* #1790: ``literalinclude`` strips empty lines at the head and tail.
* #1913: C++, fix assert bug for enumerators in next-to-global and global scope.
* #1790: ``literalinclude`` strips empty lines at the head and tail
* #1802: load plugin themes automatically when theme.conf use it as 'inherit'. Thanks to
Takayuki Hirai.
* #1794: custom theme extended from alabaster or sphinx_rtd_theme can't find base theme.
@ -47,15 +49,21 @@ Bugs fixed
* #1942: Fix a KeyError in websupport.
* #1903: Fix strange id generation for glossary terms.
* #1796, On py3, automated .mo building cause UnicodeDecodeError
* Fix: ``make text`` will crush if a definition list item has more than 1 classifiers as:
* #1796: On py3, automated .mo building cause UnicodeDecodeError
* ``make text`` will crush if a definition list item has more than 1 classifiers as:
* Fixed #1855: make gettext generates broken po file for definition lists with classifier.
``term : classifier1 : classifier2``.
* #1855: make gettext generates broken po file for definition lists with classifier.
* #1869: Fix problems when dealing with files containing non-ASCII characters. Thanks to
Marvin Schmidt.
* #1798: Fix building LaTeX with references in titles.
* #1725: On py2 environment, doctest with using non-ASCII characters causes
``'ascii' codec can't decode byte`` exception.
* #1540: Fix RuntimeError with circular referenced toctree
* #1983: i18n translation feature breaks references which uses section name.
* #1990: Use caption of toctree to title of \tableofcontents in LaTeX
* #1987: Fix ampersand is ignored in ``:menuselection:`` and ``:guilabel:`` on LaTeX builder
* #1994: More supporting non-standard parser (like recommonmark parser) for Translation and
WebSupport feature. Now node.rawsource is fall backed to node.astext() during docutils
transforming.
Documentation
-------------

View File

@ -51,7 +51,7 @@ requires = [
'Pygments>=2.0',
'docutils>=0.11',
'snowballstemmer>=1.1',
'babel>=1.3',
'babel>=1.3,!=2.0',
'alabaster>=0.7,<0.8',
'sphinx_rtd_theme>=0.1,<0.2',
]

View File

@ -160,10 +160,14 @@ class Builder(object):
def compile_catalogs(self, catalogs, message):
if not self.config.gettext_auto_build:
return
def cat2relpath(cat):
return path.relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
self.info(bold('building [mo]: ') + message)
for catalog in self.app.status_iterator(
catalogs, 'writing output... ', darkgreen, len(catalogs),
lambda c: c.mo_path):
cat2relpath):
catalog.write_mo(self.config.language)
def compile_all_catalogs(self):

View File

@ -945,7 +945,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
def assemble_doctree(self):
master = self.config.master_doc
tree = self.env.get_doctree(master)
tree = inline_all_toctrees(self, set(), master, tree, darkgreen)
tree = inline_all_toctrees(self, set(), master, tree, darkgreen, [master])
tree['docname'] = master
self.env.resolve_references(tree, master, self)
self.fix_refuris(tree)

View File

@ -102,11 +102,22 @@ class LaTeXBuilder(Builder):
doctree.settings = docsettings
doctree.settings.author = author
doctree.settings.title = title
doctree.settings.contentsname = self.get_contentsname(docname)
doctree.settings.docname = docname
doctree.settings.docclass = docclass
docwriter.write(doctree, destination)
self.info("done")
def get_contentsname(self, indexfile):
tree = self.env.get_doctree(indexfile)
contentsname = None
for toctree in tree.traverse(addnodes.toctree):
if toctree['caption']:
contentsname = toctree['caption']
break
return contentsname
def assemble_doctree(self, indexfile, toctree_only, appendices):
self.docnames = set([indexfile] + appendices)
self.info(darkgreen(indexfile) + " ", nonl=1)
@ -124,7 +135,7 @@ class LaTeXBuilder(Builder):
new_sect += node
tree = new_tree
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
darkgreen)
darkgreen, [indexfile])
largetree['docname'] = indexfile
for docname in appendices:
appendix = self.env.get_doctree(docname)

View File

@ -70,7 +70,7 @@ class ManualPageBuilder(Builder):
tree = self.env.get_doctree(docname)
docnames = set()
largetree = inline_all_toctrees(self, docnames, docname, tree,
darkgreen)
darkgreen, [docname])
self.info('} ', nonl=True)
self.env.resolve_references(largetree, docname, self)
# remove pending_xref nodes

View File

@ -180,7 +180,7 @@ class TexinfoBuilder(Builder):
new_sect += node
tree = new_tree
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
darkgreen)
darkgreen, [indexfile])
largetree['docname'] = indexfile
for docname in appendices:
appendix = self.env.get_doctree(docname)

View File

@ -142,7 +142,7 @@ class Author(Directive):
env = self.state.document.settings.env
if not env.config.show_authors:
return []
para = nodes.paragraph()
para = nodes.paragraph(translatable=False)
emph = nodes.emphasis()
para += emph
if self.name == 'sectionauthor':
@ -205,7 +205,7 @@ class VersionChange(Directive):
if len(self.arguments) == 2:
inodes, messages = self.state.inline_text(self.arguments[1],
self.lineno+1)
para = nodes.paragraph(self.arguments[1], '', *inodes)
para = nodes.paragraph(self.arguments[1], '', *inodes, translatable=False)
set_source_info(self, para)
node.append(para)
else:
@ -218,13 +218,14 @@ class VersionChange(Directive):
content.source = node[0].source
content.line = node[0].line
content += node[0].children
node[0].replace_self(nodes.paragraph('', '', content))
node[0].replace_self(nodes.paragraph('', '', content, translatable=False))
node[0].insert(0, nodes.inline('', '%s: ' % text,
classes=['versionmodified']))
else:
para = nodes.paragraph('', '',
nodes.inline('', '%s.' % text,
classes=['versionmodified']))
classes=['versionmodified']),
translatable=False)
node.append(para)
env = self.state.document.settings.env
# XXX should record node.source as well

View File

@ -49,9 +49,11 @@ from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _
from sphinx.versioning import add_uids, merge_doctrees
from sphinx.transforms import DefaultSubstitutions, MoveModuleTargets, \
HandleCodeBlocks, AutoNumbering, SortIds, CitationReferences, Locale, \
RemoveTranslatableInline, SphinxContentsFilter, ExtraTranslatableNodes
from sphinx.transforms import (
DefaultSubstitutions, MoveModuleTargets, ApplySourceWorkaround,
HandleCodeBlocks, AutoNumbering, SortIds, CitationReferences, Locale,
RemoveTranslatableInline, SphinxContentsFilter, ExtraTranslatableNodes,
)
orig_role_function = roles.role
@ -99,7 +101,7 @@ class SphinxStandaloneReader(standalone.Reader):
"""
Add our own transforms.
"""
transforms = [ExtraTranslatableNodes, Locale, CitationReferences,
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, Locale, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline]

View File

@ -9,14 +9,16 @@
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import absolute_import
import re
import sys
import time
import codecs
from os import path
import doctest
from six import itervalues, StringIO, binary_type
from six import itervalues, StringIO, binary_type, text_type, PY2
from docutils import nodes
from docutils.parsers.rst import directives
@ -26,13 +28,30 @@ from sphinx.util import force_decode
from sphinx.util.nodes import set_source_info
from sphinx.util.compat import Directive
from sphinx.util.console import bold
# circumvent relative import
doctest = __import__('doctest')
from sphinx.util.osutil import fs_encoding
blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
if PY2:
def doctest_encode(text, encoding):
if isinstance(text, text_type):
text = text.encode(encoding)
if text.startswith(codecs.BOM_UTF8):
text = text[len(codecs.BOM_UTF8):]
return text
else:
def doctest_encode(text, encoding):
return text
class _SpoofOutSphinx(doctest._SpoofOut):
# override: convert console encoding to unicode
if PY2:
def getvalue(self):
result = doctest._SpoofOut.getvalue(self)
return result.decode('string_escape')
# set up the necessary directives
@ -165,6 +184,11 @@ class TestCode(object):
class SphinxDocTestRunner(doctest.DocTestRunner):
def __init__(self, *args, **kw):
doctest.DocTestRunner.__init__(self, *args, **kw)
# Override a fake output target for capturing doctest output.
self._fakeout = _SpoofOutSphinx()
def summarize(self, out, verbose=None):
string_io = StringIO()
old_stdout = sys.stdout
@ -358,19 +382,25 @@ Doctest summary
return compile(code, name, self.type, flags, dont_inherit)
def test_group(self, group, filename):
if PY2:
filename_str = filename.encode(fs_encoding)
else:
filename_str = filename
ns = {}
def run_setup_cleanup(runner, testcodes, what):
examples = []
for testcode in testcodes:
examples.append(doctest.Example(testcode.code, '',
lineno=testcode.lineno))
examples.append(doctest.Example(
doctest_encode(testcode.code, self.env.config.source_encoding), '',
lineno=testcode.lineno))
if not examples:
return True
# simulate a doctest with the code
sim_doctest = doctest.DocTest(examples, {},
'%s (%s code)' % (group.name, what),
filename, 0, None)
filename_str, 0, None)
sim_doctest.globs = ns
old_f = runner.failures
self.type = 'exec' # the snippet may contain multiple statements
@ -389,8 +419,9 @@ Doctest summary
if len(code) == 1:
# ordinary doctests (code/output interleaved)
try:
test = parser.get_doctest(code[0].code, {}, group.name,
filename, code[0].lineno)
test = parser.get_doctest(
doctest_encode(code[0].code, self.env.config.source_encoding), {},
group.name, filename_str, code[0].lineno)
except Exception:
self.warn('ignoring invalid doctest code: %r' %
code[0].code,
@ -416,12 +447,13 @@ Doctest summary
exc_msg = m.group('msg')
else:
exc_msg = None
example = doctest.Example(code[0].code, output,
exc_msg=exc_msg,
lineno=code[0].lineno,
options=options)
example = doctest.Example(
doctest_encode(code[0].code, self.env.config.source_encoding), output,
exc_msg=exc_msg,
lineno=code[0].lineno,
options=options)
test = doctest.DocTest([example], {}, group.name,
filename, code[0].lineno, None)
filename_str, code[0].lineno, None)
self.type = 'exec' # multiple statements again
# DocTest.__init__ copies the globs namespace, which we don't want
test.globs = ns

View File

@ -22,6 +22,7 @@ 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, LITERAL_TYPE_NODES, IMAGE_TYPE_NODES,
apply_source_workaround,
)
from sphinx.util.osutil import ustrftime
from sphinx.util.i18n import find_catalog
@ -169,6 +170,18 @@ TRANSLATABLE_NODES = {
}
class ApplySourceWorkaround(Transform):
"""
update source and rawsource attributes
"""
default_priority = 10
def apply(self):
for n in self.document.traverse():
if isinstance(n, nodes.TextElement):
apply_source_workaround(n)
class ExtraTranslatableNodes(Transform):
"""
make nodes translatable
@ -277,8 +290,10 @@ class Locale(Transform):
# document nameids mapping with new name.
names = section_node.setdefault('names', [])
names.append(new_name)
if old_name in names:
names.remove(old_name)
# Original section name (reference target name) should be kept to refer
# from other nodes which is still not translated or uses explicit target
# name like "`text to display <explicit target name_>`_"..
# So, `old_name` is still exist in `names`.
_id = self.document.nameids.get(old_name, None)
explicit = self.document.nametypes.get(old_name, None)

View File

@ -50,6 +50,10 @@ def apply_source_workaround(node):
# overwrite: ``term : classifier1 : classifier2`` -> ``term text``
node.rawsource = node.astext()
# workaround: recommonmark-0.2.0 doesn't set rawsource attribute
if not node.rawsource:
node.rawsource = node.astext()
if node.source and node.rawsource:
return
@ -74,18 +78,20 @@ IGNORED_NODES = (
nodes.Inline,
nodes.literal_block,
nodes.doctest_block,
addnodes.versionmodified,
# XXX there are probably more
)
def is_translatable(node):
if isinstance(node, nodes.TextElement):
apply_source_workaround(node)
if not node.source:
return False # built-in message
if isinstance(node, IGNORED_NODES) and 'translatable' not in node:
return False
if not node.get('translatable', True):
# not(node['translatable'] == True or node['translatable'] is None)
return False
# <field_name>orphan</field_name>
# XXX ignore all metadata (== docinfo)
if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
@ -228,7 +234,7 @@ def process_index_entry(entry, targetid):
return indexentries
def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc, traversed):
"""Inline all toctrees in the *tree*.
Record all docnames in *docnameset*, and output docnames with *colorfunc*.
@ -238,23 +244,25 @@ def inline_all_toctrees(builder, docnameset, docname, tree, colorfunc):
newnodes = []
includefiles = map(text_type, toctreenode['includefiles'])
for includefile in includefiles:
try:
builder.info(colorfunc(includefile) + " ", nonl=1)
subtree = inline_all_toctrees(builder, docnameset, includefile,
builder.env.get_doctree(includefile),
colorfunc)
docnameset.add(includefile)
except Exception:
builder.warn('toctree contains ref to nonexisting '
'file %r' % includefile,
builder.env.doc2path(docname))
else:
sof = addnodes.start_of_file(docname=includefile)
sof.children = subtree.children
for sectionnode in sof.traverse(nodes.section):
if 'docname' not in sectionnode:
sectionnode['docname'] = includefile
newnodes.append(sof)
if includefile not in traversed:
try:
traversed.append(includefile)
builder.info(colorfunc(includefile) + " ", nonl=1)
subtree = inline_all_toctrees(builder, docnameset, includefile,
builder.env.get_doctree(includefile),
colorfunc, traversed)
docnameset.add(includefile)
except Exception:
builder.warn('toctree contains ref to nonexisting '
'file %r' % includefile,
builder.env.doc2path(docname))
else:
sof = addnodes.start_of_file(docname=includefile)
sof.children = subtree.children
for sectionnode in sof.traverse(nodes.section):
if 'docname' not in sectionnode:
sectionnode['docname'] = includefile
newnodes.append(sof)
toctreenode.parent.replace(toctreenode, newnodes)
return tree

View File

@ -43,6 +43,7 @@ HEADER = r'''%% Generated by Sphinx.
\usepackage{sphinx}
\usepackage{multirow}
%(usepackages)s
%(contentsname)s
%(numfig_format)s
%(preamble)s
@ -159,6 +160,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'longtable': '\\usepackage{longtable}',
'usepackages': '',
'numfig_format': '',
'contentsname': '',
'preamble': '',
'title': '',
'date': '',
@ -248,6 +250,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
return '\\usepackage{%s}' % (packagename,)
usepackages = (declare_package(*p) for p in builder.usepackages)
self.elements['usepackages'] += "\n".join(usepackages)
if getattr(document.settings, 'contentsname', None):
self.elements['contentsname'] = \
self.babel_renewcommand(builder, '\\contentsname',
document.settings.contentsname)
self.elements['numfig_format'] = self.generate_numfig_format(builder)
# allow the user to override them all
self.elements.update(builder.config.latex_elements)
@ -329,8 +335,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
encode('ascii', 'backslashreplace').decode('ascii').\
replace('\\', '_')
def generate_numfig_format(self, builder):
ret = []
def babel_renewcommand(self, builder, command, definition):
if builder.config.language == 'ja':
babel_prefix = ''
babel_suffix = ''
@ -349,15 +354,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
babel_prefix = ''
babel_suffix = ''
return ('%s\\renewcommand{%s}{%s}%s\n' %
(babel_prefix, command, definition, babel_suffix))
def generate_numfig_format(self, builder):
ret = []
figure = self.builder.config.numfig_format['figure'].split('%s', 1)
if len(figure) == 1:
ret.append('\\def\\fnum@figure{%s}\n' %
text_type(figure[0]).translate(tex_escape_map))
else:
ret.append('%s\\renewcommand{\\figurename}{%s}%s\n' %
(babel_prefix,
text_type(figure[0]).translate(tex_escape_map),
babel_suffix))
definition = text_type(figure[0]).translate(tex_escape_map)
ret.append(self.babel_renewcommand(builder, '\\figurename', definition))
if figure[1]:
ret.append('\\makeatletter\n')
ret.append('\\def\\fnum@figure{\\figurename\\thefigure%s}\n' %
@ -369,10 +377,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
ret.append('\\def\\fnum@table{%s}\n' %
text_type(table[0]).translate(tex_escape_map))
else:
ret.append('%s\\renewcommand{\\tablename}{%s}%s\n' %
(babel_prefix,
text_type(table[0]).translate(tex_escape_map),
babel_suffix))
definition = text_type(table[0]).translate(tex_escape_map)
ret.append(self.babel_renewcommand(builder, '\\tablename', definition))
if table[1]:
ret.append('\\makeatletter\n')
ret.append('\\def\\fnum@table{\\tablename\\thetable%s}\n' %
@ -1707,6 +1713,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
if classes in [['menuselection'], ['guilabel']]:
self.body.append(r'\emph{')
self.context.append('}')
elif classes in [['accelerator']]:
self.body.append(r'\underline{')
self.context.append('}')
elif classes and not self.in_title:
self.body.append(r'\DUspan{%s}{' % ','.join(classes))
self.context.append('}')

View File

@ -0,0 +1,4 @@
===
Bar
===

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
html_theme = 'classic'

View File

@ -0,0 +1,4 @@
===
Foo
===

View File

@ -0,0 +1,8 @@
test-tocdepth
=============
.. toctree::
:caption: Table of content
foo
bar

View File

@ -127,3 +127,12 @@ Special directives
import test_ext_doctest
test_ext_doctest.cleanup_call()
non-ASCII result
----------------
>>> print('umlauts: äöü.')
umlauts: äöü.
>>> print('Japanese: 日本語')
Japanese: 日本語

View File

@ -22,3 +22,4 @@ CONTENTS
versionchange
docfields
raw
refs

View File

@ -0,0 +1,85 @@
#
msgid ""
msgstr ""
"Project-Id-Version: 1191 1.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-08-08 15:31+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Translation Tips"
msgstr "X TIPS"
msgid "A-1. Here's how you can `download Sphinx`_."
msgstr "A-1. HERE'S HOW YOU CAN `download Sphinx`_."
msgid "A-2. Here's how you can `download Sphinx`_."
msgstr "A-2. HERE'S HOW YOU CAN `A1 DOWNLOAD SPHINX`_."
msgid "A-3. Here's how you can `download Sphinx`_."
msgstr ""
"A-3. HERE'S HOW YOU CAN `A3 DOWNLOAD SPHINX <download Sphinx_>`_ AND `A3 DOWNLOAD "
"SPHINX <download Sphinx_>`_."
msgid "B-1. `Docutils site`_ and `Sphinx site`_."
msgstr "B-1. `Docutils site`_ and `Sphinx site`_."
msgid "B-2. `Docutils site`_ and `Sphinx site`_."
msgstr "B-2. `B1 DOCUTILS SITE`_ AND `B1 SPHINX SITE`_."
msgid "B-3. `Docutils site`_ and `Sphinx site`_."
msgstr "B-3. `B2 SPHINX SITE`_ AND `B2 DOCUTILS SITE`_."
msgid "B-4. `Docutils site`_ and `Sphinx site`_."
msgstr ""
"B-4. `B4 SPHINX SITE <Sphinx site_>`_ AND `B4 DOCUTILS SITE <Docutils "
"site_>`_."
msgid "B-5. `Docutils site`_ and `Sphinx site`_."
msgstr ""
"B-5. `B5 SPHINX SITE <Sphinx site_>`_ AND `B5 DOCUTILS SITE <Docutils "
"site_>`_\" AND `B5 SPHINX SITE <Sphinx site_>`_."
msgid "C-1. Link to `Translation Tips`_ section."
msgstr "C-1. LINK TO `Translation Tips`_ SECTION."
msgid "C-2. Link to `Translation Tips`_ section."
msgstr "C-2. LINK TO `X TIPS`_ SECTION."
msgid "C-3. Link to `Translation Tips`_ section."
msgstr "C-3. LINK TO `X TIPS <Translation Tips_>`_ SECTION."
msgid "C-4. Link to `Translation Tips`_ section."
msgstr ""
"C-4. LINK TO `X TIPS <Translation Tips_>`_ x `X TIPS <Translation Tips_>`_ "
"SECTION."
msgid "C-5. Link to `Translation Tips`_ section."
msgstr ""
"C-5. LINK TO `TRANS <X TIPS_>`_ x `LATION <X TIPS_>`_ "
msgid "D-1. Link to `Translation Tips`_ and `Next Section`_ section."
msgstr "D-1. LINK TO `Translation Tips`_ and `Next Section`_ SECTION."
msgid "D-2. Link to `Translation Tips`_ and `Next Section`_ section."
msgstr "D-2. LINK TO `X TIPS`_ AND `N SECTION`_ SECTION."
msgid "D-3. Link to `Translation Tips`_ and `Next Section`_ section."
msgstr "D-3. LINK TO `N SECTION`_ AND `X TIPS`_ SECTION."
msgid "D-4. Link to `Translation Tips`_ and `Next Section`_ section."
msgstr ""
"D-4. LINK TO `N SECTION <Next Section_>`_ AND `X TIPS <Translation Tips_>`_ "
"SECTION."
msgid "D-5. Link to `Translation Tips`_ and `Next Section`_ section."
msgstr ""
"D-5. LINK TO `Next <N SECTION_>`_ AND `Tips <X TIPS_>`_ "
msgid "Next Section"
msgstr "N SECTION"

View File

@ -0,0 +1,47 @@
References
===========
Translation Tips
-----------------
.. _download Sphinx: https://pypi.python.org/pypi/sphinx
.. _Docutils site: http://docutils.sourceforge.net/
.. _Sphinx site: http://sphinx-doc.org/
A-1. Here's how you can `download Sphinx`_.
A-2. Here's how you can `download Sphinx`_.
A-3. Here's how you can `download Sphinx`_.
B-1. `Docutils site`_ and `Sphinx site`_.
B-2. `Docutils site`_ and `Sphinx site`_.
B-3. `Docutils site`_ and `Sphinx site`_.
B-4. `Docutils site`_ and `Sphinx site`_.
C-1. Link to `Translation Tips`_ section.
C-2. Link to `Translation Tips`_ section.
C-3. Link to `Translation Tips`_ section.
C-4. Link to `Translation Tips`_ section.
C-5. Link to `Translation Tips`_ section.
D-1. Link to `Translation Tips`_ and `Next Section`_ section.
D-2. Link to `Translation Tips`_ and `Next Section`_ section.
D-3. Link to `Translation Tips`_ and `Next Section`_ section.
D-4. Link to `Translation Tips`_ and `Next Section`_ section.
D-5. Link to `Translation Tips`_ and `Next Section`_ section.
Next Section
-------------

View File

@ -275,3 +275,25 @@ def test_latex_add_latex_package(app, status, warning):
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
assert '\\usepackage{foo}' in result
assert '\\usepackage[baz]{bar}' in result
@with_app(buildername='latex', testroot='contentsname')
def test_contentsname(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert ('\\addto\\captionsenglish{\\renewcommand{\\contentsname}{Table of content}}'
in result)
@with_app(buildername='latex', testroot='contentsname',
confoverrides={'language': 'ja'})
def test_contentsname_with_language_ja(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert '\\renewcommand{\\contentsname}{Table of content}' in result

View File

@ -751,3 +751,11 @@ def test_additional_targets_should_be_translated(app, status, warning):
expected_expr = """<img alt="IMG -&gt; I18N" src="_images/i18n.png" />"""
yield assert_count(expected_expr, result, 1)
@gen_with_intl_app('text', freshenv=True)
def test_references(app, status, warning):
app.builder.build_specific([app.srcdir / 'refs.txt'])
warnings = warning.getvalue().replace(os.sep, '/')
warning_expr = u'refs.txt:\\d+: ERROR: Unknown target name:'
yield assert_count(warning_expr, warnings, 0)

View File

@ -109,7 +109,7 @@ def test_inline():
yield (verify, ':guilabel:`&Foo -&&- &Bar`',
u'<p><span class="guilabel"><span class="accelerator">F</span>oo '
'-&amp;- <span class="accelerator">B</span>ar</span></p>',
r'\emph{\DUspan{accelerator}{F}oo -\&- \DUspan{accelerator}{B}ar}')
r'\emph{\underline{F}oo -\&- \underline{B}ar}')
# non-interpolation of dashes in option role
yield (verify_re, ':option:`--with-option`',

View File

@ -16,13 +16,24 @@ from docutils.utils import new_document
from docutils import frontend
from sphinx.util.nodes import extract_messages
from sphinx.transforms import ApplySourceWorkaround
def _get_doctree(text):
def _transform(doctree):
ApplySourceWorkaround(doctree).apply()
def create_new_document():
settings = frontend.OptionParser(
components=(rst.Parser,)).get_default_values()
document = new_document('dummy.txt', settings)
return document
def _get_doctree(text):
document = create_new_document()
rst.Parser().parse(text, document)
_transform(document)
return document
@ -119,3 +130,26 @@ def test_extract_messages():
extract_messages(_get_doctree(text)),
nodes.line, 2,
)
def test_extract_messages_without_rawsource():
"""
Check node.rawsource is fall-backed by using node.astext() value.
`extract_message` which is used from Sphinx i18n feature drop ``not node.rawsource`` nodes.
So, all nodes which want to translate must have ``rawsource`` value.
However, sometimes node.rawsource is not set.
For example: recommonmark-0.2.0 doesn't set rawsource to `paragraph` node.
refs #1994: Fall back to node's astext() during i18n message extraction.
"""
p = nodes.paragraph()
p.append(nodes.Text('test'))
p.append(nodes.Text('sentence'))
assert not p.rawsource # target node must not have rawsource value
document = create_new_document()
document.append(p)
_transform(document)
assert_node_count(extract_messages(document), nodes.TextElement, 1)
assert [m for n, m in extract_messages(document)][0], 'text sentence'