From 0cbdd98ffbf87ff4e13f1360f27231b2a088f851 Mon Sep 17 00:00:00 2001 From: Jeremy Bowman Date: Sun, 11 Aug 2024 15:34:04 -0400 Subject: [PATCH] Correctly support custom gettext output templates (#12645) Co-authored-by: Jeremy Bowman Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com> --- CHANGES.rst | 2 ++ doc/usage/advanced/intl.rst | 5 +++++ sphinx/builders/gettext.py | 19 ++++++++++++----- .../_templates/message.pot.jinja | 21 +++++++++++++++++++ .../conf.py | 1 + .../index.rst | 7 +++++++ tests/test_builders/test_build_gettext.py | 9 ++++++++ 7 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 tests/roots/test-gettext-custom-output-template/_templates/message.pot.jinja create mode 100644 tests/roots/test-gettext-custom-output-template/conf.py create mode 100644 tests/roots/test-gettext-custom-output-template/index.rst diff --git a/CHANGES.rst b/CHANGES.rst index 6141dc9af43..073de1ddb59 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -47,6 +47,8 @@ Bugs fixed Patch by James Addison. * #12639: Fix singular and plural search results text. Patch by Hugo van Kemenade. +* #12645: Correctly support custom gettext output templates. + Patch by Jeremy Bowman. Testing ------- diff --git a/doc/usage/advanced/intl.rst b/doc/usage/advanced/intl.rst index 590ef0356e0..4d52c34debe 100644 --- a/doc/usage/advanced/intl.rst +++ b/doc/usage/advanced/intl.rst @@ -119,6 +119,11 @@ section describe an easy way to translate with *sphinx-intl*. $ make gettext The generated pot files will be placed in the ``_build/gettext`` directory. + If you want to customize the output beyond what can be done via the + :ref:`intl-options`, the + :download:`default pot file template <../../../sphinx/templates/gettext/message.pot.jinja>` + can be replaced by a custom :file:`message.pot.jinja` file placed in any + directory listed in :confval:`templates_path`. #. Generate po files. diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index f1f7d7fa920..8427fcbb49d 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -7,6 +7,7 @@ from codecs import open from collections import defaultdict from os import getenv, path, walk +from pathlib import Path from typing import TYPE_CHECKING, Any, Literal from uuid import uuid4 @@ -28,7 +29,7 @@ if TYPE_CHECKING: import os - from collections.abc import Iterable, Iterator + from collections.abc import Iterable, Iterator, Sequence from docutils.nodes import Element @@ -36,6 +37,8 @@ from sphinx.config import Config from sphinx.util.typing import ExtensionMetadata +DEFAULT_TEMPLATE_PATH = Path(package_dir, 'templates', 'gettext') + logger = logging.getLogger(__name__) @@ -91,13 +94,14 @@ def __init__(self, source: str, line: int) -> None: class GettextRenderer(SphinxRenderer): def __init__( - self, template_path: list[str | os.PathLike[str]] | None = None, + self, template_path: Sequence[str | os.PathLike[str]] | None = None, outdir: str | os.PathLike[str] | None = None, ) -> None: self.outdir = outdir if template_path is None: - template_path = [path.join(package_dir, 'templates', 'gettext')] - super().__init__(template_path) + super().__init__([DEFAULT_TEMPLATE_PATH]) + else: + super().__init__([*template_path, DEFAULT_TEMPLATE_PATH]) def escape(s: str) -> str: s = s.replace('\\', r'\\') @@ -287,7 +291,12 @@ def finish(self) -> None: ensuredir(path.join(self.outdir, path.dirname(textdomain))) context['messages'] = list(catalog) - content = GettextRenderer(outdir=self.outdir).render('message.pot.jinja', context) + template_path = [ + self.app.srcdir / rel_path + for rel_path in self.config.templates_path + ] + renderer = GettextRenderer(template_path, outdir=self.outdir) + content = renderer.render('message.pot.jinja', context) pofn = path.join(self.outdir, textdomain + '.pot') if should_write(pofn, content): diff --git a/tests/roots/test-gettext-custom-output-template/_templates/message.pot.jinja b/tests/roots/test-gettext-custom-output-template/_templates/message.pot.jinja new file mode 100644 index 00000000000..5cc2975f710 --- /dev/null +++ b/tests/roots/test-gettext-custom-output-template/_templates/message.pot.jinja @@ -0,0 +1,21 @@ +# EVEN MORE DESCRIPTIVE TITLE. +# Copyright (C) {{ copyright }} +# This file is distributed under the same license as the {{ project }} package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: {{ project|e }} {{ version|e }}\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: {{ ctime|e }}\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: {{ last_translator|e }}\n" +"Language-Team: {{ language_team|e }}\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +{% for message in messages %} +msgid "{{ message.text|e }}" +msgstr "" +{% endfor -%} diff --git a/tests/roots/test-gettext-custom-output-template/conf.py b/tests/roots/test-gettext-custom-output-template/conf.py new file mode 100644 index 00000000000..3f793b7cfcc --- /dev/null +++ b/tests/roots/test-gettext-custom-output-template/conf.py @@ -0,0 +1 @@ +templates_path = ['_templates'] diff --git a/tests/roots/test-gettext-custom-output-template/index.rst b/tests/roots/test-gettext-custom-output-template/index.rst new file mode 100644 index 00000000000..efe96e02895 --- /dev/null +++ b/tests/roots/test-gettext-custom-output-template/index.rst @@ -0,0 +1,7 @@ +CONTENTS +======== + +.. toctree:: + :maxdepth: 2 + :numbered: + :caption: Table of Contents diff --git a/tests/test_builders/test_build_gettext.py b/tests/test_builders/test_build_gettext.py index 6364b17bae4..905875fe1ef 100644 --- a/tests/test_builders/test_build_gettext.py +++ b/tests/test_builders/test_build_gettext.py @@ -201,6 +201,15 @@ def test_gettext_template_msgid_order_in_sphinxpot(app): ) +@pytest.mark.sphinx('gettext', testroot='gettext-custom-output-template') +def test_gettext_custom_output_template(app): + app.build(force_all=True) + assert (app.outdir / 'index.pot').is_file() + + result = (app.outdir / 'index.pot').read_text(encoding='utf8') + assert 'EVEN MORE DESCRIPTIVE TITLE' in result + + @pytest.mark.sphinx( 'gettext', srcdir='root-gettext',