Follow us on Twitter X-Cart on Facebook Wiki
Shopping cart software Solutions for online shops and malls
 

x5 - Subdirectories for languages using htaccess rewrite

 
Reply
   X-Cart forums > X-Cart 5 > Dev Questions (X-Cart 5)
 
Thread Tools Search this Thread
  #1  
Old 07-20-2015, 06:36 AM
 
xgarb xgarb is offline
 

eXpert
  
Join Date: Jul 2004
Location: UK
Posts: 263
 

Default x5 - Subdirectories for languages using htaccess rewrite

On a previous x4 site I had something like the following set up with each language subdirectory using the files from the root of domain.com. ie just one install of X-cart for the 4 languages.

domain.com/en
domain.com/es
domain.com/it
domain.com/fr

I want to do the same with the new x5 site.

If I add the following to the .htaccess file

RewriteRule ^es/(.*) /$1
RewriteRule ^fr/(.*) /$1
RewriteRule ^it/(.*) /$1

I can access any pages from the root directory from the language subdirectories, for example domain.com/toys is available from domain.com/fr/toys and domain.com/es/toys, but the links themselves on the page are missing the language subdirectory.

Where should I look to correct this?
__________________
Core version: 5.5.xx
Reply With Quote
  #2  
Old 07-21-2015, 05:13 AM
  qualiteam's Avatar 
qualiteam qualiteam is offline
 

X-Guru
  
Join Date: Dec 2010
Posts: 6,373
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

I believe that almost all places that render links in X-Cart 5 call the \XLite\Core\Handler::buildURL() method in the end.

So, you should somehow program your custom module to insert the current language into the URL here (or in other methods that call this method).
__________________
Alex Solovev,
Qualiteam

---

User manual Video tutorials X-Cart FAQ

You are welcome to press "Thanks" button
if you find this post useful

Click here to learn how to apply patches

X-Cart Extensions
Reply With Quote
  #3  
Old 07-21-2015, 06:34 AM
 
xgarb xgarb is offline
 

eXpert
  
Join Date: Jul 2004
Location: UK
Posts: 263
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

In the end I found I had to go to the top and in var/run/classes/XLiteAbstract.php

edit getShopURL

Code:
public function getShopURL($url = '', $isSecure = null, array $params = array()) { $url = 'es/'.$url ; return \XLite\Core\URLManager::getShopURL($url, $isSecure, $params); }

to get the subdirectory to appear in links. This is just a test! I now have to incorporate the code here x5 set language from browser and make it into a module.

There is one thing that doesn't work though.. when there's more than one category in the url (ie domain.com/es/toys/rc-toys) gives a page not found.
__________________
Core version: 5.5.xx
Reply With Quote
  #4  
Old 07-22-2015, 06:41 AM
 
xgarb xgarb is offline
 

eXpert
  
Join Date: Jul 2004
Location: UK
Posts: 263
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

I've got further with this.

Code:
getShopURL now looks like this: public function getShopURL($url = '', $isSecure = null, array $params = array()) { //find current country code in URL $_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $segments = explode('/', substr($_SERVER['REQUEST_URI_PATH'], 1)); $lang_dir = $segments[0]; $store_language = $lang_dir; //code from url if (in_array($store_language, array('es','it','fr','de'))){ $url = $store_language.'/'.$url; } return \XLite\Core\URLManager::getShopURL($url, $isSecure, $params); }

and the relevant part of the htaccess file...

Code:
RewriteEngine on RewriteRule ^es/(.*) /$1 RewriteRule ^fr/(.*) /$1 RewriteRule ^de/(.*) /$1 RewriteRule ^it/(.*) /$1 # #BUG-772 Add HTTP_AUTHORIZATION header for fastCGI (need for XC\Qiwi) RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] RewriteRule (^|/)\. - [F] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^sitemap.xml(\?.+)?$ cart.php?target=sitemap [NC,L,QSA] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !^/../ RewriteRule ^((([/_a-z0-9-]+)/)?([_a-z0-9-]+)/)?([_a-z0-9-]+)(/?)(\.([_a-z0-9-]+))?$ cart.php?url=$5&last=$4&rest=$3&ext=$7 [NC,L,QSA] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} ^/../ RewriteRule ^../((([/_a-z0-9-]+)/)?([_a-z0-9-]+)/)?([_a-z0-9-]+)(/?)(\.([_a-z0-9-]+))?$ cart.php?url=$5&last=$4&rest=$3&ext=$7 [NC,L,QSA] RewriteBase /

I realised that getShopURL is used by everything to build the path so the above isn't very efficient in that the method is not just making the links have the correct path but making all the page contents have the wrong path which is then corrected by the first part of the htaccess file.

Without the second part of the htaccess there was a problem with deeper directories.

I need the have English in the root to match the current site.

Any ideas or input welcome!
__________________
Core version: 5.5.xx
Reply With Quote
  #5  
Old 07-27-2015, 08:33 AM
 
xgarb xgarb is offline
 

eXpert
  
Join Date: Jul 2004
Location: UK
Posts: 263
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

I now have this working as a module with the following functionality

One install of X-cart
English at the root of the domain (ie domain.com)
Four other languages in subdirectories (ie domain.com/fr domain.com/de etc)
Language displayed based on URL (better for SEO and linking in general)
Override selection of language via normal x-cart language selector
Cookie set to remember user's preference if they use the language selector.
I've removed the detection based on user's browsers language

The files are as follows:

In htaccess:

Code:
<IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^es/(.*) /$1 RewriteRule ^fr/(.*) /$1 RewriteRule ^de/(.*) /$1 RewriteRule ^it/(.*) /$1 RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] RewriteRule (^|/)\. - [F] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !^/../ RewriteRule ^((([/_a-z0-9-]+)/)?([_a-z0-9-]+)/)?([_a-z0-9-]+)(/?)(\.([_a-z0-9-]+))?$ cart.php?url=$5&last=$4&rest=$3&ext=$7 [NC,L,QSA] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} ^/../ RewriteRule ^../((([/_a-z0-9-]+)/)?([_a-z0-9-]+)/)?([_a-z0-9-]+)(/?)(\.([_a-z0-9-]+))?$ cart.php?url=$5&last=$4&rest=$3&ext=$7 [NC,L,QSA] #RewriteBase ____WEB_DIR____ </IfModule>


