diff options
| author | Romain Derie <rde@odoo.com> | 2019-03-26 05:56:55 +0000 |
|---|---|---|
| committer | Romain Derie <rde@odoo.com> | 2019-08-26 16:35:19 +0000 |
| commit | 269aa594111a152ad4b7714856ea745bfef57155 (patch) | |
| tree | d5f8f7e86209102d831b2e222038d45bd7fe7626 /addons/website | |
| parent | f10f120de3017bc8d0e9a5ac72eeec1280374a1d (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.py | 6 | ||||
| -rw-r--r-- | addons/website/models/ir_http.py | 16 | ||||
| -rw-r--r-- | addons/website/models/ir_qweb.py | 5 | ||||
| -rw-r--r-- | addons/website/models/ir_ui_view.py | 6 | ||||
| -rw-r--r-- | addons/website/models/res_config_settings.py | 12 | ||||
| -rw-r--r-- | addons/website/models/res_lang.py | 13 | ||||
| -rw-r--r-- | addons/website/models/website.py | 22 | ||||
| -rw-r--r-- | addons/website/models/website_visitor.py | 3 | ||||
| -rw-r--r-- | addons/website/static/src/js/content/website_root.js | 2 | ||||
| -rw-r--r-- | addons/website/static/src/js/menu/seo.js | 4 | ||||
| -rw-r--r-- | addons/website/static/src/js/menu/translate.js | 7 | ||||
| -rw-r--r-- | addons/website/static/src/xml/website.seo.xml | 2 | ||||
| -rw-r--r-- | addons/website/static/tests/tours/rte.js | 8 | ||||
| -rw-r--r-- | addons/website/tests/__init__.py | 9 | ||||
| -rw-r--r-- | addons/website/tests/test_lang_url.py | 34 | ||||
| -rw-r--r-- | addons/website/tests/test_qweb.py | 34 | ||||
| -rw-r--r-- | addons/website/tools.py | 12 | ||||
| -rw-r--r-- | addons/website/views/website_templates.xml | 10 |
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> |
