views:

115

answers:

4

There are many instances in my work projects where I need to display the size of some collection in a sentence. For example, if the collection's size is 5, it will say "5 users". If it is size of 1 or 0, it will say "1 user" or "0 user". Right now, I'm doing it with if-else statement to determine whether to print the "s" or not, which is tedious.

I'm wondering if there's an open source JSP custom tag library that allows me to accomplish this. I know I can write one myself... basically, it will have 2 parameters like this: <lib:display word="user" collection="userList" />. Depending on the collection size, it will determine whether to append an "s" or not. But then, this implementation is not going to be too robust because I also need to handle "ies" and some words don't use any of those. So, instead of creating a half-baked tool, I'm hoping there's a more robust library I could utilize right away. I'm not too worried about prefixing the word with is/are in this case.

I use Java, by the way.

Thanks much.

+1  A: 

This functionality is built into Ruby on Rails. I don't know exactly where, but it should be easy enough to find in the source code, and then you could simply crib the code.

EDIT: Found you some code:

If I remember correctly, it's mainly a matter of appending an "s" to most words, though I believe there is a list (probably hash, err dictionary) of some common exceptions. Notable is the conversion from "person" to "people" :)

You would of course be in for a world of pain if you decided you want to internationalize this to other languages than English. Welcome to the world of highly irregular grammars, and good luck!

Carl Smotricz
Thank you! Hell, if I have to internationalize this, I might as well make up my own language where a plural word always ends with a YAY... ex: 5 userYAY. :)
limc
+13  A: 

Take a look at inflector, a java project which lets you do Noun.pluralOf("user"), or Noun.pluralOf("user", userList.size()), and which handles a bunch of variations and unusual cases (person->people, loaf->loaves, etc.), as well as letting you define custom mapping rules when necessary.

JacobM
The wealth of stuff available for Java is amazing! Thanks for this info, which could save me and others a trip into the bowels of RoR. +1. Up next: KitchenSink.jar :)
Carl Smotricz
@JacobM: Okay... seriously, WOW! :) I thought you are just pulling my legs, and in fact, this is for real! Thank you so much, I'll indeed mess around with it soon. @Carl: Yes, we need kitchenSink.jar too.
limc
+1 for the surprise! factor
omerkudat
+1  A: 

Hmm, I don't quite see why you need a library for this. I would think the function to do it is trivial:

public String singlePlural(int count, String singular, String plural)
{
  return count==1 ? singular : plural;
}

Calls would look like:

singlePlural(count, "user", "users");
singlePlural(count, "baby", "babies");
singlePlural(count, "person", "people");
singlePlural(count, "cherub", "cherubim");
... etc ...

Maybe this library does a whole bunch of other things that make it useful. I suppose you could say that it supplies a dictionary of what all the plural forms are, but in any given program you don't care about the plurals of all the words in the language, just the ones you are using in this program. I guess if the word that could be singular or plural is not known at compile time, if it's something entered by the user, then I'd want a third party dictionary rather than trying to build one myself.

Edit

Suddenly it occurs to me that what you were looking for was a function for making plurals generically, embodying a set of rules like "normally just add 's', but if the word ends in 'y' change the 'y' to 'ies', if it ends in 's' change it to 'ses', ..." etc. I think in English that would be impossible for any practical purpose: there are too many special cases, like "person/people" and "child/children" etc. I think the best you could do would be to have a generic "add an 's'" rule, maybe a few other common cases, and then a long list of exceptions. Perhaps in other languages one could come up with a fairly simple rule.

So as I say, if the word is not known at compile time but comes from some user input, then yes, a third-party dictionary is highly desirable.

