Merge branch '7.1.x'

# Conflicts:
#	CHANGES
#	sphinx/__init__.py
#	sphinx/config.py
This commit is contained in:
Adam Turner 2023-07-27 21:38:35 +01:00
commit a01e1a21ac
7 changed files with 184 additions and 89 deletions

View File

@ -24,6 +24,15 @@ Bugs fixed
Testing
-------
Release 7.1.1 (released Jul 27, 2023)
=====================================
Bugs fixed
----------
* #11514: Fix ``SOURCE_DATE_EPOCH`` in multi-line copyright footer.
Patch by Bénédikt Tran.
Release 7.1.0 (released Jul 24, 2023)
=====================================

View File

@ -2,7 +2,7 @@
from __future__ import annotations
import re
import time
import traceback
import types
from os import getenv, path
@ -11,7 +11,6 @@ from typing import TYPE_CHECKING, Any, Callable, NamedTuple
from sphinx.errors import ConfigError, ExtensionError
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.i18n import format_date
from sphinx.util.osutil import fs_encoding
from sphinx.util.tags import Tags
from sphinx.util.typing import NoneType
@ -22,7 +21,7 @@ except ImportError:
from sphinx.util.osutil import _chdir as chdir
if TYPE_CHECKING:
from collections.abc import Generator, Iterator
from collections.abc import Generator, Iterator, Sequence
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
@ -31,7 +30,6 @@ logger = logging.getLogger(__name__)
CONFIG_FILENAME = 'conf.py'
UNSERIALIZABLE_TYPES = (type, types.ModuleType, types.FunctionType)
copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
class ConfigValue(NamedTuple):
@ -419,17 +417,52 @@ def init_numfig_format(app: Sphinx, config: Config) -> None:
config.numfig_format = numfig_format # type: ignore
def correct_copyright_year(app: Sphinx, config: Config) -> None:
def correct_copyright_year(_app: Sphinx, config: Config) -> None:
"""Correct values of copyright year that are not coherent with
the SOURCE_DATE_EPOCH environment variable (if set)
See https://reproducible-builds.org/specs/source-date-epoch/
"""
if getenv('SOURCE_DATE_EPOCH') is not None:
for k in ('copyright', 'epub_copyright'):
if k in config:
replace = r'\g<1>%s' % format_date('%Y', language='en')
config[k] = copyright_year_re.sub(replace, config[k])
if (source_date_epoch := getenv('SOURCE_DATE_EPOCH')) is None:
return
source_date_epoch_year = str(time.gmtime(int(source_date_epoch)).tm_year)
for k in ('copyright', 'epub_copyright'):
if k in config:
value: str | Sequence[str] = config[k]
if isinstance(value, str):
config[k] = _substitute_copyright_year(value, source_date_epoch_year)
else:
items = (_substitute_copyright_year(x, source_date_epoch_year) for x in value)
config[k] = type(value)(items) # type: ignore[call-arg]
def _substitute_copyright_year(copyright_line: str, replace_year: str) -> str:
"""Replace the year in a single copyright line.
Legal formats are:
* ``YYYY,``
* ``YYYY ``
* ``YYYY-YYYY,``
* ``YYYY-YYYY ``
The final year in the string is replaced with ``replace_year``.
"""
if not copyright_line[:4].isdigit():
return copyright_line
if copyright_line[4] in ' ,':
return replace_year + copyright_line[4:]
if copyright_line[4] != '-':
return copyright_line
if copyright_line[5:9].isdigit() and copyright_line[9] in ' ,':
return copyright_line[:5] + replace_year + copyright_line[9:]
return copyright_line
def check_confval_types(app: Sphinx | None, config: Config) -> None:

View File

@ -36,7 +36,7 @@ Documentation.addTranslations({
"Search": "Cerca",
"Search Page": "P\u00e0gina de cerca",
"Search Results": "Resultats de la cerca",
"Search finished, found ${resultCount} page(s) matching the search query.": "Cerca acabada, s'han trobat ${resultCount} p\u00e0gina/es que coincideix/en amb la consulta de cerca.",
"Search finished, found ${resultCount} page(s) matching the search query.": "Cerca acabada, s'han trobat ${resultCount} p\u00e0gines que coincideixen amb la consulta de cerca.",
"Search within %(docstitle)s": "Cerca dins de %(docstitle)s",
"Searching": "S'est\u00e0 cercant",
"Searching for multiple words only shows matches that contain\n all words.": "Cercar m\u00faltiples paraules nom\u00e9s mostrar\u00e0 les coincid\u00e8ncies\n que continguin totes les paraules.",

View File

@ -11,9 +11,9 @@ msgid ""
msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-07-24 12:38+0000\n"
"POT-Creation-Date: 2023-07-24 12:43+0000\n"
"PO-Revision-Date: 2013-04-02 08:44+0000\n"
"Last-Translator: Adam Turner, 2023\n"
"Last-Translator: Antoni Bella Pérez <antonibella5@yahoo.com>, 2023\n"
"Language-Team: Catalan (http://app.transifex.com/sphinx-doc/sphinx-1/language/ca/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -34,7 +34,7 @@ msgstr "El directori de sortida (%s) no és un directori"
#: sphinx/application.py:161
msgid "Source directory and destination directory cannot be identical"
msgstr "El directori d'origen i el directori de destinació no poden ser idèntics"
msgstr "El directori d'origen i el de destinació no poden ser idèntics"
#: sphinx/application.py:193
#, python-format
@ -313,7 +313,7 @@ msgstr "L'extensió %s és requerida per la configuració de needs_extensions, p
msgid ""
"This project needs the extension %s at least in version %s and therefore "
"cannot be built with the loaded version (%s)."
msgstr "Aquest projecte necessita l'extensió %s almenys a la versió %s i per tant no es pot construir amb la versió carregada (%s)."
msgstr "Aquest projecte necessita l'extensió %s almenys a la versió %s i, per tant, no es pot construir amb la versió carregada (%s)."
#: sphinx/highlighting.py:147
#, python-format
@ -506,7 +506,7 @@ msgstr "opció de tema no admesa, s'ha donat %r"
#: sphinx/theming.py:214
#, python-format
msgid "file %r on theme path is not a valid zipfile or contains no theme"
msgstr "el fitxer %r en el camí de temes no és un fitxer ZIP valid ni conté cap tema"
msgstr "el fitxer %r en el camí de temes no és un fitxer ZIP vàlid ni conté cap tema"
#: sphinx/theming.py:228
#, python-format
@ -1208,7 +1208,7 @@ msgstr "S'ha produït una excepció:"
msgid ""
"Please also report this if it was a user error, so that a better error "
"message can be provided next time."
msgstr "Informeu-ho també si es tractava d'un error d'usuari, de manera que la propera vegada es pugui proporcionar un missatge d'error millor."
msgstr "Informeu-ho també si es tractava d'un error d'usuari, de manera que la pròxima vegada es pugui proporcionar un missatge d'error millor."
#: sphinx/cmd/build.py:84
msgid ""
@ -1242,7 +1242,7 @@ msgid ""
"\n"
"By default, everything that is outdated is built. Output only for selected\n"
"files can be built by specifying individual filenames.\n"
msgstr "\nGenerar la documentació a partir dels fitxers font.\n\nL'eina «sphinx-build» generarà la documentació a partir dels fitxers\na SOURCEDIR i els situarà a OUTPUTDIR. Cerqueu el «conf.py» en el\nSOURCEDIR per als paràmetres de configuració. L'eina «sphinx-quickstart» es pot usar per a generar fitxers de plantilla, inclòs el «conf.py».\n\nL'eina «sphinx-build» pot crear documentació en formats diferents. A la\nlínia d'ordres se selecciona un format que especifica el nom del constructor.\nDe manera predeterminada és HTML. Els constructors també poden realitzar\naltres tasques relacionades amb el processament de la documentació.\n\nDe manera predeterminada, es construeix tot el que està desactualitzat. Es pot\ngenerar la sortida només per als fitxers seleccionats especificant noms de fitxer\nindividuals.\n"
msgstr "\nGenerar la documentació a partir dels fitxers font.\n\nL'eina «sphinx-build» generarà la documentació a partir dels fitxers\na SOURCEDIR i els situarà a OUTPUTDIR. Cerqueu el «conf.py» en el\nSOURCEDIR per als paràmetres de configuració. L'eina «sphinx-quickstart» es pot usar per a generar fitxers de plantilla, inclòs el «conf.py».\n\nL'eina «sphinx-build» pot crear documentació en formats diferents. A la\nlínia d'ordres se selecciona un format que especifica el nom del constructor.\nDe manera predeterminada és HTML. Els constructors també poden dur a terme\naltres tasques relacionades amb el processament de la documentació.\n\nDe manera predeterminada, es construeix tot el que està desactualitzat. Es pot\ngenerar la sortida només per als fitxers seleccionats especificant noms de fitxer\nindividuals.\n"
#: sphinx/cmd/build.py:130
msgid "path to documentation source files"
@ -1450,7 +1450,7 @@ msgstr "Camí arrel seleccionat: %s"
#: sphinx/cmd/quickstart.py:216
msgid "Enter the root path for documentation."
msgstr "Introduïu la camí arrel per a la documentació."
msgstr "Introduïu el camí arrel per a la documentació."
#: sphinx/cmd/quickstart.py:217
msgid "Root path for the documentation"
@ -1501,7 +1501,7 @@ msgstr "Nom del projecte"
#: sphinx/cmd/quickstart.py:250
msgid "Author name(s)"
msgstr "Noms dels autors"
msgstr "Noms de l'autoria"
#: sphinx/cmd/quickstart.py:254
msgid ""
@ -1664,7 +1664,7 @@ msgstr "Si s'especifica, se separarà el codi font i els directoris de compilaci
#: sphinx/cmd/quickstart.py:484
msgid "if specified, create build dir under source dir"
msgstr "Si s'especifica, se crearà el directori de construcció a dins del directori d'origen"
msgstr "Si s'especifica, es crearà el directori de construcció a dins del directori d'origen"
#: sphinx/cmd/quickstart.py:486
msgid "replacement for dot in _templates etc."
@ -1680,7 +1680,7 @@ msgstr "nom del projecte"
#: sphinx/cmd/quickstart.py:492
msgid "author names"
msgstr "noms dels autors"
msgstr "noms de l'autoria"
#: sphinx/cmd/quickstart.py:494
msgid "version of project"
@ -1766,7 +1766,7 @@ msgstr "s'especifica «quiet», però no s'especifica cap «project» o «author
#: sphinx/cmd/quickstart.py:584
msgid ""
"Error: specified path is not a directory, or sphinx files already exist."
msgstr "Error: el camí especificat no és un directori o ja hi ha els fitxers d'Sphinx."
msgstr "Error: el camí especificat no és un directori o ja hi ha els fitxers de Sphinx."
#: sphinx/cmd/quickstart.py:586
msgid ""
@ -1809,7 +1809,7 @@ msgstr "El fitxer inclòs %r no s'ha trobat o s'ha fallat en llegir-lo"
msgid ""
"Encoding %r used for reading included file %r seems to be wrong, try giving "
"an :encoding: option"
msgstr "La codificació %r usada per a la lectura del fitxer inclòs %r sembla estar malament, intenteu donar una opció :encoding:"
msgstr "La codificació %r usada per a la lectura del fitxer inclòs %r sembla estar malament, intenteu donar una opció «:encoding:»"
#: sphinx/directives/code.py:259
#, python-format
@ -1863,11 +1863,11 @@ msgstr "Autor: "
#: sphinx/directives/other.py:252
msgid ".. acks content is not a list"
msgstr ".. el contingut dels reconeixements no és una llista"
msgstr "... el contingut dels reconeixements no és una llista"
#: sphinx/directives/other.py:277
msgid ".. hlist content is not a list"
msgstr ".. el contingut de l'historial no és una llista"
msgstr "... el contingut de l'historial no és una llista"
#: sphinx/directives/patches.py:66
msgid ""
@ -1965,7 +1965,7 @@ msgstr "Canviat a la versió %s"
#: sphinx/domains/changeset.py:24
#, python-format
msgid "Deprecated since version %s"
msgstr "Obsolet desde la versió %s"
msgstr "Obsolet des de la versió %s"
#: sphinx/domains/citation.py:69
#, python-format
@ -2157,7 +2157,7 @@ msgstr "propietat"
msgid ""
"duplicate object description of %s, other instance in %s, use :noindex: for "
"one of them"
msgstr "descripció duplicada de l'objecte de %s, una altra instància a %s, useu :noindex: per a un d'ells"
msgstr "descripció duplicada de l'objecte de %s, una altra instància a %s, useu «:noindex:» per a un d'ells"
#: sphinx/domains/python.py:1628
#, python-format
@ -2427,7 +2427,7 @@ msgid ""
"excluded from generation.\n"
"\n"
"Note: By default this script will not overwrite already created files."
msgstr "\nMireu recursivament a <MODULE_PATH> per als mòduls i paquets de Python\ni creeu un fitxer reST amb les directives automodule per paquet en el <OUTPUT_PATH>.\n\nEls <EXCLUDE_PATTERN> poden ser fitxers i/o patrons de directori que seran\nexclosos de la generació.\n\nNota: De manera predeterminada, aquest script no sobreescriurà els fitxers que ja s'han creat."
msgstr "\nMireu recursivament a <MODULE_PATH> per als mòduls i paquets de Python\ni creeu un fitxer reST amb les directives «automodule» per paquet en el <OUTPUT_PATH>.\n\nEls <EXCLUDE_PATTERN> poden ser fitxers i/o patrons de directori que seran\nexclosos de la generació.\n\nNota: De manera predeterminada, aquest script no sobreescriurà els fitxers que ja s'han creat."
#: sphinx/ext/apidoc.py:314
msgid "path to module to document"
@ -2510,7 +2510,7 @@ msgstr "nom del projecte (predeterminat: nom del mòdul arrel)"
#: sphinx/ext/apidoc.py:370
msgid "project author(s), used when --full is given"
msgstr "autors del projecte, s'usa quan s'indica el paràmetre --full"
msgstr "autoria del projecte, s'usa quan s'indica el paràmetre --full"
#: sphinx/ext/apidoc.py:372
msgid "project version, used when --full is given"
@ -2651,7 +2651,7 @@ msgstr "«dot» no ha produït un fitxer de sortida:\n[stderr]\n%r\n[stdout]\n%r
msgid ""
"dot command %r cannot be run (needed for graphviz output), check the "
"graphviz_dot setting"
msgstr "l'ordre «dot» %r no s'ha pogut executar (necessària per a la sortida del Graphviz), comproveu la configuració de graphviz_dot"
msgstr "l'ordre «dot» %r no s'ha pogut executar (necessària per a la sortida del Graphviz), comproveu la configuració de «graphviz_dot»"
#: sphinx/ext/graphviz.py:265
#, python-format
@ -2704,21 +2704,21 @@ msgstr "«convert» ha sortit amb un error:\n[stderr]\n%r\n[stdout]\n%r"
#: sphinx/ext/imgconverter.py:64
#, python-format
msgid "convert command %r cannot be run, check the image_converter setting"
msgstr "l'ordre «convert» %r no s'ha pogut executar, comproveu la configuració d'image_converter"
msgstr "l'ordre «convert» %r no s'ha pogut executar, comproveu la configuració d'«image_converter»"
#: sphinx/ext/imgmath.py:150
#, python-format
msgid ""
"LaTeX command %r cannot be run (needed for math display), check the "
"imgmath_latex setting"
msgstr "l'ordre de LaTeX %r no s'ha pogut executar (necessària per a la visualització matemàtica), comproveu la configuració d'imgmath_latex"
msgstr "l'ordre de LaTeX %r no s'ha pogut executar (necessària per a la visualització matemàtica), comproveu la configuració d'«imgmath_latex»"
#: sphinx/ext/imgmath.py:164
#, python-format
msgid ""
"%s command %r cannot be run (needed for math display), check the imgmath_%s "
"setting"
msgstr "%s l'ordre de %r no s'ha pogut executar (necessària per a la visualització matemàtica), comproveu la configuració d'imgmath_%s "
msgstr "%s l'ordre de %r no s'ha pogut executar (necessària per a la visualització matemàtica), comproveu la configuració d'«imgmath_%s»"
#: sphinx/ext/imgmath.py:320
#, python-format
@ -2732,7 +2732,7 @@ msgstr "latex inclòs %r: %s"
#: sphinx/ext/imgmath.py:361 sphinx/ext/mathjax.py:49
msgid "Permalink to this equation"
msgstr "Enllaç permanent a aquest equació"
msgstr "Enllaç permanent a aquesta equació"
#: sphinx/ext/intersphinx.py:194
#, python-format
@ -2809,7 +2809,7 @@ msgstr "<<entrada original>>"
#: sphinx/ext/todo.py:157
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
msgstr "(L'<<entrada original>> es troba a %s, línia %d)."
msgstr "(L'<<original entry>> es troba a %s, línia %d)."
#: sphinx/ext/todo.py:167
msgid "original entry"
@ -2887,12 +2887,12 @@ msgstr "error mentre es donava format a la signatura per a %s: %s"
#: sphinx/ext/autodoc/__init__.py:995
msgid "\"::\" in automodule name doesn't make sense"
msgstr "«::» en el nom de l'automodule no té sentit"
msgstr "«::» en el nom de l'«automodule» no té sentit"
#: sphinx/ext/autodoc/__init__.py:1002
#, python-format
msgid "signature arguments or return annotation given for automodule %s"
msgstr "arguments de signatura o anotació de retorn indicats per a automodule %s"
msgstr "arguments de signatura o anotació de retorn indicats per a «automodule» %s"
#: sphinx/ext/autodoc/__init__.py:1015
#, python-format
@ -2905,7 +2905,7 @@ msgstr "__all__ ha de ser una llista de cadenes, no %r (en el mòdul %s) -s'igno
#, python-format
msgid ""
"missing attribute mentioned in :members: option: module %s, attribute %s"
msgstr "manca l'atribut esmentat a l'opció :members:: mòdul %s, atribut %s"
msgstr "manca l'atribut esmentat a l'opció «:members:»: mòdul %s, atribut %s"
#: sphinx/ext/autodoc/__init__.py:1285 sphinx/ext/autodoc/__init__.py:1362
#: sphinx/ext/autodoc/__init__.py:2750
@ -2978,7 +2978,7 @@ msgstr "autosummary: no s'ha trobat el fitxer stub %r. Verifiqueu la vostra conf
#: sphinx/ext/autosummary/__init__.py:265
msgid "A captioned autosummary requires :toctree: option. ignored."
msgstr "Un resum automàtic amb subtítols requereix l'opció :toctree:. S'ignora."
msgstr "Un resum automàtic amb subtítols requereix l'opció «:toctree:». S'ignora."
#: sphinx/ext/autosummary/__init__.py:318
#, python-format
@ -3154,7 +3154,7 @@ msgstr "Error"
#: sphinx/locale/__init__.py:219
msgid "Hint"
msgstr "Suggerència"
msgstr "Suggeriment"
#: sphinx/locale/__init__.py:220
msgid "Important"
@ -3404,7 +3404,7 @@ msgstr "Altres canvis"
#: sphinx/themes/basic/static/searchtools.js:111
msgid ""
"Search finished, found ${resultCount} page(s) matching the search query."
msgstr "Cerca acabada, s'han trobat ${resultCount} pàgina/es que coincideix/en amb la consulta de cerca."
msgstr "Cerca acabada, s'han trobat ${resultCount} pàgines que coincideixen amb la consulta de cerca."
#: sphinx/themes/basic/static/searchtools.js:209
msgid "Searching"
@ -3623,7 +3623,7 @@ msgstr "Enllaç permanent a aquest arbre TOC"
#: sphinx/writers/html5.py:675
msgid "Could not obtain image size. :scale: option is ignored."
msgstr "No s'ha pogut obtenir la mida de la imatge. S'ignora l'opció :scale:."
msgstr "No s'ha pogut obtenir la mida de la imatge. S'ignora l'opció «:scale:»."
#: sphinx/writers/latex.py:331
#, python-format
@ -3651,7 +3651,7 @@ msgstr "Notes al peu"
#: sphinx/writers/latex.py:1021
msgid ""
"both tabularcolumns and :widths: option are given. :widths: is ignored."
msgstr "s'indiquen tant les columnes tabulars com l'opció :widths:. S'ignora l'opció :widths:."
msgstr "s'indiquen tant les columnes tabulars com l'opció «:widths:». S'ignora l'opció «:widths:»."
#: sphinx/writers/latex.py:1370
#, python-format

View File

@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Sphinx 7.1.0\n"
"Project-Id-Version: Sphinx 7.1.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-07-24 12:43+0000\n"
"POT-Creation-Date: 2023-07-27 21:32+0100\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"
@ -164,61 +164,61 @@ msgstr ""
msgid "doing serial %s"
msgstr ""
#: sphinx/config.py:175
#: sphinx/config.py:177
#, python-format
msgid "config directory doesn't contain a conf.py file (%s)"
msgstr ""
#: sphinx/config.py:184
#: sphinx/config.py:186
msgid ""
"Invalid configuration value found: 'language = None'. Update your "
"configuration to a valid language code. Falling back to 'en' (English)."
msgstr ""
#: sphinx/config.py:213
#: sphinx/config.py:215
#, python-format
msgid ""
"cannot override dictionary config setting %r, ignoring (use %r to set "
"individual elements)"
msgstr ""
#: sphinx/config.py:222
#: sphinx/config.py:224
#, python-format
msgid "invalid number %r for config value %r, ignoring"
msgstr ""
#: sphinx/config.py:227
#: sphinx/config.py:229
#, python-format
msgid "cannot override config setting %r with unsupported type, ignoring"
msgstr ""
#: sphinx/config.py:256
#: sphinx/config.py:258
#, python-format
msgid "unknown config value %r in override, ignoring"
msgstr ""
#: sphinx/config.py:284
#: sphinx/config.py:286
#, python-format
msgid "No such config value: %s"
msgstr ""
#: sphinx/config.py:308
#: sphinx/config.py:310
#, python-format
msgid "Config value %r already present"
msgstr ""
#: sphinx/config.py:356
#: sphinx/config.py:358
#, python-format
msgid "There is a syntax error in your configuration file: %s\n"
msgstr ""
#: sphinx/config.py:359
#: sphinx/config.py:361
msgid ""
"The configuration file (or one of the modules it imports) called "
"sys.exit()"
msgstr ""
#: sphinx/config.py:366
#: sphinx/config.py:368
#, python-format
msgid ""
"There is a programmable error in your configuration file:\n"
@ -226,57 +226,57 @@ msgid ""
"%s"
msgstr ""
#: sphinx/config.py:389
#: sphinx/config.py:391
#, python-format
msgid ""
"The config value `source_suffix' expects a string, list of strings, or "
"dictionary. But `%r' is given."
msgstr ""
#: sphinx/config.py:408
#: sphinx/config.py:410
#, python-format
msgid "Section %s"
msgstr ""
#: sphinx/config.py:409
#: sphinx/config.py:411
#, python-format
msgid "Fig. %s"
msgstr ""
#: sphinx/config.py:410
#: sphinx/config.py:412
#, python-format
msgid "Table %s"
msgstr ""
#: sphinx/config.py:411
#: sphinx/config.py:413
#, python-format
msgid "Listing %s"
msgstr ""
#: sphinx/config.py:448
#: sphinx/config.py:485
msgid ""
"The config value `{name}` has to be a one of {candidates}, but "
"`{current}` is given."
msgstr ""
#: sphinx/config.py:466
#: sphinx/config.py:503
msgid ""
"The config value `{name}' has type `{current.__name__}'; expected "
"{permitted}."
msgstr ""
#: sphinx/config.py:478
#: sphinx/config.py:515
msgid ""
"The config value `{name}' has type `{current.__name__}', defaults to "
"`{default.__name__}'."
msgstr ""
#: sphinx/config.py:488
#: sphinx/config.py:525
#, python-format
msgid "primary_domain %r not found, ignored."
msgstr ""
#: sphinx/config.py:500
#: sphinx/config.py:537
msgid ""
"Since v2.0, Sphinx uses \"index\" as root_doc by default. Please add "
"\"root_doc = 'contents'\" to your conf.py."
@ -924,7 +924,7 @@ msgid "Failed to read build info file: %r"
msgstr ""
#: sphinx/builders/html/__init__.py:503 sphinx/builders/latex/__init__.py:182
#: sphinx/transforms/__init__.py:109 sphinx/writers/manpage.py:96
#: sphinx/transforms/__init__.py:114 sphinx/writers/manpage.py:96
#: sphinx/writers/texinfo.py:223
#, python-format
msgid "%b %d, %Y"
@ -3452,39 +3452,47 @@ msgstr ""
msgid "Contents"
msgstr ""
#: sphinx/transforms/__init__.py:217
#: sphinx/transforms/__init__.py:123
msgid "could not calculate translation progress!"
msgstr ""
#: sphinx/transforms/__init__.py:128
msgid "no translated elements!"
msgstr ""
#: sphinx/transforms/__init__.py:235
#, python-format
msgid "4 column based index found. It might be a bug of extensions you use: %r"
msgstr ""
#: sphinx/transforms/__init__.py:256
#: sphinx/transforms/__init__.py:274
#, python-format
msgid "Footnote [%s] is not referenced."
msgstr ""
#: sphinx/transforms/__init__.py:262
#: sphinx/transforms/__init__.py:280
msgid "Footnote [#] is not referenced."
msgstr ""
#: sphinx/transforms/i18n.py:201 sphinx/transforms/i18n.py:268
#: sphinx/transforms/i18n.py:202 sphinx/transforms/i18n.py:269
msgid ""
"inconsistent footnote references in translated message. original: {0}, "
"translated: {1}"
msgstr ""
#: sphinx/transforms/i18n.py:241
#: sphinx/transforms/i18n.py:242
msgid ""
"inconsistent references in translated message. original: {0}, translated:"
" {1}"
msgstr ""
#: sphinx/transforms/i18n.py:283
#: sphinx/transforms/i18n.py:284
msgid ""
"inconsistent citation references in translated message. original: {0}, "
"translated: {1}"
msgstr ""
#: sphinx/transforms/i18n.py:300
#: sphinx/transforms/i18n.py:301
msgid ""
"inconsistent term references in translated message. original: {0}, "
"translated: {1}"

View File

@ -1,5 +1,6 @@
"""Test the sphinx.config.Config class."""
import time
from unittest import mock
import pytest
@ -444,23 +445,67 @@ def test_conf_py_nitpick_ignore_list(tempdir):
assert cfg.nitpick_ignore_regex == []
@pytest.fixture(params=[
# test with SOURCE_DATE_EPOCH unset: no modification
None,
# test with SOURCE_DATE_EPOCH set: copyright year should be updated
1293840000,
1293839999,
])
def source_date_year(request, monkeypatch):
sde = request.param
with monkeypatch.context() as m:
if sde:
m.setenv('SOURCE_DATE_EPOCH', sde)
yield time.gmtime(sde).tm_year
else:
m.delenv('SOURCE_DATE_EPOCH', raising=False)
yield None
@pytest.mark.sphinx(testroot='copyright-multiline')
def test_multi_line_copyright(app, status, warning):
def test_multi_line_copyright(source_date_year, app, monkeypatch):
app.builder.build_all()
content = (app.outdir / 'index.html').read_text(encoding='utf-8')
assert ' &#169; Copyright 2006-2009, Alice.<br/>' in content
assert ' &#169; Copyright 2010-2013, Bob.<br/>' in content
assert ' &#169; Copyright 2014-2017, Charlie.<br/>' in content
assert ' &#169; Copyright 2018-2021, David.<br/>' in content
assert ' &#169; Copyright 2022-2025, Eve.' in content
if source_date_year is None:
# check the copyright footer line by line (empty lines ignored)
assert ' &#169; Copyright 2006-2009, Alice.<br/>\n' in content
assert ' &#169; Copyright 2010-2013, Bob.<br/>\n' in content
assert ' &#169; Copyright 2014-2017, Charlie.<br/>\n' in content
assert ' &#169; Copyright 2018-2021, David.<br/>\n' in content
assert ' &#169; Copyright 2022-2025, Eve.' in content
lines = (
' &#169; Copyright 2006-2009, Alice.<br/>\n \n'
' &#169; Copyright 2010-2013, Bob.<br/>\n \n'
' &#169; Copyright 2014-2017, Charlie.<br/>\n \n'
' &#169; Copyright 2018-2021, David.<br/>\n \n'
' &#169; Copyright 2022-2025, Eve.\n \n'
)
assert lines in content
# check the raw copyright footer block (empty lines included)
assert (
' &#169; Copyright 2006-2009, Alice.<br/>\n'
' \n'
' &#169; Copyright 2010-2013, Bob.<br/>\n'
' \n'
' &#169; Copyright 2014-2017, Charlie.<br/>\n'
' \n'
' &#169; Copyright 2018-2021, David.<br/>\n'
' \n'
' &#169; Copyright 2022-2025, Eve.'
) in content
else:
# check the copyright footer line by line (empty lines ignored)
assert f' &#169; Copyright 2006-{source_date_year}, Alice.<br/>\n' in content
assert f' &#169; Copyright 2010-{source_date_year}, Bob.<br/>\n' in content
assert f' &#169; Copyright 2014-{source_date_year}, Charlie.<br/>\n' in content
assert f' &#169; Copyright 2018-{source_date_year}, David.<br/>\n' in content
assert f' &#169; Copyright 2022-{source_date_year}, Eve.' in content
# check the raw copyright footer block (empty lines included)
assert (
f' &#169; Copyright 2006-{source_date_year}, Alice.<br/>\n'
f' \n'
f' &#169; Copyright 2010-{source_date_year}, Bob.<br/>\n'
f' \n'
f' &#169; Copyright 2014-{source_date_year}, Charlie.<br/>\n'
f' \n'
f' &#169; Copyright 2018-{source_date_year}, David.<br/>\n'
f' \n'
f' &#169; Copyright 2022-{source_date_year}, Eve.'
) in content