Jump to content
Grosso2020

Склонение cлова товары в зависимости от стоящих рядом с ними цифр

Recommended Posts

Всем привет!

 

Имеется opencart 2.0.3.1.

 

Необходимо решить такую задачу, то есть, чтобы выводилось, в корзине, на главной при добавлении товара  «1 товар», «2 товарА», «5 товарОВ», а не «1 товаров» и «2 товаров» и т.д.

 

Подскажите как реализовать?

Share this post


Link to post
Share on other sites

if Вам в помощь 

Share this post


Link to post
Share on other sites

Отличное решение! :ugeek:

Edited by Grosso2020

Share this post


Link to post
Share on other sites

Создаете массив из 10 элементов {'товаров','товар','товара','товара','товара','товаров',...'товаров'}

 

Значение "Стоящие рядом цифры" делите на 10, берете остаток.

 

Остаток используете как индекс массива для извлечения нужного падежа.

 

 

А можно просто выводить строку в виде "Всего товаров в корзине: $столько-то", тогда и заморочки с падежами не нужны. 

Share this post


Link to post
Share on other sites

Всем привет!

 

Имеется opencart 2.0.3.1.

 

Необходимо решить такую задачу, то есть, чтобы выводилось, в корзине, на главной при добавлении товара  «1 товар», «2 товарА», «5 товарОВ», а не «1 товаров» и «2 товаров» и т.д.

 

Подскажите как реализовать?

 

в catalog\controller\common\cart.php

$data['text_items'] = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total));

прописать код

$count = $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0);
function getWord($number, $suffix) {
$keys = array(2, 0, 1, 1, 1, 2);
$mod = $number % 100;
$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
return $suffix[$suffix_key];
}
$array = array("товар", "товара", "товаров");
$data['text_items'] = $count .' '. getWord($count, $array);

Только не знаю как сделать для других языков, может кто поможет?

Share this post


Link to post
Share on other sites

в catalog\controller\common\cart.php

$data['text_items'] = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total));

прописать код

$count = $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0);
function getWord($number, $suffix) {
$keys = array(2, 0, 1, 1, 1, 2);
$mod = $number % 100;
$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
return $suffix[$suffix_key];
}
$array = array("товар", "товара", "товаров");
$data['text_items'] = $count .' '. getWord($count, $array);

Только не знаю как сделать для других языков, может кто поможет?

так просто в массиве использовать языковые переменные ;)

Share this post


Link to post
Share on other sites

в свое время для модуля Statistica делал так:

 

в контроллере

            $total_pro = $this->model_module_statistica->getTotalProducts();
            $total_pro = sprintf(${'total_products'.($this->model_module_statistica->getMorphology($total_pro))}, number_format($total_pro, 0, '', ' '));

в модели

    public function getMorphology($total_pro) {
            $morf = strlen($total_pro) - 1; //номер последнего символа в числе
                        
            $total_pro = (string)$total_pro; // для верного вывода морфологии преобразовать в строку
            
            if (($total_pro[$morf] > 0 && $total_pro[$morf] < 5)  )    {
            
                if (($total_pro < 10) or (strlen($total_pro)!=1 && $total_pro[strlen($total_pro)-2]!=1)) {
                if ($total_pro[$morf] == 1)    {
                    $total_pro = 1;
                }    else    {
                    $total_pro = 2;
                }
                } else    {
                    $total_pro = 3;
                }
            
            }    else    {
                $total_pro = 3;
            }    
        
        return $total_pro;
    }

в языковых файлах

russian

$_['total_products1']    = 'в магазине %s товар';
$_['total_products2']    = 'в магазине %s товара';
$_['total_products3']    = 'в магазине %s товаров';

english

$_['total_products1']    = '%s product in store';
$_['total_products2']    = '%s products in store';
$_['total_products3']    = '%s products in store';

решение может и не самое изящное, но вполне рабочее - результат можно увидеть по ссылке :-)

Share this post


Link to post
Share on other sites

так просто в массиве использовать языковые переменные ;)

уточни пожалуйста (можно в личку) с меня пиво :-)

Share this post


Link to post
Share on other sites

вместо

$array = array("товар", "товара", "товаров");

