Самый элегантный способ справиться с синглами/множественными числами?
Предположим, что вы создаете программное обеспечение для блога и хотите показать количество комментариев, которые были получены. Вы можете сделать это следующим образом:
[Entry title]
[Content........]
[ <?php print($numComments;) ?> Comments]
Это может привести к:
[Entry title]
[Content........]
5 Comments
Но если запись имела только 1 комментарий, я хочу, чтобы строка говорила "Комментарий", а не "Комментарии". И строки if/else
являются уродливыми и повторяющимися.
Какой лучший способ справиться с этим?
Ответы
Ответ 1
Пожалуйста, используйте ngettext
для таких вещей. Это
позволяет правильно обрабатывать множественные числа на английском и других языках
языков, раз и навсегда. Вы используете его следующим образом:
printf(ngettext("%d Comment", "%d Comments", $numComments), $numComments);
Функция ngettext
вернет первую строку формата ("%d
Comment"
), если есть только один комментарий и второй формат
string ("%d Comments"
), если их больше. Функция printf
будет
затем введите число в строку.
Это может показаться большой работой, но она очень сильная: она работает
с языками, которые имеют более одной множественной формы (!) - они
фактически есть. В руководстве PHP приведен пример слова "окно",
который становится "1 okno", "2 okna" и "5 oken" в некоторых экзотических
язык, который я не узнаю...
Если вы связаны с использованием ngettext
, то ваши будущие пользователи
из дальних стран вам будет очень благодарен: -)
Изменить: Как указано в комментариях, существует одна функция для сделайте следующее:
function pluralize($num, $singleWord, $pluralWord) {
return printf(ngettext($singleWord, $pluralWord, $num), $num);
}
По умолчанию xgettext
не распознает эту новую функцию, но вы можете
добавьте его с флагом --keyword
. Для файла test.php
с
echo ngettext("foo", "foos", 1);
echo pluralize(2, "bar", "bars");
вы можете извлечь строки с помощью
xgettext --keyword=pluralize:2,3 test.php
В результате получившийся файл messages.po
имеет следующие записи:
#: test.php:7
msgid "foo"
msgid_plural "foos"
msgstr[0] ""
msgstr[1] ""
#: test.php:8
msgid "bar"
msgid_plural "bars"
msgstr[0] ""
msgstr[1] ""
Переводчик будет заполнять каждую форму множественного числа и правильно
сформированная строка "Plural-Forms" в заголовке каталога сообщений, вы будете
способный поддерживать все языки.
Ответ 2
Почему бы не потратить время, чтобы очеловечить вещи еще больше....
switch ($numComments)
{
case 0:
echo "Be the first to write a comment";
break;
case 1:
echo "Just one comment so far";
break;
default:
echo "There are $numComments comments";
}
Ответ 3
Создайте функцию, которая принимает число и слово, и возвращает строку, содержащую оба. Он добавит "s" (или прочитает словарь, который вы создадите), когда число больше 1.
Ответ 4
Меня удивляет, что никто этого не предложил, но я обычно использую условный оператор:
string commentWord = numComments != 1 ? "Comments" : "Comment";
Примечание: строка должна, конечно, не быть жестко закодированной, как это вообще, а скорее загружена из некоторого репозитория ресурсов, где она хранится с помощью заполнитель форматирования для номера, так что вы можете обрабатывать языки, где должен появиться номер последний (или посередине):
// should load "{0} Comments" or "{0} Comment" if we run in an English locale
string comments = string.Format(
numComments != 1 ? GetResource("Comments") : GetResource("Comment"),
numComments);
Ответ 5
Не самый элегантный, но самый легкий для вывода "Comment (s)".
[Entry title]
[Content........]
1 Comment(s)
Ответ 6
В C/С++ вы можете сделать следующее. Вы можете сделать что-то подобное в PHP.
printf("%d %s\n", numComments, numComments == 1 ? "Comment" : "Comments");
Также работает, но вы можете столкнуться с проблемами с \b
(backspace), которые неправильно обрабатываются в разных реализациях.
printf("%d Comment%s\n", numComments, numComments == 1 ? " \b" : "s");
Используя \0
(нулевой символ), чтобы ничего не печатать, вместо этого напечатайте пробел в моей реализации.
Ответ 7
Посмотрите модуль фальсификации Rails. Это обеспечивает хорошее, централизованное и настраиваемое решение этой проблемы.