diff --git a/Makefile b/Makefile index 349f6fd0a..aa8def898 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,9 @@ SPHINX_BUILD = sphinx-build CONFIG_DIR = . -SPHINXOPTS = -A google_analytics_key=$(GOOGLE_ANALYTICS_KEY) +SPHINXOPTS = -D project_root=$(ROOT) -D canonical_version=$(CANONICAL_VERSION) \ + -D versions=$(VERSIONS) -D languages=$(LANGUAGES) -D language=$(CURRENT_LANG) \ + -A google_analytics_key=$(GOOGLE_ANALYTICS_KEY) SOURCE_DIR = content BUILD_DIR = _build @@ -29,6 +31,10 @@ clean: @echo "Cleaning finished." edi: SPHINXOPTS += -A collapse_menu=True +edi: VERSIONS += 12.0,13.0,14.0 +edi: CANONICAL_VERSION += 14.0 +edi: LANGUAGES += en,fr,es +edi: CURRENT_LANG += fr edi: clean html html: extensions/odoo_theme/static/style.css diff --git a/conf.py b/conf.py index c3de7fc75..f88a88484 100644 --- a/conf.py +++ b/conf.py @@ -1,4 +1,3 @@ -import os import sys from pathlib import Path @@ -11,6 +10,10 @@ _logger = logging.getLogger(__name__) #=== General configuration ===# +# General information about the project. +project = 'odoo' +copyright = 'Odoo S.A.' + # `version` if the version info for the project being documented, acts as replacement for |version|, # also used in various other places throughout the built documents. # `release` is the full version, including alpha/beta/rc tags. Acts as replacement for |release|. @@ -19,20 +22,16 @@ version = release = '12.0' # The minimal Sphinx version required to build the documentation. needs_sphinx = '3.0.0' +# The default language in which the documentation is written. It is set as `None` because Sphinx +# considers that no language means 'en'. +language = None + # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' -# General information about the project. -project = 'odoo' -copyright = 'Odoo S.A.' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - # List of patterns, relative to source directory, that match files and directories to ignore when # looking for source files. exclude_patterns = [ @@ -128,7 +127,7 @@ github_user = 'odoo' github_project = 'documentation-user' locale_dirs = ['locale/'] -LANGUAGES = { +supported_languages = { 'de': 'German', 'en': 'English', 'es': 'Spanish', @@ -244,41 +243,90 @@ latex_documents = [ latex_logo = 'static/img/odoo_logo.png' # If true, show URL addresses after external links. -latex_show_urls = "True" +latex_show_urls = 'True' def setup(app): - app.connect('html-page-context', canonicalize) - # VFE TODO remove default before merge - app.add_config_value('canonical_root', os.path.dirname(os.path.realpath(__file__)), 'env') - app.add_config_value('canonical_branch', 'master', 'env') + # Generate all alternate URLs for each document + app.add_config_value('project_root', None, 'env') + app.add_config_value('canonical_version', None, 'env') + app.add_config_value('versions', None, 'env') + app.add_config_value('languages', None, 'env') + app.connect('html-page-context', _generate_alternate_urls) - app.connect('html-page-context', versionize) - # VFE TODO before merge, remove the default value put for testing - test_versions = ['12.0', '13.0', '14.0'] # TODO if not provided, use 'local' - app.add_config_value('versions', ",".join(test_versions), 'env') - - app.connect('html-page-context', localize) - # VFE TODO before merge remove the default value put for testing - test_languages = ['fr', 'en', 'es'] - app.add_config_value('languages', ",".join(test_languages), 'env') - - app.connect('doctree-resolved', tag_toctrees) # TODO ANVFE not used + typo + app.connect('doctree-resolved', tag_toctrees) # TODO ANVFE review + typo -def versionize(app, pagename, templatename, context, doctree): - """ Adds a version switcher below the menu, requires ``canonical_root`` - and ``versions`` (an ordered, space-separated lists of all possible - versions). +def _generate_alternate_urls(app, pagename, templatename, context, doctree): + """ Add keys of required alternate URLs for the current document in the rendering context. + + Alternate URLS are required for: + - The canonical link tag + - The version switcher + - The language switcher and related link tags """ - if not (app.config.canonical_root and app.config.versions): - return - context['versions'] = [ - (vs, _build_url(app.config.canonical_root, vs, pagename)) - for vs in app.config.versions.split(',') - if vs != app.config.version - ] + def _canonicalize(): + """ Add the canonical URL for the current document in the rendering context. + + The canonical version is the last released version of the documentation. + For a given language, the canonical root of a page is in the same language so that web + searches in that language don't redirect users to the english version of that page. + + E.g.: + - /documentation/sale.html -> canonical = /documentation/14.0/sale.html + - /documentation/11.0/fr/website.html -> canonical = /documentation/14.0/fr/website.html + """ + # If the canonical version is not set, assume that the project has a single version + _canonical_version = app.config.canonical_version or version + _canonical_lang = 'en' # Always 'en'. Don't take the value of the config option. + context['canonical'] = _build_url(_version=_canonical_version, _lang=_canonical_lang) + + def _versionize(): + """ Add the pairs of (version, url) for the current document in the rendering context. + + The entry 'version' is added by Sphinx in the rendering context. + """ + # If the list of versions is not set, assume that the project has no alternate version + _alternate_versions = app.config.versions and app.config.versions.split(',') or [] + context['alternate_versions'] = [ + (_alternate_version, _build_url(_version=_alternate_version)) + for _alternate_version in _alternate_versions if _alternate_version != version + ] + + def _localize(): + """ + + The entry 'language' is added by Sphinx in the rendering context. + + """ + _current_lang = app.config.language or 'en' + # Replace the context value by its translated description ("Français" instead of "french") + context['language'] = supported_languages.get(_current_lang) + + # If the list of languages is not set, assume that the project has no alternate language + _alternate_languages = app.config.languages and app.config.languages.split(',') or [] + context['alternate_languages'] = [ + ( + supported_languages.get(_alternate_lang), + _alternate_lang.split('_')[0] if _alternate_lang != 'en' else 'x-default', + _build_url(_lang=_alternate_lang), + ) + for _alternate_lang in _alternate_languages + if _alternate_lang in supported_languages and _alternate_lang != _current_lang + ] + + def _build_url(_version=None, _lang=None): + _root = app.config.project_root or str(Path(__file__).parent) + _version = _version or version + _lang = _lang or app.config.language or 'en' + _canonical_page = (pagename + '.html').replace('index.html', '').replace('index/', '') + return f'{_root}/{_version}{f"/{_lang}" if _lang != "en" else ""}/{_canonical_page}' + + _canonicalize() + _versionize() + _localize() + def tag_toctrees(app, doctree, docname): """Add a 'is-toc-page' metadata entry to all documents containing only a toctree node""" @@ -287,7 +335,7 @@ def tag_toctrees(app, doctree, docname): # title # compound@toctree-wrapper # .... - if not len(doctree.children) == 1: + if not len(doctree.children) <= 1: return section = doctree.children[0] if len(section.children) < 2: @@ -297,50 +345,3 @@ def tag_toctrees(app, doctree, docname): return app.env.metadata[docname]['has_only_toc'] = True - -def localize(app, pagename, templatename, context, doctree): - """ Adds a language switcher below the menu, requires ``canonical_root`` - and ``languages`` (an ordered, space-separated lists of all possible - languages). - """ - if not (app.config.canonical_root and app.config.languages): - return - - current_lang = app.config.language or 'en' - context['language'] = LANGUAGES.get(current_lang, current_lang.upper()) - context['languages'] = [ - (LANGUAGES.get(la, la.upper()), _build_url( - app.config.canonical_root, (la != 'en' and la or ''), pagename)) - for la in app.config.languages.split(',') - if la != current_lang - ] - context['language_codes'] = [ - (la.split('_')[0] if la != 'en' else 'x-default', - _build_url(app.config.canonical_root, (la != 'en' and la or ''), pagename)) - for la in app.config.languages.split(',') - ] - -def canonicalize(app, pagename, templatename, context, doctree): - """ Adds a 'canonical' URL for the current document in the rendering - context. Requires the ``canonical_root`` setting being set. The canonical - branch is ``master`` but can be overridden using ``canonical_branch``. - /documentation/user/12.0/sale.html -> /documentation/user/13.0/sale.html - /documentation/user/11.0/fr/website.html -> /documentation/user/13.0/fr/website.html - """ - if not app.config.canonical_root: - return - - lang = app.config.language or 'en' - - context['canonical'] = _build_url( - app.config.canonical_root, app.config.canonical_branch, pagename, lang) - - -def _build_url(root, branch, pagename, lang='en'): - return "{canonical_url}{canonical_branch}{lang}/{canonical_page}".format( - canonical_url=root, - canonical_branch=branch, - lang=lang != 'en' and lang or '', - canonical_page=(pagename + '.html').replace('index.html', '') - .replace('index/', ''), - ) diff --git a/extensions/odoo_theme/__init__.py b/extensions/odoo_theme/__init__.py index 4705c7c5e..32ce1e69b 100644 --- a/extensions/odoo_theme/__init__.py +++ b/extensions/odoo_theme/__init__.py @@ -22,16 +22,15 @@ def update_meta(app, pagename, templatename, context, doctree): # TODO VFE detailed explanation of the patch logic and use. -class monkey(object): +class Monkey(object): def __init__(self, obj): self.obj = obj def __call__(self, fn): name = fn.__name__ old = getattr(self.obj, name) - setattr(self.obj, name, lambda self_, *args, **kwargs: \ - fn(old, self_, *args, **kwargs)) + setattr(self.obj, name, lambda self_, *args, **kwargs: fn(old, self_, *args, **kwargs)) -@monkey(toctree.TocTree) +@Monkey(toctree.TocTree) def resolve(old_resolve, tree, docname, *args, **kwargs): resolved_toc = old_resolve(tree, docname, *args, **kwargs) if resolved_toc: diff --git a/extensions/odoo_theme/layout.html b/extensions/odoo_theme/layout.html index 6592e8f04..e414f3743 100644 --- a/extensions/odoo_theme/layout.html +++ b/extensions/odoo_theme/layout.html @@ -38,8 +38,8 @@ {% endblock %} {% block linktags %} - {% for code, url in language_codes %} - + {% for alternate_language, language_code, url in alternate_languages %} + {%- endfor %} {{ super() }} diff --git a/extensions/odoo_theme/layout_templates/header.html b/extensions/odoo_theme/layout_templates/header.html index 10ad841e7..ffd3da28d 100644 --- a/extensions/odoo_theme/layout_templates/header.html +++ b/extensions/odoo_theme/layout_templates/header.html @@ -8,7 +8,11 @@ {% include "layout_templates/searchbox.html" %}