GNU's gettext has the ngettext function for specifying a string with plural forms in your app code:
ngettext("%d file removed", "%d files removed", n)
On the translator side, it makes you write a really complex single line of code that encodes the rules of your language in selecting which translation to use:
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#, c-format
msgid "One file removed"
msgid_plural "%d files removed"
msgstr[0] "%d slika uklonjenih"
msgstr[1] "%d slika uklonjenih"
msgstr[2] "%d slika uklonjenih"
Project Fluent came out of Mozilla's localization team and volunteer community after struggling with gettext and other translation systems for years while localizing Firefox. You write a source English FTL file:
shared-photos =
{$userName} {$photoCount ->
[one] added a new photo
*[other] added {$photoCount} new photos
} to {$userGender ->
[male] his stream
[female] her stream
*[other] their stream
}.
and then translators provide an FTL file for their language with the translations filled in place of the English, with more plural forms specified as needed.
What I only learned today is that that one other stuff describing which plural forms are available are actually a standard provided in the Unicode CLDR. If you look up Polish, for example, you can see that few is used for the plural form for numbers ending in 2, 3, or 4, and many is used for the other non-fractional plurals.
(Fluent also supports arbitrary string keys, as seen with the gender selector above—"male" and "female" aren't built into Fluent, they are arbitrary keys and could be expanded to include any pronoun forms desired.)
Anyone making software that needs to be translated should be using a localization library of some sort, there's way too many edge cases and variations for you to be handling this stuff yourself!
