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.