Как стать автором
Обновить

Комментарии 92

Будем надеяться. что подобный пример поможет сайтам стать "человечнее". Спасибо.
полезно. писал по другому чуть-чуть. и в класс не оборачивал.
Ба! Как вы могли!
Ваш вариант не модный :)
А серьёзно — при наличии обертки в виде класса вкус не меняется, вкусно и полезно :)
А как же на счет 111, 112,..., 211 и т.д.?
Спасибо огромное за подсказку!
Исправил, поставил %100 там, где надо
А зачем изобретать велосипед ? Использование готовых - типа больше не модно ?
за ссылку спасибо

но иногда проще изобрести велосипед, чем тратить часы на поиск нужного
Но зато при первом подходе во вновьизобретённом велосипеде, как правило, получаются квадратные колёса (как у вас и вышло поначалу).
но как-то даже неловко искать готовое решение для такой пустяковой задачи в 10 строчек кода :)
спасибо за ссылку, очень элегантно, в одну строчку :)
Это по мнению иностранцев, отличительная сторона российских программеров — писать с нуля :)
да, этот ньюанс скорее сложен с точки зрения его "просекания" на уровне проектирования сайта/системы/итд. т.е. многим какбы сложно предугадать, что такая проблемка будет и надо ее заранее разрешить. а запрограммировать вышеописанное - уже тривиальная задача, и даже решение "влоб" подходит.
автор молодец, что уделяет внимание таким не"мелочам".
Можно бы и упростить - передавать массив слов, а не все 3 слова аргументами.
Тем более что локализации удобнее будет передавать, опятьже, массив :)
у меня, правда, немного посложнее функция, но я туда передаю 2 параметра - число и имя ассоциативного массива, в котором в локализациях лежат нужные мне слова :)
на самом деле в качестве примера была использована конечная функция
в качестве оболочки можно прописать и массивы, и чтение из базы и мультиязычность и константы - всё, что угодно
чтение из базы мультиязычносит?)) локализации лучше хранить в файле в ассоциатиных массивах и кешировать, имхо :)
ну мы делаем так.
А я вот чего понять не могу: пять лет назад придуманное решение - не используется потому что "не модно" или по каким-то другим причинам ?
не всегда есть возможность использовать GNU gettext
Потому что на корявом хостинге gettext может и отсутствовать.
На глаза попадался давно php-class как раз для корявых хостингов. Есть огромный шанс, что и это он умеет.
А вообще вопрос хостинга сегодня решается легко и безболезненно.
когда то давным давно встала подобная проблема,но только со словом "балл" (баллы,баллов,балл).Я быдлокодер,поэтому обошёлся просто:
function GetBall($vote) {
$b = $vote;
settype($vote, "string");
if(eregi("1$", $vote) && $b != '11')
$et = 'балл';
elseif( (ereg("2$", $vote) || ereg("3$", $vote) || eregi("4$", $vote)) && ($b>20 || $b '.$et.' ';
}
ereg для этой цели? Жестоко.
Мне кажется это тот самый случай, когда класс не нужен. )

ООП хорошо, но правильное ООП, это не когда все в классах, а когда все что должно быть классом им является. А класс нужен, когда есть определенный набор данных (делаем полями) и предназначенные только для работы с этими данными функции (делаем методами).
Класс нужен когда есть какая-то сущность. В данном случае есть сущность "язык", которая включает в себя функцию вывода множественного числа, а также другие вещи (скажем десятичный разделитель, разделитель тысяч и прочая). Во всяком случае я так понял.
Oops. Перечитал текст ишшо раз и понял, что никаким классом тут даже и не пахнет: класс используется как пространство имён (namespace)... Хмм - тоже вариант: в C++ до появления "нативных" пространств имён тоже так делали, в Java - до сих пор делают (см. java.lang.Integer, java.lang.Boolean, etc).
Ну да, как пространство имен. Для имени одной единственной функции)
Или разве что это намек и предложение расширить этот класс еще кучей полезнейших функций по данной тематике))
Ну вот так PHP программисты борятся с отсутсвием пространств имен(namespaces) в PHP
пространства имён уже есть, правда, пока что насколько я понял в дев-версиях php 5.3 которые можно взять на snaps.php.net
немножко красивее, аргументы расположены в более привычном порядке, число, словоформы для одного, двух и пяти

