处理单数/复数的最优雅的方式?

发布于 2024-07-29 06:15:22 字数 344 浏览 3 评论 0原文

假设您正在制作一个博客软件,并且想要显示某个条目获得的评论数量。 您可以这样做:

[Entry title]
[Content........]
[ <?php print($numComments;) ?> Comments]

这可能会导致:

[Entry title]
[Content........]
5 Comments

但如果一个条目只有 1 条评论,我希望该行显示“评论”而不是“评论”。 内联的 if/else 又丑又重复。

处理这个问题的最佳方法是什么?

Say you're making a blog software, and want to show the number of comments an entry got. You might do it this way:

[Entry title]
[Content........]
[ <?php print($numComments;) ?> Comments]

Which might result in:

[Entry title]
[Content........]
5 Comments

But if an entry had only 1 comment, I want the line to say 'Comment' rather than 'Comments'. And in-line if/elses are ugly and repetitive.

What's the best way to deal with this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

如何视而不见 2024-08-05 06:15:22

请使用 ngettext 函数来完成此类操作。 它
允许您正确处理英语和其他语言中的复数形式
语言,一劳永逸。 您可以这样使用它:

printf(ngettext("%d Comment", "%d Comments", $numComments), $numComments);

ngettext 函数将返回第一个格式字符串 ("%d
Comment"
) 如果只有一条注释且采用第二种格式
字符串("%d Comments")(如果有更多)。 printf 函数将
然后将数字放入字符串中。

这可能看起来工作量很大,但它非常强大:它有效
对于具有多个复数形式(!)的语言——它们
实际存在。 PHP 手册给出了单词“window”的示例
在某些异国情调中变成“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] ""

翻译器将填写每个复数形式并使用正确的
在消息目录标题中形成“复数形式”行,您将
能够支持所有语言。

Please use the ngettext function for things like this. It
allows you to deal correctly with plurals in English and other
languages, once and for all. You use it like this:

printf(ngettext("%d Comment", "%d Comments", $numComments), $numComments);

The ngettext function will return the first format string ("%d
Comment"
) if there is just a single comment and the second format
string ("%d Comments") if there are more. The printf function will
then put the number into the string.

This might seem like a lot of work, but it is very powerful: it works
with languages that have more than one plural form(!) -- they
actually exist. The PHP manual gives an example for the word "window"
which becomes "1 okno", "2 okna" and "5 oken" in some exotic
language I don't recognize...

If you are consequent about using ngettext, then your future users
from far-away countries will be very grateful to you :-)

Edit: As suggested in the comments, there is a single function to
do the above:

function pluralize($num, $singleWord, $pluralWord) {
    return printf(ngettext($singleWord, $pluralWord, $num), $num);
}

By default, xgettext wont recognize this new function, but you can
add it with the --keyword flag. Given a file test.php with

echo ngettext("foo", "foos", 1);
echo pluralize(2, "bar", "bars");

you can extract the strings with

xgettext --keyword=pluralize:2,3 test.php 

The resulting messages.po file has entries like these:

#: test.php:7
msgid "foo"
msgid_plural "foos"
msgstr[0] ""
msgstr[1] ""

#: test.php:8
msgid "bar"
msgid_plural "bars"
msgstr[0] ""
msgstr[1] ""

The translator will fill in each plural form and with a correctly
formed "Plural-Forms" line in the message catalog header, you will be
able to support all languages.

冬天旳寂寞 2024-08-05 06:15:22

为什么不花时间让事情变得更加人性化......

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";

}

Why not take the time to humanize things even more....

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";

}
面如桃花 2024-08-05 06:15:22

创建一个函数,它接受一个数字和一个单词,并返回一个包含两者的字符串。 当数字大于 1 时,它将附加一个“s”(或查阅您构建的字典)。

Create a function that takes a number and a word, and returns a string containing both. It will append an "s" (or consult a dictionary that you build) when the number is bigger than 1.

夜无邪 2024-08-05 06:15:22

令我惊讶的是,还没有人建议这样做,但我通常做的是使用条件运算符:

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);

It surprises me that nobody suggested that yet, but what I usually do is to use the conditional operator:

string commentWord = numComments != 1 ? "Comments" : "Comment"; 

Note: the string should of course not be hard coded like this at all, but rather loaded from some resource repository, where it is stored with a formatting placeholder for the number, so that you can handle languages where the number should appear last (or in the middle):

// 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);
三人与歌 2024-08-05 06:15:22

不是最优雅的,但最容易输出“评论”。

[Entry title]
[Content........]
1 Comment(s)

Not the most elegant, but the easiest it to output "Comment(s)".

[Entry title]
[Content........]
1 Comment(s)
苍暮颜 2024-08-05 06:15:22

在 C/C++ 中,您可以执行以下操作。 您也许可以在 PHP 中执行类似的操作。

printf("%d %s\n", numComments, numComments == 1 ? "Comment" : "Comments");

以下方法也适用,但您可能会遇到在不同实现中错误处理 \b (退格键)的问题。

printf("%d Comment%s\n", numComments, numComments == 1 ? " \b" : "s");

使用 \0 (空字符)不打印任何内容,而是在我的实现中打印一个空格。

In C/C++, you can do the following. You may be able to do something similar in PHP.

printf("%d %s\n", numComments, numComments == 1 ? "Comment" : "Comments");

The following also works, but you may run into issues with \b (backspace) being handled incorrectly in different implementations.

printf("%d Comment%s\n", numComments, numComments == 1 ? " \b" : "s");

Using \0 (null character) to print nothing, instead, printed a space in my implementation.

ˉ厌 2024-08-05 06:15:22

查看 Rails inflector 模块。 这为这个问题提供了一个很好的、集中的、可配置的解决方案。

Check out the Rails inflector module. This provides a nice, centralized and configurable solution to this problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文