Учитывая наличие интереса к этой теме у сообщества, продолжаю знакомить со своими плагинами для Smarty. С первой частью можно ознакомиться здесь.
Насущная проблема: вывести пользователю, сколько комментариев к записи в блоге есть. Самый жуткий вариант: «2 комментариев». Чуть менее ужасный — «Комментариев: 2». Но ведь так хочется увидеть надписи на нормальном русском языке: «1 комментарий», «22 комментария», «38 комментариев»!
Именно этой цели и служит очередной модификатор declension (с англ. — склонение).
Формат: {$count|declension:'словоформы':'язык'}, где:
$count — количество пересчитываемых элементов (не выводится)
'словоформы' — перечисление через точку с запятой требуемых словоформ для текущего языка. Т.е. для русского это 'пень; пня; пней' (формы для 1, 2 и 5 предметов), для английского — 'stump,stumps' (формы для 1 и нескольких предметов). Допускается (а в моих проектах это основная возможность) задания термина из локализации, в виде: 'группа/термин'.
'язык' — двухбуквенный код языка, если очень приспичит. Необязателен.
Примеры использования:
{$messages} {$messages|declension:'сообщение; сообщения; сообщений'}
или
{$messages} {$messages|declension:'Forum/messages'} — когда требуется многоязычность
Файл smarty/plugins/modifier.declension.php (скачать)
Для корректной работы модификатора помимо уже упоминавшегося в прошлых плагинах словаря терминов текущего языка ($Language), требуется ещё и переменная $currentLanguage, указывающая текущий язык. (Я уже упоминал в предыдущей статье, что наличие этих глобальных переменных — это для статьи, в моих оригинальных исходниках там находятся обращения к функциям фреймворка)
Ещё одна тривиальная задача: корректно отображать размеры файлов. «384 б», «613,8 Кб», «14,1 Тб». Кто-то ведь должен переводить эти тысячи и миллиарды байт в удобный для пользователя вид. У меня этим занимается модификатор filesize.
Формат: {$filesize|filesize:'точность'}, где:
'точность' — необязательное количество знаков после запятой для округления результатов.
Файл smarty/plugins/modifier.filesize.php (скачать)
Как и в случае с модификатором date (описанном в первой части статьи), я использую таблицы локализации не только для слов и выражений интерфейса, а ещё и для хранения технической информации (здесь — символ разделителя дробной части для текущего языка).
Для английского языка переводы выглядят так (для русского они мало чем отличаются, не буду дублировать):
Не хочется раздувать статью до неприличных размеров, поэтому пока остановлюсь. Продолжение следует.
1.2. Склонение слов
Насущная проблема: вывести пользователю, сколько комментариев к записи в блоге есть. Самый жуткий вариант: «2 комментариев». Чуть менее ужасный — «Комментариев: 2». Но ведь так хочется увидеть надписи на нормальном русском языке: «1 комментарий», «22 комментария», «38 комментариев»!
Именно этой цели и служит очередной модификатор declension (с англ. — склонение).
Формат: {$count|declension:'словоформы':'язык'}, где:
$count — количество пересчитываемых элементов (не выводится)
'словоформы' — перечисление через точку с запятой требуемых словоформ для текущего языка. Т.е. для русского это 'пень; пня; пней' (формы для 1, 2 и 5 предметов), для английского — 'stump,stumps' (формы для 1 и нескольких предметов). Допускается (а в моих проектах это основная возможность) задания термина из локализации, в виде: 'группа/термин'.
'язык' — двухбуквенный код языка, если очень приспичит. Необязателен.
Примеры использования:
{$messages} {$messages|declension:'сообщение; сообщения; сообщений'}
или
{$messages} {$messages|declension:'Forum/messages'} — когда требуется многоязычность
Файл smarty/plugins/modifier.declension.php (скачать)
<?php
/**
* Smarty plugin - declension modifier
* @package Smarty
* @subpackage plugins
*/
/**
* Модификатор declension: склонение существительных по правилам английского языка
*
* @param array $forms (напр: 0 => article, 1 => articles)
* @param int $count
* @return string
*/
function smarty_modifier_declension_en($forms, $count)
{
if ($count==1)
return $forms[0];
else
return $forms[1];
}
/**
* Модификатор declension: склонение существительных по правилам русского языка
*
* @param array $forms (напр: 0 => пень, 1 => пня, 2 => пней)
* @param int $count
* @return string
*/
function smarty_modifier_declension_ru($forms, $count)
{
$mod100 = $count % 100;
switch ($count%10) {
case 1:
if ($mod100 == 11)
return $forms[2];
else
return $forms[0];
case 2:
case 3:
case 4:
if (($mod100 > 10) && ($mod100 < 20))
return $forms[2];
else
return $forms[1];
case 5:
case 6:
case 7:
case 8:
case 9:
case 0:
return $forms[2];
}
}
/**
* Модификатор declension: склонение существительных
*
* @param int $count
* @param string $forms
* @param string $language
* @return string
*/
function smarty_modifier_declension($count, $forms, $language='')
{
global $currentLanguage, $Language;
if (!$language)
$language = $currentLanguage;
$count = abs($count);
// Пытаемся выщемить термин из словаря
if (preg_match('/^(.*)\/(.*)$/', $forms, $termine))
{
if ($termine[1] && $termine[2])
{
$forms = $Language[$termine[1]][$termine[2]];
}
}
// Выделяем отдельные словоформы
$forms = explode(';', $forms);
$fn = 'smarty_modifier_declension_'.$language;
if (function_exists($fn))
{
// Есть персональная функция для текущего языка
return $fn($forms, $count);
} else {
// Действуем по образу и подобию английского языка
return smarty_modifier_declension_en($forms, $count);
}
}
?>
Для корректной работы модификатора помимо уже упоминавшегося в прошлых плагинах словаря терминов текущего языка ($Language), требуется ещё и переменная $currentLanguage, указывающая текущий язык. (Я уже упоминал в предыдущей статье, что наличие этих глобальных переменных — это для статьи, в моих оригинальных исходниках там находятся обращения к функциям фреймворка)
1.3. Размер файлов
Ещё одна тривиальная задача: корректно отображать размеры файлов. «384 б», «613,8 Кб», «14,1 Тб». Кто-то ведь должен переводить эти тысячи и миллиарды байт в удобный для пользователя вид. У меня этим занимается модификатор filesize.
Формат: {$filesize|filesize:'точность'}, где:
'точность' — необязательное количество знаков после запятой для округления результатов.
Файл smarty/plugins/modifier.filesize.php (скачать)
<?php
/**
* Smarty plugin - filesize modifier
*
* @author Vasily Melenchuk
* @package Smarty
* @subpackage plugins
*/
/**
* Модификатор filesize: вывод размеров для файлов
*
* @param int/float $size
* @param int $precision - требуемая точность (знаков после запятой)
* @return string
*/
function smarty_modifier_filesize($size, $precision=2)
{
global $Language;
if(!is_numeric($precision) || !is_numeric($size))
{
// Что-то явно не так
trigger_error('Modifier filesize: Invalid input params');
return '';
}
// Находим подходящую величину
$result = '?';
$multiplier = 1;
while ($multiplier <= 1099511627776) // 1 Тб в байтах. Пока хватит
{
if ($size/$multiplier<1)
{
break;
} else {
$result = round($size/$multiplier, $precision).' '.$Language['global']['filesize_'.$multiplier];
}
$multiplier *= 1024;
}
// Финальный штрих: разделитель дробной части
$result = str_replace('.', $Language['global']['decimal_separator'], $result);
return $result;
}
?>
Как и в случае с модификатором date (описанном в первой части статьи), я использую таблицы локализации не только для слов и выражений интерфейса, а ещё и для хранения технической информации (здесь — символ разделителя дробной части для текущего языка).
Для английского языка переводы выглядят так (для русского они мало чем отличаются, не буду дублировать):
$Language['global']['decimal_separator'] = '.';
$Language['global']['filesize_1'] = 'b';
$Language['global']['filesize_1024'] = 'Kb';
$Language['global']['filesize_1048576'] = 'Mb';
$Language['global']['filesize_1073741824'] = 'Gb';
$Language['global']['filesize_1099511627776'] = 'Tb';
Не хочется раздувать статью до неприличных размеров, поэтому пока остановлюсь. Продолжение следует.