использовать

$total1 = $this->language->get('total1');
$total2 = $this->language->get('total2');
$total3 = $this->language->get('total3');

$array = array($total1, $total2, $total3);

$total1, $total2 и $total3 предварительно прописать в нужных языковых файлах

Share this post


Link to post
Share on other sites

Это не полное решение.

При обновлении аяксом опенкарт использует другие переменные.

Плюс, непонятно, зачем убрали вывод суммы - вроде, ТС этого не просил :-)

Полный вариант

 

В catalog\controller\common\cart.php  заменяем

$data['text_items'] = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total));

на

	$count = $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0);
	function getWord($number, $suffix) {
	$keys = array(2, 0, 1, 1, 1, 2);
	$mod = $number % 100;
	$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
	return $suffix[$suffix_key];
	}
	$text_items1 = $this->language->get('text_items1');
	$text_items2 = $this->language->get('text_items2');
	$text_items5 = $this->language->get('text_items5');
	$array = array($text_items1, $text_items2, $text_items5);
	$currency = $this->currency->format($total);
$data['text_items'] = $count .' '. getWord($count, $array).' - '.$currency;

а в \catalog\language\russian\common\cart.php добавляем

$_['text_items1']	= 'товар';
$_['text_items2']	= 'товара';
$_['text_items5']	= 'товаров';

Теперь аналогично надо сделать для аякс-запросов:

 

в файле \catalog\controller\checkout\cart.php   ДВА раза надо заменить

$json['total'] = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total));

на

	$count = $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0);
	function getWord($number, $suffix) {
	$keys = array(2, 0, 1, 1, 1, 2);
	$mod = $number % 100;
	$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
	return $suffix[$suffix_key];
	}
	$text_items1 = $this->language->get('text_items1');
	$text_items2 = $this->language->get('text_items2');
	$text_items5 = $this->language->get('text_items5');
	$array = array($text_items1, $text_items2, $text_items5);
	$currency = $this->currency->format($total);
$json['total'] = $count .' '. getWord($count, $array).' - '.$currency;

И, соответственно, в \catalog\language\russian\checkout добавляем

$_['text_items1']	= 'товар';
$_['text_items2']	= 'товара';
$_['text_items5']	= 'товаров';

Проверено на ОС 2.102, работает.

Edited by Shureg

Share this post


Link to post
Share on other sites

ТС про сумму и не говорил ничего...

 

Он просил "Подскажите", а не "Дайте готовое и ОБЯЗАТЕЛЬНО ПОЛНОЕ решение".

 

Shureg, чувствуете разницу?

Share this post


Link to post
Share on other sites

ТС про сумму и не говорил ничего...

 

Он просил "Подскажите", а не "Дайте готовое и ОБЯЗАТЕЛЬНО ПОЛНОЕ решение".

 

Shureg, чувствуете разницу?

Вам поговорить не с кем? Считаете мой ответ менее полезным, чем ваш?

Share this post


Link to post
Share on other sites

Создаете массив из 10 элементов {'товаров','товар','товара','товара','товара','товаров',...'товаров'}

Значение "Стоящие рядом цифры" делите на 10, берете остаток.

@igon, 1 товар, 11 товаров. 2 товара, 12 товаров, 22 товара

Share this post


Link to post
Share on other sites

@igon, 1 товар, 11 товаров. 2 товара, 12 товаров, 22 товара

Ну да, поэтому делить нужно на 20. Суть от этого меняется не очень сильно. ИМХО...

Share this post


Link to post
Share on other sites

Ну да, поэтому делить нужно на 20. Суть от этого меняется не очень сильно. ИМХО...

Так на 10 или на 20?

Суть очень даже меняется, ИМХО.

Вам тогда и массив надо до 20 увеличивать. Однако, при этом после 30 товаров всё опять испортится, и склонения пойдут какие попало...

Предложите делить на 30? :-D

Share this post


Link to post
Share on other sites

Ну да, поэтому делить нужно на 20. Суть от этого меняется не очень сильно. ИМХО...

Остаток от деления на 20 у любого числа меньше 21 будет равен нулю. Кстати, при делении на 10 эта же проблема будет присутствовать. 1 товаров, 2 товаров, 3 товаров...

