Post by moshair » Thu Nov 25, 2021 3:50 am

Hello,

OC 3.0.3.8

I don't know if this is a bug or it just needs some modifications.
I noticed that when I enable Use SEO URLs and give some one a seo link that assigned to language id 2 (not the default langauge) in seo_url table he doesn't see the product with that language and canonical link is the link for the default language and that also make a problem not indexing the url in search engines because the canonical link. I'm wondering why not loading the language_id from the seo_url table !!! . I thought it is just in my store. I installed oc v 3.0.3.2 on local-host the same thing happened.

Can any one give me a code to make the script load the page according to the language_id in seo_url table.
Image
Regards,
Last edited by moshair on Sat Nov 27, 2021 12:46 am, edited 2 times in total.

New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by moshair » Fri Nov 26, 2021 6:53 am

I'm trying to solve the problem but I'm not an expert.

It seems working on my local host, does any one have a better idea to optimize the codes? like removing the query and use something built in the script.

I added:

Code: Select all

if (!isset($this->request->cookie['language'])) {
  if (isset($this->request->get['_route_'])) {
    $result = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $_route_ . "' ");
    if ($result->num_rows) {
      $lng = $result->row['language_id'];
      if ($lng == 2) {
        $code = 'ar';
      }
      else {
        $code = 'en-gb';
      }
    }
  }
}
after:

Code: Select all

$languages = $this->model_localisation_language->getLanguages();
in catalog/controller/startup/startup.php

And to make the browser redirect to the correct seo url after changing the language:



I added this code at the end of the file language.twig

Code: Select all

<script>
if (window.location.href.indexOf("&") === -1){
var redirect = '{{ redirect }}';
var url = decodeURI(window.location);
redirect = decodeURI(redirect);
url = url.replace(/&amp;/g, "&");
redirect = redirect.replace(/&amp;/g, "&");
if(redirect != url){
location.replace(redirect);
}
}
</script>
Also I installed this extension Modification for striping parent categories from url to remove the category from the product url to avoid wrong redirect.

New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by by mona » Fri Nov 26, 2021 10:53 am

you could use the language of a found url keyword to override the page language, I prefer to still add a language indicator to the url.

still,

Code: Select all

$this->request->get['_route_']
contains the entire request route of the seo url like

product
category

but also

category/product
category/subcategory
category/subcategory/product
etc.

if you do a search in your seo_url table for the _route_ as a keyword, it is unlikely it will find it as keywords there are split in separate keywords for category, subcategory and product.
So you too would have to split it first using

Code: Select all

$parts = explode('/', $this->request->get['_route_']);
Then use any of the parts as in:

Code: Select all

if (isset($this->request->get['_route_'])) {
	$parts = explode('/', $this->request->get['_route_']);
	if (!empty($parts[0])) $keyword_to_search_for = $parts[0];
}
No clue what you are trying to do to the language.twig file
And that modification you installed to strip parent categories is based on wrong assumptions.

but then you want to do what you want to do irrelevant of what standards already exist so feel free to do as you wish, it is your site.

DISCLAIMER:
You should not modify core files .. if you would like to donate a cup of coffee I will write it in a modification for you.


https://www.youtube.com/watch?v=zXIxDoCRc84


User avatar
Expert Member

Posts

Joined
Mon Jun 10, 2019 9:31 am

Post by moshair » Fri Nov 26, 2021 7:39 pm

by mona wrote:
Fri Nov 26, 2021 10:53 am
you could use the language of a found url keyword to override the page language, I prefer to still add a language indicator to the url.

still,

Code: Select all

$this->request->get['_route_']
contains the entire request route of the seo url like

product
category

but also

category/product
category/subcategory
category/subcategory/product
etc.

if you do a search in your seo_url table for the _route_ as a keyword, it is unlikely it will find it as keywords there are split in separate keywords for category, subcategory and product.
So you too would have to split it first using

Code: Select all

$parts = explode('/', $this->request->get['_route_']);
Then use any of the parts as in:

Code: Select all

if (isset($this->request->get['_route_'])) {
	$parts = explode('/', $this->request->get['_route_']);
	if (!empty($parts[0])) $keyword_to_search_for = $parts[0];
}
No clue what you are trying to do to the language.twig file
And that modification you installed to strip parent categories is based on wrong assumptions.

but then you want to do what you want to do irrelevant of what standards already exist so feel free to do as you wish, it is your site.
Please see this video that will explain the bugs in open-cart multi language:
https://player.vimeo.com/video/650273438?h=a7aa16f942

New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by by mona » Fri Nov 26, 2021 8:07 pm

