Post by gxHL » Thu Aug 13, 2020 6:10 pm

I have a shop (3.0.3.2) with multiple languages.
Sending a user to lets say myshop.com/my-seo-url-in-russian will show the English (which is the default) language instead of the Russian.

Any fixes for that?

Newbie

Posts

Joined
Sun Mar 24, 2013 7:52 pm

Post by letxobnav » Thu Aug 13, 2020 6:34 pm

OC sets language in order:
1) the language in the session if present
2) the language in the cookie if present
3) the languages in browser language accept header if one of those is supported by the site
4) the site default language

Default OC does not determine language from the url itself.

As such:
no matter what url you send a user, the language of the page displayed will be based on the order above.

This is also why search engines do not index multi-lingual seo urls, only the default one as they do not retain a session, cookie and send no language accept headers and therefore always receive the page in the default language.
Normally that would mean duplicate content but since most OC pages set a canonical url, that is not the case, still that canonical url is also in your default language hence that is the only url indexed.

So, the solution is to have a language identifier in your urls be it /en/ or /ru/ or lng=en or lng=ru, does not matter which as long as you can determine the requested language from it and it does not clash with used seo url keywords.

The only other alternative would be to determine which language a matching seo url keyword has when translating the seo url to get variables and override the default language with that language. Currently the seo url class does not care what the language is for a matching keyword-query pair, which is a shame.
That solution only works for seo urls and when you make sure that keywords are unique across languages.

There is a niche solution which only works if you only have one single-byte character language and one double-byte character language, which we have (en & zh), where you can simply check for that to determine the language, i.e. check if there is a double-byte character in the url.
Last edited by letxobnav on Fri Aug 14, 2020 9:57 am, edited 2 times in total.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by gxHL » Thu Aug 13, 2020 6:46 pm

So what can I do for this?

Newbie

Posts

Joined
Sun Mar 24, 2013 7:52 pm

Post by letxobnav » Fri Aug 14, 2020 9:51 am

well, you find an extension in the marketplace which adds a language indicator to the urls and acts on that language indicator.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by letxobnav » Fri Aug 14, 2020 4:42 pm

if you cannot find one and are a little code-aware you can use these instructions:

language indication in seo urls using first 2 characters of the language code:

catalog/config.php
add:

Code: Select all

define('URL_WITH_LANGUAGE', false);
this will give you a switch to turn it on or off

catalog/controller/startup/startup.php
after:

Code: Select all

$languages = $this->model_localisation_language->getLanguages();
add:

Code: Select all

		/********** detect language indicator in the seo url *******/
		if (URL_WITH_LANGUAGE && $this->config->get('config_seo_url')) {
			if (isset($this->request->get['_route_'])) {
				$url_parts = explode('/',$this->request->get['_route_']);
				foreach ($languages as $key => $value) {
					// only active languages
					if ($value['status']) {
						// using first part of language locale
						$indicator = substr($value['code'],0,2);
						foreach ($url_parts as $url_part) {
							if ($indicator == $url_part) {
								$code = $value['code'];
								// remove language indicator
								$this->request->get['_route_'] = str_replace($indicator.'/','',$this->request->get['_route_']);
								break(2);
							}
						}
					}
				}
			}
		}
		/**********************************************************/
before:

