Проблема: разная стоимость товара для разных языков в WooCommerce
В мульти-язычных магазинах WooCommerce часто требуется показывать разную цену товара в зависимости от выбранного языка сайта. Например, цена в рублях для русского языка и в евро для английского. Стандартные решения плагинов мультиязычности не всегда поддерживают такую логику, или требуют покупки дополнительных расширений.
В этой статье разберём, как реализовать динамическое изменение цены товара на лету с помощью кода — без дополнительных плагинов для мультивалютности. Это подходит, если у вас фиксированные курсы и цены для каждого языка, а не сложные валютные конвертации.
Диагностика: почему стандартные методы не работают
Стандартный WooCommerce хранит цену товара в базе как одно значение. Плагины перевода, например WPML или Polylang, обычно не меняют цену, а переводят только текст. Отдельные плагины мультивалютности добавляют валюты и конвертации, но они часто тяжелые и сложные.
Если вы просто меняете язык сайта, но цена остаётся одинаковой, значит, нужно вмешаться программно и подменить цену при выводе.
Пошаговое решение: изменение цены товара по языку
1. Определяем язык сайта
Предположим, что у вас установлен плагин Polylang или WPML. Для WPML можно получить текущий язык так:
if (defined('ICL_LANGUAGE_CODE')) {
$current_lang = ICL_LANGUAGE_CODE;
} else {
$current_lang = 'ru';
}Для Polylang:
$current_lang = function_exists('pll_current_language') ? pll_current_language() : 'ru';2. Добавляем цены для языков в метаполя товара
Через админку добавьте произвольные поля для товаров, например price_ru и price_en с нужными значениями. Можно использовать ACF или стандартные метаполя.
3. Подменяем цену на фронтенде
Добавьте следующий код в functions.php вашей темы или в кастомный плагин:
add_filter('woocommerce_product_get_price', 'change_price_by_language', 10, 2);
add_filter('woocommerce_product_get_regular_price', 'change_price_by_language', 10, 2);
add_filter('woocommerce_product_get_sale_price', 'change_price_by_language', 10, 2);
function change_price_by_language($price, $product) {
// Определяем язык
if (defined('ICL_LANGUAGE_CODE')) {
$current_lang = ICL_LANGUAGE_CODE;
} elseif (function_exists('pll_current_language')) {
$current_lang = pll_current_language();
} else {
$current_lang = 'ru';
}
// Получаем ID товара
$product_id = $product->get_id();
// Названия метаполей с ценами для языков
$price_meta_key = 'price_' . $current_lang;
// Получаем цену из метаполя
$custom_price = get_post_meta($product_id, $price_meta_key, true);
// Если цена задана и больше 0, возвращаем её
if ($custom_price !== '' && floatval($custom_price) > 0) {
return $custom_price;
}
// Иначе возвращаем оригинальную цену
return $price;
}4. Обновляем кэш и проверяем
Очистите кэш сайта и браузера. Зайдите на страницу товара, переключайте язык и проверьте, что цена меняется в соответствии с указанными метаполями.
Проверка результата после внедрения
- Откройте страницу товара на основном языке (например, ru) — должна отображаться цена из
price_ru. - Переключитесь на другой язык (en) — цена должна обновиться на значение из
price_en. - Проверьте и корзину — цены должны соответствовать выбранному языку.
- Если есть скидки, они применяются к подставленной цене.
Частые ошибки и как исправить
- Цена не меняется при смене языка: проверьте, правильно ли определён язык, и действительно ли заполнены метаполя
price_xx. - Цена выводится некорректно (например, пустая или 0): убедитесь, что метаполя содержат числовые значения без лишних символов.
- Кэш мешает обновлению цены: очистите кэш плагинов (например, WP Rocket, LiteSpeed) и браузера.
- В корзине или на странице оформления заказа цена не обновляется: для корректного изменения цены в корзине нужно добавить следующий фильтр:
add_action('woocommerce_before_calculate_totals', 'change_cart_item_price_by_language', 20, 1);
function change_cart_item_price_by_language($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
if (defined('ICL_LANGUAGE_CODE')) {
$current_lang = ICL_LANGUAGE_CODE;
} elseif (function_exists('pll_current_language')) {
$current_lang = pll_current_language();
} else {
$current_lang = 'ru';
}
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$product_id = $product->get_id();
$price_meta_key = 'price_' . $current_lang;
$custom_price = get_post_meta($product_id, $price_meta_key, true);
if ($custom_price !== '' && floatval($custom_price) > 0) {
$product->set_price($custom_price);
}
}
}Практические советы по безопасности и производительности
- Используйте префиксы для метаполей, чтобы избежать конфликтов.
- Не храните цены в нечисловом формате — это может привести к ошибкам при подсчётах.
- Кэшируйте результаты, если у вас большой каталог и сложная логика.
- Для поддержки нескольких валют лучше использовать специализированные плагины, если требуется автоматическое обновление курса.
Сравнение подходов изменения цены по языку
| Метод | Плюсы | Минусы | Рекомендации |
|---|---|---|---|
| Использование метаполей и фильтров (код) | Легко настроить, нет лишних плагинов, полный контроль | Требует ручного заполнения цен, не подходит для динамических курсов | Для небольших магазинов с фиксированными ценами под каждый язык |
| Плагины мультивалютности | Автоматическое обновление курсов, поддержка нескольких валют | Сложность настройки, нагрузка на сайт, возможные конфликты с плагинами перевода | Для магазинов с динамическим ценообразованием и большим ассортиментом |
| Отдельные сайты под каждый язык | Максимальный контроль и гибкость | Дорого и неудобно для поддержки | Для очень крупных проектов или когда требуется очень разная ценовая политика |