Smarty Установить окончание слова по числу

Мне часто требуется просклонять слово по числам:
0 слонов, 1 слон, 2 слона
Или слово страницы, очень часто требуется.

На смарти (но переделать в php проще простого) добавила функцию.


<?php
/**
 * Преобразование слов в зависимоси от числа
 * Например: преобразование слова комментарий
 * 0 комментариев,  1 комментарий,  2 комментария
 *
 * По наблюдениям всегда различны лишь 3 окончания ($n0, $n1, $n2).
 * Для верного вывода стот только проанализировать число ($num) как сроку, его окончание из 2х символов
 * 0                =>  $n0
 * 1 != 11          =>  $n1
 * 1 == 11          =>  $n0
 * 2-4 != 12..14    =>  $n2
 * 2-4 == 12..14    =>  $n0
 * 5                =>  $n0
 *
 * @created 11.08.11
 * 
 * @author olgatcpip
 * @contact olgatcpip@ya.ru    
 */

function smarty_function_wordnum($params, $template)
{
    $num    = 0;     //число слова
    $root   = '';     //корень слова
    $n0 = $n1= $n2 = '';    //окончания
    foreach($params as $_key => $_val)
    {
        switch ($_key)
        {
            case 'num':
                $num = (int)$_val;
                break;
            case 'root':
                $root = $_val;
                break;
            case 'n0':
                $n0 = $_val;
                break;
            case 'n1':
                $n1 = $_val;
                break;
            case 'n2':
                $n2 = $_val;
                break;
            default:
                return 'Error smarty_function_doc_tree: empty params!';
        }
    }
    if(!isset($root))
    {
        Return 'Error: smarty_function_wordnum: root params required!';
    }
    $numend = substr($num,-1);
    $word   = '';
    switch($numend)
    {
        case '0':
            $word = $root.$n0;
            break;
        case '1':
            if(substr($num,-2)!='11')
                $word = $root.$n1;
            else
                $word = $root.$n0;
            break;
        case '2':
        case '3':
        case '4':
            if(substr($num,-2) == '1'.(int)$numend)
                $word = $root.$n0;
            else
                $word = $root.$n2;
            break;
        default:
            $word = $root.$n0;
    }
    return $word;
}
 ?>

Пример выполнения
0 >>>> {wordnum num=0 root="страниц" n0="" n1="а" n2="ы"}<br/>
1 >>>> {wordnum num=1 root="страниц" n0="" n1="а" n2="ы"}<br/>
2 >>>> {wordnum num=2 root="страниц" n0="" n1="а" n2="ы"}<br/>
5 >>>> {wordnum num=5 root="страниц" n0="" n1="а" n2="ы"}<br/>
10 >>>> {wordnum num=10 root="страниц" n0="" n1="а" n2="ы"}<br/>
11 >>>> {wordnum num=11 root="страниц" n0="" n1="а" n2="ы"}<br/>
12 >>>> {wordnum num=12 root="страниц" n0="" n1="а" n2="ы"}<br/>
20 >>>> {wordnum num=20 root="страниц" n0="" n1="а" n2="ы"}<br/>
21 >>>> {wordnum num=21 root="страниц" n0="" n1="а" n2="ы"}<br/>
23 >>>> {wordnum num=23 root="страниц" n0="" n1="а" n2="ы"}<br/>
25 >>>> {wordnum num=25 root="страниц" n0="" n1="а" n2="ы"}<br/>
125 >>>> {wordnum num=125 root="страниц" n0="" n1="а" n2="ы"}<br/>
101 >>>> {wordnum num=101 root="страниц" n0="" n1="а" n2="ы"}<br/>
111 >>>> {wordnum num=111 root="страниц" n0="" n1="а" n2="ы"}<br/>

Результат будет таким
0 >>>> страниц
1 >>>> страница
2 >>>> страницы
5 >>>> страниц
10 >>>> страниц
11 >>>> страниц
12 >>>> страниц
20 >>>> страниц
21 >>>> страница
23 >>>> страницы
25 >>>> страниц
125 >>>> страниц
101 >>>> страница
111 >>>> страниц


ЕСЛИ ОБНАРУЖИТЕ ОШИБКУ, ПРОШУ СООБЩИТЬ.



Комментарии

  1. Как-то сложно оно у вас
    /**
    * For the formation of endings of words.
    *
    * @param int $value number.
    * @param string $word0 word in the singular.
    * @param string $word1 word in the plural (2, 3).
    * @param string $word2 word in the plural.
    * @param string $separator separator, default ' '.
    * @return string formed words
    * @access private.
    */
    private function morph($value, $word0, $word1, $word2, $separator = ' ')
    {
    if (preg_match('/1\d$/', $value))
    {
    return $value . $separator . $word2;
    } elseif (preg_match('/1$/', $value))
    {
    return $value . $separator . $word0;
    } elseif (preg_match('/(2|3|4)$/', $value))
    {
    return $value . $separator . $word1;
    } else
    {
    return $value . $separator . $word2;

    }
    }

    ОтветитьУдалить
  2. Надо потестить. Как правило регулярки в php5 медленнее работают чем такие (как у меня) извращения.
    Но ваш вариант куда короче и приятней выглядит. :)

    ОтветитьУдалить
  3. спасибо большое коллега! все работает чики-пуки ))))

    ОтветитьУдалить

Отправить комментарий

Популярные сообщения