Code: Select all

			if (isset($this->session->data['language'])) {
add:

Code: Select all

		if ($code == '') {
before:

Code: Select all

		if (!array_key_exists($code, $languages)) {
			$code = $this->config->get('config_language');
		}
add:

Code: Select all

		}
that code will read the language indicator and set the language accordingly

catalog/controller/startup/seo_url.php
replace:

Code: Select all

			return $url_info['scheme'] . '://' . $url_info['host'] . (isset($url_info['port']) ? ':' . $url_info['port'] : '') . str_replace('/index.php', '', $url_info['path']) . $url . $query;
with:

Code: Select all

			if (URL_WITH_LANGUAGE) {
				return $url_info['scheme'] . '://' . $url_info['host'] . (isset($url_info['port']) ? ':' . $url_info['port'] : '') . str_replace('/index.php', '/'.substr($this->session->data['language'],0,2), $url_info['path']) . $url . $query;
			} else {
				return $url_info['scheme'] . '://' . $url_info['host'] . (isset($url_info['port']) ? ':' . $url_info['port'] : '') . str_replace('/index.php', '', $url_info['path']) . $url . $query;
			}
that code will add the language indicator to the seo urls

Since the language switcher is flawed when it comes to seo urls by default (it already sets the redirect url before a new language is selected making you redirect to the old language url with the new language page) and certainly when adding language indicators to the urls we need to rewrite the whole thing.

catalog/controller/common/language.php
replace everything with:

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();
		foreach ($results as $result) {
			if ($result['status']) {
				$data['languages'][] = array(
					'name' => $result['name'],
					'code' => $result['code']
				);
			}
		}
		$this->session->data['save_get'] = $this->request->get;
		return $this->load->view('common/language', $data);
	}
	
	public function language() {
		$this->load->model('localisation/language');
		$languages = $this->model_localisation_language->getLanguages();
		$url = '';
		if (isset($this->request->post['code']) && array_key_exists($this->request->post['code'],$languages) && $languages[$this->request->post['code']]['status']) {
			$this->session->data['language'] = $this->request->post['code'];
			if (isset($this->session->data['save_get'])) {
				$xlang_id = $languages[$this->request->post['code']]['language_id'];
				$curr_lang = $this->config->get('config_language_id');
				$this->config->set('config_language_id',$xlang_id);
				if (!isset($this->session->data['save_get']['route'])) {
					$url_data = $this->session->data['save_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->session->data['save_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']);
				}
				$this->config->set('config_language_id',$curr_lang);
				unset($this->session->data['save_get']);
				$this->response->redirect($redirect);
			} else {
				$this->response->redirect($this->url->link('common/home', $url, $this->request->server['HTTPS']));
			}
		} else {
			$this->response->redirect($this->url->link('common/home', $url, $this->request->server['HTTPS']));
		}
	}
}
that code will create the redirect link after the new language is selected.

now you can go back to catalog/config.php
and turn it on by changing:

Code: Select all

define('URL_WITH_LANGUAGE', false);
to:

Code: Select all

define('URL_WITH_LANGUAGE', true);

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by gxHL » Fri Aug 14, 2020 8:35 pm

holy ****! Thank you. I will give it a go.

Newbie

Posts

Joined
Sun Mar 24, 2013 7:52 pm

Post by Besti » Mon Sep 07, 2020 3:02 am

Hello!

I am coping with the same problem...
Tried different options it did not work..
The code you kindly posted here - will it add a 2 letters suffix for the default language as well, right? If so, how to make the 2 letters suffix only for the language, which is not the default one?
And maybe there is a way to fix it with hreflang.. Some code for header, to auto display a correct hreflang, deppending on the url? Just a thought..

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by letxobnav » Mon Sep 07, 2020 9:32 am

you can.

in catalog/controller/startup/startup.php
before this:

Code: Select all

		// Customer
		$customer = new Cart\Customer($this->registry);
		$this->registry->set('customer', $customer);
you add this:

Code: Select all

		// get the default language and set in session
		$this->load->model('setting/setting');
		$this->session->data['language_default'] = $this->model_setting_setting->getSettingValue('config_language', (int)$this->config->get('config_store_id'));
in catalog/controller/startup/seo_url.php
you change this:

Code: Select all

if (URL_WITH_LANGUAGE) {
to this:

Code: Select all

// add language indicator to seo urls if not default language
if (URL_WITH_LANGUAGE && $this->session->data['language'] != $this->session->data['language_default']) {
demo with default english here:https://www.crystallight.com.tw/oce/

x-hreflang has no meaning here, for that you still have to change your header controller and view with a loop thru all your languages.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by Besti » Mon Sep 07, 2020 2:00 pm

Thank you very much!
Had 500 errors, when trying to fix this before... Trying to avoid extensions, not to ruin all the work, but with the language,
I decided to try this russian extension https://opencartadmin.com/seo-langmark ... ab-review .
No idea whether it is good or not, but on the forum i saw someone recommending it.
Do you know anything about this one maybe?
If it does not work ill get back to experiments with the code.. 😇

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by letxobnav » Mon Sep 07, 2020 2:53 pm

Well, I don't know, I never install code from Eastern Europe.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by Besti » Mon Sep 07, 2020 5:01 pm

Do you know a good extension for this in the marketplace in oencart or a reliable developer?

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by letxobnav » Mon Sep 07, 2020 5:34 pm

I have not tried any, I do not use mods in general and certainly not from the OC marketplace so you just have to look at the reviews/comments and/or try them out.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by Besti » Wed Sep 09, 2020 4:33 pm

Thank you! Ok, decided to try out your code first ... and at the very beginning i got stuck.. i dont have catalog/config.php... (OC 3.0.3.6)? Any advice?

Corrected:
Ok, i guessed the config in the root directory.. :)

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by Besti » Wed Sep 09, 2020 4:50 pm

Ok, so i checked and it works! Wow! So easy and so fast!
However, not sure about the main page... Will it work for the multilanguage sitemap? The default language is yourdomain.com and the other language main page will be yourdomain.com/en/ , for example?

Both main pages have the same - index.php?route=common/home...

Will the automatic sitemap feed show it all? Or i should make a sitemap myself? And one sitemap for both or two sitemaps for each? If two, then where to put the second one for the second language?

Sorry for so many questions... :)