https://developers.google.com/search/do ... onal-sites

Read googles recommendations for multi language / multi country sites and pick the one that is most suitable


Default OC does not set language based on the url and there is no language indication for SEO urls nor non-SEO urls.
Search engine indexing will always get the default language regardless of the seo url language.
The language switcher does switch the language but does not switch to the seo url.

You can use a language indication in the url, many times discussed how to do that on this forum, search for it and read the google documentation above to enable an informed decision.

You could use this which simply adds the redirects in the correct language for all enabled languages to the view and uses that when selected.
(these are total file replacements so backup first if you have made changes there!)


Total replacement for catalog/controller/common/language.php

Code: Select all

<?php
class ControllerCommonLanguage extends Controller {
	
	public function index() {
		$this->load->language('common/language');
		$data['action'] = $this->url->link('common/language/language', '', $this->request->server['HTTPS']);
		$data['code'] = $this->session->data['language'];
		$this->load->model('localisation/language');
		$data['languages'] = array();
		$results = $this->model_localisation_language->getLanguages();
		
		// save current language id
		$language_id_save = $this->config->get('config_language_id');
		
		// for each enabled language set the name, code and seo url in that language
		foreach ($results as $result) {
			if ($result['status']) {
				$url = '';
				// determine redirect url for language
				$this->config->set('config_language_id',$result['language_id']);
				$this->session->data['language'] = $result['code'];
				if (!isset($this->request->get['route'])) {
					$url_data = $this->request->get;
					unset($url_data['_route_']);
					
					if ($url_data) $url = '&' . urldecode(http_build_query($url_data, '', '&'));
					$redirect = $this->url->link('common/home', $url, $this->request->server['HTTPS']);
				} else {
					$url_data = $this->request->get;
					unset($url_data['_route_']);
					$route = $url_data['route'];
					unset($url_data['route']);
					if ($url_data) $url = '&' . urldecode(http_build_query($url_data, '', '&'));
					$redirect = $this->url->link($route, $url, $this->request->server['HTTPS']);
				}
				// add the language redirect data to the view interface
				$data['languages'][] = array(
					'name' => $result['name'],
					'code' => $result['code'],
					'href' => $redirect
				);
			}
		}
		// restore current language id
		$this->session->data['language'] = $data['code'];
		$this->config->set('config_language_id',$language_id_save);
		return $this->load->view('common/language', $data);
	}
	
	public function language() {
		$this->load->model('localisation/language');
		$languages = $this->model_localisation_language->getLanguages();
		$url = '';
		// do we have a valid code from the language selection
		if (isset($this->request->post['code']) && array_key_exists($this->request->post['code'],$languages) && $languages[$this->request->post['code']]['status']) {
			// set the requested language
			$this->session->data['language'] = $this->request->post['code'];
			// use the correct redirect
			$this->response->redirect($this->request->post['redirect_'.$this->request->post['code']]);
		} else {
			// otherwise just go home
			$this->response->redirect($this->url->link('common/home', $url, $this->request->server['HTTPS']));
		}
	}
}
Total replacement for catalog/view/theme/default/template/common/language.twig

Code: Select all

{% if languages|length > 1 %}
<div class="pull-left">
	<form action="{{ action }}" method="post" enctype="multipart/form-data" id="form-language">
		<div class="btn-group">
			<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
			{% for language in languages %}
				{% if language.code == code %} 
					<img src="catalog/language/{{ language.code }}/{{ language.code }}.png" alt="{{ language.name }}" title="{{ language.name }}">&nbsp;<span class="hidden-xs hidden-sm hidden-md">{{ language.name }}</span>
				{% endif %}
			{% endfor %}
			<span class="hidden-xs">&nbsp;<i class="fa fa-caret-down"></i></span></button>
			<ul class="dropdown-menu">
			{% for language in languages %}
				{% if language.code != code %} 
					<li><button class="btn btn-link btn-block language-select" type="button" name="{{ language.code }}"><img src="catalog/language/{{ language.code }}/{{ language.code }}.png" alt="{{ language.name }}" title="{{ language.name }}" />&nbsp;{{ language.name }}</button></li>
					<input type="hidden" name="redirect_{{ language.code }}" value="{{ language.href }}" />
				{% endif %}
			{% endfor %}
			</ul>
		</div>
		<input type="hidden" name="code" value="" />
	</form>
</div>
{% endif %}

DISCLAIMER:
You should not modify core files .. if you would like to donate a cup of coffee I will write it in a modification for you.


https://www.youtube.com/watch?v=zXIxDoCRc84