function xform($c, $str1, $str2, $str5) {
$c = abs((int)$c) % 100;
if ( $c > 10 && $c 1 && $c < 5 ) return $str2;
if ( $c == 1 ) return $str1;
return $str5;
}
if ( $c > 10 && $c 1 && $c
что?
А, блин. Знаки "больше-меньше" накрылись
мммм, хабр как-то криво обработал знак 'меньше'=))

function xform($c, $str1, $str2, $str5) {
$c = abs($c) % 100;
if ( $c > 10 && $c 'меньше' 20 ) return $str5;
$c %= 10;
if ( $c > 1 && $c < 5 ) return $str2;
if ( $c == 1 ) return $str1;
return $str5;
}
В HTML-коде не должно встречаться знаков больше/меньше и амперсандов, но, как вижу, кто-то вам опустил карму и тем самым решил проблему...
ниправда. знаков больше в штмле может быть сколько угодно - стандарт разрешает :)

другое дело что некузяво...
Ась ? Authors should use "&gt;" (ASCII decimal 62) in text instead of ">" to avoid problems with older user agents that incorrectly perceive this as the end of a tag (tag close delimiter) when it appears in quoted attribute values

Причины, по которым знаки больше и меньше запрещены - разные, но запрещены и те и другие...
согласен, дурак :) похоже я его с xml-ными стандартами попутал...
should <> must
В класс функция внесена, что бы не дай бог не пересечья названием с уже используемой.

Куда бы теперь класс вынести, чтобы его имя не пересеклось?
достаточно во всех своих разработках использовать отдельный "суперглобальный" класс, в которые вносить подобные статические функции

а сам класс используется как namespace
А как быть с пересечением имен внутри него, если всё туда пихать?
Все когда-то писали похожую функцию. ;-)

function plural($num, $form1, $form2, $form5) {
if($num > 100) $num = $num % 100;
if($num > 20) $num = $num % 10;

switch($num) {
case(1): return $form1;
case(2):
case(3):
case(4): return $form2;
default: return $form5;
}
}
0?
А нет, извиняюсь :)
8)
Скобок в case не требуется :)
точно, запарился 8)
Скобки никогда не помешают :)
Когда-то написал такое...


function morphology($digital, $for_1, $for_2, $for_5)
{
$digital = $digital % 100;

if ($digital > 19)
$digital = $digital % 10;

if ($digital == 0) return $for_5;
if ($digital == 1) return $for_1;

if (($digital >= 2) and ($digital <= 4)) return $for_2;
if (($digital >= 5) and ($digital <= 19)) return $for_5;
}

</code>
Буквально сегодня ночью для этих целей написал небольшую функцию Smarty.

Использование:

{ending number=$reviews base="реценз" e0='ий' e1='ия' e2='ии'}
{ending number=$comments base="комментар" e0='иев' e1='ий' e2='ия'}


И сама функция (файл /smarty/libs/plugins/function.ending.php):

function smarty_function_ending($params, &$smarty)
{
// ...
// проверки входных параметров пропущены
// ...

$base = !isset($params['base']) ? '' : $params['base']:

$e0 = $params['e0'];
$e1 = $params['e1'];
$e2 = $params['e2'];
$number = $params['number'];

if ($number % 10 == 1) return $base . $e1;
if ($number % 10 >= 2 && $number % 10 <= 4) return $base . $e2;
return $base . $e0;
}
</code>
Правильный набор условий:
if ($number % 100 > 10 && $number % 100 < 20) return $base . $e0;
if ($number % 10 == 1) return $base . $e1;
if ($number % 10 >= 2 && $number % 10 <= 4) return $base . $e2;
return $base . $e0;
Давно и успешно использую нечто подобное.
Считаю, что вот такое вот "очеловечивание" сайтов - это очень правильно, всегда бесили всякие "просмотров: 164"
все супер, только

echo "онлайн 152 ".datext::proceedTextual( 152, 'человек', 'человек', 'человека' );


хочу предложить сделать вывод числового значения тоже внутри этого метода, чтобы исключить необходимость повторного ввода числа:

echo "онлайн ".datext::proceedTextual( 152, 'человек', 'человек', 'человека' );
тут дело стопорится из-за нуля

