2010-11-14 12:42:50 -06:00
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
"""
|
|
|
|
|
test_intl
|
|
|
|
|
~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
Test message patching for internationalization purposes. Runs the text
|
|
|
|
|
builder in the test root.
|
|
|
|
|
|
2016-01-14 15:54:04 -06:00
|
|
|
|
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
2010-11-14 12:42:50 -06:00
|
|
|
|
:license: BSD, see LICENSE for details.
|
|
|
|
|
"""
|
2014-01-19 04:17:10 -06:00
|
|
|
|
from __future__ import print_function
|
2010-11-14 12:42:50 -06:00
|
|
|
|
|
2012-12-04 22:11:16 -06:00
|
|
|
|
import os
|
2013-04-01 04:39:32 -05:00
|
|
|
|
import re
|
2016-01-26 10:36:43 -06:00
|
|
|
|
import pickle
|
|
|
|
|
from docutils import nodes
|
2013-04-01 04:39:32 -05:00
|
|
|
|
from subprocess import Popen, PIPE
|
2013-06-16 09:57:08 -05:00
|
|
|
|
from xml.etree import ElementTree
|
2010-11-14 12:42:50 -06:00
|
|
|
|
|
2016-01-09 00:33:43 -06:00
|
|
|
|
from babel.messages import pofile
|
2014-09-21 11:48:21 -05:00
|
|
|
|
from nose.tools import assert_equal
|
2014-09-21 10:17:02 -05:00
|
|
|
|
from six import string_types
|
2014-04-28 21:46:47 -05:00
|
|
|
|
|
2016-01-26 10:36:43 -06:00
|
|
|
|
from util import tempdir, rootdir, path, gen_with_app, with_app, SkipTest, \
|
2014-09-21 11:54:01 -05:00
|
|
|
|
assert_re_search, assert_not_re_search, assert_in, assert_not_in, \
|
2016-03-03 08:01:34 -06:00
|
|
|
|
assert_startswith, assert_node, repr_as
|
2010-11-14 12:42:50 -06:00
|
|
|
|
|
|
|
|
|
|
2014-09-21 10:17:02 -05:00
|
|
|
|
root = tempdir / 'test-intl'
|
2013-01-06 01:15:49 -06:00
|
|
|
|
|
|
|
|
|
|
2015-02-21 22:51:02 -06:00
|
|
|
|
def gen_with_intl_app(builder, confoverrides={}, *args, **kw):
|
2013-01-06 01:15:49 -06:00
|
|
|
|
default_kw = {
|
2014-09-21 10:17:02 -05:00
|
|
|
|
'testroot': 'intl',
|
2013-01-06 01:15:49 -06:00
|
|
|
|
'confoverrides': {
|
|
|
|
|
'language': 'xx', 'locale_dirs': ['.'],
|
|
|
|
|
'gettext_compact': False,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
default_kw.update(kw)
|
2015-02-21 22:51:02 -06:00
|
|
|
|
default_kw['confoverrides'].update(confoverrides)
|
|
|
|
|
return gen_with_app(builder, *args, **default_kw)
|
2012-12-04 22:11:16 -06:00
|
|
|
|
|
|
|
|
|
|
2016-01-09 10:04:38 -06:00
|
|
|
|
def read_po(pathname):
|
|
|
|
|
with pathname.open() as f:
|
|
|
|
|
return pofile.read_po(f)
|
|
|
|
|
|
|
|
|
|
|
2010-11-14 12:42:50 -06:00
|
|
|
|
def setup_module():
|
2014-09-21 10:17:02 -05:00
|
|
|
|
if not root.exists():
|
|
|
|
|
(rootdir / 'roots' / 'test-intl').copytree(root)
|
2012-12-11 01:36:50 -06:00
|
|
|
|
# Delete remnants left over after failed build
|
2010-11-14 12:42:50 -06:00
|
|
|
|
# Compile all required catalogs into binary format (*.mo).
|
2013-01-06 01:15:49 -06:00
|
|
|
|
for dirpath, dirs, files in os.walk(root):
|
2012-12-04 22:38:04 -06:00
|
|
|
|
dirpath = path(dirpath)
|
2012-12-04 22:11:30 -06:00
|
|
|
|
for f in [f for f in files if f.endswith('.po')]:
|
2012-12-04 22:38:04 -06:00
|
|
|
|
po = dirpath / f
|
2013-01-06 01:15:49 -06:00
|
|
|
|
mo = root / 'xx' / 'LC_MESSAGES' / (
|
2014-09-21 10:17:02 -05:00
|
|
|
|
os.path.relpath(po[:-3], root) + '.mo')
|
2012-12-04 22:38:04 -06:00
|
|
|
|
if not mo.parent.exists():
|
|
|
|
|
mo.parent.makedirs()
|
2012-12-04 22:11:30 -06:00
|
|
|
|
try:
|
|
|
|
|
p = Popen(['msgfmt', po, '-o', mo],
|
2014-09-21 10:17:02 -05:00
|
|
|
|
stdout=PIPE, stderr=PIPE)
|
2012-12-04 22:11:30 -06:00
|
|
|
|
except OSError:
|
|
|
|
|
raise SkipTest # most likely msgfmt was not found
|
|
|
|
|
else:
|
|
|
|
|
stdout, stderr = p.communicate()
|
|
|
|
|
if p.returncode != 0:
|
2014-01-19 04:17:10 -06:00
|
|
|
|
print(stdout)
|
|
|
|
|
print(stderr)
|
2013-01-13 03:22:38 -06:00
|
|
|
|
assert False, \
|
|
|
|
|
'msgfmt exited with return code %s' % p.returncode
|
2012-12-04 22:11:30 -06:00
|
|
|
|
assert mo.isfile(), 'msgfmt failed'
|
2010-11-14 12:42:50 -06:00
|
|
|
|
|
|
|
|
|
|
2013-06-16 10:12:02 -05:00
|
|
|
|
def elem_gettexts(elem):
|
|
|
|
|
def itertext(self):
|
|
|
|
|
# this function copied from Python-2.7 'ElementTree.itertext'.
|
2013-12-15 01:04:23 -06:00
|
|
|
|
# for compatibility to Python-2.6
|
2013-06-16 10:12:02 -05:00
|
|
|
|
tag = self.tag
|
2014-04-30 07:30:46 -05:00
|
|
|
|
if not isinstance(tag, string_types) and tag is not None:
|
2013-06-16 10:12:02 -05:00
|
|
|
|
return
|
|
|
|
|
if self.text:
|
|
|
|
|
yield self.text
|
|
|
|
|
for e in self:
|
|
|
|
|
for s in itertext(e):
|
|
|
|
|
yield s
|
|
|
|
|
if e.tail:
|
|
|
|
|
yield e.tail
|
2014-01-19 04:17:10 -06:00
|
|
|
|
return [_f for _f in [s.strip() for s in itertext(elem)] if _f]
|
2013-06-16 10:12:02 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def elem_getref(elem):
|
|
|
|
|
return elem.attrib.get('refid') or elem.attrib.get('refuri')
|
|
|
|
|
|
|
|
|
|
|
2013-06-20 20:09:13 -05:00
|
|
|
|
def assert_elem(elem, texts=None, refs=None, names=None):
|
|
|
|
|
if texts is not None:
|
|
|
|
|
_texts = elem_gettexts(elem)
|
|
|
|
|
assert _texts == texts
|
|
|
|
|
if refs is not None:
|
2014-04-30 09:25:44 -05:00
|
|
|
|
_refs = [elem_getref(x) for x in elem.findall('reference')]
|
2013-06-20 20:09:13 -05:00
|
|
|
|
assert _refs == refs
|
|
|
|
|
if names is not None:
|
|
|
|
|
_names = elem.attrib.get('names').split()
|
|
|
|
|
assert _names == names
|
2013-06-16 10:12:02 -05:00
|
|
|
|
|
|
|
|
|
|
2015-02-24 07:38:01 -06:00
|
|
|
|
def assert_count(expected_expr, result, count):
|
|
|
|
|
find_pair = (expected_expr, result)
|
|
|
|
|
return assert_equal, len(re.findall(*find_pair)), count, find_pair
|
|
|
|
|
|
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
@gen_with_intl_app('text', freshenv=True)
|
|
|
|
|
def test_text_builder(app, status, warning):
|
|
|
|
|
app.builder.build_all()
|
2010-11-14 12:50:30 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- warnings in translation
|
2012-11-21 20:43:09 -06:00
|
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
|
warnings = getwarning(warning)
|
2014-09-21 11:26:50 -05:00
|
|
|
|
warning_expr = u'.*/warnings.txt:4: ' \
|
|
|
|
|
u'WARNING: Inline literal start-string without end-string.\n'
|
2014-09-21 11:54:01 -05:00
|
|
|
|
yield assert_re_search, warning_expr, warnings
|
2012-11-21 20:43:09 -06:00
|
|
|
|
|
2013-02-04 07:23:03 -06:00
|
|
|
|
result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
|
|
|
|
|
expect = (u"\nI18N WITH REST WARNINGS"
|
|
|
|
|
u"\n***********************\n"
|
|
|
|
|
u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_equal, result, expect
|
2013-02-04 07:23:03 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- simple translation; check title underlines
|
2012-12-18 16:49:17 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
result = (app.outdir / 'bom.txt').text(encoding='utf-8')
|
|
|
|
|
expect = (u"\nDatei mit UTF-8"
|
|
|
|
|
u"\n***************\n" # underline matches new translation
|
|
|
|
|
u"\nThis file has umlauts: äöü.\n")
|
|
|
|
|
yield assert_equal, result, expect
|
2012-12-18 16:49:17 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- check translation in subdirs
|
2014-03-23 09:01:15 -05:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
|
2014-09-21 11:54:01 -05:00
|
|
|
|
yield assert_startswith, result, u"\nsubdir contents\n***************\n"
|
2014-03-23 09:01:15 -05:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- check warnings for inconsistency in number of references
|
2014-03-23 09:01:15 -05:00
|
|
|
|
|
2013-01-06 01:15:49 -06:00
|
|
|
|
result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
|
2012-12-04 22:11:16 -06:00
|
|
|
|
expect = (u"\nI18N WITH REFS INCONSISTENCY"
|
|
|
|
|
u"\n****************************\n"
|
2012-12-05 04:35:07 -06:00
|
|
|
|
u"\n* FOR FOOTNOTE [ref2].\n"
|
|
|
|
|
u"\n* reference FOR reference.\n"
|
2012-12-05 05:52:19 -06:00
|
|
|
|
u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n"
|
2012-12-04 22:11:16 -06:00
|
|
|
|
u"\n[1] THIS IS A AUTO NUMBERED FOOTNOTE.\n"
|
|
|
|
|
u"\n[ref2] THIS IS A NAMED FOOTNOTE.\n"
|
|
|
|
|
u"\n[100] THIS IS A NUMBERED FOOTNOTE.\n")
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_equal, result, expect
|
2012-12-04 22:11:16 -06:00
|
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
|
warnings = getwarning(warning)
|
2013-01-06 01:15:49 -06:00
|
|
|
|
warning_fmt = u'.*/refs_inconsistency.txt:\\d+: ' \
|
2014-09-21 10:17:02 -05:00
|
|
|
|
u'WARNING: inconsistent %s in translated message\n'
|
2012-12-07 01:38:21 -06:00
|
|
|
|
expected_warning_expr = (
|
|
|
|
|
warning_fmt % 'footnote references' +
|
|
|
|
|
warning_fmt % 'references' +
|
|
|
|
|
warning_fmt % 'references')
|
2014-09-21 11:54:01 -05:00
|
|
|
|
yield assert_re_search, expected_warning_expr, warnings
|
2012-11-27 02:30:08 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- check warning for literal block
|
2013-06-16 10:12:02 -05:00
|
|
|
|
|
2013-01-06 01:15:49 -06:00
|
|
|
|
result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
|
2012-12-16 07:56:38 -06:00
|
|
|
|
expect = (u"\nI18N WITH LITERAL BLOCK"
|
|
|
|
|
u"\n***********************\n"
|
|
|
|
|
u"\nCORRECT LITERAL BLOCK:\n"
|
|
|
|
|
u"\n this is"
|
|
|
|
|
u"\n literal block\n"
|
|
|
|
|
u"\nMISSING LITERAL BLOCK:\n"
|
2013-01-03 13:55:26 -06:00
|
|
|
|
u"\n<SYSTEM MESSAGE:")
|
2014-09-21 11:54:01 -05:00
|
|
|
|
yield assert_startswith, result, expect
|
2012-12-16 07:56:38 -06:00
|
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
|
warnings = getwarning(warning)
|
2013-01-06 01:15:49 -06:00
|
|
|
|
expected_warning_expr = u'.*/literalblock.txt:\\d+: ' \
|
2014-09-21 10:17:02 -05:00
|
|
|
|
u'WARNING: Literal block expected; none found.'
|
2014-09-21 11:54:01 -05:00
|
|
|
|
yield assert_re_search, expected_warning_expr, warnings
|
2012-12-31 23:17:53 -06:00
|
|
|
|
|
2016-01-09 00:33:43 -06:00
|
|
|
|
# --- definition terms: regression test for #975, #2198, #2205
|
2012-12-31 23:17:53 -06:00
|
|
|
|
|
2013-01-06 01:15:49 -06:00
|
|
|
|
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
|
2012-12-31 23:17:53 -06:00
|
|
|
|
expect = (u"\nI18N WITH DEFINITION TERMS"
|
|
|
|
|
u"\n**************************\n"
|
|
|
|
|
u"\nSOME TERM"
|
|
|
|
|
u"\n THE CORRESPONDING DEFINITION\n"
|
2016-01-09 00:33:43 -06:00
|
|
|
|
u"\nSOME *TERM* WITH LINK"
|
2015-07-25 10:37:21 -05:00
|
|
|
|
u"\n THE CORRESPONDING DEFINITION #2\n"
|
2016-01-09 00:33:43 -06:00
|
|
|
|
u"\nSOME **TERM** WITH : CLASSIFIER1 : CLASSIFIER2"
|
2015-07-25 10:37:21 -05:00
|
|
|
|
u"\n THE CORRESPONDING DEFINITION\n"
|
2016-01-17 20:31:48 -06:00
|
|
|
|
u"\nSOME TERM WITH : CLASSIFIER[]"
|
|
|
|
|
u"\n THE CORRESPONDING DEFINITION\n"
|
2015-07-25 10:37:21 -05:00
|
|
|
|
)
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_equal, result, expect
|
2012-12-31 23:17:53 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- glossary terms: regression test for #1090
|
2013-01-04 10:06:42 -06:00
|
|
|
|
|
2013-01-29 09:13:58 -06:00
|
|
|
|
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
|
|
|
|
|
expect = (u"\nI18N WITH GLOSSARY TERMS"
|
|
|
|
|
u"\n************************\n"
|
2013-01-30 08:41:37 -06:00
|
|
|
|
u"\nSOME NEW TERM"
|
2013-01-29 09:13:58 -06:00
|
|
|
|
u"\n THE CORRESPONDING GLOSSARY\n"
|
2013-01-30 08:41:37 -06:00
|
|
|
|
u"\nSOME OTHER NEW TERM"
|
|
|
|
|
u"\n THE CORRESPONDING GLOSSARY #2\n"
|
|
|
|
|
u"\nLINK TO *SOME NEW TERM*.\n")
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_equal, result, expect
|
2015-03-20 16:26:32 -05:00
|
|
|
|
warnings = getwarning(warning)
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_not_in, 'term not in glossary', warnings
|
2013-02-04 21:47:08 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- glossary term inconsistencies: regression test for #1090
|
2013-02-04 21:47:08 -06:00
|
|
|
|
|
2014-09-21 10:17:02 -05:00
|
|
|
|
result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8')
|
2013-01-30 08:41:37 -06:00
|
|
|
|
expect = (u"\nI18N WITH GLOSSARY TERMS INCONSISTENCY"
|
|
|
|
|
u"\n**************************************\n"
|
|
|
|
|
u"\n1. LINK TO *SOME NEW TERM*.\n")
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_equal, result, expect
|
2013-01-29 09:13:58 -06:00
|
|
|
|
|
2015-03-20 16:26:32 -05:00
|
|
|
|
warnings = getwarning(warning)
|
2013-01-30 08:41:37 -06:00
|
|
|
|
expected_warning_expr = (
|
2014-09-21 10:17:02 -05:00
|
|
|
|
u'.*/glossary_terms_inconsistency.txt:\\d+: '
|
|
|
|
|
u'WARNING: inconsistent term references in translated message\n')
|
2014-09-21 11:54:01 -05:00
|
|
|
|
yield assert_re_search, expected_warning_expr, warnings
|
2013-01-30 08:41:37 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- seealso
|
2013-01-29 09:13:58 -06:00
|
|
|
|
|
2013-01-06 05:14:57 -06:00
|
|
|
|
result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
|
2012-12-15 22:20:01 -06:00
|
|
|
|
expect = (u"\nI18N WITH SEEALSO"
|
|
|
|
|
u"\n*****************\n"
|
2013-01-06 04:44:58 -06:00
|
|
|
|
u"\nSee also: SHORT TEXT 1\n"
|
|
|
|
|
u"\nSee also: LONG TEXT 1\n"
|
|
|
|
|
u"\nSee also: SHORT TEXT 2\n"
|
|
|
|
|
u"\n LONG TEXT 2\n")
|
2014-09-21 11:26:50 -05:00
|
|
|
|
yield assert_equal, result, expect
|
2013-01-06 04:44:58 -06:00
|
|
|
|
|
2014-09-21 11:26:50 -05:00
|
|
|
|
# --- figure captions: regression test for #940
|
2013-01-06 05:14:57 -06:00
|
|
|
|
|
2015-02-22 04:24:14 -06:00
|
|
|
|
result = (app.outdir / 'figure.txt').text(encoding='utf-8')
|
2013-01-04 10:06:42 -06:00
|
|
|
|
expect = (u"\nI18N WITH FIGURE CAPTION"
|
|
|
|
|
u"\n************************\n"
|
|
|
|
|
u"\n [image]MY CAPTION OF THE FIGURE\n"
|
|
|
|
|
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
|
2013-11-12 09:17:09 -06:00
|
|
|
|
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
|
|
|
|
|
u"\n"
|
|
|
|
|
u"\nFIGURE IN THE BLOCK"
|
|
|
|
|
u"\n===================\n"
|
|
|
|
|
u"\nBLOCK\n"
|
|
|
|
|
u"\n [image]MY CAPTION OF THE FIGURE\n"
|
|
|
|
|
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
|
2015-02-22 04:24:14 -06:00
|
|
|
|
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
|
|
|
|
|
u"\n"
|
|
|
|
|
u"\n"
|
|
|
|
|
u"IMAGE URL AND ALT\n"
|
|
|
|
|
u"=================\n"
|
|
|
|
|
u"\n"
|
|
|
|
|
u"[image: i18n][image]\n"
|
|
|
|
|
u"\n"
|
|
|
|
|
u" [image: img][image]\n"
|
2016-11-20 03:17:16 -06:00
|
|
|
|
u" |