summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfja-odoo <fja@odoo.com>2020-08-12 15:07:13 +0000
committerqsm-odoo <qsm@odoo.com>2020-08-14 17:40:58 +0000
commit704bcc552709f3b1e024f4a7aa83743f982fd5df (patch)
tree52da8928ede4572cb0a37626d27f5a8685f5ce93
parent0b2f2b5d9632d49a384834885ef7d76b79320bd7 (diff)
[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>
-rw-r--r--addons/http_routing/models/ir_http.py7
-rw-r--r--addons/portal/models/__init__.py1
-rw-r--r--addons/portal/models/ir_http.py7
-rw-r--r--addons/portal/models/ir_ui_view.py26
-rw-r--r--addons/portal/static/src/scss/portal.scss16
-rw-r--r--addons/portal/views/portal_templates.xml26
-rw-r--r--addons/website/models/ir_http.py2
-rw-r--r--addons/website/models/ir_ui_view.py4
-rw-r--r--addons/website/models/res_lang.py8
-rw-r--r--addons/website/static/src/scss/website.scss16
-rw-r--r--addons/website/views/website_templates.xml32
-rw-r--r--odoo/addons/base/models/res_lang.py11
-rw-r--r--odoo/addons/base/wizard/base_language_install.py2
13 files changed, 102 insertions, 56 deletions
diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py
index aa072912b31..6da75e3ef61 100644
--- a/addons/http_routing/models/ir_http.py
+++ b/addons/http_routing/models/ir_http.py
@@ -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
diff --git a/addons/portal/models/__init__.py b/addons/portal/models/__init__.py
index c9f2b8d412c..1c70d12386a 100644
--- a/addons/portal/models/__init__.py
+++ b/addons/portal/models/__init__.py
@@ -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
diff --git a/addons/portal/models/ir_http.py b/addons/portal/models/ir_http.py
index 3fad96ff9f1..9320f6d4f82 100644
--- a/addons/portal/models/ir_http.py
+++ b/addons/portal/models/ir_http.py
@@ -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()
diff --git a/addons/portal/models/ir_ui_view.py b/addons/portal/models/ir_ui_view.py
new file mode 100644
index 00000000000..e51261170aa
--- /dev/null
+++ b/addons/portal/models/ir_ui_view.py
@@ -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
diff --git a/addons/portal/static/src/scss/portal.scss b/addons/portal/static/src/scss/portal.scss
index cdaccb9117c..604c0a70a25 100644
--- a/addons/portal/static/src/scss/portal.scss
+++ b/addons/portal/static/src/scss/portal.scss
@@ -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;
+ }
+ }
+ }
+}
diff --git a/addons/portal/views/portal_templates.xml b/addons/portal/views/portal_templates.xml
index 195a7c5a7cb..7cbfe33844f 100644
--- a/addons/portal/views/portal_templates.xml
+++ b/addons/portal/views/portal_templates.xml
@@ -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">
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index a3fa817754a..d29d367e5c2 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -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()
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index e62b25f7399..c7169067cbb 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -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,
))
diff --git a/addons/website/models/res_lang.py b/addons/website/models/res_lang.py
index 9fc3f69e998..3c8ee9dcb52 100644
--- a/addons/website/models/res_lang.py
+++ b/addons/website/models/res_lang.py
@@ -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()
diff --git a/addons/website/static/src/scss/website.scss b/addons/website/static/src/scss/website.scss
index 99f5fd9eef0..088ebb12b0e 100644
--- a/addons/website/static/src/scss/website.scss
+++ b/addons/website/static/src/scss/website.scss
@@ -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;
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index c74d73835ae..2d18621957f 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -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">
diff --git a/odoo/addons/base/models/res_lang.py b/odoo/addons/base/models/res_lang.py
index dcf901e1a22..f3f54eb3e96 100644
--- a/odoo/addons/base/models/res_lang.py
+++ b/odoo/addons/base/models/res_lang.py
@@ -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
diff --git a/odoo/addons/base/wizard/base_language_install.py b/odoo/addons/base/wizard/base_language_install.py
index f9f495c56f8..0d4fd9bc233 100644
--- a/odoo/addons/base/wizard/base_language_install.py
+++ b/odoo/addons/base/wizard/base_language_install.py
@@ -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)