ведь часть нулевые значения нужно и показывать и обрабатывать иначе - например не показывать ссылку и т.д.
Никто не мешает в случае нуля совсем этот метод не вызывать... А если его вызывать - приходится ещё отдельно число печатать. В чём выигрыш ?
ноль тут никак не влияет, так как обработка этого случая затронет и фиксированную часть "онлайн "

а вот повторный ввод числа (переменной) - может привести к ошибкам, например в одном месте поправил - во втором забыл.
я писал подобную функцию - для рублей, на VBA в Excel, для расшифровки сумм.
Многие писали. И я, наверное, был не единственный, кто потом исходил матами, когда узнавал через пару месяцев, что там уже есть готовая библиотека.
ха-ха, я не знал. но это было году в 99м
исследование тянет таки на докторскую степень по ПХП
Порадовало, что хоть один switch использовал :) Это говорит об уровне? О читаемости кода молчу :)
У меня вот такой вариант:
function declension($int, $expressions) {
settype($int, 'integer');
$count = $int % 100;
if ($count >= 5 && $count <= 20) {
$result = $int . ' ' . $expressions['2'];
} else {
$count = $count % 10;
if ($count == 1) {
$result = $int . ' ' . $expressions['0'];
} elseif ($count >= 2 && $count <= 4) {
$result = $int . ' ' . $expressions['1'];
} else {
$result = $int . ' ' . $expressions['2'];
}
}
return $result;
}</pre>

Вызов: <?=declension(152, array('пряник', 'пряника', 'пряников')); ?>
имхо, наилучший из вариантов.
В английском почти нет понятия "склонение" и declension очень неадаптированная ассоциация ("фор русишь виc дикшнари" стайл). А так ничо.
НЛО прилетело и опубликовало эту надпись здесь
У вас код залезает на меню справа (1024х768). Сделайте поменьше отступы слева.
для пользвателей Smarty, в шаблонах удобно использовать это как плагин-функцию:

{$comments|@count}

{amount_string amount=$comments|@count strings="комментарий,комментария,комментариев"}

для этого создаём файлик: /Smarty/plugins/function.amount_string.php

с кодом:

function smarty_function_amount_string($params, &$smarty)
{
$locales = array('rus');

if (empty($params['amount']) || empty($params['strings']))
$smarty->trigger_error('amount_string: missing parameters "amount" or "strings"');
elseif (!is_numeric($params['amount']))
$smarty->trigger_error('amount_string: parameter "amount" must be integer');
elseif (isset($params['locale']) && !in_array($params['locale'], $locales))
$smarty->trigger_error('amount_string: unkown "locale", it must be one of: '.implode(', ',$locales));
else
{
$amount = abs($params['amount']);
$locale = isset($params['locale']) ? $params['locale'] : reset($locales);

$strings = is_array($params['strings']) ? $params['strings'] : array_map("trim", explode(',', $params['strings']));

if($locale == 'rus')
{
if(count($strings) != 3)
$smarty->trigger_error('amount_string: in "rus" locale "strings" must contains tow "," separators');
else
{
$amount %= 100;

if($amount > 20)
$amount %= 10;

return !$amount || $amount > 4 ? $strings[2] : ($amount == 1 ? $strings[0] : $strings[1]);
}
}
}
}

sub plural{
my ( $num, $one, $two, $five ) = @_;
$num = abs int $num;
$num %= 100;
$num %= 10 if $num > 19;
return $five if $num==0 || $num > 4;
return $one if $num == 1;
return $two;
}

/**
* @param mixed $n число
* @param mixed $words массив слов для 1, 2х и 5ти, пример: array("час", "часа", "часов")
* @return
*/
function plural($n, $words)
{
$plural=($n%10==1 && $n%100!=11) ? 0 : (($n%10>=2 && $n%10<=4 && ($n%100<10 || $n%100>=20)) ? 1 : 2);
return $words[$plural];
}
В этой теме, кажется, все показали свои способности. Не припомню топика с большим количеством кода в комментариях :) Думаю, что многим пригодится )
Может, вы ещё пиписьками померяетесь?
Простейший код, но каждый должен показать. Кодеры, блин.
Такое бывает только с PHP программистами...
Сколько программистов столько и вариантов написания одной задачи!
Наглядно продемонстрировано в коментариях
Обилие кода и его просмотр навело меня на такую мысль, 25 лет назад на экзамене я смог бы претендовать разве что на тройку, за решение из wiki, потому как оно самое короткое.
За решение которое я приведу, пятерки тоже не было бы. Но все же.