Если суть - это наличие рабочего алгоритма, то как истинная блондинка, я считаю: он или есть или его нет. Я думал, приведён готовый алгоритм.

Share this post


Link to post
Share on other sites

Всем  привет! Да задачи не было показывать сумму, но убирать ее не совсем корректно. То есть задача была склонить слова без ущерба функционала))) Спасибо за решение)))

Edited by Grosso2020

Share this post


Link to post
Share on other sites

Остаток от деления на 20 у любого числа меньше 21 будет равен нулю. Кстати, при делении на 10 эта же проблема будет присутствовать. 1 товаров, 2 товаров, 3 товаров...

Если суть - это наличие рабочего алгоритма, то как истинная блондинка, я считаю: он или есть или его нет. Я думал, приведён готовый алгоритм.

Ну какой тут готовый алгоритм! Всего лишь подсказка, что падежи можно извлекать по индексу массива, а сам индекс получать из остатка от деления.

Share this post


Link to post
Share on other sites

Зачем изобретать велосипед?

Для склонения существительных рядом с числительным есть несколько готовых, опробованных алгоритмов.

Желающим ознакомиться - гугл в помощь.

В примере specussa использован один из самых красивых, имхо.

Доработанное готовое решение для opencarta:

Проверено на ОС 2.102, работает.

PS:

Остаток от деления на 20 у любого числа меньше 21 будет равен нулю. Кстати, при делении на 10 эта же проблема будет присутствовать. 1 товаров, 2 товаров, 3 товаров...

деление по модулю в php работает не так, как арифметический остаток. Вывод 2%10 будет не 0, как ожидается математически, а 2.

Edited by Shureg

Share this post


Link to post
Share on other sites

Замечательная идея. Для склонения одного слова всего-то и потребуется:

прочитать длинный мануал

установить словари

установить собственно библиотеку

подключить это счастье в индексе опенкарта

откорректировать (согласно длинному мануалу) файлы темы.

:huh:

Share this post


Link to post
Share on other sites

кстати вот делал для себя склонение слова "отзыв" в товаре, если кому надо то вот

в файле controller/product/product.php строку

$data['reviews'] = sprintf($this->language->get('text_reviews'), (int)$product_info['reviews']);

заменить на:

$count = (int)$product_info['reviews'];
function getWords($number, $suffix) {
$keys = array(2, 0, 1, 1, 1, 2);
$mod = $number % 100;
$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
return $suffix[$suffix_key];
}
$total1 = $this->language->get('text_reviews1');
$total2 = $this->language->get('text_reviews2');
$total3 = $this->language->get('text_reviews3');

$array = array($total1, $total2, $total3);
            
$data['reviews'] = $count .' '. getWords($count, $array);

ну и соответственно добавить переменные в языки

$_['text_reviews1']                           = 'отзыв';
$_['text_reviews2']                           = 'отзыва';
$_['text_reviews3']                           = 'отзывов';

Share this post


Link to post
Share on other sites
В 17.04.2016 в 15:58, ussa сказал:

кстати вот делал для себя склонение слова "отзыв" в товаре, если кому надо то вот

в файле controller/product/product.php строку

$data['reviews'] = sprintf($this->language->get('text_reviews'), (int)$product_info['reviews']);

заменить на:

$count = (int)$product_info['reviews'];
function getWords($number, $suffix) {
$keys = array(2, 0, 1, 1, 1, 2);
$mod = $number % 100;
$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
return $suffix[$suffix_key];
}
$total1 = $this->language->get('text_reviews1');
$total2 = $this->language->get('text_reviews2');
$total3 = $this->language->get('text_reviews3');

$array = array($total1, $total2, $total3);
            
$data['reviews'] = $count .' '. getWords($count, $array);

ну и соответственно добавить переменные в языки

$_['text_reviews1']                           = 'отзыв';
$_['text_reviews2']                           = 'отзыва';
$_['text_reviews3']                           = 'отзывов';

Спасибо, пригодилось)

Share this post


Link to post
Share on other sites
В 18.03.2016 в 03:13, Shureg сказал:

Это не полное решение.

При обновлении аяксом опенкарт использует другие переменные.