Jay
I'll keep this approach in mind, but in my case, the noun is something pulled programmatically from the database.
limc
Ah, well, that gets you to the "if the word is not known at compile time" exception that I mentioned. So yes, in that case, having a third party dictionary is very useful. See my update.
Jay
Your method won't handle multiple languages. Plural and singular variations can be a mess. One way you could do is like this:String function plural(rule, int count, Array<String> strings){ int plural = rule(count); return strings[plural];}Not valide code but you should understand.Rule is a function passed to determine the plural index. There should be a test to return index 0 if plural doesn't exist. Anyway this method suck.You should only have to insert the "key" and the count...like in gettext.
Sybiam
@Sybiam: When you say it wouldn't work, do you mean my first method, i.e. just say "here's the singular and here's the plural"? Or my second method mentioning a rule? My intent was to say that that was a bad idea. It would be wildly impractical in English because there are so many exceptions. In Latin it would be tough because there are five basic rules and then many exceptions. I suppose it would work in Esperanto. Any other languages with one consistent rule for forming plurals? My guess is that it's very few.
Jay
@Sybiam: I meant to say, I think my first method would work in almost any language. In languages that have single/dual/plural as noted elsewhere on this question, you'd need three forms. If there are other languages that get more complicated, then I guess it would break down. I18n'ing adds another level of complexity.
Jay
I meant it wouldn't work with other languages with different plural/singular rules. It should be fine without translations. And now that I think about it. If you ever need to handle translations, it will definitively not work. For exemple, in english you have singular and plural, your function would receive singular and plural, if you want to handle translations to russian. You simply can't output the third argument as english only receive 2 arguments. In the end, the code will be messy. I prefer this solution _("dog", count).
Sybiam
You keep the singular key in the code, and in a file, you have translations and plurals forms. If you don't want to handle translations, at least it will handle plural forms without making the code a mess. One basic example would be: _("you deleted %d post", count)in a file you'd have "you deleted %d post" and "you deleted %d posts". %d can be replaced by any number and _() guess which plural form to use on the current language. that's how gettext works. I haven't seen anything better yet.
Sybiam
@Sybiam: "wouldn't work with other languages with different singular/plural rules": That's why I dismissed the idea of trying to do it with a rule. Note I've repeatedly said that trying to have a "rule" would be impractical. I think we have a communication problem here: You've now twice said that the scheme I said was a bad idea is, in fact, a bad idea, but you seem to think you're disagreeing with me. The scheme that I actually proposed was to give the singular and the plural as two arguments to a function and then have the function pick one based on the count. (continued ...)
Jay
(continued) The only difference I see between my idea and yours is that I'm saying to put singlular and plural in one place -- two arguments to a function -- while you're saying to put them in two places -- the function and a separate file. I think it's more convenient to put them together. Whatever.
Jay
Well it's not exactly that, the file may contain the rule that choose the singular/plural form. I didn't invent it, that's how gettext works. Your code only keep a singular key. That way, you have your text inside the code for simplicity. The function use the current locale or any configuration that lets it know which language to open. In that file there is a rule that define the plural form. That way you can handle translations/plural forms in document outside the code. http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html have a look.
Sybiam
+1  A: 

This gets complicated in languages other than English, that inflector aims to support in the future.

I am familiar with Czech where user = uživatel and:

1 uživatel
2 uživatelé
3 uživatelé
4 uživatelé
5 uživatelů

...

You can see why programs written with hardcoded singular+plural would get un-i18n-able.

Roman Zenka
This is why I like languages that don't care about singular or plural, like Bahasa Melayu, ex: "1 orang", "2 orang" regardless of x users. :)
limc
Really? You're saying that in Czech there is a form for 1, another form for 2-4, and a different form for 5? How interesting. Why 5 rather than, say, 6, or 42? Are there different numbers for different words? I'm no philologist, but this sounds so peculiar that it's quite interesting.
Jay
Really. And it is not just Czech. You might be interested in reading about "dual" as addition to "singular" and "plural" here: http://en.wikipedia.org/wiki/Dual_(grammatical_number)
Roman Zenka
@Jay I don't know czech, but other languages have gender for words (kinda like you have actor/actress in english, only for all the words) and singular/plural forms for both genders. Also, in romanian we have cases where the suffix is different based on the role the noun plays in the sentence. While you in english might say 'to the user', we would add the suffix '-ului' to our word for user (utilizator -> utilizatorului; and this is for the male version). This makes these language less ambiguous, but also harder to learn. (verbs also have suffixes based on person/time combinations).
Andrei Fierbinteanu
Ah, and we also make the articulated form using a suffix so 'the user' also has a different form (utilizator - > utilizatorul)
Andrei Fierbinteanu
@Zenka: Yes, I was aware that Arabic has singular/dual/plural -- I see from the link that it's not the only such language. What struck me about the example here though was "5". It makes sense to me to go 1, >1; or 1, 2, >2; there's a logical sequence. But 1, 2-4, 5? Why is 5 special?
Jay
@Andrei: I'm no linguist, but I took some Latin when I was a kid, so I'm familiar with gendered nouns and changing endings depending on the usage in the sentence. IMHO, what makes a language harder to learn is not the suffixes per se, but having different sets of suffixes for different words and then exceptions to those. If there was just one set, this would be very neat and, I would think, easy. (I'll remember that next time I invent a new language ...)
Jay
@Jay I misunderstood Roman's answer earlier, and now your initial question is more valid as well. I thought he said that the word might have a lot more different forms than English words have (possibly grouping them by case or something). It is a bit strange to have a different plural form for 5 items, although at this point I'm not as surprised by these sort of things as I used to be. As for less exceptions = easier to learn, you do indeed have a point. We don't have many exceptions, but there are quite a few rules, and some are not obvious from examples (may seem random or counterintuitive).
Andrei Fierbinteanu
Roman Zenka