function getEnding($n, $w){
  if((4 < $n) && ($n < 21))
    return $w[0];
  $n=$n % 10;
  if ($n==1)
    return $w[1];
  elseif(($n > 4) ||($n==0))
    return $w[0];
  else
    return $w[2];
}

Друзья, программист не тот кто синтаксис знает, а тот кто способен оставить для компьютера только те задачи, которые сам не смог решить.
Программист - это тот, кто, в первую очередь, пишет работающий код. Проверьте своё творение на числе 111...
Кодер - это тот, кто пишет работающий код. Программист придумает работающий алгоритм, а код он напишет на любом языке.
if ( (numeric % 100 == 1 || ($numeric % 100 > 20) && ( $numeric % 10 == 1 ) ) return $one;

надо поправить на

if ( $numeric % 100 == 1 || ($numeric % 100 > 20) && ( $numeric % 10 == 1 ) ) return $one;
Как быть с такой ситуацией.

В магазине 2 тетради
В магазине нет 2 тетрадей.
А как быть с "ножницами" и "пальто"? :)
Имелоь ввиду несколько другое.
НАпример В магазине 2 тетради (тут три словоформы)
А В магазине нет одной тетради.
И В магазине нет двух, трех, ....... и .тд. тетрадей (2 словоформы)
Причем алгоритм перевода в первом случае и втором не пересекаются
Т.е. в зависимости от падежа нужны разные алгоритмы.
Вас не удивляет то, что в Русском шесть падежей, но у почти всех слов только пять падежных словоформ ? Почему тогда удивляет что из трёх словоформ, требуемых для вывода чисел две могут совпадать ? Или вы хотите придумать суперуниверсальный алгоритм, который бы согласовывал все слова в предложении ?

Решение тривиально:
ngettext("Shop does not have %d sketch-book", "Shop does not have %d sketch-books", n)

В .po-файле:
msgid "Shop does not have %d sketch-book"
msgid_plural "Shop does not have %d sketch-books"
msgstr[0] "В магазине нет %d тетради"
msgstr[1] "В магазине нет %d тетрадей"
msgstr[2] "В магазине нет %d тетрадей"
Все подсознательные велосипеды вырвались наружу, померялись колёсами, позвенели клаксонами и увезлись на помойку сознания (а может в четвертый томик Кнута про web 2.0 алгоритмы?)
Ну, друзья, Вы мега-круты :) Столько примеров понаписывать :)
Да уж )

Нужно было не в "PHP" а в "Ревизию кода" отправлять мне )
В английском всё проще. Достаточно написать 10 user(s). И будет просто понятно и быстро.
НЛО прилетело и опубликовало эту надпись здесь
if ( (numeric % 100 == 1 || ($numeric % 100 > 20) && ( $numeric % 10 == 1 ) ) return $one;
Пропущен знако $ перед именем переменной.
У меня в блоге количество комментариев примерно так и выводится.
я один не чувствую разницы между "1 комментариев" и "1 комментарий" ? о_О
Следующий топик предлагаю посвятить проблеме проверки простого числа на четность. Я уже написал библиотеку, содержащую все необходимые интерфейсы для выполнения этой задачи. Есть оптимизированные версии для одноядерных и многоядерных систем, в ближайших планах стоит разработка 64-рязрядной версии. Образ DVD с исходниками и примерами на всех существующих языках программирования (особое внимание уделено перспективному Brainfuck.NET) ждите в ближайшее время.
не забудьте о версии для корпоративных пользователей ))
Давно изобретенное колесо!
В конце статьи ссылки
по правьте пожалуйста
"ngettext вместо gettext"
ссылка правильная, а вот сам текст

а то вводит в заблуждение
"Plural-Forms: nplurals=3; plural=((((n%10)==1)&&((n%100)!=11))?(0):(((((n%10)>=2)&&((n%10)
парсер на хабре кривоват(съел разметку), как и некоторые вещи ещё :) ...
к предыдущему нужно добавить:
((n%100)>=20)))?(1):2));\n"

з.ы. кучу глюков на сайте - даже написать некуда, хаброахабр :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации