代码之家  ›  专栏  ›  技术社区  ›  Ali

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

  •  10
  • Ali  · 技术社区  · 15 年前

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

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

    可能导致:

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

    但是如果一个条目只有一条注释,我希望该行说“注释”,而不是“注释”。和在线 if/else S是丑陋和重复的。

    最好的方法是什么?

    7 回复  |  直到 8 年前
        1
  •  13
  •   Martin Geisler    15 年前

    请使用 ngettext 对这样的事情有用。它 允许您正确处理英语和其他语言中的复数。 语言,一劳永逸。你这样使用它:

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

    这个 NGETTEX 函数将返回第一个格式字符串( "%d Comment" )如果只有一条注释和第二种格式 琴弦( "%d Comments" )如果还有更多。这个 printf 功能意志 然后将数字放入字符串中。

    这似乎是一个很大的工作,但它是非常强大的:它工作。 使用的语言 多个复数形式(!) --他们 实际上存在。PHP手册给出了“window”一词的示例。 变成“1 okno”、“2 okna”和 5奥肯 “在异国情调中 我不认识的语言…

    如果你对使用 NGETTEX ,然后是未来的用户 远方的国家会非常感谢你的:-)

    编辑: 正如注释中所建议的,有一个函数可以 做到以上几点:

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

    翻译员将正确填写每个复数形式和 在邮件目录标题中形成“复数形式”行,您将 能够支持所有语言。

        2
  •  4
  •   Paul Dixon    15 年前

    为什么不花点时间让事情更人性化呢?

    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
  •  3
  •   Sinan Taifour    15 年前

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

        4
  •  3
  •   Fredrik Mörk    15 年前

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

    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
  •  2
  •   Dusty    15 年前

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

    [Entry title]
    [Content........]
    1 Comment(s)
    
        6
  •  2
  •   Pulseczar    8 年前

    在C/C++中,你可以做到以下几点。您可以在PHP中做类似的事情。

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

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

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

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

        7
  •  0
  •   ndp    15 年前

    退房 Rails inflector module . 这为这个问题提供了一个好的、集中的和可配置的解决方案。