Declension function for words after numbers (PHP, JS)
Often there is a need to display a number with a label, and in this case, in the Russian language, the ending of the label will depend on the specified number. For example, displaying the number of days: "1 day", "2 days", "5 days". As can be seen, the form of the word changes depending on the number.
Thus, we need a function that would decline words that come after a number.
Below, I tried to write a universal option for declining words after a numeral.
/**
* 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.2
*/
function num_decline( $number, $titles, $show_number = true ): string {
if( is_string( $titles ) ){
$titles = preg_split( '/, */', $titles );
}
// when 2 elements are specified
if( empty( $titles[2] ) ){
$titles[2] = $titles[1];
}
$cases = [ 2, 0, 1, 1, 1, 2 ];
$intnum = abs( (float) strip_tags( $number ) );
$intnum = (int) round( $intnum );
$title_index = ( $intnum % 100 > 4 && $intnum % 100 < 20 )
? 2
: $cases[ min( $intnum % 10, 5 ) ];
return ( $show_number ? "$number " : '' ) . $titles[ $title_index ];
}
#1 Usage Example
It is convenient that parameters can be passed in different ways. To avoid having to remember how to do it each time, for example:
echo num_decline( 4, 'книга, книги, книг' ); // 4 книги echo num_decline( 5, ['книга','книги','книг'] ); // 5 книг echo num_decline( 4, 'книга, книги, книг', 0 ); // книги
#1 Let's output the inflected text before and after the number
$num = 23; echo sprintf( "%s $num %s", num_decline( $num, 'Опубликован,Опубликовано', 0 ), num_decline( $num, 'комментарий,комментария,комментариев', 0 ) ); // Опубликовано 23 комментария
Declension function for words after numbers (JS)
The same function but for JS.
/**
* Declension of a word after a number.
*
* // Example of invocation:
* num_decline( num, 'книга,книги,книг' )
* num_decline( num, 'book,books' )
* num_decline( num, [ 'книга','книги','книг' ] )
* num_decline( num, [ 'book','books' ] )
*
* @param {int|string} number The number after which the word will be. You can specify the number in HTML tags.
* @param {string|array} titles Variants of declension or the first word for multiples of 1.
* @param {boolean} show_number Specify 00 here when you do not need to output the number itself.
*
* @return string For example: 1 книга, 2 книги, 10 книг.
*
* @version 3.1
*/
function num_decline( number, titles, show_number = true ){
if( typeof titles === 'string' ){
titles = titles.split( /, */ )
}
// when 2 elements are specified
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 ];
}
A shorter version:
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 ]
}
// usage
numDecline( 1, ['книга', 'книги', 'книг'] )