summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2022-01-13 01:39:14 +0900
committerGitHub <noreply@github.com>2022-01-13 01:39:14 +0900
commit14821a97773b21a3a104bfdea5f660396541ca43 (patch)
treea6c26f2b06699752e6ced3be07aaabb5966f394a
parent3ed92651d5c14343a127fcbcdcf5e44fcc6fc214 (diff)
parent0269bec1ed3a8492427048152770e13bb24d06f0 (diff)
downloadsphinx-git-14821a97773b21a3a104bfdea5f660396541ca43.tar.gz
Merge pull request #10091 from Jean-Abou-Samra/sorted-glossary
In translated docs, sort glossaries by translated terms
-rw-r--r--doc/usage/restructuredtext/directives.rst3
-rw-r--r--sphinx/domains/std.py16
-rw-r--r--sphinx/transforms/__init__.py22
-rw-r--r--tests/roots/test-intl/glossary_terms.txt15
-rw-r--r--tests/roots/test-intl/xx/LC_MESSAGES/glossary_terms.po94
-rw-r--r--tests/test_intl.py30
6 files changed, 125 insertions, 55 deletions
diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst
index 2a9743e94..bd1b1a3c6 100644
--- a/doc/usage/restructuredtext/directives.rst
+++ b/doc/usage/restructuredtext/directives.rst
@@ -831,6 +831,9 @@ Glossary
.. versionchanged:: 1.4
Index key for glossary term should be considered *experimental*.
+ .. versionchanged:: 4.4
+ In internationalized documentation, the ``:sorted:`` flag sorts
+ according to translated terms.
Meta-information markup
-----------------------
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 11a95e13b..82803597d 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -9,7 +9,6 @@
"""
import re
-import unicodedata
import warnings
from copy import copy
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional,
@@ -336,6 +335,7 @@ class Glossary(SphinxDirective):
def run(self) -> List[Node]:
node = addnodes.glossary()
node.document = self.state.document
+ node['sorted'] = ('sorted' in self.options)
# This directive implements a custom format of the reST definition list
# that allows multiple lines of terms before the definition. This is
@@ -400,9 +400,8 @@ class Glossary(SphinxDirective):
was_empty = False
# now, parse all the entries into a big definition list
- items = []
+ items: List[nodes.definition_list_item] = []
for terms, definition in entries:
- termtexts: List[str] = []
termnodes: List[Node] = []
system_messages: List[Node] = []
for line, source, lineno in terms:
@@ -416,7 +415,6 @@ class Glossary(SphinxDirective):
node_id=None, document=self.state.document)
term.rawsource = line
system_messages.extend(sysmsg)
- termtexts.append(term.astext())
termnodes.append(term)
termnodes.extend(system_messages)
@@ -426,16 +424,10 @@ class Glossary(SphinxDirective):
self.state.nested_parse(definition, definition.items[0][1],
defnode)
termnodes.append(defnode)
- items.append((termtexts,
- nodes.definition_list_item('', *termnodes)))
+ items.append(nodes.definition_list_item('', *termnodes))
- if 'sorted' in self.options:
- items.sort(key=lambda x:
- unicodedata.normalize('NFD', x[0][0].lower()))
-
- dlist = nodes.definition_list()
+ dlist = nodes.definition_list('', *items)
dlist['classes'].append('glossary')
- dlist.extend(item[1] for item in items)
node += dlist
return messages + [node]
diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py
index f1359dfad..26e075a7a 100644
--- a/sphinx/transforms/__init__.py
+++ b/sphinx/transforms/__init__.py
@@ -9,8 +9,9 @@
"""
import re
+import unicodedata
import warnings
-from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Tuple
+from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node, Text
@@ -405,6 +406,24 @@ class ManpageLink(SphinxTransform):
node.attributes.update(info)
+class GlossarySorter(SphinxTransform):
+ """Sort glossaries that have the ``sorted`` flag."""
+ # This must be done after i18n, therefore not right
+ # away in the glossary directive.
+ default_priority = 500
+
+ def apply(self, **kwargs: Any) -> None:
+ for glossary in self.document.findall(addnodes.glossary):
+ if glossary["sorted"]:
+ definition_list = cast(nodes.definition_list, glossary[0])
+ definition_list[:] = sorted(
+ definition_list,
+ key=lambda item: unicodedata.normalize(
+ 'NFD',
+ cast(nodes.term, item)[0].astext().lower())
+ )
+
+
def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_transform(ApplySourceWorkaround)
app.add_transform(ExtraTranslatableNodes)
@@ -420,6 +439,7 @@ def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_transform(SphinxSmartQuotes)
app.add_transform(DoctreeReadEvent)
app.add_transform(ManpageLink)
+ app.add_transform(GlossarySorter)
return {
'version': 'builtin',
diff --git a/tests/roots/test-intl/glossary_terms.txt b/tests/roots/test-intl/glossary_terms.txt
index a6e16c948..473d857e7 100644
--- a/tests/roots/test-intl/glossary_terms.txt
+++ b/tests/roots/test-intl/glossary_terms.txt
@@ -12,3 +12,18 @@ i18n with glossary terms
The corresponding glossary #2
link to :term:`Some term`.
+
+Translated glossary should be sorted by translated terms:
+
+.. glossary::
+ :sorted:
+
+ AAA
+ Define AAA
+
+ CCC
+ EEE
+ Define CCC
+
+ BBB
+ Define BBB
diff --git a/tests/roots/test-intl/xx/LC_MESSAGES/glossary_terms.po b/tests/roots/test-intl/xx/LC_MESSAGES/glossary_terms.po
index 2746655ee..83542f1c3 100644
--- a/tests/roots/test-intl/xx/LC_MESSAGES/glossary_terms.po
+++ b/tests/roots/test-intl/xx/LC_MESSAGES/glossary_terms.po
@@ -1,35 +1,59 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) 2012, foof
-# This file is distributed under the same license as the foo package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: sphinx 1.0\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-01-29 14:10+0000\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"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "i18n with glossary terms"
-msgstr "I18N WITH GLOSSARY TERMS"
-
-msgid "Some term"
-msgstr "SOME NEW TERM"
-
-msgid "The corresponding glossary"
-msgstr "THE CORRESPONDING GLOSSARY"
-
-msgid "Some other term"
-msgstr "SOME OTHER NEW TERM"
-
-msgid "The corresponding glossary #2"
-msgstr "THE CORRESPONDING GLOSSARY #2"
-
-msgid "link to :term:`Some term`."
-msgstr "LINK TO :term:`SOME NEW TERM`."
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2012, foof
+# This file is distributed under the same license as the foo package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sphinx 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-01-29 14:10+0000\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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "i18n with glossary terms"
+msgstr "I18N WITH GLOSSARY TERMS"
+
+msgid "Some term"
+msgstr "SOME NEW TERM"
+
+msgid "The corresponding glossary"
+msgstr "THE CORRESPONDING GLOSSARY"
+
+msgid "Some other term"
+msgstr "SOME OTHER NEW TERM"
+
+msgid "The corresponding glossary #2"
+msgstr "THE CORRESPONDING GLOSSARY #2"
+
+msgid "link to :term:`Some term`."
+msgstr "LINK TO :term:`SOME NEW TERM`."
+
+msgid "Translated glossary should be sorted by translated terms:"
+msgstr "TRANSLATED GLOSSARY SHOULD BE SORTED BY TRANSLATED TERMS:"
+
+msgid "BBB"
+msgstr "TRANSLATED TERM XXX"
+
+msgid "Define BBB"
+msgstr "DEFINE XXX"
+
+msgid "AAA"
+msgstr "TRANSLATED TERM YYY"
+
+msgid "Define AAA"
+msgstr "DEFINE YYY"
+
+msgid "CCC"
+msgstr "TRANSLATED TERM ZZZ"
+
+msgid "EEE"
+msgstr "VVV"
+
+msgid "Define CCC"
+msgstr "DEFINE ZZZ"
diff --git a/tests/test_intl.py b/tests/test_intl.py
index f84e72a84..92d7badf4 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -241,13 +241,29 @@ def test_text_glossary_term(app, warning):
app.build()
# --- glossary terms: regression test for #1090
result = (app.outdir / 'glossary_terms.txt').read_text()
- expect = ("18. I18N WITH GLOSSARY TERMS"
- "\n****************************\n"
- "\nSOME NEW TERM"
- "\n THE CORRESPONDING GLOSSARY\n"
- "\nSOME OTHER NEW TERM"
- "\n THE CORRESPONDING GLOSSARY #2\n"
- "\nLINK TO *SOME NEW TERM*.\n")
+ expect = (r"""18. I18N WITH GLOSSARY TERMS
+****************************
+
+SOME NEW TERM
+ THE CORRESPONDING GLOSSARY
+
+SOME OTHER NEW TERM
+ THE CORRESPONDING GLOSSARY #2
+
+LINK TO *SOME NEW TERM*.
+
+TRANSLATED GLOSSARY SHOULD BE SORTED BY TRANSLATED TERMS:
+
+TRANSLATED TERM XXX
+ DEFINE XXX
+
+TRANSLATED TERM YYY
+ DEFINE YYY
+
+TRANSLATED TERM ZZZ
+VVV
+ DEFINE ZZZ
+""")
assert result == expect
warnings = getwarning(warning)
assert 'term not in glossary' not in warnings