[FIX] website: language prefixed URL on website
In 10.0 and before, if we were eg. on website page /fr_FR/contact, if
`fr_FR` language (french) is installed and not the default website
language we would have all URL towards translated content (route with
multilang=True) prefixed with /fr_FR/ (the language code).
With 9cd982bcc some improvments were done to CDN but this also breaks
language prefixing, so this cause an unecessary redirect:
- we are on /fr_FR/contact and click on "Shop"
- we go to /shop
- odoo redirects US /fr_FR/shop
With this PR, URLs are prefixed with language once again.
note: the added test is hackish but the function tested depends on a lot
of odoo.http things that are hard to use for test (request.render,
request.context, request.httpreqest).
opw-1922051
closes #31792
Signed-off-by: Christophe Simonis <chs@odoo.com>
This commit is contained in:
@@ -6,6 +6,7 @@ from collections import OrderedDict
|
||||
from odoo import models
|
||||
from odoo.http import request
|
||||
|
||||
from odoo.addons.http_routing.models.ir_http import url_for
|
||||
|
||||
re_background_image = re.compile(r"(background-image\s*:\s*url\(\s*['\"]?\s*)([^)'\"]+)")
|
||||
|
||||
@@ -37,10 +38,16 @@ class QWeb(models.AbstractModel):
|
||||
if not website and options.get('website_id'):
|
||||
website = self.env['website'].browse(options['website_id'])
|
||||
|
||||
if not website or not website.cdn_activated:
|
||||
if not website:
|
||||
return atts
|
||||
|
||||
name = self.URL_ATTRS.get(tagName)
|
||||
if request and name and name in atts:
|
||||
atts[name] = url_for(atts[name])
|
||||
|
||||
if not website.cdn_activated:
|
||||
return atts
|
||||
|
||||
if name and name in atts:
|
||||
atts = OrderedDict(atts)
|
||||
atts[name] = website.get_cdn_url(atts[name])
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import re
|
||||
|
||||
import odoo
|
||||
from odoo import tools
|
||||
from odoo.modules.module import get_module_resource
|
||||
from odoo.tests.common import TransactionCase
|
||||
@@ -63,3 +64,96 @@ class TestQweb(TransactionCase):
|
||||
"css": attachments[1].url,
|
||||
"user_id": demo.id,
|
||||
}).encode('utf8'))
|
||||
|
||||
class MockObject(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.__dict__ = kwargs
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self
|
||||
def __getitem__(self, index):
|
||||
return self
|
||||
|
||||
class MockRequest(object):
|
||||
""" Class with context manager mocking odoo.http.request for tests """
|
||||
def __init__(self, env, website=None, context=None, multilang=True):
|
||||
app = MockObject(routing={
|
||||
'type': 'http',
|
||||
'website': True,
|
||||
'multilang': multilang,
|
||||
})
|
||||
app.get_db_router = app.bind = app.match = app
|
||||
self.request = MockObject(
|
||||
env=env, context=context or {}, db=None, debug=False,
|
||||
website=website, httprequest=MockObject(
|
||||
path='/hello/',
|
||||
app=app
|
||||
)
|
||||
)
|
||||
odoo.http._request_stack.push(self.request)
|
||||
def __enter__(self):
|
||||
return self.request
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
odoo.http._request_stack.pop()
|
||||
|
||||
class TestQwebProcessAtt(TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestQwebProcessAtt, self).setUp()
|
||||
self.website = self.env['website'].browse(1)
|
||||
self.website.language_ids = self.env.ref('base.lang_en') + self.env.ref('base.lang_fr')
|
||||
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$"])
|
||||
|
||||
def _test_att(self, url, expect, tag='a', attribute='href'):
|
||||
self.assertEqual(
|
||||
self.env['ir.qweb']._post_processing_att(tag, {attribute: url}, {}),
|
||||
expect
|
||||
)
|
||||
|
||||
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/'})
|
||||
# no URL rewritting for CDN
|
||||
self._test_att('/a', {'href': '/a'})
|
||||
|
||||
def test_process_att_no_website(self):
|
||||
with MockRequest(self.env) as request:
|
||||
# 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/'})
|
||||
# no URL rewritting for CDN
|
||||
self._test_att('/a', {'href': '/a'})
|
||||
|
||||
def test_process_att_monolang_route(self):
|
||||
with MockRequest(self.env, website=self.website, multilang=False) as request:
|
||||
# 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('/b', {'href': 'http://test.cdn/b'})
|
||||
self._test_att('/en_US/b', {'href': '/en_US/b'})
|
||||
|
||||
def test_process_att_no_request_lang(self):
|
||||
with MockRequest(self.env, self.website) as request:
|
||||
self._test_att('/', {'href': '/'})
|
||||
self._test_att('/en_US/', {'href': '/'})
|
||||
self._test_att('/fr_FR/', {'href': '/fr_FR/'})
|
||||
|
||||
def test_process_att_with_request_lang(self):
|
||||
with MockRequest(self.env, self.website, context={'lang': 'fr_FR'}) as request:
|
||||
self._test_att('/', {'href': '/fr_FR/'})
|
||||
self._test_att('/en_US/', {'href': '/'})
|
||||
self._test_att('/fr_FR/', {'href': '/fr_FR/'})
|
||||
|
||||
def test_process_att_matching_cdn_and_lang(self):
|
||||
with MockRequest(self.env, self.website) as request:
|
||||
# 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('/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'})
|
||||
|
||||
Reference in New Issue
Block a user