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

时间:2009-07-21 19:53:10

标签: code-readability

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

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

可能导致:

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

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

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

7 个答案:

答案 0 :(得分:13)

请使用ngettext功能进行此类操作。它 允许您正确处理英语和其他复数形式 语言,一劳永逸。你这样使用它:

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

ngettext函数将返回第一个格式字符串("%d Comment"),如果只有一个注释和第二个格式 字符串("%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”行,您将成为 能够支持所有语言。

答案 1 :(得分: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";

}

答案 2 :(得分:3)

创建一个带有数字和单词的函数,并返回包含两者的字符串。当数字大于1时,它会附加一个“s”(或查询你建立的字典)。

答案 3 :(得分: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);

答案 4 :(得分:2)

不是最优雅的,但最容易输出“Comment(s)”。

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

答案 5 :(得分: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(空字符)打印任何内容,而不是在我的实现中打印一个空格。

答案 6 :(得分:0)

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