CommerCentr
EN
Sign in

Плюралізатор іменників [множини] (для пагінації)

#1
доброго часу, коллеги!
може комусь у private-note знадобиться плюралізатор множини:
/*
/ autor: vaso aKa Baco; use ex.:
/ $apples_text = reNumerator(101, array('бал', 'бали', 'балів')
*/

function reNumerator(int $number, array $target): string {
$cases = [2, 0, 1, 1, 1, 2];
return $number . ' ' . ($target ? $target[($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)]] : false);
}

де вхідними даними є: число - цифрове значення, для котрого обирається множина, та массив із варіантів множин, я використовував тестово при плюралізації балів у кабінеті користувача у одному із проектів, ось як відображає:
$page = (int)$_GET['page'] ?? 0;
$page = 101; //
для одиничного елементу в массиві множин
reNumerator($page, array('бал', 'бали', 'балів')
1687965322571.png
для 2-3-4 кінцевих значеннях:
$page = 523; reNumerator($page, array('бал', 'бали', 'балів')
1687965396102.png
та для 0-х значень:
$page = 300; reNumerator($page, array('бал', 'бали', 'балів')
1687965537904.png

Ви можете використовувати як постфіксні пагінаційні назви сторінок, по типу:
<показано 1 із (101, 523, 300) сторінка/сторінки\сторінок, де в коді відповідно описано:
$current_page = 7;
$total_pages = 21;
$pagination_text = sprint_f($this->language->get('text_postfix'), reNumerator($current_page, array('сторінка', 'сторінки', 'сторінок')), $total_pages);
view:
$_['text_postfix'] = 'Показано %s з %d';

на вихлопі вангую щось таке:
Показано 7 сторінок з 21

Як реалізувати для ОС (опенкарту, брокарту, тощо...) послідовні кроки:
0 - додати у хелпери (внизу у файлі додаті і збереги system/helper/general.php) ось цю функцію, що описана вище, та для ОС я б підправив трохи:
function reNumerator($number, $target) {
$cases = [2, 0, 1, 1, 1, 2];
return $number . ' ' . ($target ? $target[($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)]] : false);
}

SEx [save && exit]...

1 - у основному мовному файлі вашої локалі (у мене це: catalog/language/uk-ua/uk-ua.php), шукаємо змінну:$_['text_pagination']та міняємо аж до крпки з комою (;) на таке значення:
//$_['text_pagination'] = 'Показано з %d по %d із %d (%d сторінок)';
$_['text_postfix'] = array('сторінка', 'сторінки', 'сторінок');
$_['text_pagination'] = 'Показано з %d по %d із %d (%s)';

SEx...

2. у файлі контроллера [у мене це список у категорії: catalog/controller/product/category.php], де омріяно заюзати дану фічу, шукаємо ось такий рядок в коді:
$data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($product_total - $limit)) ? $product_total : ((($page - 1) * $limit) + $limit), $product_total, ceil($product_total / $limit));


розбирати не стану, напишу просто, що потрібно 4-й аргумент, котрий залітає до sprintf, пропустити через плюралізатор, надавши загальну к-сть сторінок, котрий знаходиться у виразіceil($product_total / $limit)і массив наших множин, котрі підбираємо по задачі і виходить ось такий код (замінити попередні рядки:

//$data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($product_total - $limit)) ? $product_total : ((($page - 1) * $limit) + $limit), $product_total, ceil($product_total / $limit));

$data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $limit) + 1 : 0, ((($page - 1) * $limit) > ($product_total - $limit)) ? $product_total : ((($page - 1) * $limit) + $limit), $product_total, reNumerator(ceil($product_total / $limit), $this->language->get('text_postfix')));


SEx... clear modification... enjoyВкладення: 1687965322571.png · 1687965396102.png · 1687965537904.png
#2
Baco$target[($number

тут беда

Треба перевіряти наявність індекса
#3
SlaSoftтут беда

Треба перевіряти наявність індекса

так, писав з мінімалізму код, з урахуванням, що всі змінні\массиви будуть в наявності, якщо правильно підійти, то ось так би було найоптимальніше написати цю функцію (як на мене, та може є й своє бачення):
function reNumerator($number, $target) {
if ($number && is_array($target)) {
$cases = [2, 0, 1, 1, 1, 2];
$word_index = ($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)];
return $number . ' ' . (isset($target[$word_index]) ? $target[$word_index] : '');
}
return '';
}
#4
Я не проверял
Принцип - проверяй все, не доверяй входящим

Anyone can read. To post and vote, sign in.