diff --git a/.babel.cfg b/.babel.cfg new file mode 100644 index 00000000..cc4c9de0 --- /dev/null +++ b/.babel.cfg @@ -0,0 +1,3 @@ +[javascript: **.js] + +[jinja2: **.html] diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 2bcd70e3..00000000 --- a/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max-line-length = 88 diff --git a/.github/workflows/documentation-links.yml b/.github/workflows/documentation-links.yml index f05df37b..a4de7dcd 100644 --- a/.github/workflows/documentation-links.yml +++ b/.github/workflows/documentation-links.yml @@ -6,9 +6,6 @@ on: pull_request_target: types: - opened - paths: - - 'Doc/**' - - '.github/workflows/doc.yml' permissions: pull-requests: write diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 88c0c7cb..795f7b0d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: "3.x" diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml index c7acc055..bec94a2b 100644 --- a/.github/workflows/pypi-package.yml +++ b/.github/workflows/pypi-package.yml @@ -11,6 +11,9 @@ on: permissions: contents: read +env: + FORCE_COLOR: 1 + jobs: # Always build & lint package. build-package: @@ -18,7 +21,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-python@v5 + + - name: Compile translations + run: | + pip install --upgrade pip + pip install -r requirements.txt + python babel_runner.py compile - uses: hynek/build-and-inspect-python-package@v2 @@ -38,10 +48,12 @@ jobs: steps: - name: Download packages built by build-and-inspect-python-package - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: Packages path: dist - name: Upload package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + with: + attestations: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1b58d3ed..60257eef 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,12 +12,12 @@ jobs: strategy: fail-fast: false matrix: - branch: ["origin/main", "3.12", "3.11", "3.10"] + branch: ["3.14", "3.13", "3.12"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: - python-version: 3 + python-version: ${{ matrix.branch }} allow-prereleases: true cache: pip - name: Clone docsbuild scripts @@ -34,11 +34,12 @@ jobs: --build-root ./build_root --www-root ./www --log-directory ./logs - --group $(id -g) + --group "$(id -g)" --skip-cache-invalidation - --theme $(pwd) - --language en - --branch ${{ matrix.branch }} + --theme "$(pwd)" + --languages en + --branches ${{ matrix.branch }} + ${{ matrix.branch == '3.14' && '--select-output no-html' || '' }} - name: Show logs if: failure() run: | @@ -48,3 +49,38 @@ jobs: with: name: doc-html-${{ matrix.branch }} path: www/ + + translations: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "windows-latest"] + # Test minimum supported and latest stable from 3.x series + python-version: ["3.12", "3"] + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + allow-prereleases: true + cache: pip + - name: Install dependencies + run: | + pip install --upgrade pip + pip install -r requirements.txt + - name: Remove locale file for testing + shell: bash + run: rm -rf python_docs_theme/locale/pt_BR/ + - run: python babel_runner.py extract + - run: python babel_runner.py init -l pt_BR + - run: python babel_runner.py update + - run: python babel_runner.py update -l pt_BR + - run: python babel_runner.py compile + - run: python babel_runner.py compile -l pt_BR + - name: Print .pot file + shell: bash + run: cat python_docs_theme/locale/python-docs-theme.pot + - name: Print .po file + shell: bash + run: cat python_docs_theme/locale/pt_BR/LC_MESSAGES/python-docs-theme.po diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70b4e19a..9a7e83b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,34 +1,17 @@ repos: - - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.9.3 hooks: - - id: pyupgrade - args: [--py38-plus] + - id: ruff + args: [--exit-non-zero-on-fix] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.1.1 + rev: 24.10.0 hooks: - id: black - - repo: https://github.com/PyCQA/isort - rev: 5.13.2 - hooks: - - id: isort - - - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - additional_dependencies: - [flake8-2020, flake8-implicit-str-concat, flake8-logging] - - - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.10.0 - hooks: - - id: python-check-blanket-noqa - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v5.0.0 hooks: - id: check-case-conflict - id: check-merge-conflict @@ -38,14 +21,24 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.31.0 + hooks: + - id: check-dependabot + - id: check-github-workflows + + - repo: https://github.com/rhysd/actionlint + rev: v1.7.7 + hooks: + - id: actionlint + - repo: https://github.com/tox-dev/pyproject-fmt - rev: 1.7.0 + rev: v2.5.0 hooks: - id: pyproject-fmt - args: [--max-supported-python=3.13] - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.16 + rev: v0.23 hooks: - id: validate-pyproject diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6ba1903c..c411e71f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,81 @@ Changelog ========= -`2024.4 `_ ----------------------------------------------------------------------------- +`2025.9.1 `_ +------------------------------------------------------------------------------- + +* Add Japanese, Turkish and Spanish translations from Transifex in https://github.com/python/python-docs-theme/pull/259 + +`2025.9 `_ +--------------------------------------------------------------------------- + +* Enable theme translation and add Polish by @StanFromIreland in https://github.com/python/python-docs-theme/pull/246 +* Add Greek translation by @lysnikolaou and @skpanagiotis in https://github.com/python/python-docs-theme/pull/256 and https://github.com/python/python-docs-theme/pull/257 +* Add Swedish translation by @yeager in https://github.com/python/python-docs-theme/pull/250 +* Add Brazilian Portuguese, Simplified Chinese and Traditional Chinese translations from `Transifex `_ in https://github.com/python/python-docs-theme/pull/253 + +`2025.5 `_ +--------------------------------------------------------------------------- + +* Make the copy button only appear when hovered over or clicked on by @kevteg in https://github.com/python/python-docs-theme/pull/243 + +`2025.4.1 `_ +------------------------------------------------------------------------------- + +* Fix copy button with multiple tracebacks by @tomasr8 in https://github.com/python/python-docs-theme/pull/240 + +`2025.4 `_ +--------------------------------------------------------------------------- + +* Require Sphinx 7.3 by @AA-Turner in https://github.com/python/python-docs-theme/pull/221 +* Add support for Python 3.14 by @hugovk https://github.com/python/python-docs-theme/pull/236 +* Drop support for Python 3.10 and 3.11 by @hugovk in https://github.com/python/python-docs-theme/pull/234 +* Add a copy button to code samples by @tomasr8 in https://github.com/python/python-docs-theme/pull/231 +* Add missing i18n for copy button titles by @tomasr8 in https://github.com/python/python-docs-theme/pull/225 +* Use consistent line-height for light & dark theme by @tomasr8 in https://github.com/python/python-docs-theme/pull/227 +* Remove self-closing tags by @hugovk in https://github.com/python/python-docs-theme/pull/226 +* Replace deprecated classifier with licence expression (PEP 639) by @hugovk in https://github.com/python/python-docs-theme/pull/237 + +`2025.2 `_ +--------------------------------------------------------------------------- + +- Note minimum requirements for Sphinx (#216) + Contributed by Adam Turner +- Horizontally centre the sidebar collapse button (#219) + Contributed by Tomas Roun +- Make sidebar width more flexible (#218) + Contributed by Tomas Roun +- Set ``__version__`` in the runtime package (#222) + Contributed by Adam Turner + +`2024.12 `_ +----------------------------------------------------------------------------- + +- Hide header and search bar when printing (#204) + Contributed by Hugo van Kemenade + +`2024.10 `_ +----------------------------------------------------------------------------- + +- Add support for Python 3.13 (#196) + Contributed by Hugo van Kemenade +- Drop support for Python 3.8 (#197) + Contributed by Hugo van Kemenade +- Add script for handling translations (#195) + Contributed by Rafael Fontenelle +- Generate digital attestations for PyPI (PEP 740) (#198) + Contributed by Hugo van Kemenade + +`2024.6 `_ +--------------------------------------------------------------------------- + +- Add backgrounds and borders to admonitions (#190) + Contributed by Hugo van Kemenade +- Use different colour for 'Return value: Borrowed reference' (#188) + Contributed by Hugo van Kemenade + +`2024.4 `_ +--------------------------------------------------------------------------- - Add colour to version change directives (#185) Contributed by Hugo van Kemenade @@ -11,24 +84,24 @@ Changelog - Use system font stack for all code (#186) Contributed by Hugo van Kemenade -`2024.3 `_ ----------------------------------------------------------------------------- +`2024.3 `_ +--------------------------------------------------------------------------- - Modernise font: use system font stack to improve text readability and webpage performance (#174) Contributed by Hugo van Kemenade - Remove incorrect CSS property (#178) Contributed by Kerim Kabirov -`2024.2 `_ ----------------------------------------------------------------------------- +`2024.2 `_ +--------------------------------------------------------------------------- - Do not underline navigation links (#169) Contributed by Hugo van Kemenade - Only apply underline offset to code formatting for underline visibility (#171) Contributed by Hugo van Kemenade -`2024.1 `_ ----------------------------------------------------------------------------- +`2024.1 `_ +--------------------------------------------------------------------------- - Underline links for readability and a11y (#160, #166) Contributed by Hugo van Kemenade @@ -39,14 +112,14 @@ Changelog - Dark mode: fix contrast of footer highlight (#162) Contributed by Hugo van Kemenade -`2023.9 `_ ----------------------------------------------------------------------------- +`2023.9 `_ +--------------------------------------------------------------------------- - Focus search box when pressing slash (#153) Contributed by Hugo van Kemenade -`2023.8 `_ ----------------------------------------------------------------------------- +`2023.8 `_ +--------------------------------------------------------------------------- - Add Python 3.12 and 3.13 classifiers (#147) Contributed by Hugo van Kemenade @@ -55,8 +128,8 @@ Changelog - Restore the menu on mobile devices (inadvertently broken in 2023.7) (#146) Contributed by Hugo van Kemenade -`2023.7 `_ ----------------------------------------------------------------------------- +`2023.7 `_ +--------------------------------------------------------------------------- - Fix compatibility with Sphinx 7.1 (#137) Contributed by Pradyun Gedam @@ -71,8 +144,8 @@ Changelog - Test with Python 3.12 (#140) Contributed by Hugo van Kemenade -`2023.5 `_ ----------------------------------------------------------------------------- +`2023.5 `_ +--------------------------------------------------------------------------- - Add a dark theme. (#44) Contributed by Nils K @@ -86,14 +159,14 @@ Changelog Contributed by Hugo van Kemenade -`2023.3.1 `_ --------------------------------------------------------------------------------- +`2023.3.1 `_ +------------------------------------------------------------------------------- - Skip cache-busting for old Sphinx #113 -`2023.3 `_ ----------------------------------------------------------------------------- +`2023.3 `_ +--------------------------------------------------------------------------- - Fix problem with monospace rendering in Vivaldi #104 - Fix mobile nav obstructing content #96 @@ -101,30 +174,30 @@ Changelog - Append a hash ?digest to CSS files for cache-busting #108 -`2022.1 `_ ----------------------------------------------------------------------------------- +`2022.1 `_ +---------------------------------------------------------------------------- - Add a configuration for license URL. (#90) - Exclude the floating navbar from CHM help. (#84) - Make sidebar scrollable and sticky (on modern browsers) (#91) -`2021.11.1 `_ ------------------------------------------------------------------------------------ +`2021.11.1 `_ +---------------------------------------------------------------------------------- - Fix monospace again, on buggy Google Chrome (#87) Contributed by Tushar Sadhwani -`2021.11 `_ -------------------------------------------------------------------------------- +`2021.11 `_ +------------------------------------------------------------------------------ - Fix monospace on buggy Google Chrome (#85) Contributed by Tushar Sadhwani -`2021.8 `_ ------------------------------------------------------------------------------- +`2021.8 `_ +----------------------------------------------------------------------------- - Add the copyright_url variable in the theme (#67) Contributed by jablonskidev @@ -136,8 +209,8 @@ Changelog Contributed by Olga Bulat -`2021.5 `_ ------------------------------------------------------------------------------- +`2021.5 `_ +----------------------------------------------------------------------------- - Make the theme responsive (#46) Contributed by Olga Bulat. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2533e96a..c85b77ca 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -2,7 +2,7 @@ How to release -------------- - Update ``CHANGELOG.rst`` -- Bump version (YYYY.MM) in ``pyproject.toml`` +- Bump version (YYYY.MM) in ``python_docs_theme/__init__.py`` - Commit - Push to check tests pass on `GitHub Actions `__ diff --git a/Makefile b/Makefile index bae89325..dda3c238 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ CPYTHON_PATH = ../cpython PYTHON = python3 PACKAGE_ABS_PATH = $(shell pwd)/$(shell find dist/python-docs-theme-*.tar.gz) +SPHINXOPTS = .PHONY: help @@ -22,7 +23,7 @@ venv: .PHONY: html html: venv cd $(CPYTHON_PATH)/Doc && \ - make html + make SPHINXOPTS="$(SPHINXOPTS)" html .PHONY: htmlview htmlview: html diff --git a/README.md b/README.md index f77b4910..fedd7f76 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Python Docs Sphinx Theme This is the theme for the Python documentation. +It requires Python 3.12 or newer and Sphinx 7.3 or newer. Note that when adopting this theme, you're also borrowing an element of the trust and credibility established by the CPython core developers over the diff --git a/babel_runner.py b/babel_runner.py new file mode 100755 index 00000000..677f6da2 --- /dev/null +++ b/babel_runner.py @@ -0,0 +1,139 @@ +"""Script for handling translations with Babel""" + +from __future__ import annotations + +import argparse +import ast +import subprocess +import tomllib +from pathlib import Path + +# Global variables used by pybabel below (paths relative to PROJECT_DIR) +DOMAIN = "python-docs-theme" +COPYRIGHT_HOLDER = "Python Software Foundation" +SOURCE_DIR = "python_docs_theme" +MAPPING_FILE = ".babel.cfg" + +PROJECT_DIR = Path(__file__).resolve().parent +PYPROJECT_TOML = Path(PROJECT_DIR, "pyproject.toml") +INIT_PY = PROJECT_DIR / SOURCE_DIR / "__init__.py" +LOCALES_DIR = Path(f"{SOURCE_DIR}", "locale") +POT_FILE = Path(LOCALES_DIR, f"{DOMAIN}.pot") + + +def get_project_info() -> dict: + """Retrieve project's info to populate the message catalog template""" + pyproject_text = PYPROJECT_TOML.read_text(encoding="utf-8") + project_data = tomllib.loads(pyproject_text)["project"] + + # read __version__ from __init__.py + for child in ast.parse(INIT_PY.read_bytes()).body: + if not isinstance(child, ast.Assign): + continue + target = child.targets[0] + if not isinstance(target, ast.Name) or target.id != "__version__": + continue + version_node = child.value + if not isinstance(version_node, ast.Constant): + continue + project_data["version"] = version_node.value + break + + return project_data + + +def extract_messages() -> None: + """Extract messages from all source files into message catalog template""" + Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True) + project_data = get_project_info() + subprocess.run( + [ + "pybabel", + "extract", + "-F", + MAPPING_FILE, + "--copyright-holder", + COPYRIGHT_HOLDER, + "--project", + project_data["name"], + "--version", + project_data["version"], + "--msgid-bugs-address", + project_data["urls"]["Issue tracker"], + "-o", + POT_FILE, + SOURCE_DIR, + ], + cwd=PROJECT_DIR, + check=True, + ) + + +def init_locale(locale: str) -> None: + """Initialize a new locale based on existing message catalog template""" + pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po" + if pofile.exists(): + print(f"There is already a message catalog for locale {locale}, skipping.") + return + cmd = [ + "pybabel", + "init", + "-i", + POT_FILE, + "-d", + LOCALES_DIR, + "-D", + DOMAIN, + "-l", + locale, + ] + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) + + +def update_catalogs(locale: str) -> None: + """Update translations from existing message catalogs""" + cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR, "-D", DOMAIN] + if locale: + cmd.extend(["-l", locale]) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) + + +def compile_catalogs(locale: str) -> None: + """Compile existing message catalogs""" + cmd = ["pybabel", "compile", "-d", LOCALES_DIR, "-D", DOMAIN] + if locale: + cmd.extend(["-l", locale]) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "command", + choices=["extract", "init", "update", "compile"], + help="command to be executed", + ) + parser.add_argument( + "-l", + "--locale", + default="", + help="language code (needed for init, optional for update and compile)", + ) + + args = parser.parse_args() + locale = args.locale + + if args.command == "extract": + extract_messages() + elif args.command == "init": + if not locale: + parser.error("init requires passing the --locale option") + init_locale(locale) + elif args.command == "update": + update_catalogs(locale) + elif args.command == "compile": + compile_catalogs(locale) + + +if __name__ == "__main__": + main() diff --git a/code_of_conduct.rst b/code_of_conduct.rst deleted file mode 100644 index 4bc6630f..00000000 --- a/code_of_conduct.rst +++ /dev/null @@ -1,13 +0,0 @@ -Code of Conduct -=============== - -Please note that all interactions on -`Python Software Foundation `__-supported -infrastructure is `covered -`__ -by the `PSF Code of Conduct `__, -which includes all infrastructure used in the development of Python itself -(e.g. mailing lists, issue trackers, GitHub, etc.). - -In general this means everyone is expected to be open, considerate, and -respectful of others no matter what their position is within the project. diff --git a/pyproject.toml b/pyproject.toml index 9e46db68..a614351d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,49 +1,73 @@ [build-system] build-backend = "flit_core.buildapi" requires = [ - "flit_core>=3.7", + "flit-core>=3.7", ] [project] name = "python-docs-theme" -version = "2024.4" description = "The Sphinx theme for the CPython docs and related projects" readme = "README.md" -license.file = "LICENSE" -authors = [{name = "PyPA", email = "distutils-sig@python.org"}] -requires-python = ">=3.8" +license = "PSF-2.0" +license-files = [ "LICENSE" ] +authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ] +requires-python = ">=3.12" classifiers = [ "Development Status :: 5 - Production/Stable", "Framework :: Sphinx :: Theme", "Intended Audience :: Developers", - "License :: OSI Approved :: Python Software Foundation License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Documentation", "Topic :: Software Development :: Documentation", ] +dynamic = [ "version" ] + +dependencies = [ + "sphinx>=7.3", +] + urls.Code = "https://github.com/python/python-docs-theme" urls.Download = "https://pypi.org/project/python-docs-theme/" urls.Homepage = "https://github.com/python/python-docs-theme/" urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues" -[project.entry-points."sphinx.html_themes"] -python_docs_theme = 'python_docs_theme' +entry-points."sphinx.html_themes".python_docs_theme = "python_docs_theme" [tool.flit.module] name = "python_docs_theme" [tool.flit.sdist] -include = [ - "python_docs_theme/", +include = [ "python_docs_theme/" ] + +[tool.ruff] +fix = true + +lint.select = [ + "C4", # flake8-comprehensions + "E", # pycodestyle errors + "F", # pyflakes errors + "I", # isort + "ISC", # flake8-implicit-str-concat + "LOG", # flake8-logging + "PGH", # pygrep-hooks + "PYI", # flake8-pyi + "RUF022", # unsorted-dunder-all + "RUF100", # unused noqa (yesqa) + "UP", # pyupgrade + "W", # pycodestyle warnings + "YTT", # flake8-2020 +] +lint.ignore = [ + "E203", # Whitespace before ':' + "E221", # Multiple spaces before operator + "E226", # Missing whitespace around arithmetic operator + "E241", # Multiple spaces after ',' ] +lint.isort.required-imports = [ "from __future__ import annotations" ] -[tool.isort] -add_imports = "from __future__ import annotations" -profile = "black" +[tool.pyproject-fmt] +max_supported_python = "3.14" diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py index 77476754..875206b4 100644 --- a/python_docs_theme/__init__.py +++ b/python_docs_theme/__init__.py @@ -1,64 +1,51 @@ from __future__ import annotations -import hashlib -import os -from functools import lru_cache from pathlib import Path -from typing import Any -import sphinx.application -from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.locale import get_translation -THEME_PATH = Path(__file__).parent.resolve() +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Any + from sphinx.application import Sphinx + from sphinx.util.typing import ExtensionMetadata -@lru_cache(maxsize=None) -def _asset_hash(path: str) -> str: - """Append a `?digest=` to an url based on the file content.""" - full_path = THEME_PATH / path.replace("_static/", "static/") - digest = hashlib.sha1(full_path.read_bytes()).hexdigest() +__version__ = "2025.9.1" - return f"{path}?digest={digest}" +THEME_PATH = Path(__file__).resolve().parent +LOCALE_DIR = THEME_PATH / "locale" +MESSAGE_CATALOG_NAME = "python-docs-theme" -def _add_asset_hashes(static: list[str], add_digest_to: list[str]) -> None: - for asset in add_digest_to: - index = static.index(asset) - static[index].filename = _asset_hash(asset) # type: ignore - - -def _html_page_context( - app: sphinx.application.Sphinx, +def add_translation_to_context( + app: Sphinx, pagename: str, templatename: str, context: dict[str, Any], - doctree: Any, + doctree: None, ) -> None: - if app.config.html_theme != "python_docs_theme": - return - - assert isinstance(app.builder, StandaloneHTMLBuilder) + theme_gettext = get_translation(MESSAGE_CATALOG_NAME) + sphinx_gettext = get_translation("sphinx") - if (4,) <= sphinx.version_info < (7, 1) and "css_files" in context: - if "_static/pydoctheme.css" not in context["css_files"]: - raise ValueError( - "This documentation is not using `pydoctheme.css` as the stylesheet. " - "If you have set `html_style` in your conf.py file, remove it." - ) + def combined(message: str) -> str: + translation = theme_gettext(message) + if translation == message: + return sphinx_gettext(message) + return translation - _add_asset_hashes( - context["css_files"], - ["_static/pydoctheme.css"], - ) + context["_"] = context["gettext"] = context["ngettext"] = combined -def setup(app): - current_dir = os.path.abspath(os.path.dirname(__file__)) - app.add_html_theme("python_docs_theme", current_dir) +def setup(app: Sphinx) -> ExtensionMetadata: + app.require_sphinx("7.3") - app.connect("html-page-context", _html_page_context) + app.add_html_theme("python_docs_theme", str(THEME_PATH)) + app.add_message_catalog(MESSAGE_CATALOG_NAME, LOCALE_DIR) + app.connect("html-page-context", add_translation_to_context) return { + "version": __version__, "parallel_read_safe": True, "parallel_write_safe": True, } diff --git a/python_docs_theme/footerdonate.html b/python_docs_theme/footerdonate.html index 2aef2ac2..010014d6 100644 --- a/python_docs_theme/footerdonate.html +++ b/python_docs_theme/footerdonate.html @@ -1,3 +1,3 @@ {% trans %}The Python Software Foundation is a non-profit corporation.{% endtrans %} {% trans %}Please donate.{% endtrans %} -
+
diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html index 9762b06c..1903fad4 100644 --- a/python_docs_theme/layout.html +++ b/python_docs_theme/layout.html @@ -14,7 +14,7 @@

{{ _('Navigation') }}

{%- endfor %} {%- block rootrellink %} -
  • {{ theme_root_icon_alt_text }}
  • +
  • {{ theme_root_icon_alt_text }}
  • {{theme_root_name}}{{ reldelim1 }}
  • @@ -48,8 +48,8 @@

    {{ _('Navigation') }}

    {%- if builder != "htmlhelp" %} {%- endif %} @@ -71,7 +71,7 @@

    {{ _('Navigation') }}

    {%- block extrahead -%} - + {%- if builder != "htmlhelp" %} {%- if not embedded %} @@ -93,14 +93,14 @@

    {{ _('Navigation') }}

    {%- if builder != 'htmlhelp' %}
    + aria-pressed="false" aria-expanded="false" role="button" aria-label="{{ _('Menu')}}">