Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most elegant way to deal with singles/plurals?

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?

like image 207
Ali Avatar asked Jul 21 '09 19:07

Ali


1 Answers

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.

like image 92
Martin Geisler Avatar answered Sep 29 '22 14:09

Martin Geisler