10

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

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

这可能会导致:

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

但是,如果一个条目只有 1 条评论,我希望该行显示“评论”而不是“评论”。并且 in-lineif/else丑陋且重复。

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

4

7 回答 7

13

请将此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] ""

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

于 2009-07-21T23:01:32.960 回答
4

为什么不花时间将事物更加人性化......

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

}
于 2009-07-21T20:03:25.113 回答
3

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

于 2009-07-21T19:55:54.363 回答
3

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

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);
于 2009-07-21T22:43:20.190 回答
2

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

[Entry title]
[Content........]
1 Comment(s)
于 2009-07-21T19:57:25.593 回答
2

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

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

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

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

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

于 2012-09-06T21:16:24.223 回答
0

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

于 2009-09-13T06:49:02.607 回答