What are best practices for pluralization in Visualforce pages? I find myself doing a lot of this, which feels clunky and makes the code hard to read:

{!numUnread} unread message{!IF(numUnread > 1,'s', '')}

If you are using standard object labels, you just use the label:

$ObjectType.Account.label -> singular label: Account
$Objecttype.Account.labelplural -> plural label: Accounts

Otherwise, I would go with two separate custom labels:

$Label.UnitSingular  -> "Stock Unit"
$Label.UnitPlural   -> "Stock Units"

The reason I would go with the above instead of hard coding an "s" is because the way something is pluralized may be different. For instance you might get a business requirement to change the terminology around the word "Unit" above. Someone might get the idea that they like "Merchandise". This will break the code that you have in your question. Whereas using a custom label, an administrator can simply go in and provide the new text value for the plural and singular word and your code still works.

Your code might actually end up being harder to read, but it will require less maintenance.

| improve this answer | |
  • I agree with this approach in principle, but there are tons of places to possibly pluralize, so we're talking about creating lots of custom labels. That's probably the best approach long-term, and will support future i18n, but feels like a big hurdle for the moment. I guess it's time to practice jumping... – Benj Dec 16 '13 at 14:32
  • 2
    So I would use it like this? {!numUnread} {!IF(numUnread > 1, $Label.UnreadMessagesPlural, $Label.UnreadMessagesSingular)}? – Benj Dec 16 '13 at 14:33
  • I was purposefully staying out of the "how to get at them syntactically" part of the argument, because I agree with you, it is still a clunky solution at getting to these and a pain in large implementations with lots of Visualforce. But yes, I've used the {!IF()} syntax to access different labels. On the plus side you can create label categories and custom list views for custom labels to help you manage them. And beware, I seem to recall a limit being added around custom labels in a recent release. – pchittum Dec 16 '13 at 15:32
  • 1
    ~5000 per namespace, I believe. Doesn't seem very high for a large app... – Benj Dec 16 '13 at 15:48

The standard way to achieve pluralization, even across different languages is to use message formats:

<apex:outputText value="{0} unread {0,choice,0#messages|1#message|1<messages}.">
    <apex:param value="{!numUnread}" />

See outputText documentation for details on the VF tag, and Java docs for details on the formats.

The beauty of this approach is that you can put the string into custom labels and have completely different sentence structure for different languages.

| improve this answer | |
  • Thanks! Sometimes I have to use messages inside of an HTML attribute (such as a title tag). How would I use this approach to do that, or to save an evaluated message as an apex:variable for re-use later? AFAIK, you can't embed an apex:outputText in either of those places. – Benj Dec 16 '13 at 16:39
  • Message formats are also available in Apex, using String.format, which you can make available from the controller as properties and embed anywhere using the merge field syntax. It is interesting how format parameters can only be Strings, unlike in the Java method beneath. – kresho Dec 16 '13 at 21:14

This is an area of a frustration for me. It's these little bits that make or break the "feel" of a web-app. Anyway

I usually define a custom visualforce component that handles this for me. That way, I'm reusing code, rather than mixing that logic all around views everywhere.

Something kinda like this:

  <apex:attribute name="toPluarlizeMaybe" 
     type="String" description="Hey, I just met you, and I know this is crazy, but here's a number so Pluralize me maybe?"/>
  <apex:attribute name="heresMyNumber" type="Integer" description="Pluarlize me Maybe?"/>
  {!toPluralizeMaybe}{!IF(heresMyNumber > 1,'s', '')}

To use, then:

<c:PluralizeMeMaybe toPluralizeMaybe="Unread Messages", heresMyNumber={!YourMergeVaraibleHere}/>
| improve this answer | |
  • Actually, Peter's answer below is 1094% better than mine. (edit: bad joke removed) – Kevin P Dec 16 '13 at 14:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.