Setting Up Multilingual and Multi-currency in Magento 2
Magento 2 provides a complete architecture for managing multiple languages and currencies within a single installation. Proper configuration requires understanding the Global → Website → Store → Store View hierarchy and how each level affects the catalog, prices, and transactions.
Store View Hierarchy and Localization
Each Store View in Magento 2 corresponds to one locale. Basic structure for multilingual store:
- Website — domain or group of domains (example.com)
- Store — root category of catalog
-
Store View — language:
en_US,de_DE,ru_RU
Creating Store View via CLI:
bin/magento store:website:create --code=eu --name="Europe" --sort-order=10
bin/magento store:group:create --website-id=2 --name="EU Store" --root-category-id=2
bin/magento store:store:create --name="German" --code=de --website-id=2 --group-id=2 --locale=de_DE --sort-order=10
After creating Store View, language packs must be installed. Magento uses i18n CSV files, Composer packages for main languages published in magento/language-* repository:
composer require magento/language-de_de
composer require magento/language-ru_ru
bin/magento setup:upgrade
bin/magento setup:static-content:deploy de_DE ru_RU en_US -f
Multi-currency Configuration
Magento 2 works with base currency (Base Currency) and display currencies (Display Currencies). Rates are updated via providers: built-in Webservicex is outdated, recommended fixer.io or currencyconverterapi.com.
Configuration via app/etc/config.php or Admin Panel:
<!-- app/etc/env.php — don't store API keys in VCS -->
'currency' => [
'options' => [
'base' => 'EUR',
'default' => 'EUR',
'allow' => 'EUR,USD,GBP,PLN,RUB'
]
]
Setting exchange rate provider via core_config_data:
INSERT INTO core_config_data (scope, scope_id, path, value) VALUES
('default', 0, 'currency/import/service', 'Magento_CurrencySymbol/service/fixerio'),
('default', 0, 'currency/import/api_key', 'YOUR_FIXER_KEY'),
('default', 0, 'currency/import/time', '00:00:00');
Automatic exchange rate update via cron:
<!-- etc/crontab.xml -->
<group id="default">
<job name="currency_rates_update" instance="Magento\CurrencySymbol\Model\System\Currencysymbol" method="scheduledUpdateCurrencyRates">
<schedule>0 */6 * * *</schedule>
</job>
</group>
Content Translations: Products and Categories
Product attributes are translated at the Store View level. For bulk translation use import mechanism with store_view_code:
sku,store_view_code,name,description,short_description
product-001,de,Produkt Eins,"Vollständige Beschreibung","Kurze Beschreibung"
product-001,ru,Продукт Один,"Полное описание","Краткое описание"
Import via CLI:
bin/magento import:run --entity=catalog_product --behavior=update \
--validation-strategy=validation-stop-on-errors \
--allowed-error-count=0 \
--input-file=var/import/products_de.csv \
--import-dir=var/import
URL Structure and hreflang
For SEO, it's critical to configure URL structure properly. Magento 2 supports two approaches:
| Approach | Example | Configuration |
|---|---|---|
| Subdomain | de.example.com |
Separate Website |
| Subfolder | example.com/de/ |
Store View with Base URL |
| GET parameter | example.com?___store=de |
Not recommended |
Setting up hreflang via XML layout:
<!-- view/frontend/layout/default_head_blocks.xml -->
<page>
<head>
<block class="Vendor\Module\Block\Hreflang" name="hreflang" template="Vendor_Module::hreflang.phtml"/>
</head>
</page>
Pricing by Store View and Website
Prices in Magento 2 are set at Website level. For different prices by region use catalog_product_entity_decimal records with website_id binding. Specific pricing implemented via Tier Prices and Customer Group Prices:
// Program set price for website
$product->setPrice(99.99);
$product->setWebsiteIds([1, 2]);
$product->setData('price', 89.99); // overwrite for scope
// Via repository with scope
$this->productRepository->save($product, true); // saveOptions = true
Taxes and price display: set up Tax Zones by country and bind to Customer Groups. For EU, support inclusive/exclusive prices with VAT is mandatory — configured in Stores → Configuration → Tax → Price Display Settings.
Typical Implementation Timeline
- Basic setup of 2 languages + 2 currencies: 2–3 days
- Catalog translation (1000–5000 SKU): 3–5 days (including import validation)
- SEO configuration with hreflang and canonical: 1–2 days
- Automatic exchange rate update + monitoring: 1 day







