refactor versions and languages switchers logic + canonical urls + Makefile
This commit is contained in:
parent
936fae4b40
commit
c1f2fc9cd3
8
Makefile
8
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
|
||||
|
171
conf.py
171
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/', ''),
|
||||
)
|
||||
|
@ -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:
|
||||
|
@ -38,8 +38,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block linktags %}
|
||||
{% for code, url in language_codes %}
|
||||
<link rel="alternate" hreflang="{{ code }}" href="{{ url }}" />
|
||||
{% for alternate_language, language_code, url in alternate_languages %}
|
||||
<link rel="alternate" hreflang="{{ language_code }}" href="{{ url }}" />
|
||||
{%- endfor %}
|
||||
<link rel="canonical" href="{{ canonical }}" />
|
||||
{{ super() }}
|
||||
|
@ -8,7 +8,11 @@
|
||||
</div>
|
||||
{% include "layout_templates/searchbox.html" %}
|
||||
<div class="d-none d-md-flex">
|
||||
{% include "layout_templates/lang_switcher.html" %}
|
||||
{% include "layout_templates/version_switcher.html" %}
|
||||
{#{% if alternate_languages %}#}
|
||||
{% include "layout_templates/language_switcher.html" %}
|
||||
{#{% endif %}#}
|
||||
{#{% if alternate_versions %}#}
|
||||
{% include "layout_templates/version_switcher.html" %}
|
||||
{#{% endif %}#}
|
||||
<a class="btn btn-primary fw_semibold" href="https://odoo.com/trial">Try Odoo for FREE</a>
|
||||
</div>
|
@ -1,17 +0,0 @@
|
||||
{% if languages %}
|
||||
<div class="o_languages me-2">
|
||||
<select class="languages form-select">
|
||||
<!-- <a class="dropdown-toggle" href="#" data-toggle="dropdown">
|
||||
English
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ url }}">English</a></li>
|
||||
<li><a href="{{ url }}">French</a></li>
|
||||
</ul> -->
|
||||
<option>{{ language }}</option> {# Current language #}
|
||||
{% for name, url in languages %}
|
||||
<option><a href="{{ url }}">{{ name }}</a></option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
@ -0,0 +1,22 @@
|
||||
<div class="o_languages me-2">
|
||||
{# <!-- TODO EDI <a> inside <option> is illegal
|
||||
<select class="languages form-select">
|
||||
<a class="dropdown-toggle" href="#" data-toggle="dropdown">
|
||||
English
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{ url }}">English</a></li>
|
||||
<li><a href="{{ url }}">French</a></li>
|
||||
</ul>
|
||||
<option>{{ language }}</option> {# The current language #}
|
||||
{% for alternate_language, language_code, url in alternate_languages %}
|
||||
<option><a href="{{ url }}">{{ alternate_language }}</a></option>
|
||||
{% endfor %}
|
||||
</select> --> #}
|
||||
<div>
|
||||
<a>{{ language }}</a> {# The current language #}
|
||||
{% for alternate_language, language_code, url in alternate_languages %}
|
||||
<a href="{{ url }}">{{ alternate_language }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
@ -3,11 +3,18 @@
|
||||
<label class="fw_bold small mr-2">Version</label>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
{# <!-- TODO EDI <a> inside <option> is illegal
|
||||
<select class="form-select">
|
||||
<option>{{ version }}</option> {# Current version #}
|
||||
{% for name, url in versions %}
|
||||
<option><a href="{{ url }}">{{ name }}</a></option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<option>{{ version }}</option> {# The current version #}
|
||||
{% for alternate_version, url in versions %}
|
||||
<option><a href="{{ url }}">{{ alternate_version }}</a></option>
|
||||
{% endfor %}
|
||||
</select> --> #}
|
||||
<div>
|
||||
<a>{{ version }}</a> {# The current version #}
|
||||
{% for alternate_version, url in alternate_versions %}
|
||||
<a href="{{ url }}">{{ alternate_version }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user