PrestaShop Multilingual and Multi-Currency Setup
PrestaShop is designed with multilingualism as a core function: _lang tables exist for most entities (Product, Category, CMS pages, attributes). Multi-currency is implemented through conversion system relative to base currency. Both features are natively supported without third-party modules.
Adding Languages
Languages in PrestaShop correspond to PHP locales and come with language packs (back-office + front-office translations):
# Install Russian language via CLI
php bin/console prestashop:language:install ru-RU
# Or via Language object
$language = new Language();
$language->name = 'Русский';
$language->iso_code = 'ru';
$language->locale = 'ru-RU';
$language->language_code = 'ru-RU';
$language->date_format_lite = 'd.m.Y';
$language->date_format_full = 'd.m.Y H:i:s';
$language->is_rtl = false;
$language->active = true;
$language->add();
Translation storage structure:
-- Example: product translations
SELECT p.id_product, pl.name, pl.description_short, l.iso_code
FROM ps_product p
JOIN ps_product_lang pl ON pl.id_product = p.id_product
JOIN ps_lang l ON l.id_lang = pl.id_lang
WHERE p.id_product = 42;
URL Structure for SEO
PrestaShop supports several URL strategies for multilingual sites:
| Strategy | URL | Configuration |
|---|---|---|
| GET parameter | /product?id_lang=2 |
Default, not recommended |
| Language prefix | /ru/product |
PS_LANGUAGE_DETECTION + .htaccess |
| Subdomain | ru.example.com |
Multishop |
| Separate domain | example.ru |
Multishop |
Configure language prefix in app/config/parameters.php and Admin → International → Localization:
// In PrestaShop .htaccess, rules added automatically
// For manual Nginx management:
location / {
rewrite ^/ru/(.*)$ /$1?id_lang=2 last;
rewrite ^/en/(.*)$ /$1?id_lang=1 last;
try_files $uri $uri/ /index.php$is_args$args;
}
Add hreflang in PrestaShop via displayHeader hook in custom module:
public function hookDisplayHeader(): string
{
$languages = Language::getLanguages(true);
$currentController = $this->context->controller;
$hreflangs = [];
foreach ($languages as $lang) {
$url = $this->context->link->getLanguageLink($lang['id_lang']);
$hreflangs[] = sprintf(
'<link rel="alternate" hreflang="%s" href="%s">',
$lang['language_code'],
$url
);
}
$hreflangs[] = '<link rel="alternate" hreflang="x-default" href="' .
$this->context->link->getLanguageLink(Configuration::get('PS_LANG_DEFAULT')) . '">';
return implode("\n", $hreflangs);
}
Currency Setup
PrestaShop stores all prices in base currency (configured in Admin → International → Currencies → Default currency). Conversion happens automatically on display.
// Add currency programmatically
$currency = new Currency();
$currency->name = 'Polish Zloty';
$currency->iso_code = 'PLN';
$currency->iso_code_num = '985';
$currency->sign = 'zł';
$currency->conversion_rate = 0.21; // relative to base (EUR)
$currency->decimals = 2;
$currency->active = true;
$currency->add();
Automatic Exchange Rate Updates
PrestaShop supports several providers via CurrencyRateProviderInterface:
// Custom rate provider (e.g., Central Bank of Russia)
namespace MyModule\Provider;
use PrestaShop\PrestaShop\Core\Currency\ExchangeRateProvider\AbstractApiExchangeRateProvider;
class CbRfExchangeRateProvider extends AbstractApiExchangeRateProvider
{
const API_URL = 'https://www.cbr.ru/scripts/XML_daily.asp';
public function getRates(array $currencyIsoCodes): array
{
$xml = simplexml_load_file(self::API_URL);
$rates = [];
foreach ($xml->Valute as $valute) {
$isoCode = (string) $valute->CharCode;
if (in_array($isoCode, $currencyIsoCodes)) {
$nominal = (float) str_replace(',', '.', (string) $valute->Nominal);
$value = (float) str_replace(',', '.', (string) $valute->Value);
$rates[$isoCode] = $value / $nominal;
}
}
return $rates;
}
}
Cron for rate updates:
# Update rates every 6 hours
0 */6 * * * www-data php /var/www/prestashop/bin/console prestashop:currencies:update-exchange-rates
Catalog Content Translation
Mass translation via CSV import (PrestaShop format):
ID;Active (0/1);Name *;Short description;Description;Meta title;Meta description;URL rewritten
42;1;Winter Jacket;"Warm jacket for winter";"Full jacket description...";"Buy winter jacket";"Winter jacket — buy in store";kurtka-zimnyaya
# Import via web: Admin → Advanced Parameters → Import
# Or via Webkul module or custom importer with API
# Direct SQL update for bulk operations:
UPDATE ps_product_lang
SET name = 'Winter Jacket',
description_short = 'Warm jacket',
link_rewrite = 'winter-jacket'
WHERE id_lang = 2 -- Russian language ID
AND id_product IN (42, 43, 44);
Price and Number Formatting by Locale
Each currency has own formatting via CurrencyFormatter:
use PrestaShop\PrestaShop\Core\Localization\Locale\Repository as LocaleRepository;
$locale = $localeRepository->getLocale('ru-RU');
$formattedPrice = $locale->formatPrice(1299.99, 'RUB');
// → "1 299,99 ₽"
$formattedPrice = $locale->formatPrice(99.99, 'EUR');
// → "99,99 €" (for ru-RU locale)
Setup Timeline
- Adding 1–2 languages + back-office translations: 1 day
- Setup 3–5 currencies + auto-update rates: 1 day
- SEO configuration hreflang + URL structure: 1–2 days
- Translate catalog 1,000–10,000 products (with quality check): 3–7 days







