Комментарии 92
Будем надеяться. что подобный пример поможет сайтам стать "человечнее". Спасибо.
полезно. писал по другому чуть-чуть. и в класс не оборачивал.
А как же на счет 111, 112,..., 211 и т.д.?
Спасибо огромное за подсказку!
Исправил, поставил %100 там, где надо
Исправил, поставил %100 там, где надо
за ссылку спасибо
но иногда проще изобрести велосипед, чем тратить часы на поиск нужного
но иногда проще изобрести велосипед, чем тратить часы на поиск нужного
Но зато при первом подходе во вновьизобретённом велосипеде, как правило, получаются квадратные колёса (как у вас и вышло поначалу).
Это по мнению иностранцев, отличительная сторона российских программеров писать с нуля :)
да, этот ньюанс скорее сложен с точки зрения его "просекания" на уровне проектирования сайта/системы/итд. т.е. многим какбы сложно предугадать, что такая проблемка будет и надо ее заранее разрешить. а запрограммировать вышеописанное - уже тривиальная задача, и даже решение "влоб" подходит.
автор молодец, что уделяет внимание таким не"мелочам".
автор молодец, что уделяет внимание таким не"мелочам".
Можно бы и упростить - передавать массив слов, а не все 3 слова аргументами.
Тем более что локализации удобнее будет передавать, опятьже, массив :)
у меня, правда, немного посложнее функция, но я туда передаю 2 параметра - число и имя ассоциативного массива, в котором в локализациях лежат нужные мне слова :)
Тем более что локализации удобнее будет передавать, опятьже, массив :)
у меня, правда, немного посложнее функция, но я туда передаю 2 параметра - число и имя ассоциативного массива, в котором в локализациях лежат нужные мне слова :)
на самом деле в качестве примера была использована конечная функция
в качестве оболочки можно прописать и массивы, и чтение из базы и мультиязычность и константы - всё, что угодно
в качестве оболочки можно прописать и массивы, и чтение из базы и мультиязычность и константы - всё, что угодно
чтение из базы мультиязычносит?)) локализации лучше хранить в файле в ассоциатиных массивах и кешировать, имхо :)
ну мы делаем так.
ну мы делаем так.
когда то давным давно встала подобная проблема,но только со словом "балл" (баллы,баллов,балл).Я быдлокодер,поэтому обошёлся просто:
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.' ';
}
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.' ';
}
Мне кажется это тот самый случай, когда класс не нужен. )
ООП хорошо, но правильное ООП, это не когда все в классах, а когда все что должно быть классом им является. А класс нужен, когда есть определенный набор данных (делаем полями) и предназначенные только для работы с этими данными функции (делаем методами).
ООП хорошо, но правильное ООП, это не когда все в классах, а когда все что должно быть классом им является. А класс нужен, когда есть определенный набор данных (делаем полями) и предназначенные только для работы с этими данными функции (делаем методами).
Класс нужен когда есть какая-то сущность. В данном случае есть сущность "язык", которая включает в себя функцию вывода множественного числа, а также другие вещи (скажем десятичный разделитель, разделитель тысяч и прочая). Во всяком случае я так понял.
Oops. Перечитал текст ишшо раз и понял, что никаким классом тут даже и не пахнет: класс используется как пространство имён (namespace)... Хмм - тоже вариант: в C++ до появления "нативных" пространств имён тоже так делали, в Java - до сих пор делают (см. java.lang.Integer, java.lang.Boolean, etc).
Ну вот так PHP программисты борятся с отсутсвием пространств имен(namespaces) в PHP
немножко красивее, аргументы расположены в более привычном порядке, число, словоформы для одного, двух и пяти
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;
}
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;
}
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 ">" (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
Причины, по которым знаки больше и меньше запрещены - разные, но запрещены и те и другие...
Причины, по которым знаки больше и меньше запрещены - разные, но запрещены и те и другие...
В класс функция внесена, что бы не дай бог не пересечья названием с уже используемой.
Куда бы теперь класс вынести, чтобы его имя не пересеклось?
Все когда-то писали похожую функцию. ;-)
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;
}
}
Когда-то написал такое...
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>
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>
Использование:
{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>
Давно и успешно использую нечто подобное.
Считаю, что вот такое вот "очеловечивание" сайтов - это очень правильно, всегда бесили всякие "просмотров: 164"
Считаю, что вот такое вот "очеловечивание" сайтов - это очень правильно, всегда бесили всякие "просмотров: 164"
все супер, только
хочу предложить сделать вывод числового значения тоже внутри этого метода, чтобы исключить необходимость повторного ввода числа:
echo "онлайн 152 ".datext::proceedTextual( 152, 'человек', 'человек', 'человека' );
хочу предложить сделать вывод числового значения тоже внутри этого метода, чтобы исключить необходимость повторного ввода числа:
echo "онлайн ".datext::proceedTextual( 152, 'человек', 'человек', 'человека' );
тут дело стопорится из-за нуля
ведь часть нулевые значения нужно и показывать и обрабатывать иначе - например не показывать ссылку и т.д.
ведь часть нулевые значения нужно и показывать и обрабатывать иначе - например не показывать ссылку и т.д.
Никто не мешает в случае нуля совсем этот метод не вызывать... А если его вызывать - приходится ещё отдельно число печатать. В чём выигрыш ?
ноль тут никак не влияет, так как обработка этого случая затронет и фиксированную часть "онлайн "
а вот повторный ввод числа (переменной) - может привести к ошибкам, например в одном месте поправил - во втором забыл.
а вот повторный ввод числа (переменной) - может привести к ошибкам, например в одном месте поправил - во втором забыл.
я писал подобную функцию - для рублей, на VBA в Excel, для расшифровки сумм.
исследование тянет таки на докторскую степень по ПХП
Порадовало, что хоть один 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('пряник', 'пряника', 'пряников')); ?>
НЛО прилетело и опубликовало эту надпись здесь
У вас код залезает на меню справа (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]);
}
}
}
}
{$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];
}
В этой теме, кажется, все показали свои способности. Не припомню топика с большим количеством кода в комментариях :) Думаю, что многим пригодится )
Может, вы ещё пиписьками померяетесь?
Простейший код, но каждый должен показать. Кодеры, блин.
Простейший код, но каждый должен показать. Кодеры, блин.
Обилие кода и его просмотр навело меня на такую мысль, 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];
}
Друзья, программист не тот кто синтаксис знает, а тот кто способен оставить для компьютера только те задачи, которые сам не смог решить.
За решение которое я приведу, пятерки тоже не было бы. Но все же.
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];
}
Друзья, программист не тот кто синтаксис знает, а тот кто способен оставить для компьютера только те задачи, которые сам не смог решить.
if ( (numeric % 100 == 1 || ($numeric % 100 > 20) && ( $numeric % 10 == 1 ) ) return $one;
надо поправить на
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 тетрадей.
А как быть с "ножницами" и "пальто"? :)
Имелоь ввиду несколько другое.
НАпример В магазине 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 тетрадей"
Решение тривиально:
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 алгоритмы?)
Ну, друзья, Вы мега-круты :) Столько примеров понаписывать :)
В английском всё проще. Достаточно написать 10 user(s). И будет просто понятно и быстро.
НЛО прилетело и опубликовало эту надпись здесь
if ( (numeric % 100 == 1 || ($numeric % 100 > 20) && ( $numeric % 10 == 1 ) ) return $one;
Пропущен знако $ перед именем переменной.
Пропущен знако $ перед именем переменной.
я один не чувствую разницы между "1 комментариев" и "1 комментарий" ? о_О
Следующий топик предлагаю посвятить проблеме проверки простого числа на четность. Я уже написал библиотеку, содержащую все необходимые интерфейсы для выполнения этой задачи. Есть оптимизированные версии для одноядерных и многоядерных систем, в ближайших планах стоит разработка 64-рязрядной версии. Образ DVD с исходниками и примерами на всех существующих языках программирования (особое внимание уделено перспективному Brainfuck.NET) ждите в ближайшее время.
Давно изобретенное колесо!
В конце статьи ссылки
по правьте пожалуйста
"ngettext вместо gettext"
ссылка правильная, а вот сам текст
а то вводит в заблуждение
по правьте пожалуйста
"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"
з.ы. кучу глюков на сайте - даже написать некуда, хаброахабр :)
к предыдущему нужно добавить:
((n%100)>=20)))?(1):2));\n"
з.ы. кучу глюков на сайте - даже написать некуда, хаброахабр :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Множественные числа