summaryrefslogtreecommitdiff
path: root/addons/website
diff options
context:
space:
mode:
authorRomain Derie <rde@odoo.com>2019-03-26 05:56:55 +0000
committerRomain Derie <rde@odoo.com>2019-08-26 16:35:19 +0000
commit269aa594111a152ad4b7714856ea745bfef57155 (patch)
treed5f8f7e86209102d831b2e222038d45bd7fe7626 /addons/website
parentf10f120de3017bc8d0e9a5ac72eeec1280374a1d (diff)
[IMP] http_routing, website: allow to customize the lang in URL
With this commit it is now possible to change the lang displayed in the URL. Eg, you could use `/fr` instead of `/fr_BE`, or even a fancier `/french`. Task-32838 Courtesy of pla@odoo.com closes odoo/odoo#35135 Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Diffstat (limited to 'addons/website')
-rw-r--r--addons/website/controllers/main.py6
-rw-r--r--addons/website/models/ir_http.py16
-rw-r--r--addons/website/models/ir_qweb.py5
-rw-r--r--addons/website/models/ir_ui_view.py6
-rw-r--r--addons/website/models/res_config_settings.py12
-rw-r--r--addons/website/models/res_lang.py13
-rw-r--r--addons/website/models/website.py22
-rw-r--r--addons/website/models/website_visitor.py3
-rw-r--r--addons/website/static/src/js/content/website_root.js2
-rw-r--r--addons/website/static/src/js/menu/seo.js4
-rw-r--r--addons/website/static/src/js/menu/translate.js7
-rw-r--r--addons/website/static/src/xml/website.seo.xml2
-rw-r--r--addons/website/static/tests/tours/rte.js8
-rw-r--r--addons/website/tests/__init__.py9
-rw-r--r--addons/website/tests/test_lang_url.py34
-rw-r--r--addons/website/tests/test_qweb.py34
-rw-r--r--addons/website/tools.py12
-rw-r--r--addons/website/views/website_templates.xml10
18 files changed, 117 insertions, 88 deletions
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index a1cca57919f..f91870adfaf 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -107,10 +107,14 @@ class Website(Home):
# Business
# ------------------------------------------------------
+ @http.route('/website/get_languages', type='json', auth="user", website=True)
+ def website_languages(self, **kwargs):
+ return [(lg.code, lg.url_code, lg.name) for lg in request.website.language_ids]
+
@http.route('/website/lang/<lang>', type='http', auth="public", website=True, multilang=False)
def change_lang(self, lang, r='/', **kwargs):
if lang == 'default':
- lang = request.website.default_lang_code
+ lang = request.website.default_lang_id.url_code
r = '/%s%s' % (lang, r or '/')
redirect = werkzeug.utils.redirect(r or ('/%s' % lang), 303)
redirect.set_cookie('frontend_lang', lang)
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 58c15a8128c..ecacdc62bac 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -15,7 +15,7 @@ import odoo
from odoo import api, models, registry
from odoo import SUPERUSER_ID
from odoo.http import request
-from odoo.tools import config
+from odoo.tools import config, ormcache
from odoo.tools.safe_eval import safe_eval
from odoo.osv.expression import FALSE_DOMAIN, OR
@@ -133,18 +133,6 @@ class Http(models.AbstractModel):
request.website = request.website.with_context(request.context)
@classmethod
- def _get_languages(cls):
- if getattr(request, 'website', False):
- return request.website.language_ids
- return super(Http, cls)._get_languages()
-
- @classmethod
- def _get_language_codes(cls):
- if getattr(request, 'website', False):
- return request.website._get_languages()
- return super(Http, cls)._get_language_codes()
-
- @classmethod
def _get_default_lang(cls):
if getattr(request, 'website', False):
return request.website.default_lang_id
@@ -205,7 +193,7 @@ class Http(models.AbstractModel):
@classmethod
def _handle_exception(cls, exception):
code = 500 # default code
- is_website_request = bool(getattr(request, 'is_frontend', False) and getattr(request, 'website', False))
+ is_website_request = bool(getattr(request, 'is_frontend', False) and get_request_website())
if not is_website_request:
# Don't touch non website requests exception handling
return super(Http, cls)._handle_exception(exception)
diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py
index 0e93876be45..d3483fcb1b4 100644
--- a/addons/website/models/ir_qweb.py
+++ b/addons/website/models/ir_qweb.py
@@ -4,9 +4,10 @@ import re
from collections import OrderedDict
from odoo import models
-from odoo.addons.http_routing.models.ir_http import url_for
from odoo.http import request
from odoo.addons.base.models.assetsbundle import AssetsBundle
+from odoo.addons.http_routing.models.ir_http import url_for
+from odoo.addons.website.models import ir_http
from odoo.tools import html_escape as escape
re_background_image = re.compile(r"(background-image\s*:\s*url\(\s*['\"]?\s*)([^)'\"]+)")
@@ -47,7 +48,7 @@ class QWeb(models.AbstractModel):
options.get('edit_translations') or options.get('debug') or (request and request.session.debug):
return atts
- website = request and getattr(request, 'website', None)
+ website = ir_http.get_request_website()
if not website and options.get('website_id'):
website = self.env['website'].browse(options['website_id'])
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index 6949f173a46..6b1efe5a717 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -302,7 +302,7 @@ class View(models.Model):
if request and getattr(request, 'is_frontend', False):
editable = request.website.is_publisher()
- translatable = editable and self._context.get('lang') != request.website.default_lang_code
+ translatable = editable and self._context.get('lang') != request.website.default_lang_id.code
editable = not translatable and editable
# in edit mode ir.ui.view will tag nodes
@@ -355,7 +355,7 @@ class View(models.Model):
url_for=url_for,
res_company=request.website.company_id.sudo(),
default_lang_code=request.env['ir.http']._get_default_lang().code,
- languages=request.env['ir.http']._get_language_codes(),
+ languages=request.env['res.lang'].get_available(),
translatable=translatable,
editable=editable,
menu_data=self.env['ir.ui.menu'].load_menus_root() if request.website.is_user() else None,
@@ -367,7 +367,7 @@ class View(models.Model):
def get_default_lang_code(self):
website_id = self.env.context.get('website_id')
if website_id:
- lang_code = self.env['website'].browse(website_id).default_lang_code
+ lang_code = self.env['website'].browse(website_id).default_lang_id.code
return lang_code
else:
return super(View, self).get_default_lang_code()
diff --git a/addons/website/models/res_config_settings.py b/addons/website/models/res_config_settings.py
index 6bcae68b61f..0fff2f6eb3b 100644
--- a/addons/website/models/res_config_settings.py
+++ b/addons/website/models/res_config_settings.py
@@ -19,15 +19,11 @@ class ResConfigSettings(models.TransientModel):
website_country_group_ids = fields.Many2many(related='website_id.country_group_ids', readonly=False)
website_company_id = fields.Many2one(related='website_id.company_id', string='Website Company', readonly=False)
website_logo = fields.Binary(related='website_id.logo', readonly=False)
- language_ids = fields.Many2many(related='website_id.language_ids', relation='res.lang',
- readonly=False)
+ language_ids = fields.Many2many(related='website_id.language_ids', relation='res.lang', readonly=False)
website_language_count = fields.Integer(string='Number of languages', compute='_compute_website_language_count', readonly=True)
- website_default_lang_id = fields.Many2one(
- string='Default language', related='website_id.default_lang_id', readonly=False,
- relation='res.lang')
- website_default_lang_code = fields.Char(
- 'Default language code', related='website_id.default_lang_code', readonly=False,
- )
+ website_default_lang_id = fields.Many2one(string='Default language', related='website_id.default_lang_id',
+ readonly=False, relation='res.lang')
+ website_default_lang_code = fields.Char('Default language code', related='website_id.default_lang_id.code', readonly=False)
specific_user_account = fields.Boolean(related='website_id.specific_user_account', readonly=False,
help='Are newly created user accounts website specific')
diff --git a/addons/website/models/res_lang.py b/addons/website/models/res_lang.py
index c84a212ed5a..9fc3f69e998 100644
--- a/addons/website/models/res_lang.py
+++ b/addons/website/models/res_lang.py
@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import api, models, _
+from odoo import api, models, tools, _
+from odoo.addons.website.models import ir_http
from odoo.exceptions import UserError
+from odoo.http import request
class Lang(models.Model):
@@ -13,3 +15,12 @@ class Lang(models.Model):
if self.env['website'].search([('language_ids', 'in', self._ids)]):
raise UserError(_("Cannot deactivate a language that is currently used on a website."))
return super(Lang, self).write(vals)
+
+ @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()
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 8ce3d46568a..29398c35872 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -56,7 +56,6 @@ class Website(models.Model):
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.company, required=True)
language_ids = fields.Many2many('res.lang', 'website_lang_rel', 'website_id', 'lang_id', 'Languages', default=_active_languages)
default_lang_id = fields.Many2one('res.lang', string="Default Language", default=_default_language, required=True)
- default_lang_code = fields.Char("Default language code", related='default_lang_id.code', store=True, readonly=False)
auto_redirect_lang = fields.Boolean('Autoredirect Language', default=True, help="Should users be redirected to their browser's language")
def _default_social_facebook(self):
@@ -156,7 +155,8 @@ class Website(models.Model):
public_user_to_change_websites = self.env['website']
self._handle_favicon(values)
- self._get_languages.clear_cache(self)
+ self.clear_caches()
+
if 'company_id' in values and 'user_id' not in values:
public_user_to_change_websites = self.filtered(lambda w: w.sudo().user_id.company_id.id != values['company_id'])
if public_user_to_change_websites:
@@ -437,19 +437,11 @@ class Website(models.Model):
# Languages
# ----------------------------------------------------------
- def get_languages(self):
- self.ensure_one()
- return self._get_languages()
-
- @tools.cache('self.id')
- def _get_languages(self):
- return [(lg.code, lg.name) for lg in self.language_ids]
-
def get_alternate_languages(self, req=None):
langs = []
if req is None:
req = request.httprequest
- default = self.get_current_website().default_lang_code
+ default = self.get_current_website().default_lang_id.url_code
shorts = []
def get_url_localized(router, lang):
@@ -460,11 +452,11 @@ class Website(models.Model):
return router.build(request.endpoint, arguments)
router = request.httprequest.app.get_db_router(request.db).bind('')
- for code, dummy in self.get_languages():
- lg_path = ('/' + code) if code != default else ''
- lg_codes = code.split('_')
+ for lg in self.language_ids:
+ lg_path = ('/' + lg.url_code) if lg.url_code != default else ''
+ lg_codes = lg.code.split('_')
shorts.append(lg_codes[0])
- uri = get_url_localized(router, code) if request.endpoint else request.httprequest.path
+ uri = get_url_localized(router, lg.url_code) if request.endpoint else request.httprequest.path
if req.query_string:
uri += u'?' + req.query_string.decode('utf-8')
lang = {
diff --git a/addons/website/models/website_visitor.py b/addons/website/models/website_visitor.py
index 9b262c26031..307ba256214 100644
--- a/addons/website/models/website_visitor.py
+++ b/addons/website/models/website_visitor.py
@@ -122,10 +122,9 @@ class WebsiteVisitor(models.Model):
def _create_visitor(self, website_page_id=False):
country_code = request.session.get('geoip', {}).get('country_code', False)
country_id = request.env['res.country'].sudo().search([('code', '=', country_code)], limit=1).id if country_code else False
- lang_id = request.env['res.lang'].sudo().search([('code', '=', request.lang)], limit=1).id
vals = {
'last_connection_datetime': datetime.now(),
- 'lang_id': lang_id,
+ 'lang_id': request.lang.id,
'country_id': country_id,
'website_id': request.website.id
}
diff --git a/addons/website/static/src/js/content/website_root.js b/addons/website/static/src/js/content/website_root.js
index 4b61a33d779..a8e208f1408 100644
--- a/addons/website/static/src/js/content/website_root.js
+++ b/addons/website/static/src/js/content/website_root.js
@@ -105,7 +105,7 @@ var WebsiteRoot = publicRootData.PublicRoot.extend({
var $target = $(ev.target);
// retrieve the hash before the redirect
var redirect = {
- lang: $target.data('lang'),
+ lang: $target.data('url_code'),
url: encodeURIComponent($target.attr('href').replace(/[&?]edit_translations[^&?]+/, '')),
hash: encodeURIComponent(window.location.hash)
};
diff --git a/addons/website/static/src/js/menu/seo.js b/addons/website/static/src/js/menu/seo.js
index 3844a1d4731..2ac6d7fcded 100644
--- a/addons/website/static/src/js/menu/seo.js
+++ b/addons/website/static/src/js/menu/seo.js
@@ -497,9 +497,7 @@ var MetaKeywords = Widget.extend({
},
});
this._rpc({
- model: 'website',
- method: 'get_languages',
- args: [[context.website_id]],
+ route: '/website/get_languages',
}).then(function (data) {
self.$('#language-box').html(core.qweb.render('Configurator.language_promote', {
'language': data,
diff --git a/addons/website/static/src/js/menu/translate.js b/addons/website/static/src/js/menu/translate.js
index 043a900fff6..cab37bf3473 100644
--- a/addons/website/static/src/js/menu/translate.js
+++ b/addons/website/static/src/js/menu/translate.js
@@ -46,14 +46,11 @@ var TranslatePageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
* @returns {Promise}
*/
_goToMasterPage: function () {
- var lang = '/' + utils.get_cookie('frontend_lang');
-
var current = document.createElement('a');
current.href = window.location.toString();
current.search += (current.search ? '&' : '?') + 'enable_editor=1';
- if (current.pathname.indexOf(lang) === 0) {
- current.pathname = current.pathname.replace(lang, '');
- }
+ // we are in translate mode, the pathname starts with '/<url_code/'
+ current.pathname = current.pathname.substr(current.pathname.indexOf('/', 1));
var link = document.createElement('a');
link.href = '/website/lang/default';
diff --git a/addons/website/static/src/xml/website.seo.xml b/addons/website/static/src/xml/website.seo.xml
index e3c442d8f32..6bafe769f16 100644
--- a/addons/website/static/src/xml/website.seo.xml
+++ b/addons/website/static/src/xml/website.seo.xml
@@ -2,7 +2,7 @@
<templates id="template" xml:space="preserve">
<t t-name="Configurator.language_promote">
<t t-foreach="language" t-as="lang">
- <option t-att-value="lang[0]" t-att-selected="lang[0] == def_lang ? 'selected' : null"><t t-esc="lang[1]" /></option>
+ <option t-att-value="lang[0]" t-att-selected="lang[0] == def_lang ? 'selected' : null"><t t-esc="lang[2]" /></option>
</t>
</t>
diff --git a/addons/website/static/tests/tours/rte.js b/addons/website/static/tests/tours/rte.js
index a57b282bd09..a5cd53eaf61 100644
--- a/addons/website/static/tests/tours/rte.js
+++ b/addons/website/static/tests/tours/rte.js
@@ -32,7 +32,7 @@ tour.register('rte_translator', {
timeout: 60000,
}, {
content: "go to english version",
- trigger: '.js_language_selector a[data-lang="en_US"]',
+ trigger: '.js_language_selector a[data-url_code="en"]',
extra_trigger: 'html[lang*="fr"]',
}, {
content: "Open new page menu",
@@ -73,7 +73,7 @@ tour.register('rte_translator', {
extra_trigger: 'body:not(.o_wait_reload):not(:has(.note-editor))',
}, {
content: "click on french version",
- trigger: '.js_language_selector a[data-lang="fr_BE"]',
+ trigger: '.js_language_selector a[data-url_code="fr_BE"]',
extra_trigger: 'html[lang*="en"]:not(:has(button[data-action=save]))',
}, {
content: "translate",
@@ -137,7 +137,7 @@ tour.register('rte_translator', {
extra_trigger: 'html[lang*="fr"]:not(:has(#wrap p span))',
}, {
content: "return to english version",
- trigger: '.js_language_selector a[data-lang="en_US"]',
+ trigger: '.js_language_selector a[data-url_code="en"]',
}, {
content: "edit english version",
trigger: 'a[data-action=edit]',
@@ -170,7 +170,7 @@ tour.register('rte_translator', {
trigger : '.js_language_selector .dropdown-toggle',
}, {
content: "return in french",
- trigger : 'html[lang="en-US"] .js_language_selector .js_change_lang[data-lang="fr_BE"]',
+ trigger : 'html[lang="en-US"] .js_language_selector .js_change_lang[data-url_code="fr_BE"]',
}, {
content: "check bis: content is translated",
trigger: '#wrap p font:first:contains(translated french text)',
diff --git a/addons/website/tests/__init__.py b/addons/website/tests/__init__.py
index dc24bd6e22a..9bb3efd60de 100644
--- a/addons/website/tests/__init__.py
+++ b/addons/website/tests/__init__.py
@@ -1,15 +1,16 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from . import test_converter
from . import test_base_url
+from . import test_converter
+from . import test_crawl
from . import test_get_current_website
+from . import test_lang_url
+from . import test_menu
+from . import test_page
from . import test_qweb
-from . import test_crawl
from . import test_ui
from . import test_views
-from . import test_menu
-from . import test_page
from . import test_website_favicon
from . import test_website_reset_password
from . import test_website_visitor
diff --git a/addons/website/tests/test_lang_url.py b/addons/website/tests/test_lang_url.py
new file mode 100644
index 00000000000..f4998168074
--- /dev/null
+++ b/addons/website/tests/test_lang_url.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.addons.http_routing.models.ir_http import url_for
+from odoo.addons.website.tools import MockRequest
+from odoo.tests import HttpCase, tagged
+
+
+@tagged('-at_install', 'post_install')
+class TestLangUrl(HttpCase):
+ def setUp(self):
+ super(TestLangUrl, self).setUp()
+
+ # Simulate multi lang without loading translations
+ self.website = self.env['website'].browse(1)
+ lang_fr = self.env.ref('base.lang_fr')
+ lang_fr.write({'active': True, 'url_code': 'fr'})
+ self.website.language_ids = self.env.ref('base.lang_en') + lang_fr
+ self.website.default_lang_id = self.env.ref('base.lang_en')
+
+ def test_01_url_for(self):
+ with MockRequest(self.env, website=self.website):
+ self.assertEqual(url_for('', '[lang]'), '/[lang]/hello/', "`[lang]` is used to be replaced in the url_return after installing a language, it should not be replaced or removed.")
+
+ def test_02_url_redirect(self):
+ url = '/fr_WHATEVER/contactus'
+ r = self.url_open(url)
+ self.assertEqual(r.status_code, 200)
+ self.assertTrue(r.url.endswith('/fr/contactus'), "fr_WHATEVER should be forwarded to 'fr_FR' lang as closest match")
+
+ url = '/fr_FR/contactus'
+ r = self.url_open(url)
+ self.assertEqual(r.status_code, 200)
+ self.assertTrue(r.url.endswith('/fr/contactus'), "lang in url should use url_code ('fr' in this case)")
diff --git a/addons/website/tests/test_qweb.py b/addons/website/tests/test_qweb.py
index 9386c9f81e3..9cc199291a9 100644
--- a/addons/website/tests/test_qweb.py
+++ b/addons/website/tests/test_qweb.py
@@ -77,7 +77,7 @@ class TestQwebProcessAtt(TransactionCase):
self.website.default_lang_id = self.env.ref('base.lang_en')
self.website.cdn_activated = True
self.website.cdn_url = "http://test.cdn"
- self.website.cdn_filters = "\n".join(["^(/[a-z]{2}_[A-Z]{2})?/a$", "^/b$"])
+ self.website.cdn_filters = "\n".join(["^(/[a-z]{2}_[A-Z]{2})?/a$", "^(/[a-z]{2})?/a$", "^/b$"])
def _test_att(self, url, expect, tag='a', attribute='href'):
self.assertEqual(
@@ -88,8 +88,8 @@ class TestQwebProcessAtt(TransactionCase):
def test_process_att_no_request(self):
# no request so no URL rewriting
self._test_att('/', {'href': '/'})
- self._test_att('/en_US/', {'href': '/en_US/'})
- self._test_att('/fr_FR/', {'href': '/fr_FR/'})
+ self._test_att('/en/', {'href': '/en/'})
+ self._test_att('/fr/', {'href': '/fr/'})
# no URL rewritting for CDN
self._test_att('/a', {'href': '/a'})
@@ -97,8 +97,8 @@ class TestQwebProcessAtt(TransactionCase):
with MockRequest(self.env):
# no website so URL rewriting
self._test_att('/', {'href': '/'})
- self._test_att('/en_US/', {'href': '/en_US/'})
- self._test_att('/fr_FR/', {'href': '/fr_FR/'})
+ self._test_att('/en/', {'href': '/en/'})
+ self._test_att('/fr/', {'href': '/fr/'})
# no URL rewritting for CDN
self._test_att('/a', {'href': '/a'})
@@ -106,37 +106,37 @@ class TestQwebProcessAtt(TransactionCase):
with MockRequest(self.env, website=self.website, multilang=False):
# lang not changed in URL but CDN enabled
self._test_att('/a', {'href': 'http://test.cdn/a'})
- self._test_att('/en_US/a', {'href': 'http://test.cdn/en_US/a'})
+ self._test_att('/en/a', {'href': 'http://test.cdn/en/a'})
self._test_att('/b', {'href': 'http://test.cdn/b'})
- self._test_att('/en_US/b', {'href': '/en_US/b'})
+ self._test_att('/en/b', {'href': '/en/b'})
def test_process_att_no_request_lang(self):
with MockRequest(self.env, website=self.website):
self._test_att('/', {'href': '/'})
- self._test_att('/en_US/', {'href': '/'})
- self._test_att('/fr_FR/', {'href': '/fr_FR/'})
+ self._test_att('/en/', {'href': '/'})
+ self._test_att('/fr/', {'href': '/fr/'})
def test_process_att_with_request_lang(self):
with MockRequest(self.env, website=self.website, context={'lang': 'fr_FR'}):
- self._test_att('/', {'href': '/fr_FR/'})
- self._test_att('/en_US/', {'href': '/'})
- self._test_att('/fr_FR/', {'href': '/fr_FR/'})
+ self._test_att('/', {'href': '/fr/'})
+ self._test_att('/en/', {'href': '/'})
+ self._test_att('/fr/', {'href': '/fr/'})
def test_process_att_matching_cdn_and_lang(self):
with MockRequest(self.env, website=self.website):
# lang prefix is added before CDN
self._test_att('/a', {'href': 'http://test.cdn/a'})
- self._test_att('/en_US/a', {'href': 'http://test.cdn/a'})
- self._test_att('/fr_FR/a', {'href': 'http://test.cdn/fr_FR/a'})
+ self._test_att('/en/a', {'href': 'http://test.cdn/a'})
+ self._test_att('/fr/a', {'href': 'http://test.cdn/fr/a'})
self._test_att('/b', {'href': 'http://test.cdn/b'})
- self._test_att('/en_US/b', {'href': 'http://test.cdn/b'})
- self._test_att('/fr_FR/b', {'href': '/fr_FR/b'})
+ self._test_att('/en/b', {'href': 'http://test.cdn/b'})
+ self._test_att('/fr/b', {'href': '/fr/b'})
def test_process_att_no_route(self):
with MockRequest(self.env, website=self.website, context={'lang': 'fr_FR'}, routing=False):
# default on multilang=True if route is not /{module}/static/
self._test_att('/web/static/hi', {'href': '/web/static/hi'})
- self._test_att('/my-page', {'href': '/fr_FR/my-page'})
+ self._test_att('/my-page', {'href': '/fr/my-page'})
def test_process_att_url_crap(self):
with MockRequest(self.env, website=self.website) as request:
diff --git a/addons/website/tools.py b/addons/website/tools.py
index e3bb897ec52..e7058d65541 100644
--- a/addons/website/tools.py
+++ b/addons/website/tools.py
@@ -84,14 +84,24 @@ class MockRequest(object):
app.get_db_router = app.bind = app.match = app
if not kw.get('routing', True):
app.match = werkzeugRaiseNotFound
+
+ lang = kw.get('lang')
+ if not lang:
+ lang_code = kw.get('context', {}).get('lang', env.context.get('lang', 'en_US'))
+ lang = env['res.lang']._lang_get(lang_code)
+
+ context = kw.get('context', {})
+ context.setdefault('lang', lang_code)
+
self.request = DotDict({
- 'context': kw.get('context', {}),
+ 'context': context,
'db': None,
'env': env,
'httprequest': {
'path': '/hello/',
'app': app,
},
+ 'lang': lang,
'redirect': werkzeug.utils.redirect,
'session': {
'geoip': {
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index 312d1ce701c..b89cb0721b4 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -227,7 +227,6 @@
</t>
</t>
- <t t-set="languages" t-value="website.get_languages() if website else None"/>
<t t-if="request and request.is_frontend_multilang and website">
<t t-foreach="website.get_alternate_languages(request.httprequest)" t-as="lg">
<link rel="alternate" t-att-hreflang="lg['hreflang']" t-att-href="lg['href']"/>
@@ -395,16 +394,15 @@
<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][1].split('/').pop()"/>
+ <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=lg[0])"
+ <a t-att-href="url_for(request.httprequest.path + '?' + keep_query(), lang_code=lg[0])"
class="dropdown-item js_change_lang"
- t-att-data-default-lang="(editable or translatable) and 'true' if website and lg[0] == website.default_lang_code else None"
- t-att-data-lang="lg[0]">
- <t t-esc="lg[1].split('/').pop()"/>
+ t-att-data-url_code="lg[1]">
+ <t t-esc="lg[2].split('/').pop()"/>
</a>
</t>
</div>