Плюс, непонятно, зачем убрали вывод суммы - вроде, ТС этого не просил :-)

Полный вариант

 

В catalog\controller\common\cart.php  заменяем

$data['text_items'] = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total));

на

	$count = $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0);
	function getWord($number, $suffix) {
	$keys = array(2, 0, 1, 1, 1, 2);
	$mod = $number % 100;
	$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
	return $suffix[$suffix_key];
	}
	$text_items1 = $this->language->get('text_items1');
	$text_items2 = $this->language->get('text_items2');
	$text_items5 = $this->language->get('text_items5');
	$array = array($text_items1, $text_items2, $text_items5);
	$currency = $this->currency->format($total);
$data['text_items'] = $count .' '. getWord($count, $array).' - '.$currency;

а в \catalog\language\russian\common\cart.php добавляем

$_['text_items1']	= 'товар';
$_['text_items2']	= 'товара';
$_['text_items5']	= 'товаров';

Теперь аналогично надо сделать для аякс-запросов:

 

в файле \catalog\controller\checkout\cart.php   ДВА раза надо заменить

$json['total'] = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total));

на

	$count = $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0);
	function getWord($number, $suffix) {
	$keys = array(2, 0, 1, 1, 1, 2);
	$mod = $number % 100;
	$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
	return $suffix[$suffix_key];
	}
	$text_items1 = $this->language->get('text_items1');
	$text_items2 = $this->language->get('text_items2');
	$text_items5 = $this->language->get('text_items5');
	$array = array($text_items1, $text_items2, $text_items5);
	$currency = $this->currency->format($total);
$json['total'] = $count .' '. getWord($count, $array).' - '.$currency;

И, соответственно, в \catalog\language\russian\checkout добавляем

$_['text_items1']	= 'товар';
$_['text_items2']	= 'товара';
$_['text_items5']	= 'товаров';

Проверено на ОС 2.102, работает.

 

 

Данное решение не работает с модулем - Simple - упрощенная регистрация и заказ.

 

Подскажите пожалуйста как адаптировать этот код для  Simple?

 $minicart = $this->simplecheckout->getSettingValue('minicartText', 'cart');
            
            $text_items = '';
            $language_code = $this->simplecheckout->getCurrentLanguageCode();

            if ($minicart && !empty($minicart[$language_code])) {
                $text_items = $minicart[$language_code];
            }

            if (!$text_items) {
                $this->language->load('checkout/cart');
                $text_items = $this->language->get('text_items');
                $this->language->load('checkout/simplecheckout');
            }

            $this->_templateData['cart_total'] = sprintf($text_items, $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->simplecheckout->formatCurrency($total));
        

 

Edited by mx928

Share this post


Link to post
Share on other sites
В 17.04.2016 в 15:58, ussa сказал:

кстати вот делал для себя склонение слова "отзыв" в товаре, если кому надо то вот

в файле controller/product/product.php строку

$data['reviews'] = sprintf($this->language->get('text_reviews'), (int)$product_info['reviews']);

заменить на:

$count = (int)$product_info['reviews'];
function getWords($number, $suffix) {
$keys = array(2, 0, 1, 1, 1, 2);
$mod = $number % 100;
$suffix_key = ($mod > 7 && $mod < 20) ? 2: $keys[min($mod % 10, 5)];
return $suffix[$suffix_key];
}
$total1 = $this->language->get('text_reviews1');
$total2 = $this->language->get('text_reviews2');
$total3 = $this->language->get('text_reviews3');

$array = array($total1, $total2, $total3);
            
$data['reviews'] = $count .' '. getWords($count, $array);

ну и соответственно добавить переменные в языки

$_['text_reviews1']                           = 'отзыв';
$_['text_reviews2']                           = 'отзыва';
$_['text_reviews3']                           = 'отзывов';

Благодарю! Пригодилось. А как его в рекомендуемые товары прикрутить такое же можно? (catalog/controller/extension/module/featured.php)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
You are posting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×

Important Information

On our site, cookies are used and personal data is processed to improve the user interface. To find out what and what personal data we are processing, please go to the link. If you click "I agree," it means that you understand and accept all the conditions specified in this Privacy Notice.