User avatar
Expert Member

Posts

Joined
Mon Jun 10, 2019 9:31 am

Post by moshair » Fri Nov 26, 2021 9:41 pm

Thank you by mona, your codes work like magic, I think this fix should be included in the official oc script.

I read google recommendations. I think as long each page has a different url and page content, there should be no problem. I don't like the idea of adding a switch to the link, the idea of using seo url is to get rid of & and ? in the links.

I will try the code in startup.php on live store and see the results. Now google has 0 page indexed with the second language. How my store content with the second language will appear for people in search engines.

Regards,

New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by moshair » Fri Nov 26, 2021 9:45 pm

moshair wrote:
Fri Nov 26, 2021 9:41 pm
Thank you by mona 💐, your codes work like magic, I think this fix should be included in the official oc script.

I read google recommendations. I think as long each page has a different url and page content, there should be no problem. I don't like the idea of adding a switch to the link, the idea of using seo url is to get rid of & and ? in the links.

I will try the code in startup.php on live store and see the results. Now google has 0 page indexed with the second language. How my store content with the second language will appear for people in search engines.

Regards,

New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by by mona » Fri Nov 26, 2021 10:43 pm

;D and they will last forever
thank you

If this is now solved please edit your title to include [SOLVED]

DISCLAIMER:
You should not modify core files .. if you would like to donate a cup of coffee I will write it in a modification for you.


https://www.youtube.com/watch?v=zXIxDoCRc84


User avatar
Expert Member

Posts

Joined
Mon Jun 10, 2019 9:31 am

Post by ilian359 » Sat Nov 27, 2021 4:09 am

I know that I am late, but anyway I am posting my solution:
https://www.opencart.com/index.php?rout ... n_id=42611
It is forever free to use.

Image Image
Laptop repair specialist in Sofia, Bulgaria.
Maintaining own OC 3 shop for laptop screens


Newbie

Posts

Joined
Tue Aug 11, 2020 4:37 am

Post by moshair » Sat Nov 27, 2021 4:59 am

ilian359 wrote:
Sat Nov 27, 2021 4:09 am
I know that I am late, but anyway I am posting my solution:
https://www.opencart.com/index.php?rout ... n_id=42611
It is forever free to use.
Thanks but your extension didn't work as I want because:

Disadvantages and limitations:
- Letters in SEO URLs must be of English alphabet;

You need to optimize the code to deal with utf8 characters.

:) I used your file to make an extension that do the same as yours but it supports none English letters. I used my code above in startup.php in this extension. You can advice me if it needs tweaks.

Good luck

Attachments


New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by by mona » Sat Nov 27, 2021 10:57 pm

if you want to set the language based on seo url language you might want to think about doing it like this:

in catalog/controller/startup/seo_url.php

change:

Code: Select all

    foreach ($parts as $part) {
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $this->db->escape($part) . "' AND store_id = '" . (int)$this->config->get('config_store_id') . "'");
to:

Code: Select all

    foreach ($parts as $part) {
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $this->db->escape($part) . "' AND store_id = '" . (int)$this->config->get('config_store_id') . "'");

/************ START override the language if request url seo keyword is found but in a different language than the currently set language *************/
    if ($query->num_rows == 1) {
        if ($query->row['language_id'] != $this->config->get('config_language_id')) {
            $language_id = $query->row['language_id'];
            // set the language in the requested url language.
            $this->config->set('config_language_id', $language_id);
            // get the new language code
            $lcq = $this->db->query("SELECT code FROM " . DB_PREFIX . "language WHERE language_id = '" . $language_id . "'");
            $code = $lcq->row['code'];
            // set the session language
            $this->session->data['language'] = $code;
            // set the cookie language
            setcookie(
                'language', 
                $code, 
                ['expires' => time() + 60 * 60 * 24 * 30, 
                'path' => '/', 
                'domain' =>  $this->request->server['HTTP_HOST'], 
                'samesite' => 'None', 
                'secure' => true, 
                'httponly' => true]);
            // Overwrite the default language object
            $language = new Language($code);
            $language->load($code);
            $this->registry->set('language', $language);
        }
    }
/************ END override the language if request url seo keyword is found but in a different language than the currently set language *************/

But again, be aware you can never have the same keyword anywhere across all languages for this to work, with a language indicator in the url you can.

DISCLAIMER:
You should not modify core files .. if you would like to donate a cup of coffee I will write it in a modification for you.


https://www.youtube.com/watch?v=zXIxDoCRc84


User avatar
Expert Member

Posts

Joined
Mon Jun 10, 2019 9:31 am

