[FIX] website: use correct url code to get canonical url

Before this commit, we would compare a lang `code` (used in context) and a lang
`url_code`. For languages where those 2 are differents, the `if` condition
would always be falsy, making the canonical URL impossible to be reached.

Technically, this condition is used to get the translated name of records to
later construct the canonical URL.

Since the canonical URL will be incorrect and unreachable, the whole system to
tell search engine/crawler about translation won't work since no
`alternate/hreflang`[1] will be set in the DOM.

[1] see https://developers.google.com/search/docs/advanced/crawling/localized-versions

--------

Technical explanation:
- italian language `code` = `it_IT`, `url_code` = `it`
- belgian french language `code` = `fr_BE`, `url_code` = `fr_BE`
Install those languages on website as secondary languages.
Translate blog `Travel` to `Voyager` in french and `Viaggi` in italian.
Visiting `/fr_BE/blog/travel-1/post/post-1` will redirect to
`/fr_BE/blog/voyager-1/post/post-1` as it should, and the canonical URL will be
set to that same URL.
Visiting `/it/blog/travel-1/post/post-1` will redirect to
`/it/blog/voyager-1/post/post-1` as it should, but the canonical URL will be
set to `/it/blog/travel-1/post/post-1`.

opw-2486918

closes odoo/odoo#69918

X-original-commit: 733411fe03b924832d6b10cadf93c8fc09cc5802
Signed-off-by: Romain Derie <rdeodoo@users.noreply.github.com>
This commit is contained in:
Romain Derie
2021-04-27 12:14:38 +00:00
parent f7824fdf7a
commit 7ea3a73c18
3 changed files with 50 additions and 1 deletions
+4
View File
@@ -44,6 +44,10 @@ class WebsiteTest(Home):
def test_company_context(self):
return request.make_response(json.dumps(request.context.get('allowed_company_ids')))
@http.route('/test_lang_url/<model("res.country"):country>', type='http', auth='public', website=True, sitemap=False)
def test_lang_url(self, **kwargs):
return request.render('test_website.test_view')
# Test Session
@http.route('/test_get_dbname', type='json', auth='public', website=True, sitemap=False)
@@ -24,3 +24,48 @@ class TestIsMultiLang(odoo.tests.HttpCase):
self.assertEqual(fr_prefix + '/post', body.find('./form[@id="post"]').get('action'))
self.assertEqual(fr_prefix + '/get_post', body.find('./a[@id="get_post"]').get('href'))
self.assertEqual('/get_post_nomultilang', body.find('./a[@id="get_post_nomultilang"]').get('href'))
def test_02_url_lang_code_underscore(self):
website = self.env['website'].browse(1)
it = self.env.ref('base.lang_it').sudo()
en = self.env.ref('base.lang_en').sudo()
be = self.env.ref('base.lang_fr_BE').sudo()
country1 = self.env['res.country'].create({'name': "My Super Country"})
it.active = True
be.active = True
website.domain = 'http://127.0.0.1:8069' # for _is_canonical_url
website.default_lang_id = en
website.language_ids = en + it + be
params = {
'src': country1.name,
'value': country1.name + ' Italia',
'type': 'model',
'name': 'res.country,name',
'res_id': country1.id,
'lang': it.code,
'state': 'translated',
}
self.env['ir.translation'].create(params)
params.update({
'value': country1.name + ' Belgium',
'lang': be.code,
})
self.env['ir.translation'].create(params)
r = self.url_open('/test_lang_url/%s' % country1.id)
self.assertEqual(r.status_code, 200)
self.assertTrue(r.url.endswith('/test_lang_url/my-super-country-%s' % country1.id))
r = self.url_open('/%s/test_lang_url/%s' % (it.url_code, country1.id))
self.assertEqual(r.status_code, 200)
self.assertTrue(r.url.endswith('/%s/test_lang_url/my-super-country-italia-%s' % (it.url_code, country1.id)))
body = lxml.html.fromstring(r.content)
# Note: this test is indirectly testing the `ref=canonical` tag is correctly set,
# as it is required in order for `rel=alternate` tags to be inserted in the DOM
it_href = body.find('./head/link[@rel="alternate"][@hreflang="it"]').get('href')
fr_href = body.find('./head/link[@rel="alternate"][@hreflang="fr"]').get('href')
en_href = body.find('./head/link[@rel="alternate"][@hreflang="en"]').get('href')
self.assertTrue(it_href.endswith('/%s/test_lang_url/my-super-country-italia-%s' % (it.url_code, country1.id)))
self.assertTrue(fr_href.endswith('/%s/test_lang_url/my-super-country-belgium-%s' % (be.url_code, country1.id)))
self.assertTrue(en_href.endswith('/test_lang_url/my-super-country-%s' % country1.id))
+1 -1
View File
@@ -1105,7 +1105,7 @@ class Website(models.Model):
for key, val in list(arguments.items()):
if isinstance(val, models.BaseModel):
if val.env.context.get('lang') != lang.code:
arguments[key] = val.with_context(lang=lang.url_code)
arguments[key] = val.with_context(lang=lang.code)
path = router.build(request.endpoint, arguments)
else:
# The build method returns a quoted URL so convert in this case for consistency.