Функция склонения слов после чисел (PHP, JS)

Не редко возникает необходимость вывода числа с подписью и в этом случае в русском языке окончание подписи будет зависеть от того какое число указано. Например, вывод количества дней: 1 день, 2 дня, 5 дней. Как видно форма слова меняется в зависимости от числа.

Таким образом нам нужна функция, которая бы склоняла слова, которые идут после числа.

Ниже я постарался написать универсальный вариант склонение слов после числительного.

/**
 * Word declension after a number.
 *
 *     // Examples of invocation:
 *     num_decline( $num, 'книга,книги,книг' )
 *     num_decline( $num, 'book,books' )
 *     num_decline( $num, [ 'книга','книги','книг' ] )
 *     num_decline( $num, [ 'book','books' ] )
 *
 * @param int|string   $number       The number that is followed by the word. You can use HTML tags.
 * @param string|array $titles       Variants of words for numbers.
 * @param bool         $show_number  Set to `false`, when you don't want to output the number itself.
 *
 * @return string For example: 1 book, 2 books, 10 books.
 *
 * @version 3.1
 */
function num_decline( $number, $titles, $show_number = true ){

	if( is_string( $titles ) ){
		$titles = preg_split( '/, */', $titles );
	}

	// когда указано 2 элемента
	if( empty( $titles[2] ) ){
		$titles[2] = $titles[1];
	}

	$cases = [ 2, 0, 1, 1, 1, 2 ];

	$intnum = abs( (int) strip_tags( $number ) );

	$title_index = ( $intnum % 100 > 4 && $intnum % 100 < 20 )
		? 2
		: $cases[ min( $intnum % 10, 5 ) ];

	return ( $show_number ? "$number " : '' ) . $titles[ $title_index ];
}

#1 Пример использования

Удобно, что параметры можно передавать по-разному. Чтобы каждый раз не вспоминать как именно нужно это делать, например:

echo num_decline( 4, 'книга, книги, книг' );     // 4 книги

echo num_decline( 5, ['книга','книги','книг'] ); // 5 книг

echo num_decline( 4, 'книга, книги, книг', 0 );  // книги

#1 Выведем склоняемый текст до и после числа

$num = 23;
echo sprintf( "%s $num %s",
	num_decline( $num, 'Опубликован,Опубликовано', 0 ),
	num_decline( $num, 'комментарий,комментария,комментариев', 0 )
);
// Опубликовано 23 комментария

Функция склонения слов после чисел (JS)

Та же самая функция только для JS.

/**
 * Склонение слова после числа.
 *
 *     // Примеры вызова:
 *     num_decline( num, 'книга,книги,книг' )
 *     num_decline( num, 'book,books' )
 *     num_decline( num, [ 'книга','книги','книг' ] )
 *     num_decline( num, [ 'book','books' ] )
 *
 * @param {int|string}   number       Число после которого будет слово. Можно указать число в HTML тегах.
 * @param {string|array} titles       Варианты склонения или первое слово для кратного 1.
 * @param {boolean}      show_number  Указываем тут 00, когда не нужно выводить само число.
 *
 * @return string Например: 1 книга, 2 книги, 10 книг.
 *
 * @version 3.1
 */
function num_decline( number, titles, show_number = true ){

	if( typeof titles === 'string' ){
		titles = titles.split( /, */ )
	}

	// когда указано 2 элемента
	if( typeof titles[2] === 'undefined' ){
		titles[2] = titles[1]
	}

	const cases = [ 2, 0, 1, 1, 1, 2 ]

	// strip_tags
	const intnum = Math.abs( parseInt( `${number}`.replace(/<\/?[^>]+>/gi, '') ) )

	let title_index = ( intnum % 100 > 4 && intnum % 100 < 20 )
		? 2
		: cases[ Math.min( intnum % 10, 5 ) ];

	return ( show_number ? `${number} ` : '' ) + titles[ title_index ];
}

Более короткий вариант:

function numDecline( n, titles )
{
	return titles[ 1 === n % 10 && 11 !== n % 100 ? 0 : 2 <= n % 10 && 4 >= n % 10 && ( 10 > n % 100 || 20 <= n % 100 ) ? 1 : 2 ]
}

// использование
numDecline( 1, ['книга', 'книги', 'книг'] )

Эта заметка встроена в: Полезные PHP коды — для опытных