mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
899 lines
32 KiB
Python
899 lines
32 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
test_intl
|
||
~~~~~~~~~
|
||
|
||
Test message patching for internationalization purposes. Runs the text
|
||
builder in the test root.
|
||
|
||
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||
:license: BSD, see LICENSE for details.
|
||
"""
|
||
from __future__ import print_function
|
||
|
||
import os
|
||
import re
|
||
import pickle
|
||
from docutils import nodes
|
||
from subprocess import Popen, PIPE
|
||
from xml.etree import ElementTree
|
||
|
||
from babel.messages import pofile
|
||
from nose.tools import assert_equal
|
||
from six import string_types
|
||
|
||
from util import tempdir, rootdir, path, gen_with_app, with_app, SkipTest, \
|
||
assert_re_search, assert_not_re_search, assert_in, assert_not_in, \
|
||
assert_startswith, assert_node, repr_as
|
||
|
||
|
||
root = tempdir / 'test-intl'
|
||
|
||
|
||
def gen_with_intl_app(builder, confoverrides={}, *args, **kw):
|
||
default_kw = {
|
||
'testroot': 'intl',
|
||
'confoverrides': {
|
||
'language': 'xx', 'locale_dirs': ['.'],
|
||
'gettext_compact': False,
|
||
},
|
||
}
|
||
default_kw.update(kw)
|
||
default_kw['confoverrides'].update(confoverrides)
|
||
return gen_with_app(builder, *args, **default_kw)
|
||
|
||
|
||
def read_po(pathname):
|
||
with pathname.open() as f:
|
||
return pofile.read_po(f)
|
||
|
||
|
||
def setup_module():
|
||
if not root.exists():
|
||
(rootdir / 'roots' / 'test-intl').copytree(root)
|
||
# Delete remnants left over after failed build
|
||
# Compile all required catalogs into binary format (*.mo).
|
||
for dirpath, dirs, files in os.walk(root):
|
||
dirpath = path(dirpath)
|
||
for f in [f for f in files if f.endswith('.po')]:
|
||
po = dirpath / f
|
||
mo = root / 'xx' / 'LC_MESSAGES' / (
|
||
os.path.relpath(po[:-3], root) + '.mo')
|
||
if not mo.parent.exists():
|
||
mo.parent.makedirs()
|
||
try:
|
||
p = Popen(['msgfmt', po, '-o', mo],
|
||
stdout=PIPE, stderr=PIPE)
|
||
except OSError:
|
||
raise SkipTest # most likely msgfmt was not found
|
||
else:
|
||
stdout, stderr = p.communicate()
|
||
if p.returncode != 0:
|
||
print(stdout)
|
||
print(stderr)
|
||
assert False, \
|
||
'msgfmt exited with return code %s' % p.returncode
|
||
assert mo.isfile(), 'msgfmt failed'
|
||
|
||
|
||
def elem_gettexts(elem):
|
||
def itertext(self):
|
||
# this function copied from Python-2.7 'ElementTree.itertext'.
|
||
# for compatibility to Python-2.6
|
||
tag = self.tag
|
||
if not isinstance(tag, string_types) and tag is not None:
|
||
return
|
||
if self.text:
|
||
yield self.text
|
||
for e in self:
|
||
for s in itertext(e):
|
||
yield s
|
||
if e.tail:
|
||
yield e.tail
|
||
return [_f for _f in [s.strip() for s in itertext(elem)] if _f]
|
||
|
||
|
||
def elem_getref(elem):
|
||
return elem.attrib.get('refid') or elem.attrib.get('refuri')
|
||
|
||
|
||
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:
|
||
_refs = [elem_getref(x) for x in elem.findall('reference')]
|
||
assert _refs == refs
|
||
if names is not None:
|
||
_names = elem.attrib.get('names').split()
|
||
assert _names == names
|
||
|
||
|
||
def assert_count(expected_expr, result, count):
|
||
find_pair = (expected_expr, result)
|
||
return assert_equal, len(re.findall(*find_pair)), count, find_pair
|
||
|
||
|
||
@gen_with_intl_app('text', freshenv=True)
|
||
def test_text_builder(app, status, warning):
|
||
app.builder.build_all()
|
||
|
||
# --- warnings in translation
|
||
|
||
warnings = getwarning(warning)
|
||
warning_expr = u'.*/warnings.txt:4: ' \
|
||
u'WARNING: Inline literal start-string without end-string.\n'
|
||
yield assert_re_search, warning_expr, warnings
|
||
|
||
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")
|
||
yield assert_equal, result, expect
|
||
|
||
# --- simple translation; check title underlines
|
||
|
||
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
|
||
|
||
# --- check translation in subdirs
|
||
|
||
result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
|
||
yield assert_startswith, result, u"\nsubdir contents\n***************\n"
|
||
|
||
# --- check warnings for inconsistency in number of references
|
||
|
||
result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
|
||
expect = (u"\nI18N WITH REFS INCONSISTENCY"
|
||
u"\n****************************\n"
|
||
u"\n* FOR FOOTNOTE [ref2].\n"
|
||
u"\n* reference FOR reference.\n"
|
||
u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n"
|
||
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")
|
||
yield assert_equal, result, expect
|
||
|
||
warnings = getwarning(warning)
|
||
warning_fmt = u'.*/refs_inconsistency.txt:\\d+: ' \
|
||
u'WARNING: inconsistent %s in translated message\n'
|
||
expected_warning_expr = (
|
||
warning_fmt % 'footnote references' +
|
||
warning_fmt % 'references' +
|
||
warning_fmt % 'references')
|
||
yield assert_re_search, expected_warning_expr, warnings
|
||
|
||
# --- check warning for literal block
|
||
|
||
result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
|
||
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"
|
||
u"\n<SYSTEM MESSAGE:")
|
||
yield assert_startswith, result, expect
|
||
|
||
warnings = getwarning(warning)
|
||
expected_warning_expr = u'.*/literalblock.txt:\\d+: ' \
|
||
u'WARNING: Literal block expected; none found.'
|
||
yield assert_re_search, expected_warning_expr, warnings
|
||
|
||
# --- definition terms: regression test for #975, #2198, #2205
|
||
|
||
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
|
||
expect = (u"\nI18N WITH DEFINITION TERMS"
|
||
u"\n**************************\n"
|
||
u"\nSOME TERM"
|
||
u"\n THE CORRESPONDING DEFINITION\n"
|
||
u"\nSOME *TERM* WITH LINK"
|
||
u"\n THE CORRESPONDING DEFINITION #2\n"
|
||
u"\nSOME **TERM** WITH : CLASSIFIER1 : CLASSIFIER2"
|
||
u"\n THE CORRESPONDING DEFINITION\n"
|
||
u"\nSOME TERM WITH : CLASSIFIER[]"
|
||
u"\n THE CORRESPONDING DEFINITION\n"
|
||
)
|
||
yield assert_equal, result, expect
|
||
|
||
# --- glossary terms: regression test for #1090
|
||
|
||
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
|
||
expect = (u"\nI18N WITH GLOSSARY TERMS"
|
||
u"\n************************\n"
|
||
u"\nSOME NEW TERM"
|
||
u"\n THE CORRESPONDING GLOSSARY\n"
|
||
u"\nSOME OTHER NEW TERM"
|
||
u"\n THE CORRESPONDING GLOSSARY #2\n"
|
||
u"\nLINK TO *SOME NEW TERM*.\n")
|
||
yield assert_equal, result, expect
|
||
warnings = getwarning(warning)
|
||
yield assert_not_in, 'term not in glossary', warnings
|
||
|
||
# --- glossary term inconsistencies: regression test for #1090
|
||
|
||
result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8')
|
||
expect = (u"\nI18N WITH GLOSSARY TERMS INCONSISTENCY"
|
||
u"\n**************************************\n"
|
||
u"\n1. LINK TO *SOME NEW TERM*.\n")
|
||
yield assert_equal, result, expect
|
||
|
||
warnings = getwarning(warning)
|
||
expected_warning_expr = (
|
||
u'.*/glossary_terms_inconsistency.txt:\\d+: '
|
||
u'WARNING: inconsistent term references in translated message\n')
|
||
yield assert_re_search, expected_warning_expr, warnings
|
||
|
||
# --- seealso
|
||
|
||
result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
|
||
expect = (u"\nI18N WITH SEEALSO"
|
||
u"\n*****************\n"
|
||
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")
|
||
yield assert_equal, result, expect
|
||
|
||
# --- figure captions: regression test for #940
|
||
|
||
result = (app.outdir / 'figure.txt').text(encoding='utf-8')
|
||
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"
|
||
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"
|
||
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"
|
||
u" |