Post by moshair » Sat Nov 27, 2021 11:13 pm

by mona wrote:
Sat Nov 27, 2021 10:57 pm
if you want to set the language based on seo url language you might want to think about doing it like this:

in catalog/controller/startup/seo_url.php

change:

Code: Select all

    foreach ($parts as $part) {
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $this->db->escape($part) . "' AND store_id = '" . (int)$this->config->get('config_store_id') . "'");
to:

Code: Select all

    foreach ($parts as $part) {
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $this->db->escape($part) . "' AND store_id = '" . (int)$this->config->get('config_store_id') . "'");

/************ START override the language if request url seo keyword is found but in a different language than the currently set language *************/
    if ($query->num_rows == 1) {
        if ($query->row['language_id'] != $this->config->get('config_language_id')) {
            $language_id = $query->row['language_id'];
            // set the language in the requested url language.
            $this->config->set('config_language_id', $language_id);
            // get the new language code
            $lcq = $this->db->query("SELECT code FROM " . DB_PREFIX . "language WHERE language_id = '" . $language_id . "'");
            $code = $lcq->row['code'];
            // set the session language
            $this->session->data['language'] = $code;
            // set the cookie language
            setcookie(
                'language', 
                $code, 
                ['expires' => time() + 60 * 60 * 24 * 30, 
                'path' => '/', 
                'domain' =>  $this->request->server['HTTP_HOST'], 
                'samesite' => 'None', 
                'secure' => true, 
                'httponly' => true]);
            // Overwrite the default language object
            $language = new Language($code);
            $language->load($code);
            $this->registry->set('language', $language);
        }
    }
/************ END override the language if request url seo keyword is found but in a different language than the currently set language *************/

But again, be aware you can never have the same keyword anywhere across all languages for this to work, with a language indicator in the url you can.
Thank you, I used your code and it is working very good and now there is no need to strip the category name from the product url. Don't worry open-cart doesn't allow using the same keyword, I tried putting the same keyword I got error:
Warning: Please check the form carefully for errors!
SEO URL must be unique!

Regards,

New member

Posts

Joined
Sun Jul 21, 2019 3:27 pm

Post by Nadalb » Thu Jul 21, 2022 2:00 pm

moshair wrote:
Sat Nov 27, 2021 11:13 pm
by mona wrote:
Sat Nov 27, 2021 10:57 pm
if you want to set the language based on seo url language you might want to think about doing it like this:

in catalog/controller/startup/seo_url.php

change:

Code: Select all

    foreach ($parts as $part) {
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $this->db->escape($part) . "' AND store_id = '" . (int)$this->config->get('config_store_id') . "'");
to:

Code: Select all

    foreach ($parts as $part) {
        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword = '" . $this->db->escape($part) . "' AND store_id = '" . (int)$this->config->get('config_store_id') . "'");

/************ START override the language if request url seo keyword is found but in a different language than the currently set language *************/
    if ($query->num_rows == 1) {
        if ($query->row['language_id'] != $this->config->get('config_language_id')) {
            $language_id = $query->row['language_id'];
            // set the language in the requested url language.
            $this->config->set('config_language_id', $language_id);
            // get the new language code
            $lcq = $this->db->query("SELECT code FROM " . DB_PREFIX . "language WHERE language_id = '" . $language_id . "'");
            $code = $lcq->row['code'];
            // set the session language
            $this->session->data['language'] = $code;
            // set the cookie language
            setcookie(
                'language', 
                $code, 
                ['expires' => time() + 60 * 60 * 24 * 30, 
                'path' => '/', 
                'domain' =>  $this->request->server['HTTP_HOST'], 
                'samesite' => 'None', 
                'secure' => true, 
                'httponly' => true]);
            // Overwrite the default language object
            $language = new Language($code);
            $language->load($code);
            $this->registry->set('language', $language);
        }
    }
/************ END override the language if request url seo keyword is found but in a different language than the currently set language *************/

But again, be aware you can never have the same keyword anywhere across all languages for this to work, with a language indicator in the url you can.
Thank you, I used your code and it is working very good and now there is no need to strip the category name from the product url. Don't worry open-cart doesn't allow using the same keyword, I tried putting the same keyword I got error:
Warning: Please check the form carefully for errors!
SEO URL must be unique!

Regards,
Hi there,

I noticed a problem with this code, when on a product page you try to change the language the website stay on the same language, so if a French user want to see the US version page he can't, the language switch will never work

New member

Posts

Joined
Tue Jan 04, 2022 2:12 am
Who is online

Users browsing this forum: pprmkr, Stinger23 and 10 guests