wittom.in (maybe some other advices on what should i fix here... )

P.S. Checked sitemap generator and it does not see the pages in other language... (((

P.P.S. The instructions you gave are awesome! :) Thank you! Thank you! Thank you!

P.P.S. The funny thing that happens now - when you put products in cart, you go to cart, (added) - change language in the cart!, then back to the homepage through logo, from there you change the language to the other one using flag, you get redirected back to the cart... Why can that be?! (OC 3.0.3.6, theme default) (added- happens from time to time, not only on cart, simply redirects to last page visited)

P.P.P.S. Managed to get the sitemap for other language - if i put for the url yourdomain.com/en/and the name for english version i set for it in seo urls...

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by letxobnav » Wed Sep 09, 2020 5:41 pm

index.php?route=common/home is a different issue of default OC not seo-ing the home page or any other route like account/login which you can solve by:
viewtopic.php?p=798357#p798357

OC google sitemap does not do multi-lingual by default but uses the config language setting, best to copy the original file so you have google_sitemap_en.php and google_sitemap_de.php or any name you wish.
Then in each you set the language with:

Code: Select all

$this->config->set('config_language_id', x);
where x is the respective language id just after:

Code: Select all

public function index() {
then submit both sitemaps.
P.P.S. The funny thing that happens now - when you put products in cart, you go to cart, (added) - change language in the cart!, then back to the homepage through logo, from there you change the language to the other one using flag, you get redirected back to the cart... Why can that be?! (OC 3.0.3.6, theme default) (added- happens from time to time, not only on cart, simply redirects to last page visited)
that is because you are using an external cache (varnish), when you get a cache hit, it does not set a new save get so it retains the get variables of the previous-previous page.

as I said many times, additional external cache modules are more trouble than they are worth.
Last edited by letxobnav on Wed Sep 09, 2020 6:35 pm, edited 2 times in total.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by Besti » Wed Sep 09, 2020 6:30 pm

Why i did not follow your advices from the Forum from the very beginning!!!???!?!? You are a wonder and your explanation is simply perfect!
Gosh, you have just made my day and saved lots of my time and effort!!!!!

With you it is all so easy.. One hundred thousand thank you! :-*
Any advice on the website in general, if i dont ask for too much? ::) Is there anything else i should fix maybe, anything important that i have overlooked?

P.S. Good, if you do not experience this, ill check maybe its something on my end... Thank you for looking into it!

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by letxobnav » Wed Sep 09, 2020 8:01 pm

well,
1) I would implement http/2.0
2) update your cookies for samesite chrome
3) getting some 400 return code on an image
4) getting a 502 bad gateway on your youtube video

other than that, looks good.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by letxobnav » Wed Sep 09, 2020 9:00 pm

P.S. Good, if you do not experience this, ill check maybe its something on my end... Thank you for looking into it!
Read my correction in that post, you are caching so the save get variables do not get updated if your varnish external cache gets a hit.

you could possibly avoid this by putting this:

Code: Select all

$this->session->data['save_get'] = $this->request->get;
before the last } in function index of controller catalog/controller/startup/seo_url.php
as that is the first opportunity to obtain the get variables when using seo urls and that is not cached.
Then take that statement out of the common/language class though I don't think it is necessary.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan

Post by Besti » Wed Sep 09, 2020 9:26 pm

Wow... Thank you once again! 😁
I will research what you mean about those 4 points.. (quit a noob, so need to google what you write about 😇 )

I will try to look into caching as well! Thanks again for very valuable hints!!!!! I want to make it work finally! 😁

New member

Posts

Joined
Sun May 24, 2020 4:27 pm

Post by letxobnav » Wed Sep 09, 2020 10:53 pm

forget that last part, it would not work with the non-seo urls, see if you can prevent your varnich cache to prevent caching the header.

Crystal Light Centrum Taiwan
Extensions: MailQueue | SUKHR | VBoces

“Data security is paramount at [...], and we are committed to protecting the privacy of anyone who is associated with our [...]. We’ve made a lot of improvements and will continue to make them.”
When you know your life savings are gone.


User avatar
Expert Member

Posts

Joined
Fri Aug 18, 2017 4:35 pm
Location - Taiwan
Who is online

Users browsing this forum: No registered users and 5 guests