Рубрики
Backend

Функция склонения чисел на PHP по русски

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

Все правила закладываются в перевод, но иногда возникает необходимость просклонять числа программно.

Далее я приведу пример функции склонения чисел на языке PHP. Пример довольно простой, поэтому не должно возникнуть сложностей переписать его на другом языке при необходимости.

Зачем на сайте склонение чисел?

Данную функцию можно применять к количеству оставленных комментарием, числа товаров, оставшихся секунд и тп.

Теория склонения чисел

Для правильного склонения чисел необходимо всего три формы:

  1. существительное в единственном числе в именительном падеже;
  2. существительное во множественном числе в именительном падеже;
  3. существительное во множественном числе в родительском падеже.

Пример:

  1. деталь;
  2. детали;
  3. деталей.

Если считать от 0 до 9, то при значении от 2 до 4 применяется второй вариант.

При значении равном единице — первый. А при значениях 0 и от 5 до 9 применяется третий вариант.

Также, третий вариант применяется при счете от 10 до 20.

Как реализовать склонение чисел?

Если делить число по модулю 10, то в остатке будет число меньше 10. В числах от 0 до 9 и от 21 склонение производится именно по этому остатку. Поэтому нам просто нужно делить числа по модулю, так мы сможем определить форму склонения.

Условимся, что наша функция будет принимать два параметра: число и массив с формами склонений.

При запуске функции в цикле такого вида:

$words = [ 'деталь', 'детали', 'деталей' ];
for ( $i = 0; $i <= 32; $i ++ ) {
	echo numberMood( $i, $words ) . PHP_EOL;
}

получим следующий вывод:

0 деталей
1 деталь
2 детали
3 детали
4 детали
5 деталей
6 деталей
7 деталей
8 деталей
9 деталей
10 деталей
11 деталей
12 деталей
13 деталей
14 деталей
15 деталей
16 деталей
17 деталей
18 деталей
19 деталей
20 деталей
21 деталь
22 детали
23 детали
24 детали
25 деталей
26 деталей
27 деталей
28 деталей
29 деталей
30 деталей
31 деталь
32 детали

Это явно показывает, что функция работает верно.

Код функции

Листинг функции приведен ниже:

/**
 * Склонение чисел
 * 
 * @param int $value
 * @param array $words - массив состоящий из трех строк.
 * первый элемент: существительное в единственном числе в именительном падеже,
 * второй: существительное во множественном числе в именительном падеже
 * третий: существительное в родительном падеже
 * Пример: ['деталь', 'детали', 'деталей']
 *
 * @return string
 */
function numberMood( int $value, array $words ): string {
	// если число отрицательное, то $sign = true
	$sign = ! ! $value < 0;

	// определяем цифру, стоящую справа
	$number = abs( $value ) % 10;

	// если правая цифра 0 или больше 5 или число в диапазоне 10-20
	if ( 0 == $number || 5 <= $number || ( 20 >= $value && 10 <= $value ) ) {
		$value .= " {$words[2]}";
	} // если это единица
	elseif ( 1 == $number ) {
		$value .= " {$words[0]}";
		// если в диапазоне от 2 до 4 включительно
	} elseif ( 4 >= $number && 2 <= $number ) {
		$value .= " {$words[1]}";
	}

	// возвращаем строку
	return $sign ? '-' : '' . $value;
}

Внимание!

Информация для тех кто использует старые версии PHP(ниже 7). Чтобы код работал корректно, вам следует удалить в определении функции указание типов.