mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #6110 from tk0miya/refactor_catalog
Refactor catalog detection and compilation
This commit is contained in:
commit
8d0d75fea7
3
CHANGES
3
CHANGES
@ -17,6 +17,9 @@ Deprecated
|
||||
* ``sphinx.ext.autodoc.importer.MockLoader``
|
||||
* ``sphinx.ext.autodoc.importer.mock()``
|
||||
* ``sphinx.ext.autosummary.autolink_role()``
|
||||
* ``sphinx.util.i18n.find_catalog()``
|
||||
* ``sphinx.util.i18n.find_catalog_files()``
|
||||
* ``sphinx.util.i18n.find_catalog_source_files()``
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
@ -254,6 +254,21 @@ The following is a list of deprecated interfaces.
|
||||
- 4.0
|
||||
- ``sphinx.ext.autosummary.AutoLink``
|
||||
|
||||
* - ``sphinx.util.i18n.find_catalog()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.util.i18n.docname_to_domain()``
|
||||
|
||||
* - ``sphinx.util.i18n.find_catalog_files()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.util.i18n.CatalogRepository``
|
||||
|
||||
* - ``sphinx.util.i18n.find_catalog_source_files()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.util.i18n.CatalogRepository``
|
||||
|
||||
* - ``encoding`` argument of ``autodoc.Documenter.get_doc()``,
|
||||
``autodoc.DocstringSignatureMixin.get_doc()``,
|
||||
``autodoc.DocstringSignatureMixin._find_signature()``, and
|
||||
|
@ -40,7 +40,7 @@ from sphinx.util import logging
|
||||
from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import directive_helper
|
||||
from sphinx.util.i18n import find_catalog_source_files
|
||||
from sphinx.util.i18n import CatalogRepository
|
||||
from sphinx.util.logging import prefixed_warnings
|
||||
from sphinx.util.osutil import abspath, ensuredir, relpath
|
||||
from sphinx.util.tags import Tags
|
||||
@ -265,21 +265,21 @@ class Sphinx:
|
||||
"""Load translated strings from the configured localedirs if enabled in
|
||||
the configuration.
|
||||
"""
|
||||
if self.config.language is not None:
|
||||
if self.config.language is None:
|
||||
self.translator, has_translation = locale.init([], None)
|
||||
else:
|
||||
logger.info(bold(__('loading translations [%s]... ') % self.config.language),
|
||||
nonl=True)
|
||||
user_locale_dirs = [
|
||||
path.join(self.srcdir, x) for x in self.config.locale_dirs]
|
||||
|
||||
# compile mo files if sphinx.po file in user locale directories are updated
|
||||
for catinfo in find_catalog_source_files(
|
||||
user_locale_dirs, self.config.language, domains=['sphinx'],
|
||||
charset=self.config.source_encoding):
|
||||
catinfo.write_mo(self.config.language)
|
||||
locale_dirs = [None, path.join(package_dir, 'locale')] + user_locale_dirs
|
||||
else:
|
||||
locale_dirs = []
|
||||
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
||||
if self.config.language is not None:
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
for catalog in repo.catalogs:
|
||||
if catalog.domain == 'sphinx' and catalog.is_outdated():
|
||||
catalog.write_mo(self.config.language)
|
||||
|
||||
locale_dirs = [None, path.join(package_dir, 'locale')] + list(repo.locale_dirs)
|
||||
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
||||
if has_translation or self.config.language == 'en':
|
||||
# "en" never needs to be translated
|
||||
logger.info(__('done'))
|
||||
|
@ -19,12 +19,11 @@ from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.io import read_doc
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import i18n, import_object, logging, rst, progress_message, status_iterator
|
||||
from sphinx.util import import_object, logging, rst, progress_message, status_iterator
|
||||
from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import sphinx_domains
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.matching import Matcher
|
||||
from sphinx.util.i18n import CatalogRepository, docname_to_domain
|
||||
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
|
||||
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
|
||||
parallel_available
|
||||
@ -236,14 +235,10 @@ class Builder:
|
||||
|
||||
def compile_all_catalogs(self):
|
||||
# type: () -> None
|
||||
catalogs = i18n.find_catalog_source_files(
|
||||
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
|
||||
self.config.language,
|
||||
charset=self.config.source_encoding,
|
||||
force_all=True,
|
||||
excluded=Matcher(['**/.?**']))
|
||||
message = __('all of %d po files') % len(catalogs)
|
||||
self.compile_catalogs(catalogs, message)
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
message = __('all of %d po files') % len(list(repo.catalogs))
|
||||
self.compile_catalogs(set(repo.catalogs), message)
|
||||
|
||||
def compile_specific_catalogs(self, specified_files):
|
||||
# type: (List[str]) -> None
|
||||
@ -251,28 +246,25 @@ class Builder:
|
||||
# type: (str) -> str
|
||||
docname = self.env.path2doc(path.abspath(fpath))
|
||||
if docname:
|
||||
return find_catalog(docname, self.config.gettext_compact)
|
||||
return docname_to_domain(docname, self.config.gettext_compact)
|
||||
else:
|
||||
return None
|
||||
|
||||
specified_domains = set(map(to_domain, specified_files))
|
||||
specified_domains.discard(None)
|
||||
catalogs = i18n.find_catalog_source_files(
|
||||
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
|
||||
self.config.language,
|
||||
domains=list(specified_domains),
|
||||
charset=self.config.source_encoding,
|
||||
excluded=Matcher(['**/.?**']))
|
||||
catalogs = set()
|
||||
domains = set(map(to_domain, specified_files))
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
for catalog in repo.catalogs:
|
||||
if catalog.domain in domains and catalog.is_outdated():
|
||||
catalogs.add(catalog)
|
||||
message = __('targets for %d po files that are specified') % len(catalogs)
|
||||
self.compile_catalogs(catalogs, message)
|
||||
|
||||
def compile_update_catalogs(self):
|
||||
# type: () -> None
|
||||
catalogs = i18n.find_catalog_source_files(
|
||||
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
|
||||
self.config.language,
|
||||
charset=self.config.source_encoding,
|
||||
excluded=Matcher(['**/.?**']))
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
catalogs = {c for c in repo.catalogs if c.is_outdated()}
|
||||
message = __('targets for %d po files that are out of date') % len(catalogs)
|
||||
self.compile_catalogs(catalogs, message)
|
||||
|
||||
|
@ -22,7 +22,7 @@ from sphinx.errors import ThemeError
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import split_index_msg, logging, status_iterator
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.i18n import docname_to_domain
|
||||
from sphinx.util.nodes import extract_messages, traverse_translatable_index
|
||||
from sphinx.util.osutil import relpath, ensuredir, canon_path
|
||||
from sphinx.util.tags import Tags
|
||||
@ -140,7 +140,7 @@ class I18nBuilder(Builder):
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
catalog = self.catalogs[find_catalog(docname, self.config.gettext_compact)]
|
||||
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
|
||||
|
||||
for node, msg in extract_messages(doctree):
|
||||
catalog.add(msg, node)
|
||||
|
@ -25,7 +25,7 @@ from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import DownloadFiles, FilenameUniqDict
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.docutils import LoggingReporter
|
||||
from sphinx.util.i18n import find_catalog_files
|
||||
from sphinx.util.i18n import CatalogRepository, docname_to_domain
|
||||
from sphinx.util.nodes import is_translatable
|
||||
|
||||
if False:
|
||||
@ -395,15 +395,13 @@ class BuildEnvironment:
|
||||
# move i18n process into the writing phase, and remove these lines.
|
||||
if builder.use_message_catalog:
|
||||
# add catalog mo file dependency
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
for docname in self.found_docs:
|
||||
catalog_files = find_catalog_files(
|
||||
docname,
|
||||
self.srcdir,
|
||||
self.config.locale_dirs,
|
||||
self.config.language,
|
||||
self.config.gettext_compact)
|
||||
for filename in catalog_files:
|
||||
self.dependencies[docname].add(filename)
|
||||
domain = docname_to_domain(docname, self.config.gettext_compact)
|
||||
for catalog in repo.catalogs:
|
||||
if catalog.domain == domain:
|
||||
self.dependencies[docname].add(catalog.mo_path)
|
||||
except OSError as exc:
|
||||
raise DocumentError(__('Failed to scan documents in %s: %r') % (self.srcdir, exc))
|
||||
|
||||
|
@ -21,7 +21,7 @@ from sphinx.domains.std import make_glossary_term, split_term_classifiers
|
||||
from sphinx.locale import __, init as init_locale
|
||||
from sphinx.transforms import SphinxTransform
|
||||
from sphinx.util import split_index_msg, logging
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.i18n import docname_to_domain
|
||||
from sphinx.util.nodes import (
|
||||
LITERAL_TYPE_NODES, IMAGE_TYPE_NODES, NodeMatcher,
|
||||
extract_messages, is_pending_meta, traverse_translatable_index,
|
||||
@ -94,7 +94,7 @@ class Locale(SphinxTransform):
|
||||
assert source.startswith(self.env.srcdir)
|
||||
docname = path.splitext(relative_path(path.join(self.env.srcdir, 'dummy'),
|
||||
source))[0]
|
||||
textdomain = find_catalog(docname, self.config.gettext_compact)
|
||||
textdomain = docname_to_domain(docname, self.config.gettext_compact)
|
||||
|
||||
# fetch translations
|
||||
dirs = [path.join(self.env.srcdir, directory)
|
||||
|
@ -19,19 +19,19 @@ import babel.dates
|
||||
from babel.messages.mofile import write_mo
|
||||
from babel.messages.pofile import read_po
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.matching import Matcher
|
||||
from sphinx.util.osutil import SEP, relpath
|
||||
from sphinx.util.osutil import SEP, canon_path, relpath
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Callable, List, Set # NOQA
|
||||
from typing import Callable, Generator, List, Set, Tuple # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
LocaleFileInfoBase = namedtuple('CatalogInfo', 'base_dir,domain,charset')
|
||||
@ -81,8 +81,55 @@ class CatalogInfo(LocaleFileInfoBase):
|
||||
logger.warning(__('writing error: %s, %s'), self.mo_path, exc)
|
||||
|
||||
|
||||
class CatalogRepository:
|
||||
"""A repository for message catalogs."""
|
||||
|
||||
def __init__(self, basedir, locale_dirs, language, encoding):
|
||||
# type: (str, List[str], str, str) -> None
|
||||
self.basedir = basedir
|
||||
self._locale_dirs = locale_dirs
|
||||
self.language = language
|
||||
self.encoding = encoding
|
||||
|
||||
@property
|
||||
def locale_dirs(self):
|
||||
# type: () -> Generator[str, None, None]
|
||||
if not self.language:
|
||||
return
|
||||
|
||||
for locale_dir in self._locale_dirs:
|
||||
locale_dir = path.join(self.basedir, locale_dir)
|
||||
if path.exists(path.join(locale_dir, self.language, 'LC_MESSAGES')):
|
||||
yield locale_dir
|
||||
|
||||
@property
|
||||
def pofiles(self):
|
||||
# type: () -> Generator[Tuple[str, str], None, None]
|
||||
for locale_dir in self.locale_dirs:
|
||||
basedir = path.join(locale_dir, self.language, 'LC_MESSAGES')
|
||||
for root, dirnames, filenames in os.walk(basedir):
|
||||
# skip dot-directories
|
||||
for dirname in dirnames:
|
||||
if dirname.startswith('.'):
|
||||
dirnames.remove(dirname)
|
||||
|
||||
for filename in filenames:
|
||||
if filename.endswith('.po'):
|
||||
fullpath = path.join(root, filename)
|
||||
yield basedir, relpath(fullpath, basedir)
|
||||
|
||||
@property
|
||||
def catalogs(self):
|
||||
# type: () -> Generator[CatalogInfo, None, None]
|
||||
for basedir, filename in self.pofiles:
|
||||
domain = canon_path(path.splitext(filename)[0])
|
||||
yield CatalogInfo(basedir, domain, self.encoding)
|
||||
|
||||
|
||||
def find_catalog(docname, compaction):
|
||||
# type: (str, bool) -> str
|
||||
warnings.warn('find_catalog() is deprecated.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
if compaction:
|
||||
ret = docname.split(SEP, 1)[0]
|
||||
else:
|
||||
@ -91,8 +138,19 @@ def find_catalog(docname, compaction):
|
||||
return ret
|
||||
|
||||
|
||||
def docname_to_domain(docname, compation):
|
||||
# type: (str, bool) -> str
|
||||
"""Convert docname to domain for catalogs."""
|
||||
if compation:
|
||||
return docname.split(SEP, 1)[0]
|
||||
else:
|
||||
return docname
|
||||
|
||||
|
||||
def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
|
||||
# type: (str, str, List[str], str, bool) -> List[str]
|
||||
warnings.warn('find_catalog_files() is deprecated.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
if not(lang and locale_dirs):
|
||||
return []
|
||||
|
||||
@ -120,6 +178,8 @@ def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact
|
||||
default is False.
|
||||
:return: [CatalogInfo(), ...]
|
||||
"""
|
||||
warnings.warn('find_catalog_source_files() is deprecated.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
if gettext_compact is not None:
|
||||
warnings.warn('gettext_compact argument for find_catalog_source_files() '
|
||||
'is deprecated.', RemovedInSphinx30Warning, stacklevel=2)
|
||||
|
@ -0,0 +1 @@
|
||||
language = 'xx'
|
@ -17,18 +17,19 @@ from sphinx.testing.util import find_files
|
||||
@pytest.fixture
|
||||
def setup_test(app_params):
|
||||
srcdir = app_params.kwargs['srcdir']
|
||||
locale_dir = srcdir / 'locale'
|
||||
src_locale_dir = srcdir / 'xx' / 'LC_MESSAGES'
|
||||
dest_locale_dir = srcdir / 'locale'
|
||||
# copy all catalogs into locale layout directory
|
||||
for po in find_files(srcdir, '.po'):
|
||||
copy_po = (locale_dir / 'en' / 'LC_MESSAGES' / po)
|
||||
for po in find_files(src_locale_dir, '.po'):
|
||||
copy_po = (dest_locale_dir / 'en' / 'LC_MESSAGES' / po)
|
||||
if not copy_po.parent.exists():
|
||||
copy_po.parent.makedirs()
|
||||
shutil.copy(srcdir / po, copy_po)
|
||||
shutil.copy(src_locale_dir / po, copy_po)
|
||||
|
||||
yield
|
||||
|
||||
# delete remnants left over after failed build
|
||||
locale_dir.rmtree(True)
|
||||
dest_locale_dir.rmtree(True)
|
||||
(srcdir / '_build').rmtree(True)
|
||||
|
||||
|
||||
|
@ -41,31 +41,21 @@ def write_mo(pathname, po):
|
||||
return mofile.write_mo(f, po)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def build_mo():
|
||||
def builder(srcdir):
|
||||
"""
|
||||
:param str srcdir: app.srcdir
|
||||
"""
|
||||
srcdir = path(srcdir)
|
||||
for dirpath, dirs, files in os.walk(srcdir):
|
||||
dirpath = path(dirpath)
|
||||
for f in [f for f in files if f.endswith('.po')]:
|
||||
po = dirpath / f
|
||||
mo = srcdir / 'xx' / 'LC_MESSAGES' / (
|
||||
os.path.relpath(po[:-3], srcdir) + '.mo')
|
||||
if not mo.parent.exists():
|
||||
mo.parent.makedirs()
|
||||
|
||||
if not mo.exists() or mo.stat().st_mtime < po.stat().st_mtime:
|
||||
# compile .mo file only if needed
|
||||
write_mo(mo, read_po(po))
|
||||
return builder
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_intl(app_params, build_mo):
|
||||
build_mo(app_params.kwargs['srcdir'])
|
||||
def setup_intl(app_params):
|
||||
srcdir = path(app_params.kwargs['srcdir'])
|
||||
for dirpath, dirs, files in os.walk(srcdir):
|
||||
dirpath = path(dirpath)
|
||||
for f in [f for f in files if f.endswith('.po')]:
|
||||
po = dirpath / f
|
||||
mo = srcdir / 'xx' / 'LC_MESSAGES' / (
|
||||
os.path.relpath(po[:-3], srcdir) + '.mo')
|
||||
if not mo.parent.exists():
|
||||
mo.parent.makedirs()
|
||||
|
||||
if not mo.exists() or mo.stat().st_mtime < po.stat().st_mtime:
|
||||
# compile .mo file only if needed
|
||||
write_mo(mo, read_po(po))
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@ -296,7 +286,7 @@ def test_text_glossary_term_inconsistencies(app, warning):
|
||||
def test_gettext_section(app):
|
||||
app.build()
|
||||
# --- section
|
||||
expect = read_po(app.srcdir / 'section.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'section.po')
|
||||
actual = read_po(app.outdir / 'section.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -309,7 +299,7 @@ def test_text_section(app):
|
||||
app.build()
|
||||
# --- section
|
||||
result = (app.outdir / 'section.txt').text()
|
||||
expect = read_po(app.srcdir / 'section.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'section.po')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.string in result
|
||||
|
||||
@ -445,7 +435,7 @@ def test_text_admonitions(app):
|
||||
def test_gettext_toctree(app):
|
||||
app.build()
|
||||
# --- toctree
|
||||
expect = read_po(app.srcdir / 'index.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'index.po')
|
||||
actual = read_po(app.outdir / 'index.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -457,7 +447,7 @@ def test_gettext_toctree(app):
|
||||
def test_gettext_table(app):
|
||||
app.build()
|
||||
# --- toctree
|
||||
expect = read_po(app.srcdir / 'table.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'table.po')
|
||||
actual = read_po(app.outdir / 'table.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -470,7 +460,7 @@ def test_text_table(app):
|
||||
app.build()
|
||||
# --- toctree
|
||||
result = (app.outdir / 'table.txt').text()
|
||||
expect = read_po(app.srcdir / 'table.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'table.po')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.string in result
|
||||
|
||||
@ -481,7 +471,7 @@ def test_text_table(app):
|
||||
def test_gettext_topic(app):
|
||||
app.build()
|
||||
# --- topic
|
||||
expect = read_po(app.srcdir / 'topic.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'topic.po')
|
||||
actual = read_po(app.outdir / 'topic.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -494,7 +484,7 @@ def test_text_topic(app):
|
||||
app.build()
|
||||
# --- topic
|
||||
result = (app.outdir / 'topic.txt').text()
|
||||
expect = read_po(app.srcdir / 'topic.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'topic.po')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.string in result
|
||||
|
||||
@ -505,7 +495,7 @@ def test_text_topic(app):
|
||||
def test_gettext_definition_terms(app):
|
||||
app.build()
|
||||
# --- definition terms: regression test for #2198, #2205
|
||||
expect = read_po(app.srcdir / 'definition_terms.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'definition_terms.po')
|
||||
actual = read_po(app.outdir / 'definition_terms.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -517,7 +507,7 @@ def test_gettext_definition_terms(app):
|
||||
def test_gettext_glossary_terms(app, warning):
|
||||
app.build()
|
||||
# --- glossary terms: regression test for #1090
|
||||
expect = read_po(app.srcdir / 'glossary_terms.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'glossary_terms.po')
|
||||
actual = read_po(app.outdir / 'glossary_terms.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -531,7 +521,7 @@ def test_gettext_glossary_terms(app, warning):
|
||||
def test_gettext_glossary_term_inconsistencies(app):
|
||||
app.build()
|
||||
# --- glossary term inconsistencies: regression test for #1090
|
||||
expect = read_po(app.srcdir / 'glossary_terms_inconsistency.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'glossary_terms_inconsistency.po')
|
||||
actual = read_po(app.outdir / 'glossary_terms_inconsistency.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -543,7 +533,7 @@ def test_gettext_glossary_term_inconsistencies(app):
|
||||
def test_gettext_literalblock(app):
|
||||
app.build()
|
||||
# --- gettext builder always ignores ``only`` directive
|
||||
expect = read_po(app.srcdir / 'literalblock.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'literalblock.po')
|
||||
actual = read_po(app.outdir / 'literalblock.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
if len(expect_msg.id.splitlines()) == 1:
|
||||
@ -559,7 +549,7 @@ def test_gettext_literalblock(app):
|
||||
def test_gettext_buildr_ignores_only_directive(app):
|
||||
app.build()
|
||||
# --- gettext builder always ignores ``only`` directive
|
||||
expect = read_po(app.srcdir / 'only.po')
|
||||
expect = read_po(app.srcdir / 'xx' / 'LC_MESSAGES' / 'only.po')
|
||||
actual = read_po(app.outdir / 'only.pot')
|
||||
for expect_msg in [m for m in expect if m.id]:
|
||||
assert expect_msg.id in [m.id for m in actual if m.id]
|
||||
@ -568,7 +558,7 @@ def test_gettext_buildr_ignores_only_directive(app):
|
||||
@sphinx_intl
|
||||
# use individual shared_result directory to avoid "incompatible doctree" error
|
||||
@pytest.mark.sphinx(testroot='builder-gettext-dont-rebuild-mo')
|
||||
def test_gettext_dont_rebuild_mo(make_app, app_params, build_mo):
|
||||
def test_gettext_dont_rebuild_mo(make_app, app_params):
|
||||
# --- don't rebuild by .mo mtime
|
||||
def get_number_of_update_targets(app_):
|
||||
app_.env.find_files(app_.config, app_.builder)
|
||||
@ -579,7 +569,6 @@ def test_gettext_dont_rebuild_mo(make_app, app_params, build_mo):
|
||||
|
||||
# phase1: build document with non-gettext builder and generate mo file in srcdir
|
||||
app0 = make_app('dummy', *args, **kwargs)
|
||||
build_mo(app0.srcdir)
|
||||
app0.build()
|
||||
assert (app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').exists()
|
||||
# Since it is after the build, the number of documents to be updated is 0
|
||||
|
@ -255,3 +255,47 @@ def test_get_filename_for_language(app):
|
||||
app.env.config.figure_language_filename = '{root}.{invalid}{ext}'
|
||||
with pytest.raises(SphinxError):
|
||||
i18n.get_image_filename_for_language('foo.png', app.env)
|
||||
|
||||
|
||||
def test_CatalogRepository(tempdir):
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / '.dotdir').makedirs()
|
||||
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / '.dotdir' / 'test5.po').write_text('#')
|
||||
(tempdir / 'loc1' / 'yy' / 'LC_MESSAGES').makedirs()
|
||||
(tempdir / 'loc1' / 'yy' / 'LC_MESSAGES' / 'test6.po').write_text('#')
|
||||
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
|
||||
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
||||
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test7.po').write_text('#')
|
||||
|
||||
# for language xx
|
||||
repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], 'xx', 'utf-8')
|
||||
assert list(repo.locale_dirs) == [str(tempdir / 'loc1'),
|
||||
str(tempdir / 'loc2')]
|
||||
assert all(isinstance(c, i18n.CatalogInfo) for c in repo.catalogs)
|
||||
assert sorted(c.domain for c in repo.catalogs) == ['sub/test3', 'sub/test4',
|
||||
'test1', 'test1', 'test2', 'test7']
|
||||
|
||||
# for language yy
|
||||
repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], 'yy', 'utf-8')
|
||||
assert sorted(c.domain for c in repo.catalogs) == ['test6']
|
||||
|
||||
# unknown languages
|
||||
repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], 'zz', 'utf-8')
|
||||
assert sorted(c.domain for c in repo.catalogs) == []
|
||||
|
||||
# no languages
|
||||
repo = i18n.CatalogRepository(tempdir, ['loc1', 'loc2'], None, 'utf-8')
|
||||
assert sorted(c.domain for c in repo.catalogs) == []
|
||||
|
||||
# unknown locale_dirs
|
||||
repo = i18n.CatalogRepository(tempdir, ['loc3'], None, 'utf-8')
|
||||
assert sorted(c.domain for c in repo.catalogs) == []
|
||||
|
||||
# no locale_dirs
|
||||
repo = i18n.CatalogRepository(tempdir, [], None, 'utf-8')
|
||||
assert sorted(c.domain for c in repo.catalogs) == []
|
||||
|
Loading…
Reference in New Issue
Block a user