Quantus - the library to handle plurals of nouns for Sitecore Dictionary and Habitat Dictionary

Why?

It happens very often. There is some static label on a website that displays a number of something like a number of products or number or results. It looks fine until someone finds out that it does not for some edge case. For example, your label is like this {0} products and it works fine for 1.5 products, 10 products, 15 products or even for 101 products, but for some reason, it does not work for 1 products.

It's easy to fix for English. The one can add another field or dictionary entry {0} product and use it only when number equals 1. However, for Polish, the rules are more complicated. There are 0 produktów, 1 produkt, 1,5 produktu, 2-4 produkty, 5-21 produktów, 22-24 produkty and so on. Each language has its own rules. There is no native implementation for this in Sitecore, that's why I created the Quantus library.

How?

Fortunately, there is a page where rules for cardinal and ordinal numbering are described for all languages: Language Plural Rules. There are up to six plural categories for each language: zero, one, two, few, many and other. English, for example, uses only two of them: one and other. Polish uses one, few, many and other

The rules for English cardinal numbering looks like this:

English Cardinal Rules

if number == 1 || number == -1 then use one category otherwise use other category. For Polish, rules are more complicated:

Polish cardinal rules

The library

The library consists of two assemblies: Quantus and Quantus.Sitecore. The first one contains providers for different languages and the second one provides basic integration of the first one with Sitecore. At the moment library supports only a few languages, but the aim is to support all of them.

The provider is a very simple class that implements IPluralProvider interface, and for English, it looks like this:

public class EnglishPluralProvider : ProviderBase, IPluralProvider
{
    public PluralCategory GetPluralCategory(decimal n)
    {
        return n == 1 || n == -1 ? PluralCategory.One : PluralCategory.Other;
    }
}

Quantus.Sitecore assembly implements a repository for providers and adds Sitecore config section:

<quantus>
  <patch:attribute name="defaultProvider">fallback</patch:attribute>
  <providers>
    <add name="fallback" type="Quantus.Providers.OtherPluralProvider, Quantus" />
    <add name="en" type="Quantus.Providers.EnglishPluralProvider, Quantus" />
    ...
  </providers>
</quantus>

Provider name is two letter language iso code. Default fallback provider is used when there is no provider for the specified language, and it always returns PluralCategory.Other. The PluralService class has one method, and it returns plural category for a given language and quantity:

PluralCategory GetPluralCategory(string language, decimal quantity);

The Sitecore Dictionary

I don't want to force the way one can use that library. That's why helper methods are not included in Quantus.Sitecore assembly. I'm going to change that when I or the community figure out the best way to implement it. However here is an example how to use it with Sitecore Dictionary.

First create a Dictionary Folder (Month) and six Dictionary Entries (Month Zero, Month One …) like in the following picture (the item names don't matter):

Sitecore Dictionary example

For each dictionary entry set the key to month + . + {category} so for Month Zero set it to moth.zero, for Month One: month.one etc. Then you can use following helper method to render correct translation:

public string PluralText(string key, decimal quantity)
{
    var category = PluralService.GetPluralCategory(Context.Language.Name, quantity);
    return Sitecore.Globalization.Translate.Text(key + "." + category.ToString().ToLower());
}

And use it like this:

PluralText("month", 10);

The Habitat Dictionary

I also created an example integration of Quantus library with custom dictionary implementation in Habitat. I created a pull request for this here: Pull request to Habitat repository. I created a new DictionaryPluralEntry template with fields like this:

Habitat dictionary example

I also created helper methods for Habitat dictionary. The example usage is in SearchResultHeader.cshtml view file:

@string.Format(Html.Sitecore().DictionaryPlural("/search/header/Title With Results", totalResults, "Your search for '{0}' yielded '{1}' results:"), Model.Context.Query, totalResults)

Source code

Source code for both Quantus and Quantus.Sitecore is available on my GitHub.

What next?

The aim is to implement providers for all languages and add support for ordinal numbering. I would also like to figure out the best way to use that library in Sitecore with the community. And if you wish to contribute, please do!