I found this French tutorial at
http://www.vemeo.fr/blog/ecommerce/prest...ltilingue/ site. So I translated it to English also.
If you follow this blog regularly you know we very rarely talk about development, code, PHP, MySql etc ...
For once we'll make an exception by making a tutorial that lets you turn into a real shop Prestashop multilingual.
For we must not fool ourselves Prestashop claims that its solution is multilingual, which is perfectly true at the user level but wrong in referencing (even for version 1.2.3). Here is a method optimized for Prestashop 1.1 but I think it works for version 1.2.3.
Preamble
To manage the change of language, Prestashop uses cookies. Simply put, when you arrive on site Prestashop in French, the website stores the value "French" of the cookie and when you click a flag to change language of the site changes the cookie value. Problem: Search engines are unable to store cookies ...
The result is that your visitors can "switch" languages without problems, but Goolgle indexing your site with the default language.
For example, for a client we had the following problem:
The site was bilingual (French / Spanish) and the default language was French. We therefore for the same product 2 pages 2 URL (1 per language):
http://www.mon-site.com/01-mon-produit.html (for French)
http://www.mon-site.com/01-mi-producto.html (Spanish)
But Google can not store cookies, was unable to see content in a language other than the default language.
Indeed, the code Prestashop is made so that if you can not store cookies, you will be back on the default language (I'm simplifying).
Results for two URLs to our site we content in French (default).
You can imagine the problems: poorly Google.es indexing pages (since nothing was in Spanish except the URL), the Spanish visitors arriving by Google.es had a content in French, and we had a big duplicate content!
A site two URLs ...
The only solution we found was to force the default language by URL (the area more precisely). For this, we first created the subdomain es.mon-site.com, which points to the same directory as
http://www.my-site.com.
NB: We do not normally try but it also works with another domain (eg
http://www.my-site.es)
For example: if the field is
http://www.my-site.com, we force the French, and if the field is es.mon-site.com, we force the Spanish.
To do this, we must go into the classes folder and open the file Tools.php
Around line 112, change the code like this (a big thank you to
Julian Breux):
PHP Code:
/* Automatically detect language if not already defined */
if ( isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
$array = split(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
// It forces the language by field
if($_SERVER['HTTP_HOST'] == 'www.mon-site.com') // FR
{
$array[0] = 'fr';
}
if($_SERVER['HTTP_HOST'] == 'es.mon-site.com') // ES
{
$array[0] = 'es';
}
Warning! If you want to use the multilingual mode on your admin, you must specify that it should be applied only on the public part of your site. For this, we will verify that the URL is not that the admin.
Then use this code instead of the previous:
PHP Code:
/* Automatically detect language if not already defined */
// Check if you are in the admin or not
if(ereg('admin', $_SERVER['REQUEST_URI']))
/* Above replace 'admin' with the directory of your admin
For example if the url to access your admin is www.mon-site.com/admin-boutique/
Rempalcer 'admin' to 'admin-shop'
*/
$admin = 1;
if ( isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) AND $admin != 1)
{
$array = split(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
// It forces the language by field
if($_SERVER['HTTP_HOST'] == 'www.mon-site.com') // FR
{
$array[0] = 'fr';
}
if($_SERVER['HTTP_HOST'] == 'es.mon-site.com') // ES
{
$array[0] = 'es';
}
At this point you are already well advanced. Now we must make a small configuration that will cause the engines to index the URL property of the 2 languages.
To do this, go to your classes and modify the file as Configuratrion.php below (thank you to
Cédric Girard):
Around line 99
PHP Code:
elseif (key_exists($key, self::$_CONF))
{
// MODIFICATION LANGUE PAR DEFAUT POUR LES ROBOTS
if($key=='PS_LANG_DEFAULT')
{
// Variable langue => on verifie le domaine et on force la langue
if($_SERVER['HTTP_HOST'] == 'www.mon-site.com') // FR
{
return '2'; // L'id du français
}
if($_SERVER['HTTP_HOST'] == 'es.mon-site.com') // ES
{
return '5'; // L'id de l'espagnol
}
}
else
{
return self::$_CONF[$key];
}
// FIN DE MODIFICATION
}
NB: For the id of your language, simply go to your admin, click the Tools tab and then under the tab "Languages" and there you will have the id of your language.
Now that everything is optimized for search engines must re-optimized the site for the visitor.
For this, we must modify the module blocklanguages. In the Modules folder, then blocklanguages folder, edit the file blocklanguages.tpl like below:
To line 3
PHP Code:
<ul id="first-languages">
{foreach from=$languages key=k item=language name="languages"}
<li {if $language.iso_code == $lang_iso}class="selected_language"{/if}>
{if $language.iso_code != $lang_iso}
<!--On modifie les url selon le code iso de la langue -->
<a href="{if $language.iso_code == 'es'}http://es.mon-site.com{/if}{if $language.iso_code == 'fr'}http://www.mon-site.com{/if}" title="{$language.name}">{/if}
<img src="{$img_lang_dir}{$language.id_lang}.jpg" alt="{$language.name}" />
{if $language.iso_code != $lang_iso}</a>{/if}
</li>
{/foreach}
</ul>
NB: For the iso code of your language, simply go to the same place as the id.
Note 2: With this change, you must pass by the home every time you change language. It's annoying but you can not do otherwise.
If you use a subdomain and only if you use a subdomain, you must configure it in the admin area of your shop. To do this go to your admin, click the Tools tab and then under the tab "Subdomains". Then just click again and add your subdomain (in this case "es").
At this level, and if you have any monitoring well, all will work.
Now if you want to use a sitemap, make the changes below.
We still have a problem with the sitemap, it will therefore be necessary to optimize the module gsitmap. I confess that we have not had time too look into this module and it is very poorly optimized but it works ...
Then you head to the modules folder, then gsitemap and edit the file gsitemap.php.
From the line about 47, you must modify the code as follows:
PHP Code:
/// Modifications multilingue
private function _postProcess()
{
// On génére le fichier français
$link = new Link();
$fp = fopen($this->_filename, 'w');
$xml = new SimpleXMLElement('<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"></urlset>');
// Catégories françaises
$categories = Db::getInstance()->ExecuteS('
SELECT c.id_category, c.level_depth, link_rewrite, DATE_FORMAT(date_add, \'%Y-%m-%d\') AS date_add, cl.id_lang
FROM '._DB_PREFIX_.'category c
LEFT JOIN '._DB_PREFIX_.'category_lang cl ON c.id_category = cl.id_category
LEFT JOIN '._DB_PREFIX_.'lang l ON cl.id_lang = l.id_lang
WHERE l.`active` = 1 AND cl.`id_lang` = 2');
// Ci dessus mettre l'id de votre 1ere langue dans `id_lang` = 2
foreach($categories as $category)
{
if (($priority = 0.9 - ($category['level_depth'] / 10)) < 0.1)
$priority = 0.1;
$sitemap = $xml->addChild('url');
// On définie les urls des catégories françaises. Mettre le domaine définie pour la langue française
$sitemap->addChild('loc','http://www.mon-site.com'.htmlspecialchars($link->getCategoryLink($category['id_category'], $category['link_rewrite'])));
$sitemap->addChild('priority', $priority);
$sitemap->addChild('lastmod', $category['date_add']);
$sitemap->addChild('changefreq', 'monthly');
}
// Produit français
$products = Db::getInstance()->ExecuteS('
SELECT p.id_product, pl.link_rewrite, DATE_FORMAT(date_add, \'%Y-%m-%d\') AS date_add, pl.id_lang, cl.`link_rewrite` AS category, (
SELECT MIN(level_depth)
FROM '._DB_PREFIX_.'product p2
LEFT JOIN '._DB_PREFIX_.'category_product cp2 ON p2.id_product = cp2.id_product
LEFT JOIN '._DB_PREFIX_.'category c2 ON cp2.id_category = c2.id_category
WHERE p2.id_product = p.id_product) AS level_depth
FROM '._DB_PREFIX_.'product p
LEFT JOIN '._DB_PREFIX_.'product_lang pl ON p.id_product = pl.id_product
LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND pl.`id_lang` = cl.`id_lang`)
LEFT JOIN '._DB_PREFIX_.'lang l ON cl.id_lang = l.id_lang
WHERE l.`active` = 1 AND pl.`id_lang` = 2' );
// Ci dessus mettre l'id de votre 1ere langue dans `id_lang` = 2
foreach($products as $product)
{
if (($priority = 0.7 - ($product['level_depth'] / 10)) < 0.1)
$priority = 0.1;
$sitemap = $xml->addChild('url');
// On définie les urls des produit français. Mettre le domaine définie pour la langue française
$sitemap->addChild('loc', 'http://www.mon-site.com'.htmlspecialchars($link->getProductLink($product['id_product'], $product['link_rewrite'], $product['category'])));
$sitemap->addChild('priority', $priority);
$sitemap->addChild('lastmod', $product['date_add']);
$sitemap->addChild('changefreq', 'weekly');
}
$xmlString = $xml->asXML();
fwrite($fp, $xmlString, Tools::strlen($xmlString));
fclose($fp);
$res = file_exists($this->_filename);
$this->_html .= '<h3 style="margin-bottom: 20px">';
$this->_html .= $res ? $this->l('Sitemap file successfully generated') : $this->l('Error while creating sitemap file');
$this->_html .= '</h3>';
// On génére le fichier de la 2eme langue
$link_es = new Link();
$fp_es = fopen($this->_filename_es, 'w');
$xml = new SimpleXMLElement('<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"></urlset>');
// Catégories de la 2eme langue
$categories = Db::getInstance()->ExecuteS('
SELECT c.id_category, c.level_depth, link_rewrite, DATE_FORMAT(date_add, \'%Y-%m-%d\') AS date_add, cl.id_lang
FROM '._DB_PREFIX_.'category c
LEFT JOIN '._DB_PREFIX_.'category_lang cl ON c.id_category = cl.id_category
LEFT JOIN '._DB_PREFIX_.'lang l ON cl.id_lang = l.id_lang
WHERE l.`active` = 1 AND cl.`id_lang` = 5');
// Ci dessus mettre l'id de votre 2eme langue dans `id_lang` = 5
foreach($categories as $category) {
if (($priority = 0.9 - ($category['level_depth'] / 10)) < 0.1)
$priority = 0.1;
$sitemap = $xml->addChild('url');
// On définie les urls des catégories de la 2eme langue. Mettre le domaine définie pour la 2eme langue
$sitemap->addChild('loc','http://es.mon-site.com'.htmlspecialchars($link->getCategoryLink($category['id_category'], $category['link_rewrite'])));
$sitemap->addChild('priority', $priority);
$sitemap->addChild('lastmod', $category['date_add']);
$sitemap->addChild('changefreq', 'monthly');
}
$products = Db::getInstance()->ExecuteS('
SELECT p.id_product, pl.link_rewrite, DATE_FORMAT(date_add, \'%Y-%m-%d\') AS date_add, pl.id_lang, cl.`link_rewrite` AS category, (
SELECT MIN(level_depth)
FROM '._DB_PREFIX_.'product p2
LEFT JOIN '._DB_PREFIX_.'category_product cp2 ON p2.id_product = cp2.id_product
LEFT JOIN '._DB_PREFIX_.'category c2 ON cp2.id_category = c2.id_category
WHERE p2.id_product = p.id_product) AS level_depth
FROM '._DB_PREFIX_.'product p
LEFT JOIN '._DB_PREFIX_.'product_lang pl ON p.id_product = pl.id_product
LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND pl.`id_lang` = cl.`id_lang`)
LEFT JOIN '._DB_PREFIX_.'lang l ON cl.id_lang = l.id_lang
WHERE l.`active` = 1 AND pl.`id_lang` = 5');
// Ci dessus mettre l'id de votre 2eme langue dans `id_lang` = 5
foreach($products as $product)
{
if (($priority = 0.7 - ($product['level_depth'] / 10)) < 0.1)
$priority = 0.1;
$sitemap = $xml->addChild('url');
// On définie les urls des produits de la 2eme langue. Mettre le domaine définit pour votre 2eme langue
$sitemap->addChild('loc', 'http://es.mon-site.com'.htmlspecialchars($link->getProductLink($product['id_product'], $product['link_rewrite'], $product['category'])));
$sitemap->addChild('priority', $priority);
$sitemap->addChild('lastmod', $product['date_add']);
$sitemap->addChild('changefreq', 'weekly');
}
$xmlString_es = $xml->asXML();
fwrite($fp_es, $xmlString_es, Tools::strlen($xmlString_es));
fclose($fp_es);
$res_es = file_exists($this->_filename_es);
$this->_html .= '<h3 style="margin-bottom: 20px">';
$this->_html .= $res_es ? $this->l('Sitemap file successfully generated') : $this->l('Error while creating sitemap file');
$this->_html .= '</h3>';
}
//// Fin modif
With this technique, you will have 2 sitemaps (1 per language). One called sitemap.xml and the other sitemap_es.xml. If you feel the change of names you can.
You need 2 for Google Sitemaps does not accept URLs from 2 different areas in the same sitemap. Do not forget to post the two sitemaps on your account "tool for webmasters.
That is a bit complicated but so far it is the only solution we have found a real site Prestashop in multiple languages.
If you have any questions please. Do not hesitate to give your further information.