1 яблоко. 2 яблока. 5 яблок. Или о миграции алгоритмов

| Комментариев: 4

В начале века я пользовался функцией на парсере, не уверен, что точно знаю, кем написанной, и не знаю, где сегодня найти в архиве. Она умела выбирать правильный падеж существительного, поставленного после числа. Хорошо помню, что она называлась ^rightCase[], но сходу не смог найти ее в бекапах. Но зато нашел ее предшественницу:

@grammar[count]
    $count[0$count]

    $last2[^count.match[(\d\d)^$]]
    $last2[$last2.1]

    ^if(^last2.match[[02-9]1]){
        $ending[]
    }{
        ^if(^last2.match[[2-4]^$]){
            $ending[а]
        }{
            $ending[ов]
        }
    }
    $result[язык$ending]

Потом долгое время пользовался (и продолжаю) функцией на перле, переписанной по мотивам этого алгоритма, и размещенной на спане в модуле Lingua::RU::Numeric::Declension:

sub numdecl {
   my ($number, $nominative, $genitive, $plural) = @_;

   return $plural if $number =~ /1.$/;

   my ($last_digit) = $number =~ /(.)$/;

   return $nominative if $last_digit == 1;
   return $genitive if $last_digit > 0 && $last_digit < 5;
   return $plural;
}

А сегодня еще раз скопировал этот алгоритм, но уже на XSLT:

<func:function name="w:declension">
    <xsl:param name="number"/>
    <xsl:param name="nominative"/>
    <xsl:param name="genitive"/>
    <xsl:param name="plural"/>
    <xsl:variable name="length" select="string-length(string($number))"/>
    <xsl:variable name="last" select="substring(string($number), $length, 1)"/>
    <func:result>
        <xsl:choose>
            <xsl:when test="$length &gt; 1 and substing(string($number), $length - 1, 1) = '1'">
                <xsl:value-of select="$plural"/>
            </xsl:when>
            <xsl:when test="$last = '1'">
                <xsl:value-of select="$nominative"/>
            </xsl:when>
            <xsl:when test="$last &gt; 0 and $last &lt; 5">
                <xsl:value-of select="$genitive"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$plural"/>
            </xsl:otherwise>
        </xsl:choose>
    </func:result>
</func:function>

Какая из этого мораль? Да такая, что в большинстве случаев выбор языка не важен.

Комментариев: 4

Не обязательно усложнять жизнь регэкспами:

# Russian, Ukrainian, Belarusian, Croatian, Serbian
if ($lang eq 'ru' || $lang eq 'uk' || $lang eq 'be' || $lang eq 'hr' || $lang eq 'sr') {
    $r = sub {
        my $n = shift;
        $n = -$n if $n < 0;
        # nplurals = 3
        return $n % 10 == 1 && $n % 100 != 11 ? 0 :
                $n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2;
    }
}

Верстка пожрала код в коменте.
Вот здесь полностью + много всяких языков:
http://github.com/alien/ali-samples/raw/master/Ali/I18N/PluralForms.pm

Текущая версия для Парсера: http://www.parser.ru/examples/decline/

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

Комментировать

Страницы

  • img

Об этой записи

Сообщение опубликовано 20.04.2010 22:39. Автор — ash.

Предыдущая запись — История одного проекта

Следующая запись — Libapreq2 + <SUP> + MSIE = Fail

Смотрите новые записи на главной странице или загляните в архив, где есть ссылки на все сообщения.