View Single Post
  #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