diff --git a/CHANGES b/CHANGES
index c39023896ec..19fa32ddb38 100644
--- a/CHANGES
+++ b/CHANGES
@@ -43,6 +43,8 @@ Bugs fixed
``autodoc_typehints="description"``
* #8180: autodoc: Docstring metadata ignored for attributes
* #10443: epub: EPUB builder can't detect the mimetype of .webp file
+* #10104: gettext: Duplicated locations are shown if 3rd party extension does
+ not provide correct information
* #10456: py domain: ``:meta:`` fields are displayed if docstring contains two
or more meta-field
* #9096: sphinx-build: the value of progress bar for paralle build is wrong
diff --git a/EXAMPLES b/EXAMPLES
index da41e20e22c..1f1d92365b2 100644
--- a/EXAMPLES
+++ b/EXAMPLES
@@ -40,7 +40,7 @@ Documentation using the alabaster theme
* `pytest `__ (customized)
* `python-apt `__
* `PyVisfile `__
-* `Requests `__
+* `Requests `__
* `searx `__
* `Spyder `__ (customized)
* `Tablib `__
diff --git a/doc/conf.py b/doc/conf.py
index 8da5f4b1617..a0d2f4df994 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -109,7 +109,7 @@
intersphinx_mapping = {
'python': ('https://docs.python.org/3/', None),
- 'requests': ('https://docs.python-requests.org/en/latest/', None),
+ 'requests': ('https://requests.readthedocs.io/en/latest/', None),
'readthedocs': ('https://docs.readthedocs.io/en/stable', None),
}
diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst
index 847f0372b87..4029b04e67b 100644
--- a/doc/usage/restructuredtext/directives.rst
+++ b/doc/usage/restructuredtext/directives.rst
@@ -592,6 +592,13 @@ __ https://pygments.org/docs/lexers
.. versionadded:: 1.3
+ .. rst:directive:option:: class: class names
+ :type: a list of class names separated by spaces
+
+ The class name of the graph.
+
+ .. versionadded:: 1.4
+
.. rst:directive:option:: dedent: number
:type: number or no value
@@ -758,6 +765,9 @@ __ https://pygments.org/docs/lexers
Added the ``diff``, ``lineno-match``, ``caption``, ``name``, and
``dedent`` options.
+ .. versionchanged:: 1.4
+ Added the ``class`` option.
+
.. versionchanged:: 1.5
Added the ``start-at``, and ``end-at`` options.
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index e8bc547b77f..0d7d0ac11d8 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -57,7 +57,8 @@ def add(self, msg: str, origin: Union[Element, "MsgOrigin"]) -> None:
def __iter__(self) -> Generator[Message, None, None]:
for message in self.messages:
- positions = [(source, line) for source, line, uuid in self.metadata[message]]
+ positions = sorted(set((source, line) for source, line, uuid
+ in self.metadata[message]))
uuids = [uuid for source, line, uuid in self.metadata[message]]
yield Message(message, positions, uuids)
diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py
index 3c4617e849c..cca6fab929b 100644
--- a/tests/test_build_gettext.py
+++ b/tests/test_build_gettext.py
@@ -8,9 +8,29 @@
import pytest
+from sphinx.builders.gettext import Catalog, MsgOrigin
from sphinx.util.osutil import cd
+def test_Catalog_duplicated_message():
+ catalog = Catalog()
+ catalog.add('hello', MsgOrigin('/path/to/filename', 1))
+ catalog.add('hello', MsgOrigin('/path/to/filename', 1))
+ catalog.add('hello', MsgOrigin('/path/to/filename', 2))
+ catalog.add('hello', MsgOrigin('/path/to/yetanother', 1))
+ catalog.add('world', MsgOrigin('/path/to/filename', 1))
+
+ assert len(list(catalog)) == 2
+
+ msg1, msg2 = list(catalog)
+ assert msg1.text == 'hello'
+ assert msg1.locations == [('/path/to/filename', 1),
+ ('/path/to/filename', 2),
+ ('/path/to/yetanother', 1)]
+ assert msg2.text == 'world'
+ assert msg2.locations == [('/path/to/filename', 1)]
+
+
@pytest.mark.sphinx('gettext', srcdir='root-gettext')
def test_build_gettext(app):
# Generic build; should fail only when the builder is horribly broken.