Skip to content
Browse files

[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 9cd982b 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).

closes #31792
  • Loading branch information...
nle-odoo committed Mar 12, 2019
1 parent a11147a commit 10e1b98c77ccd898c92f0c4212bee7ccfd7da95a
Showing with 90 additions and 1 deletion.
  1. +8 −1 addons/website/models/
  2. +82 −0 addons/website/tests/
@@ -6,6 +6,7 @@
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 @@ def _post_processing_att(self, tagName, atts, options):
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,10 +3,36 @@

import re

import odoo
from odoo import tools
from odoo.modules.module import get_module_resource
from odoo.tests.common import TransactionCase

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, context, routing):
app = MockObject(routing=routing)
app.get_db_router = app.bind = app.match = app
self.request = MockObject(
env=env, context=context, db=None, debug=False,
def __enter__(self):
return self.request
def __exit__(self, exc_type, exc_value, traceback):

class TestQweb(TransactionCase):
def _load(self, module, *args):
@@ -63,3 +89,59 @@ def test_qweb_cdn(self):
"css": attachments[1].url,

def test_process_att_href(self):
def att(url, tag='a', attribute='href'):
return self.env['ir.qweb']._post_processing_att(tag, {attribute: url}, {})

website = self.env['website'].browse(1)
website.language_ids = self.env.ref('base.lang_en') + self.env.ref('base.lang_fr')
website.default_lang_id = self.env.ref('base.lang_fr')
website.cdn_activated = True
website.cdn_url = "http://test.cdn"
website.cdn_filters = "\n".join(["^(/[a-z]{2}_[A-Z]{2})?/a$", "^/b$"])

# no request so URL are not modified
self.assertEqual(att('/'), {'href': '/'})
self.assertEqual(att('/en_US/'), {'href': '/en_US/'})
self.assertEqual(att('/fr_FR/'), {'href': '/fr_FR/'})

# no request so CDN is not activated
self.assertEqual(att('/a'), {'href': '/a'})

routing = {'type': 'http', 'website': True, 'multilang': True}
context = {'lang': 'fr_FR'}
with MockRequest(self.env, context, routing=routing) as request:
# no website so URL are not modified
self.assertEqual(att('/'), {'href': '/'})
self.assertEqual(att('/en_US/'), {'href': '/en_US/'})
self.assertEqual(att('/fr_FR/'), {'href': '/fr_FR/'})

# no website so CDN is not activated
self.assertEqual(att('/a'), {'href': '/a'}) = website
# remove /fr_FR/ default and keep / as if no lang specified
self.assertEqual(att('/'), {'href': '/'})
self.assertEqual(att('/en_US/'), {'href': '/en_US/'})
self.assertEqual(att('/fr_FR/'), {'href': '/'})

context['lang'] = 'en_US'
# remove /fr_FR/ default and add request context /en_US/ if no lang
self.assertEqual(att('/'), {'href': '/en_US/'})
self.assertEqual(att('/en_US/'), {'href': '/en_US/'})
self.assertEqual(att('/fr_FR/'), {'href': '/'})

# CDN is working but lang prefix is added before
self.assertEqual(att('/a'), {'href': 'http://test.cdn/en_US/a'})
self.assertEqual(att('/en_US/a'), {'href': 'http://test.cdn/en_US/a'})
self.assertEqual(att('/fr_FR/a'), {'href': 'http://test.cdn/a'})
self.assertEqual(att('/b'), {'href': '/en_US/b'})
self.assertEqual(att('/en_US/b'), {'href': '/en_US/b'})
self.assertEqual(att('/fr_FR/b'), {'href': 'http://test.cdn/b'})

routing['multilang'] = False
self.assertEqual(att('/a'), {'href': 'http://test.cdn/a'})
self.assertEqual(att('/fr_FR/a'), {'href': 'http://test.cdn/fr_FR/a'})
self.assertEqual(att('/b'), {'href': 'http://test.cdn/b'})
self.assertEqual(att('/fr_FR/b'), {'href': '/fr_FR/b'})

0 comments on commit 10e1b98

Please sign in to comment.
You can’t perform that action at this time.