Правильная форма существительного рядом с числом (счетная форма)
Часто бывает нужно рядом с числом (числительным) написать существительное в правильной форме. Например, 99 франков, 1000 и 1 ночь, но 33 коровы.
Для этого есть специальная функция, которая в качестве параметров принимает число и три возможные варианта написания, например:
- «рубль» — для единственного числа именительного падежа
- «рубля» — для единственного числа родительного падежа
- «рублей» — для множественного числа родительного падежа
Реализация на Java Script
/* * Правильная форма cуществительного рядом с числом (счетная форма). * * @param integer _number Число * @param string _case1 Единственное число именительный падеж * @param string _case2 Единственное число родительный падеж * @param string _case3 Множественное число родительный падеж * @return string */ function getCase(_number, _case1, _case2, _case3) { var base = _number - Math.floor(_number / 100) * 100; var result; if (base > 9 && base < 20) { result = _case3; } else { var remainder = _number - Math.floor(_number / 10) * 10; if (1 == remainder) result = _case1; else if (0 < remainder && 5 > remainder) result = _case2; else result = _case3; } return result; }
Вызов, чтоб попробовать
var tryNumbers = new Array(51, 52, 55); for (var i = 0; i < tryNumbers.length; i++) { alert(tryNumbers[i] + " " + getCase(tryNumbers[i], "рубль", "рубля", "рублей")); }
Реализация на PHP
/** * Правильная форма cуществительного рядом с числом (счетная форма). * * @param integer _number Число * @param string _case1 Единственное число именительный падеж * @param string _case2 Единственное число родительный падеж * @param string _case3 Множественное число родительный падеж * @return string */ function getCase($_number, $_case1, $_case2, $_case3) { $base = $_number - floor($_number / 100) * 100; $result = null; if ($base > 9 && $base < 20) { $result = $_case3; } else { $remainder = $_number - floor($_number / 10) * 10; if (1 == $remainder) $result = $_case1; else if (0 < $remainder && 5 > $remainder) $result = $_case2; else $result = $_case3; } return $result; }
Вызов, чтоб попробовать
foreach (array(51, 52, 55) as $number) { echo $number, ' ' , getCase($number, 'рубль', 'рубля', 'рублей') . PHP_EOL; }
Реализация на XSL(T)
<!-- Правильная форма cуществительного рядом с числом (счетная форма). --> <xsl:template name="get-case"> <xsl:param name="number"/> <!-- Число --> <xsl:param name="case1" /> <!-- Единственное число именительный падеж --> <xsl:param name="case2" /> <!-- Единственное число родительный падеж --> <xsl:param name="case3" /> <!-- Множественное число родительный падеж --> <xsl:variable name="base" select="$number - floor($number div 100) * 100" /> <xsl:choose> <xsl:when test="$base > 9 and $base < 20"> <xsl:value-of select="$case3" /> </xsl:when> <xsl:otherwise> <xsl:variable name="remainder" select="$number - floor($number div 10) * 10" /> <xsl:choose> <xsl:when test="$remainder = 1"> <xsl:value-of select="$case2" /> </xsl:when> <xsl:when test="$remainder > 0 and $remainder < 5"> <xsl:value-of select="$case2" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$case3" /> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template>
Вызов, чтоб попробовать
<xsl:text>51 </xsl:text> <xsl:call-template name="get-case"> <xsl:with-param name="number" select="51" /> <xsl:with-param name="case1">рубль</xsl:with-param> <xsl:with-param name="case2">рубля</xsl:with-param> <xsl:with-param name="case3">рублей</xsl:with-param> </xsl:call-template> <xsl:text>52 </xsl:text> <xsl:call-template name="get-case"> <xsl:with-param name="number" select="52" /> <xsl:with-param name="case1">рубль</xsl:with-param> <xsl:with-param name="case2">рубля</xsl:with-param> <xsl:with-param name="case3">рублей</xsl:with-param> </xsl:call-template> <xsl:text>55 </xsl:text> <xsl:call-template name="get-case"> <xsl:with-param name="number" select="55" /> <xsl:with-param name="case1">рубль</xsl:with-param> <xsl:with-param name="case2">рубля</xsl:with-param> <xsl:with-param name="case3">рублей</xsl:with-param> </xsl:call-template>
Благодарю за статью!
Впринципе нет ничего плохого в том, чтобы использовать приведенное решение, однако важно понимать, что его будет очень сложно масштабировать, особенно когда потребуется перевести сайт или приложение на другие языки.
Специально для таких простых задач, я разработал небольшой модуль на JavaScript, который позволяет склонять любые слова в зависимости от используемых числительных. Библиотека использует базу данных CLDR и таким образом работает практически с любым языком в мире. Она называется — Numerous: https://github.com/betsol/numerous.
Также, я написал небольшую статью о том, как можно ей воспользоваться: «How to pluralize any word in different languages using JavaScript?»: https://gist.github.com/slavafomin/f2e5259cab17d55af5d9fa4c2c2baa08. Извиняюсь, что на английском, но суть должна быть понятна.
Буду очень рад, если она Вам пригодится. Также буду рад любым отзывам и предложениям! Удачных склонений!