From 0832aa73ab64d8cf5accbe4a5bbeaeedb7b46a52 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 6 Mar 2017 18:03:40 -0800 Subject: [PATCH 1/3] Default SPHINXBUILD to 'python -msphinx' instead of 'sphinx-build'. Using `python -msphinx` as the default for SPHINXBUILD in the Makefile/make.bat ensures that whatever virtual environment is currently active (if any) gets picked up. In the current situation, imaging that we are working on project $foo which is also installed system-wide, but we want to build docs for a venv-installed version; that sphinx is installed system-wide but not in the current environment, and that e.g. conf.py imports $foo (e.g. to retrieve a version string). Then sphinx-build will resolve to the globally installed version, and the global (wrong) version of $foo will be imported as well. With this fix, `make html` will do everything in the correct virtualenv (if any). This switch is similar in spirit to e.g. the deprecation of the `pyvenv` script in Py3.6, in favor of `python -mvenv`. --- sphinx/templates/quickstart/Makefile.new_t | 2 +- sphinx/templates/quickstart/Makefile_t | 2 +- sphinx/templates/quickstart/make.bat.new_t | 10 +++++----- sphinx/templates/quickstart/make.bat_t | 23 +++++++--------------- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/sphinx/templates/quickstart/Makefile.new_t b/sphinx/templates/quickstart/Makefile.new_t index c7cd62dda..bba767a4c 100644 --- a/sphinx/templates/quickstart/Makefile.new_t +++ b/sphinx/templates/quickstart/Makefile.new_t @@ -3,7 +3,7 @@ # You can set these variables from the command line. SPHINXOPTS = -SPHINXBUILD = sphinx-build +SPHINXBUILD = python -msphinx SPHINXPROJ = {{ project_fn }} SOURCEDIR = {{ rsrcdir }} BUILDDIR = {{ rbuilddir }} diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile_t index 5505f23f5..fdcf05691 100644 --- a/sphinx/templates/quickstart/Makefile_t +++ b/sphinx/templates/quickstart/Makefile_t @@ -3,7 +3,7 @@ # You can set these variables from the command line. SPHINXOPTS = -SPHINXBUILD = sphinx-build +SPHINXBUILD = python -msphinx PAPER = BUILDDIR = {{ rbuilddir }} diff --git a/sphinx/templates/quickstart/make.bat.new_t b/sphinx/templates/quickstart/make.bat.new_t index e49ffbe78..a52951ebb 100644 --- a/sphinx/templates/quickstart/make.bat.new_t +++ b/sphinx/templates/quickstart/make.bat.new_t @@ -5,7 +5,7 @@ pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build + set SPHINXBUILD=python -msphinx ) set SOURCEDIR={{ rsrcdir }} set BUILDDIR={{ rbuilddir }} @@ -16,10 +16,10 @@ if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. + echo.The Sphinx module was not found. Make sure you have Sphinx installed, + echo.then set the SPHINXBUILD environment variable to point to the full + echo.path of the 'sphinx-build' executable. Alternatively you may add the + echo.Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat_t index 8438b5f7e..03ae9d423 100644 --- a/sphinx/templates/quickstart/make.bat_t +++ b/sphinx/templates/quickstart/make.bat_t @@ -5,7 +5,7 @@ REM Command file for Sphinx documentation pushd %~dp0 if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build + set SPHINXBUILD=python -msphinx ) set BUILDDIR={{ rbuilddir }} set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% {{ rsrcdir }} @@ -52,29 +52,20 @@ if "%1" == "clean" ( ) -REM Check if sphinx-build is available and fallback to Python version if any +REM Check if sphinx-build is available %SPHINXBUILD% 1>NUL 2>NUL -if errorlevel 9009 goto sphinx_python -goto sphinx_ok - -:sphinx_python - -set SPHINXBUILD=python -m sphinx.__init__ -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( +if errorlevel 1 ( echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. + echo.The Sphinx module was not found. Make sure you have Sphinx installed, + echo.then set the SPHINXBUILD environment variable to point to the full + echo.path of the 'sphinx-build' executable. Alternatively you may add the + echo.Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) -:sphinx_ok - if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html From c42db788d0138299de4059928267fe0c0a59ced2 Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 7 Mar 2017 18:50:22 +0100 Subject: [PATCH 2/3] Sync with 1.0 footnotehyper Since #3022 (Sphinx 1.5) more footnotes are hyperlinked but it became impossible for Sphinx user to pass option ``hyperfootnotes=false`` to package ``hyperref``. Release 1.0 of LaTeX package ``footnotehyper``, which serves as bugfix replacement to older package ``footnote``, is compatible with ``hyperfootnotes=false``, hence it is again possible to Sphinx user to completely disable hyperlinking of footnotes, if ever needed. --- sphinx/texinputs/footnotehyper-sphinx.sty | 39 +++++++++++------------ 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/sphinx/texinputs/footnotehyper-sphinx.sty b/sphinx/texinputs/footnotehyper-sphinx.sty index fde802c1a..ff23f6ebe 100644 --- a/sphinx/texinputs/footnotehyper-sphinx.sty +++ b/sphinx/texinputs/footnotehyper-sphinx.sty @@ -1,9 +1,9 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{footnotehyper-sphinx}% - [2017/02/25 v1.6 hyperref aware footnote.sty for sphinx (JFB)] + [2017/03/07 v1.6 hyperref aware footnote.sty for sphinx (JFB)] %% %% Package: footnotehyper-sphinx -%% Version: based on footnotehyper.sty 2017/02/16 v0.99 +%% Version: based on footnotehyper.sty 2017/03/07 v1.0 %% as available at http://www.ctan.org/pkg/footnotehyper %% License: the one applying to Sphinx %% @@ -11,12 +11,11 @@ %% the code comments. %% %% Differences: -%% 1. Error message if hyperref not loaded or with hyperfootnotes=false, -%% 2. a partial tabulary compatibility layer added (enough for Sphinx mark-up), -%% 3. use of \spx@opt@BeforeFootnote from sphinx.sty, -%% 4. use of \sphinxunactivateextrasandspace from sphinx.sty, -%% 5. macro definition \sphinxfootnotemark, -%% 6. macro definition \sphinxlongtablepatch +%% 1. a partial tabulary compatibility layer added (enough for Sphinx mark-up), +%% 2. use of \spx@opt@BeforeFootnote from sphinx.sty, +%% 3. use of \sphinxunactivateextrasandspace from sphinx.sty, +%% 4. macro definition \sphinxfootnotemark, +%% 5. macro definition \sphinxlongtablepatch \DeclareOption*{\PackageWarning{footnotehyper-sphinx}{Option `\CurrentOption' is unknown}}% \ProcessOptions\relax \newbox\FNH@notes @@ -24,10 +23,9 @@ \let\FNH@colwidth\columnwidth \newif\ifFNH@savingnotes \AtBeginDocument {% - \@ifpackageloaded{hyperref} - {\ifHy@hyperfootnotes \let\FNH@latex@footnote \footnote \let\FNH@latex@footnotetext\footnotetext + \let\FNH@H@@footnotetext \@footnotetext \newenvironment{savenotes} {\FNH@savenotes\ignorespaces}{\FNH@spewnotes\ignorespacesafterend}% \let\spewnotes \FNH@spewnotes @@ -35,14 +33,13 @@ \let\footnotetext \FNH@footnotetext \let\endfootnote \FNH@endfntext \let\endfootnotetext\FNH@endfntext - \else - \PackageError{sphinx} - {^^J\@spaces\@spaces******^^J% - hyperref option "hyperfootnotes=false" is incompatible with Sphinx!^^J}% - \fi}% - {\PackageError{sphinx}{^^J\@spaces\@spaces******^^J% - hyperref is required by Sphinx!^^J}% - }% + \@ifpackageloaded{hyperref} + {\ifHy@hyperfootnotes + \let\FNH@H@@footnotetext\H@@footnotetext + \else + \let\FNH@hyper@fntext\FNH@nohyp@fntext + \fi}% + {\let\FNH@hyper@fntext\FNH@nohyp@fntext}% }% \def\FNH@hyper@fntext{\FNH@fntext\FNH@hyper@fntext@i}% \def\FNH@nohyp@fntext{\FNH@fntext\FNH@nohyp@fntext@i}% @@ -120,7 +117,7 @@ \let\@makefntext\@empty \let\@finalstrut\@gobble \let\rule\@gobbletwo - \H@@footnotetext{\unvbox\FNH@notes}% + \FNH@H@@footnotetext{\unvbox\FNH@notes}% \endgroup \fi \fi @@ -138,7 +135,7 @@ }% \def\FNH@footnoteenv{% % this line added for Sphinx (footnotes in parsed literal blocks): - \catcode13=5\sphinxunactivateextrasandspace + \catcode13=5 \sphinxunactivateextrasandspace \@ifnextchar[% \FNH@footnoteenv@i %] {\stepcounter\@mpfn @@ -178,7 +175,7 @@ \ifFNH@savingnotes \def\FNH@endfntext@fntext{\FNH@nohyp@fntext}% \else - \def\FNH@endfntext@fntext{\H@@footnotetext}% + \def\FNH@endfntext@fntext{\FNH@H@@footnotetext}% \fi \FNH@startfntext }% From 15114e596dc9a21ac30c89ad401c8bd852726ecd Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 9 Mar 2017 12:23:23 +0900 Subject: [PATCH 3/3] Initialize i18n module earlier --- sphinx/application.py | 135 +++++++++++++++++++------------------- sphinx/config.py | 22 ++++--- sphinx/locale/__init__.py | 10 ++- 3 files changed, 89 insertions(+), 78 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 85d730726..3589de46f 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -38,6 +38,7 @@ from sphinx.domains.std import GenericObject, Target, StandardDomain from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning from sphinx.environment import BuildEnvironment from sphinx.io import SphinxStandaloneReader +from sphinx.locale import _ from sphinx.roles import XRefRole from sphinx.util import pycompat # noqa: F401 from sphinx.util import import_object @@ -189,14 +190,18 @@ class Sphinx(object): self.config.check_unicode() # defer checking types until i18n has been initialized - # initialize some limited config variables before loading extensions + # initialize some limited config variables before initialize i18n and loading + # extensions self.config.pre_init_values() + # set up translation infrastructure + self._init_i18n() + # check the Sphinx version if requested if self.config.needs_sphinx and self.config.needs_sphinx > sphinx.__display_version__: raise VersionRequirementError( - 'This project needs at least Sphinx v%s and therefore cannot ' - 'be built with this version.' % self.config.needs_sphinx) + _('This project needs at least Sphinx v%s and therefore cannot ' + 'be built with this version.') % self.config.needs_sphinx) # set confdir to srcdir if -C given (!= no confdir); a few pieces # of code expect a confdir to be set @@ -224,9 +229,9 @@ class Sphinx(object): self.config.setup(self) else: raise ConfigError( - "'setup' that is specified in the conf.py has not been " + - "callable. Please provide a callable `setup` function " + - "in order to behave as a sphinx extension conf.py itself." + _("'setup' that is specified in the conf.py has not been " + "callable. Please provide a callable `setup` function " + "in order to behave as a sphinx extension conf.py itself.") ) # now that we know all config values, collect them from conf.py @@ -236,23 +241,22 @@ class Sphinx(object): if self.config.needs_extensions: for extname, needs_ver in self.config.needs_extensions.items(): if extname not in self._extensions: - logger.warning('needs_extensions config value specifies a ' - 'version requirement for extension %s, but it is ' - 'not loaded', extname) + logger.warning(_('needs_extensions config value specifies a ' + 'version requirement for extension %s, but it is ' + 'not loaded'), extname) continue has_ver = self._extension_metadata[extname]['version'] if has_ver == 'unknown version' or needs_ver > has_ver: raise VersionRequirementError( - 'This project needs the extension %s at least in ' - 'version %s and therefore cannot be built with the ' - 'loaded version (%s).' % (extname, needs_ver, has_ver)) + _('This project needs the extension %s at least in ' + 'version %s and therefore cannot be built with the ' + 'loaded version (%s).') % (extname, needs_ver, has_ver)) # check primary_domain if requested if self.config.primary_domain and self.config.primary_domain not in self.domains: - logger.warning('primary_domain %r not found, ignored.', self.config.primary_domain) + logger.warning(_('primary_domain %r not found, ignored.'), + self.config.primary_domain) - # set up translation infrastructure - self._init_i18n() # check all configuration values for permissible types self.config.check_types() # set up source_parsers @@ -286,7 +290,7 @@ class Sphinx(object): if self.config.language is not None: if has_translation or self.config.language == 'en': # "en" never needs to be translated - logger.info('done') + logger.info(_('done')) else: logger.info('not available for built-in messages') @@ -307,28 +311,28 @@ class Sphinx(object): self.env.domains[domain] = self.domains[domain](self.env) else: try: - logger.info(bold('loading pickled environment... '), nonl=True) + logger.info(bold(_('loading pickled environment... ')), nonl=True) self.env = BuildEnvironment.frompickle( self.srcdir, self.config, path.join(self.doctreedir, ENV_PICKLE_FILENAME)) self.env.domains = {} for domain in self.domains.keys(): # this can raise if the data version doesn't fit self.env.domains[domain] = self.domains[domain](self.env) - logger.info('done') + logger.info(_('done')) except Exception as err: if isinstance(err, IOError) and err.errno == ENOENT: - logger.info('not yet created') + logger.info(_('not yet created')) else: - logger.info('failed: %s', err) + logger.info(_('failed: %s'), err) self._init_env(freshenv=True) def _init_builder(self, buildername): # type: (unicode) -> None if buildername is None: - print('No builder selected, using default: html', file=self._status) + logger.info(_('No builder selected, using default: html')) buildername = 'html' if buildername not in self.builderclasses: - raise SphinxError('Builder name %s not registered' % buildername) + raise SphinxError(_('Builder name %s not registered') % buildername) builderclass = self.builderclasses[buildername] self.builder = builderclass(self) @@ -355,13 +359,13 @@ class Sphinx(object): self.builder.build_update() status = (self.statuscode == 0 and - 'succeeded' or 'finished with problems') + _('succeeded') or _('finished with problems')) if self._warncount: - logger.info(bold('build %s, %s warning%s.' % + logger.info(bold(_('build %s, %s warning%s.') % (status, self._warncount, self._warncount != 1 and 's' or ''))) else: - logger.info(bold('build %s.' % status)) + logger.info(bold(_('build %s.') % status)) except Exception as err: # delete the saved env to force a fresh build next time envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME) @@ -472,20 +476,20 @@ class Sphinx(object): if extension in self._extensions: return if extension in EXTENSION_BLACKLIST: - logger.warning('the extension %r was already merged with Sphinx since version %s; ' - 'this extension is ignored.', + logger.warning(_('the extension %r was already merged with Sphinx since ' + 'version %s; this extension is ignored.'), extension, EXTENSION_BLACKLIST[extension]) return self._setting_up_extension.append(extension) try: mod = __import__(extension, None, None, ['setup']) except ImportError as err: - logger.verbose('Original exception:\n' + traceback.format_exc()) - raise ExtensionError('Could not import extension %s' % extension, + logger.verbose(_('Original exception:\n') + traceback.format_exc()) + raise ExtensionError(_('Could not import extension %s') % extension, err) if not hasattr(mod, 'setup'): - logger.warning('extension %r has no setup() function; is it really ' - 'a Sphinx extension module?', extension) + logger.warning(_('extension %r has no setup() function; is it really ' + 'a Sphinx extension module?'), extension) ext_meta = None else: try: @@ -493,9 +497,9 @@ class Sphinx(object): except VersionRequirementError as err: # add the extension name to the version required raise VersionRequirementError( - 'The %s extension used by this project needs at least ' - 'Sphinx v%s; it therefore cannot be built with this ' - 'version.' % (extension, err)) + _('The %s extension used by this project needs at least ' + 'Sphinx v%s; it therefore cannot be built with this ' + 'version.') % (extension, err)) if ext_meta is None: ext_meta = {} # special-case for compatibility @@ -505,9 +509,9 @@ class Sphinx(object): if not ext_meta.get('version'): ext_meta['version'] = 'unknown version' except Exception: - logger.warning('extension %r returned an unsupported object from ' - 'its setup() function; it should return None or a ' - 'metadata dictionary', extension) + logger.warning(_('extension %r returned an unsupported object from ' + 'its setup() function; it should return None or a ' + 'metadata dictionary'), extension) ext_meta = {'version': 'unknown version'} self._extensions[extension] = mod self._extension_metadata[extension] = ext_meta @@ -529,7 +533,7 @@ class Sphinx(object): def _validate_event(self, event): # type: (unicode) -> None if event not in self._events: - raise ExtensionError('Unknown event name: %s' % event) + raise ExtensionError(_('Unknown event name: %s') % event) def connect(self, event, callback): # type: (unicode, Callable) -> int @@ -560,7 +564,7 @@ class Sphinx(object): pass results = [] if event in self._listeners: - for _, callback in iteritems(self._listeners[event]): + for listener_id, callback in iteritems(self._listeners[event]): results.append(callback(self, *args)) return results @@ -577,12 +581,11 @@ class Sphinx(object): # type: (Type[Builder]) -> None logger.debug('[app] adding builder: %r', builder) if not hasattr(builder, 'name'): - raise ExtensionError('Builder class %s has no "name" attribute' + raise ExtensionError(_('Builder class %s has no "name" attribute') % builder) if builder.name in self.builderclasses: - raise ExtensionError( - 'Builder %r already exists (in module %s)' % ( - builder.name, self.builderclasses[builder.name].__module__)) + raise ExtensionError(_('Builder %r already exists (in module %s)') % + (builder.name, self.builderclasses[builder.name].__module__)) self.builderclasses[builder.name] = builder def add_config_value(self, name, default, rebuild, types=()): @@ -590,7 +593,7 @@ class Sphinx(object): logger.debug('[app] adding config value: %r', (name, default, rebuild) + ((types,) if types else ())) # type: ignore if name in self.config: - raise ExtensionError('Config value %r already present' % name) + raise ExtensionError(_('Config value %r already present') % name) if rebuild in (False, True): rebuild = rebuild and 'env' or '' self.config.add(name, default, rebuild, types) @@ -604,7 +607,7 @@ class Sphinx(object): def set_translator(self, name, translator_class): # type: (unicode, Any) -> None - logger.info(bold('A Translator for the %s builder is changed.' % name)) + logger.info(bold(_('A Translator for the %s builder is changed.') % name)) self._translators[name] = translator_class def add_node(self, node, **kwds): @@ -612,8 +615,8 @@ class Sphinx(object): logger.debug('[app] adding node: %r', (node, kwds)) if not kwds.pop('override', False) and \ hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__): - logger.warning('while setting up extension %s: node class %r is ' - 'already registered, its visitors will be overridden', + logger.warning(_('while setting up extension %s: node class %r is ' + 'already registered, its visitors will be overridden'), self._setting_up_extension, node.__name__, type='app', subtype='add_node') nodes._add_node_class_names([node.__name__]) @@ -621,8 +624,8 @@ class Sphinx(object): try: visit, depart = val except ValueError: - raise ExtensionError('Value for key %r must be a ' - '(visit, depart) function tuple' % key) + raise ExtensionError(_('Value for key %r must be a ' + '(visit, depart) function tuple') % key) translator = self._translators.get(key) translators = [] if translator is not None: @@ -665,8 +668,8 @@ class Sphinx(object): return convert_directive_function(obj) else: if content or arguments or options: - raise ExtensionError('when adding directive classes, no ' - 'additional arguments may be given') + raise ExtensionError(_('when adding directive classes, no ' + 'additional arguments may be given')) return obj def add_directive(self, name, obj, content=None, arguments=None, **options): @@ -674,8 +677,8 @@ class Sphinx(object): logger.debug('[app] adding directive: %r', (name, obj, content, arguments, options)) if name in directives._directives: - logger.warning('while setting up extension %s: directive %r is ' - 'already registered, it will be overridden', + logger.warning(_('while setting up extension %s: directive %r is ' + 'already registered, it will be overridden'), self._setting_up_extension[-1], name, type='app', subtype='add_directive') directives.register_directive( @@ -685,8 +688,8 @@ class Sphinx(object): # type: (unicode, Any) -> None logger.debug('[app] adding role: %r', (name, role)) if name in roles._roles: - logger.warning('while setting up extension %s: role %r is ' - 'already registered, it will be overridden', + logger.warning(_('while setting up extension %s: role %r is ' + 'already registered, it will be overridden'), self._setting_up_extension[-1], name, type='app', subtype='add_role') roles.register_local_role(name, role) @@ -697,8 +700,8 @@ class Sphinx(object): # register_canonical_role logger.debug('[app] adding generic role: %r', (name, nodeclass)) if name in roles._roles: - logger.warning('while setting up extension %s: role %r is ' - 'already registered, it will be overridden', + logger.warning(_('while setting up extension %s: role %r is ' + 'already registered, it will be overridden'), self._setting_up_extension[-1], name, type='app', subtype='add_generic_role') role = roles.GenericRole(name, nodeclass) @@ -708,17 +711,17 @@ class Sphinx(object): # type: (Type[Domain]) -> None logger.debug('[app] adding domain: %r', domain) if domain.name in self.domains: - raise ExtensionError('domain %s already registered' % domain.name) + raise ExtensionError(_('domain %s already registered') % domain.name) self.domains[domain.name] = domain def override_domain(self, domain): # type: (Type[Domain]) -> None logger.debug('[app] overriding domain: %r', domain) if domain.name not in self.domains: - raise ExtensionError('domain %s not yet registered' % domain.name) + raise ExtensionError(_('domain %s not yet registered') % domain.name) if not issubclass(domain, self.domains[domain.name]): - raise ExtensionError('new domain not a subclass of registered %s ' - 'domain' % domain.name) + raise ExtensionError(_('new domain not a subclass of registered %s ' + 'domain') % domain.name) self.domains[domain.name] = domain def add_directive_to_domain(self, domain, name, obj, @@ -727,7 +730,7 @@ class Sphinx(object): logger.debug('[app] adding directive to domain: %r', (domain, name, obj, content, arguments, options)) if domain not in self.domains: - raise ExtensionError('domain %s not yet registered' % domain) + raise ExtensionError(_('domain %s not yet registered') % domain) self.domains[domain].directives[name] = \ self._directive_helper(obj, content, arguments, **options) @@ -735,14 +738,14 @@ class Sphinx(object): # type: (unicode, unicode, Any) -> None logger.debug('[app] adding role to domain: %r', (domain, name, role)) if domain not in self.domains: - raise ExtensionError('domain %s not yet registered' % domain) + raise ExtensionError(_('domain %s not yet registered') % domain) self.domains[domain].roles[name] = role def add_index_to_domain(self, domain, index): # type: (unicode, Type[Index]) -> None logger.debug('[app] adding index to domain: %r', (domain, index)) if domain not in self.domains: - raise ExtensionError('domain %s not yet registered' % domain) + raise ExtensionError(_('domain %s not yet registered') % domain) self.domains[domain].indices.append(index) def add_object_type(self, directivename, rolename, indextemplate='', @@ -844,8 +847,8 @@ class Sphinx(object): # type: (unicode, Parser) -> None logger.debug('[app] adding search source_parser: %r, %r', suffix, parser) if suffix in self._additional_source_parsers: - logger.warning('while setting up extension %s: source_parser for %r is ' - 'already registered, it will be overridden', + logger.warning(_('while setting up extension %s: source_parser for %r is ' + 'already registered, it will be overridden'), self._setting_up_extension[-1], suffix, type='app', subtype='add_source_parser') self._additional_source_parsers[suffix] = parser diff --git a/sphinx/config.py b/sphinx/config.py index 26efa9f33..03d38fd77 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -16,7 +16,7 @@ from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integ from typing import Any, NamedTuple, Union from sphinx.errors import ConfigError -from sphinx.locale import l_ +from sphinx.locale import l_, _ from sphinx.util import logging from sphinx.util.i18n import format_date from sphinx.util.osutil import cd @@ -233,8 +233,8 @@ class Config(object): else: defvalue = self.values[name][0] if isinstance(defvalue, dict): - raise ValueError('cannot override dictionary config setting %r, ' - 'ignoring (use %r to set individual elements)' % + raise ValueError(_('cannot override dictionary config setting %r, ' + 'ignoring (use %r to set individual elements)') % (name, name + '.key=value')) elif isinstance(defvalue, list): return value.split(',') @@ -242,20 +242,22 @@ class Config(object): try: return int(value) except ValueError: - raise ValueError('invalid number %r for config value %r, ignoring' % + raise ValueError(_('invalid number %r for config value %r, ignoring') % (value, name)) elif hasattr(defvalue, '__call__'): return value elif defvalue is not None and not isinstance(defvalue, string_types): - raise ValueError('cannot override config setting %r with unsupported ' - 'type, ignoring' % name) + raise ValueError(_('cannot override config setting %r with unsupported ' + 'type, ignoring') % name) else: return value def pre_init_values(self): # type: () -> None - """Initialize some limited config variables before loading extensions""" - variables = ['needs_sphinx', 'suppress_warnings'] + """ + Initialize some limited config variables before initialize i18n and loading extensions + """ + variables = ['needs_sphinx', 'suppress_warnings', 'language', 'locale_dirs'] for name in variables: try: if name in self.overrides: @@ -275,7 +277,7 @@ class Config(object): config.setdefault(realvalname, {})[key] = value continue elif valname not in self.values: - logger.warning('unknown config value %r in override, ignoring', valname) + logger.warning(_('unknown config value %r in override, ignoring'), valname) continue if isinstance(value, string_types): config[valname] = self.convert_overrides(valname, value) @@ -294,7 +296,7 @@ class Config(object): if name.startswith('_'): raise AttributeError(name) if name not in self.values: - raise AttributeError('No such config value: %s' % name) + raise AttributeError(_('No such config value: %s') % name) default = self.values[name][0] if hasattr(default, '__call__'): return default(self) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index 6c112b6df..7c0f9b4f9 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -229,11 +229,17 @@ translators = {} # type: Dict[unicode, Any] if PY3: def _(message): # type: (unicode) -> unicode - return translators['sphinx'].gettext(message) + try: + return translators['sphinx'].gettext(message) + except KeyError: + return message else: def _(message): # type: (unicode) -> unicode - return translators['sphinx'].ugettext(message) + try: + return translators['sphinx'].ugettext(message) + except KeyError: + return message def init(locale_dirs, language, catalog='sphinx'):