[IMP] portal, *: move language switcher to portal

*: base, http_routing, website

Make the language switcher available on portal without website
installed.

Part of https://github.com/odoo/odoo/pull/55300
task-2203383

Co-authored-by: Jeremy Kersten <jke@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
This commit is contained in:
fja-odoo
2020-08-14 17:40:58 +00:00
committed by qsm-odoo
co-authored by Jeremy Kersten qsm-odoo
parent 0b2f2b5d96
commit 704bcc5527
13 changed files with 102 additions and 56 deletions
+3 -4
View File
@@ -147,7 +147,7 @@ def url_lang(path_or_uri, lang_code=None):
# relative URL with either a path or a force_lang
if not url.netloc and not url.scheme and (url.path or force_lang):
location = werkzeug.urls.url_join(request.httprequest.path, location)
lang_url_codes = [url_code for _, url_code, _ in Lang.get_available()]
lang_url_codes = [url_code for _, url_code, *_ in Lang.get_available()]
lang_code = pycompat.to_text(lang_code or request.context['lang'])
lang_url_code = Lang._lang_code_to_urlcode(lang_code)
lang_url_code = lang_url_code if lang_url_code in lang_url_codes else lang_code
@@ -208,7 +208,7 @@ def is_multilang_url(local_url, lang_url_codes=None):
2. If not matching 1., everything not under /static/ will be translatable
'''
if not lang_url_codes:
lang_url_codes = [url_code for _, url_code, _ in request.env['res.lang'].get_available()]
lang_url_codes = [url_code for _, url_code, *_ in request.env['res.lang'].get_available()]
spath = local_url.split('/')
# if a language is already in the path, remove it
if spath[1] in lang_url_codes:
@@ -388,8 +388,7 @@ class IrHttp(models.AbstractModel):
path = request.httprequest.path.split('/')
is_a_bot = cls.is_a_bot()
available_langs = Lang.get_available()
lang_codes = [code for code, _, _ in available_langs]
lang_codes = [code for code, *_ in Lang.get_available()]
nearest_lang = not func and cls.get_nearest_lang(Lang._lang_get_code(path[1]))
cook_lang = request.httprequest.cookies.get('frontend_lang')
cook_lang = cook_lang in lang_codes and cook_lang
+1
View File
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import ir_http
from . import ir_ui_view
from . import mail_thread
from . import mail_message
from . import portal_mixin
+7
View File
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
from odoo.http import request
class IrHttp(models.AbstractModel):
@@ -11,3 +12,9 @@ class IrHttp(models.AbstractModel):
def _get_translation_frontend_modules_name(cls):
mods = super(IrHttp, cls)._get_translation_frontend_modules_name()
return mods + ['portal']
@classmethod
def _get_frontend_langs(cls):
if request and request.is_frontend:
return [lang[0] for lang in filter(lambda l: l[3], request.env['res.lang'].get_available())]
return super()._get_frontend_langs()
+26
View File
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models
from odoo.http import request
from odoo.addons.http_routing.models.ir_http import url_for
class View(models.Model):
_inherit = "ir.ui.view"
@api.model
def _prepare_qcontext(self):
""" Returns the qcontext : rendering context with portal specific value (required
to render portal layout template)
"""
qcontext = super(View, self)._prepare_qcontext()
if request and getattr(request, 'is_frontend', False):
Lang = request.env['res.lang']
portal_lang_code = request.env['ir.http']._get_frontend_langs()
qcontext.update(dict(
self._context.copy(),
languages=[lang for lang in Lang.get_available() if lang[0] in portal_lang_code],
url_for=url_for,
))
return qcontext
+16
View File
@@ -535,3 +535,19 @@ form label {
}
}
}
// Copyright
.o_footer_copyright {
.js_language_selector {
display: inline-block;
}
@include media-breakpoint-up(md) {
.row {
display: flex;
> div {
margin: auto 0;
}
}
}
}
+26
View File
@@ -40,6 +40,32 @@
</div>
</div>
</xpath>
<xpath expr="//*[hasclass('o_footer_copyright_name')]" position="after">
<t t-call="portal.language_selector"/>
</xpath>
</template>
<template id="language_selector" name="Language Selector">
<t t-set="language_selector_visible" t-value="len(languages) &gt; 1"/>
<ul class="js_language_selector mb0 list-inline" t-if="language_selector_visible">
<li class="list-inline-item">
<div class="dropup">
<button class="btn btn-sm btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span t-esc="list(filter(lambda lg : lg[0] == lang, languages))[0][2].split('/').pop()"/>
<span class="caret ml4"/>
</button>
<div class="dropdown-menu" role="menu">
<t t-foreach="languages" t-as="lg">
<a t-att-href="url_for(request.httprequest.path + '?' + keep_query(), lang_code=lg[0])"
class="dropdown-item js_change_lang"
t-att-data-url_code="lg[1]">
<t t-esc="lg[2].split('/').pop()"/>
</a>
</t>
</div>
</div>
</li>
</ul>
</template>
<template id="portal_breadcrumbs" name="Portal Breadcrumbs">
+1 -1
View File
@@ -216,7 +216,7 @@ class Http(models.AbstractModel):
@classmethod
def _get_frontend_langs(cls):
if get_request_website():
return [code for code, _, _ in request.env['res.lang'].get_available()]
return [code for code, *_ in request.env['res.lang'].get_available()]
else:
return super()._get_frontend_langs()
-4
View File
@@ -9,7 +9,6 @@ import werkzeug
from odoo import api, fields, models
from odoo import tools
from odoo.addons import website
from odoo.addons.http_routing.models.ir_http import url_for
from odoo.exceptions import AccessError
from odoo.osv import expression
from odoo.http import request
@@ -431,13 +430,10 @@ class View(models.Model):
]
qcontext.update(dict(
self._context.copy(),
main_object=self,
website=request.website,
is_view_active=request.website.is_view_active,
url_for=url_for,
res_company=request.website.company_id.sudo(),
languages=request.env['res.lang'].get_available(),
translatable=translatable,
editable=editable,
))
+4 -4
View File
@@ -19,8 +19,8 @@ class Lang(models.Model):
@api.model
@tools.ormcache_context(keys=("website_id",))
def get_available(self):
""" Return the available languages as a list of (code, name) sorted by name. """
website = ir_http.get_request_website()
if website:
return sorted([(lang.code, lang.url_code, lang.name) for lang in request.website.language_ids])
return super(Lang, self).get_available()
if not website:
return super().get_available()
# Return the website-available ones in this case
return request.website.language_ids.get_sorted()
@@ -864,22 +864,6 @@ header {
}
}
// Copyright
.o_footer_copyright {
.js_language_selector {
display: inline-block;
}
@include media-breakpoint-up(md) {
.row {
display: flex;
> div {
margin: auto 0;
}
}
}
}
// Figure with special style
.o_figure_relative_layout {
position: relative;
+9 -23
View File
@@ -156,9 +156,6 @@
<!-- Background now controlled by css configuration, using color combinations -->
<attribute name="class" add="o_colored_level o_cc" separator=" "/>
</xpath>
<xpath expr="//div[hasclass('o_footer_copyright')]//span[hasclass('o_footer_copyright_name')]" position="after">
<t t-call="website.language_selector"/>
</xpath>
<xpath expr="//t[@t-call='web.brand_promotion']/.." position="attributes">
<attribute name="class" add="o_not_editable" separator=" "/>
<attribute name="t-if">not editable</attribute>
@@ -594,25 +591,14 @@
</xpath>
</template>
<template id="language_selector" name="Language Selector">
<ul class="js_language_selector mb0 list-inline" t-if="(request and request.is_frontend_multilang and len(languages) &gt; 1) or (website and (editable or translatable))">
<li class="list-inline-item">
<div class="dropup">
<button class="btn btn-sm btn-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span t-esc="list(filter(lambda lg : lg[0] == lang, languages))[0][2].split('/').pop()"/>
<span class="caret ml4"/>
</button>
<div class="dropdown-menu" role="menu">
<t t-foreach="languages" t-as="lg">
<a t-att-href="url_for(request.httprequest.path + '?' + keep_query(), lang_code=lg[0])"
class="dropdown-item js_change_lang"
t-att-data-url_code="lg[1]">
<t t-esc="lg[2].split('/').pop()"/>
</a>
</t>
</div>
</div>
</li>
<template id="language_selector" inherit_id="portal.language_selector">
<!-- Always show the language selector on editable websites -->
<xpath expr="//t[@t-set='language_selector_visible']" position="after">
<t t-set="language_selector_visible" t-value="language_selector_visible or (website and (editable or translatable))"/>
</xpath>
<!-- Add the button to add a language -->
<xpath expr="//ul/li" position="after">
<li groups="website.group_website_publisher" class="list-inline-item">
<t t-set="url_return" t-value="quote_plus(url_for('', '[lang]') + '?' + keep_query())"/>
<a class="d-none d-sm-block" t-attf-href="/web#action=base.action_view_base_language_install&amp;website_id=#{website.id if website else ''}&amp;url_return=#{url_return}">
@@ -620,7 +606,7 @@
Add a language...
</a>
</li>
</ul>
</xpath>
</template>
<template id="record_cover">
+8 -3
View File
@@ -209,9 +209,14 @@ class Lang(models.Model):
@api.model
@tools.ormcache()
def get_available(self):
""" Return the available languages as a list of (code, name) sorted by name. """
""" Return the available languages as a list of (code, url_code, name,
active) sorted by name.
"""
langs = self.with_context(active_test=False).search([])
return sorted([(lang.code, lang.url_code, lang.name) for lang in langs], key=itemgetter(2))
return langs.get_sorted()
def get_sorted(self):
return sorted([(lang.code, lang.url_code, lang.name, lang.active) for lang in self], key=itemgetter(2))
@tools.ormcache('self.id')
def _get_cached_values(self):
@@ -229,7 +234,7 @@ class Lang(models.Model):
@api.model
@tools.ormcache('code')
def _lang_code_to_urlcode(self, code):
for c, urlc, name in self.get_available():
for c, urlc, name, *_ in self.get_available():
if c == code:
return urlc
return self._lang_get(code).url_code
@@ -20,7 +20,7 @@ class BaseLanguageInstall(models.TransientModel):
@api.model
def _get_languages(self):
return [[code, name] for code, _, name in self.env['res.lang'].get_available()]
return [[code, name] for code, _, name, *_ in self.env['res.lang'].get_available()]
lang = fields.Selection(_get_languages, string='Language', required=True,
default=_default_language)