Commit | Line | Data |
---|---|---|
7418ec5b VN |
1 | # SPDX-License-Identifier: GPL-2.0 |
2 | # | |
3 | # Copyright © 2023, Oracle and/or its affiliates. | |
4 | # Author: Vegard Nossum <vegard.nossum@oracle.com> | |
5 | # | |
6 | # Add translation links to the top of the document. | |
7 | # | |
8 | ||
9 | import os | |
10 | ||
11 | from docutils import nodes | |
12 | from docutils.transforms import Transform | |
13 | ||
14 | import sphinx | |
15 | from sphinx import addnodes | |
16 | from sphinx.errors import NoUri | |
17 | ||
18 | all_languages = { | |
19 | # English is always first | |
20 | None: 'English', | |
21 | ||
22 | # Keep the rest sorted alphabetically | |
23 | 'zh_CN': 'Chinese (Simplified)', | |
24 | 'zh_TW': 'Chinese (Traditional)', | |
25 | 'it_IT': 'Italian', | |
26 | 'ja_JP': 'Japanese', | |
27 | 'ko_KR': 'Korean', | |
28 | 'sp_SP': 'Spanish', | |
29 | } | |
30 | ||
31 | class LanguagesNode(nodes.Element): | |
32 | def __init__(self, current_language, *args, **kwargs): | |
33 | super().__init__(*args, **kwargs) | |
34 | ||
35 | self.current_language = current_language | |
36 | ||
37 | class TranslationsTransform(Transform): | |
38 | default_priority = 900 | |
39 | ||
40 | def apply(self): | |
41 | app = self.document.settings.env.app | |
42 | docname = self.document.settings.env.docname | |
43 | ||
44 | this_lang_code = None | |
45 | components = docname.split(os.sep) | |
46 | if components[0] == 'translations' and len(components) > 2: | |
47 | this_lang_code = components[1] | |
48 | ||
49 | # normalize docname to be the untranslated one | |
50 | docname = os.path.join(*components[2:]) | |
51 | ||
52 | new_nodes = LanguagesNode(all_languages[this_lang_code]) | |
53 | ||
54 | for lang_code, lang_name in all_languages.items(): | |
55 | if lang_code == this_lang_code: | |
56 | continue | |
57 | ||
58 | if lang_code is None: | |
59 | target_name = docname | |
60 | else: | |
61 | target_name = os.path.join('translations', lang_code, docname) | |
62 | ||
63 | pxref = addnodes.pending_xref('', refdomain='std', | |
64 | reftype='doc', reftarget='/' + target_name, modname=None, | |
65 | classname=None, refexplicit=True) | |
66 | pxref += nodes.Text(lang_name) | |
67 | new_nodes += pxref | |
68 | ||
69 | self.document.insert(0, new_nodes) | |
70 | ||
71 | def process_languages(app, doctree, docname): | |
72 | for node in doctree.traverse(LanguagesNode): | |
73 | if app.builder.format not in ['html']: | |
74 | node.parent.remove(node) | |
75 | continue | |
76 | ||
77 | languages = [] | |
78 | ||
79 | # Iterate over the child nodes; any resolved links will have | |
80 | # the type 'nodes.reference', while unresolved links will be | |
81 | # type 'nodes.Text'. | |
82 | languages = list(filter(lambda xref: | |
83 | isinstance(xref, nodes.reference), node.children)) | |
84 | ||
85 | html_content = app.builder.templates.render('translations.html', | |
86 | context={ | |
87 | 'current_language': node.current_language, | |
88 | 'languages': languages, | |
89 | }) | |
90 | ||
91 | node.replace_self(nodes.raw('', html_content, format='html')) | |
92 | ||
93 | def setup(app): | |
94 | app.add_node(LanguagesNode) | |
95 | app.add_transform(TranslationsTransform) | |
96 | app.connect('doctree-resolved', process_languages) | |
97 | ||
98 | return { | |
99 | 'parallel_read_safe': True, | |
100 | 'parallel_write_safe': True, | |
101 | } |