SetLanguageFromDir.php (sets the language based on URL but redirects if the cookie value differs)

Code:
abstract class SetLanguageFromDir extends \XLite\Core\Session implements \XLite\Base\IDecorator { /** * Get language * * @return \XLite\Model\Language */ public function getLanguage() { if (!isset($this->language)){ $current_language = 'en'; // default in case no language set $_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $segments = explode('/', substr($_SERVER['REQUEST_URI_PATH'], 1)); $url_lang = $segments[0]; if (in_array($url_lang, array('es','it','fr','de'))){ $current_language = $url_lang; } $this->language = \XLite\Core\Database::getRepo('XLite\Model\Language') ->findOneByCode($current_language); } return $this->language; } /** * language cooookies! * */ public function getLanguageCookie() { $store_language_codes = array('en','es','fr','de','it') ; $cookieLanguageCode = NULL; // -- If cookie is set if ( in_array(strtolower($_COOKIE[store_language]), $store_language_codes) ) { $cookieLanguageCode = strtolower($_COOKIE[store_language]) ; } return $cookieLanguageCode; } /** * Create session * * @return void */ protected function createSession() { $_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $segments = explode('/', substr($_SERVER['REQUEST_URI_PATH'], 1)); $url_lang = $segments[0]; $http_or_https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://' ; //basic check $lang_cookie = $this->getLanguageCookie(); if (strlen($url_lang) == 2 && !empty($lang_cookie)){ // a language is set in the URL and cookie if ($lang_cookie != $url_lang){ // the user's cookie is different from the language in the URL $reuse_uri = $_SERVER['REQUEST_URI']; $reuse_uri = substr($reuse_uri,3); // remove current character code if ($lang_cookie != 'en'){ $redirect_to = $http_or_https.$_SERVER['SERVER_NAME']."/".$lang_cookie.$reuse_uri; header("Location: ".$redirect_to,TRUE,307); //redirect to url with a language code exit; } if ($lang_cookie == 'en'){ $redirect_to = $http_or_https.$_SERVER['SERVER_NAME'].$reuse_uri; header("Location: ".$redirect_to,TRUE,307); //redirect to url without a language code exit; } } } if (strlen($url_lang) != 2 && !empty($lang_cookie) && $lang_cookie != 'en'){ // no language is set in the URL but a non-English cookie is set $reuse_uri = $_SERVER['REQUEST_URI']; $redirect_to = $http_or_https.$_SERVER['SERVER_NAME']."/".$lang_cookie."/".$reuse_uri; header("Location: ".$redirect_to,TRUE,307); //redirect to url with a language code exit; } if ($this->useDumpSession()) { $this->session = new \XLite\Model\SessionDump(); } else { $this->session = new \XLite\Model\Session(); $this->session->updateExpiry(); $this->session->setSid(\XLite\Core\Database::getRepo('XLite\Model\Session')->generatePublicSessionId()); \XLite\Core\Database::getEM()->persist($this->session); \XLite\Core\Database::getEM()->flush(); } } }


SetLanguageFromSelector.php (sets cookies and redirects)

Code:
abstract class SetLanguageFromSelector extends \XLite\Controller\AController implements \XLite\Base\IDecorator { /** * Change current language * * @return void */ protected function doActionChangeLanguage() { $code = strval(\XLite\Core\Request::getInstance()->language); if (!empty($code)) { $language = \XLite\Core\Database::getRepo('\XLite\Model\Language')->findOneByCode($code); setcookie('store_language', $code, time()+31536000,"/"); // new line $_COOKIE['store_language'] = $code; // new line if (isset($language) && $language->getEnabled()) { \XLite\Core\Session::getInstance()->setLanguage($language->getCode()); if (\XLite\Core\Auth::getInstance()->isLogged()) { \XLite\Core\Auth::getInstance()->getProfile()->setLanguage($language->getCode()); \XLite\Core\Database::getEM()->flush(); } } } // finding and redoing current URL to add/remove language code $_SERVER['REQUEST_URI_PATH'] = parse_url($this->getReferrerURL(), PHP_URL_PATH); $segments = explode('/', substr($_SERVER['REQUEST_URI_PATH'], 1)); $url_lang = $segments[0]; $http_or_https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://' ; //basic check if (strlen($url_lang) == 2){ // a language is set in the URL $reuse_uri = parse_url($this->getReferrerURL(), PHP_URL_PATH); $reuse_uri = substr($reuse_uri,3); // remove current character code if ($code != 'en'){ $new_url = $http_or_https.$_SERVER['SERVER_NAME']."/".$code.$reuse_uri; } if ($code == 'en'){ $new_url = $http_or_https.$_SERVER['SERVER_NAME'].$reuse_uri; } } if (strlen($url_lang) != 2){ // no language is set in the URL $reuse_uri = parse_url($this->getReferrerURL(), PHP_URL_PATH); if ($code != 'en'){ $new_url = $http_or_https.$_SERVER['SERVER_NAME']."/".$code.$reuse_uri; } if ($code == 'en'){ $new_url = $http_or_https.$_SERVER['SERVER_NAME'].$reuse_uri; } } $this->setReturnURL($new_url); } }

AddLanguageDirToLinks.php

Code:
abstract class AddLanguageDirToLinks extends \XLite implements \XLite\Base\IDecorator { public function getShopURL($url = '', $isSecure = null, array $params = array()) { $_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $segments = explode('/', substr($_SERVER['REQUEST_URI_PATH'], 1)); $lang_dir = $segments[0]; $url_language = $lang_dir; //code from url if (in_array($url_language, array('es','it','fr','de'))){ $url = $url_language .'/'.$url; } return \XLite\Core\URLManager::getShopURL($url, $isSecure, $params); } }


If anyone spots anything that can be replace with X-cart functions or constants let me know. I don't really like the http stuff I've used.
__________________
Core version: 5.5.xx
Reply With Quote

The following user thanks xgarb for this useful post:
totaltec (11-13-2015)
  #6  
Old 07-27-2015, 09:34 PM
  qualiteam's Avatar 
qualiteam qualiteam is offline
 

X-Guru
  
Join Date: Dec 2010
Posts: 6,373
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

I believe this will be a very useful module!

However, I'm not sure about the following things:

1. "return \XLite\Core\URLManager::getShopURL($url, $isSecure, $params);"

I think you should use parent::getShopURL() there.

2. Changes to .htaccess

I believe modules can't alter .htaccess, so the changes should be explained somewhere in the module description or documentation.
__________________
Alex Solovev,
Qualiteam

---

User manual Video tutorials X-Cart FAQ

You are welcome to press "Thanks" button
if you find this post useful

Click here to learn how to apply patches

X-Cart Extensions
Reply With Quote
  #7  
Old 11-12-2018, 06:41 AM
 
xgarb xgarb is offline
 

eXpert
  
Join Date: Jul 2004
Location: UK
Posts: 263
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

Looks like most of this is in the core now. Just edit this line in config.php

Code:
[clean_urls] ; Is use urls like domain.com/LG for languages ; possible values "Y", "N" ; Changing this setting requires to re-deploy your store use_language_url = "Y"
__________________
Core version: 5.5.xx
Reply With Quote
  #8  
Old 11-14-2018, 04:05 AM
  qualiteam's Avatar 
qualiteam qualiteam is offline
 

X-Guru
  
Join Date: Dec 2010
Posts: 6,373
 

Default Re: x5 - Subdirectories for languages using htaccess rewrite

Quote:
Originally Posted by xgarb
Looks like most of this is in the core now. Just edit this line in config.php

Code:
[clean_urls] ; Is use urls like domain.com/LG for languages ; possible values "Y", "N" ; Changing this setting requires to re-deploy your store use_language_url = "Y"


That is correct, this is in the core now.
__________________
Alex Solovev,
Qualiteam

---

User manual Video tutorials X-Cart FAQ

You are welcome to press "Thanks" button
if you find this post useful

Click here to learn how to apply patches

X-Cart Extensions
Reply With Quote
Reply
   X-Cart forums > X-Cart 5 > Dev Questions (X-Cart 5)



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -8. The time now is 08:52 AM.

   

 
X-Cart forums © 2001-2020