Pluralization in software development

Due to its deceptive simplicity, pluralization can be a somewhat overlooked element when handling strings in programs. If your application only speaks one language, say English, pluralizing is oftentimes as simple as suffixing its nouns with an “s” or “es”. But, if you rightfully chose to localize/internationalize your app in multiple locales, the languages and their own pluralization rules and forms might make the once ignorable task of pluralization a bit of a challenge to overcome!

Be it for a front-end or back-end language, coders use different methods and tools to perform pluralization. So, without further ado, let’s explore a few programming languages and figure out how each of them tackles pluralization, shall we?

We will cover the following in this article:

  • A step-by-step guide to creating a Vanilla JavaScript app and performing string pluralization in it.
  • Basic pluralization using hardcoded JS functions.
  • Using the Pluralize JS library to pluralize English strings.
  • Performing pluralization for multiple locales utilizing the Numerous JS library.
  • A walkthrough on setting up a simple Java project and pluralizing strings in it.
  • Utilizing the ICU MessageFormat class for Java pluralization.
  • Placeholder usage through the JavaScript Pluralize library.
  • Using ICU MessageFormat arguments as placeholders when pluralizing in a Java application.

Assumptions

Basic knowledge of:

  • JavaScript
  • Java

Prerequisites

A local environment set up with:

  • JavaScript-supported IDE.
  • JavaScript-enabled browser.
  • Java-supported IDE.
  • JDK 5 or higher.
  • Maven 3.3 or higher.

Environment

I will be using the following environment for my development purposes:

  • WebStorm 2019.1 Build #WS-191.7141.49
  • Firefox 94.0 (64-bit)
  • IntelliJ IDEA 2019.1.2 Build #IU-191.7141.44
  • JDK 8u301
  • Maven 3.3.9

JavaScript pluralization

As our first language, let’s take a look at how we can pluralize strings in JavaScript.

The source code is available on GitHub.

Basic JavaScript project setup

Time to count some apples! First up, let us create a simple JavaScript project where we’ll later place our pluralization examples.

Let’s open our JavaScript IDE and create a new project named “PluralizationJS” inside a directory of an equal name.

Secondly, we’ll create an “index.html” file inside our PluralizationJS project to act as our project’s default page. Don’t forget to fill it with some initial HTML elements, like so:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>PluralizationJS</title>
</head>
<body>
</body>
</html>

Note: You’re in luck if using WebStorm, since typing “!” and pressing Tab will generate the entire code in one go!

Thirdly, let’s populate our “index.html” file’s HTML <body> with some skeleton HTML elements:

<table>
    <tr>
        <td id="apple_count_zero"> </td>
    </tr>
    <tr>
        <td id="apple_count_one"> </td>
    </tr>
    <tr>
        <td id="apple_count_few"> </td>
    </tr>
    <tr>
        <td id="apple_count_many"> </td>
    </tr>
</table>

As you might have already guessed, we’ll learn ways to fill this table with correctly populated apple counts in the upcoming sections.

Child’s play pluralization

Before touching on any libraries, how about we get to grips with JavaScript pluralization in the simplest way imaginable? Let’s use our good old if/else functions to portray a count of apples that is correctly pluralized according to English pluralization rules.

Firstly, we’ll head over to our PluralizationJS project’s “index.html” file and place a function inside its <head> tag:

.
<script>
    function getAppleCount(count) {  // 1
        if (count === 1) {  // 2
            return "1 apple";
        } else if (count === 0 || count > 1) {  // 3
            return count + " apples";
        } else {  // 4
            return "That's surely an invalid count of apples!";
        }
    }
</script>
  1. Create a getAppleCount function that accepts a count parameter.
  2. In the case that the count is 1, return a string with a value of “1 apple”.
  3. If the count is 0 or greater than 1, return a string concatenating the count with an “apples” string.
  4. If no match was found for the provided count, return a string informing of the invalid input.

Secondly, let’s add another <script> in the “index.html” file’s <body> tag:

.
<script>
    document.getElementById("apple_count_zero").innerHTML = getAppleCount(0);
    document.getElementById("apple_count_one").innerHTML = getAppleCount(1);
    document.getElementById("apple_count_few").innerHTML = getAppleCount(2);
    document.getElementById("apple_count_many").innerHTML = getAppleCount(5);
</script>

Important note: Make sure to place this script below the previously placed skeleton HTML table. This is so that by the time the JavaScript code looks for table elements by ID, they will already be rendered and available.

This script calls the getAppleCount function passing different counts and sets the relevant table element’s value to the function’s return value.

Test it out

Running our PluralizationJS application should show the properly pluralized apple counts:

Time to use a 3rd-party library

The previous method was easy enough—but, what if we needed to count oranges instead of apples? We’d either need to change all the strings in the getAppleCount function to represent orange counts or code a new function altogether. What if it’s not just apples and oranges but a thousand more types of fruit that we need to count?

Thankfully, there are far more efficient and far less messy approaches to counting the fruit—or in other words, pluralizing the strings—in our JavaScript applications.

Use Pluralize library

The Pluralize JavaScript library lets us pluralize strings in the English locale quite easily. Why don’t we find out how to set it up for our PluralizationJS app?

First things first, download the Pluralize library as a ZIP file from GitHub. Secondly, let’s extract this ZIP file and place the pluralize.js file inside it at the root of our PluralizationJS project directory:

Thirdly, let’s not forget to import this library to our project’s “index.html” file by placing this line inside its <head> tag:

<head>
.
<script src="pluralize.js"></script>
</head>
view raw index.html hosted with ❤ by GitHub

Fourthly, let’s add a new getAppleCountUsingPluralizeLib function inside the <head> tag of our PluralizationJS project’s “index.html” file:

.
<script>
    function getAppleCountUsingPluralizeLib(count) {  // 1
        if (count >= 0) {  // 2
            return pluralize("apple", count, true);  // 3
        } else {  // 4
            return "That's surely an invalid count of apples!";
        }
    }
</script>
  1. Create a getAppleCountUsingPluralizeLib function that accepts a count parameter.
  2. Check if the count value is greater than or equal to zero—that is to say, a countable quantity of apples.
  3. Call the pluralize method from the Pluralize library, successively passing in:
    • the word to pluralize in its singular form, which in our case would be “apple”.
    • the count of items to base the pluralization on—here we’ll directly pass the getAppleCountUsingPluralizeLib function’s count argument.
    • a boolean informing the pluralize method whether to prefix the result with the item count or not.
  4. If the condition in step 2 isn’t met, return a string informing of the invalid input.

Finally, we’ll make a few changes to our <script> inside the <body>, which changes the HTML table values. This time around, let us call our getAppleCountUsingPluralizeLib function to receive values to set on the HTML table elements:

.
<script>
    document.getElementById("apple_count_zero").innerHTML = getAppleCountUsingPluralizeLib(0);
    document.getElementById("apple_count_one").innerHTML = getAppleCountUsingPluralizeLib(1);
    document.getElementById("apple_count_few").innerHTML = getAppleCountUsingPluralizeLib(2);
    document.getElementById("apple_count_many").innerHTML = getAppleCountUsingPluralizeLib(5);
</script>
Test it out

Let’s run our PluralizationJS application to see if everything works as expected:

As we can see, the apple counts are nicely pluralized. But don’t forget! This time we didn’t manually code the pluralization logic. We only supplied the word “apple” in its singular form to the Pluralize library, along with the counts, and the library worked its magic to conveniently provide us with the words in their properly pluralized forms.

Enter Numerous library

Although the Pluralize library was easy to set up and use, there’s a catch, and a quite big one in fact! It’s designed to only work for the English language. Hence, if we need our JavaScript application to pluralize its string values in multiple locales, we’re out of luck with Pluralize.

When it comes to pluralizing values in several locales, a handy Numerous JS library comes to the rescue. Let’s see how we can use it.

Firstly, let’s add a few HTML buttons to our PluralizationJS project’s “index.html” file <body>:

.
<button id="lang_choice_en">Pluralize in English</button>
<button id="lang_choice_ru">Pluralize in Russian</button>

Later on, we’ll set up event listeners to call the Numerous library once they are clicked.

Set up Numerous library

Next, it’s time to download the Numerous library.

Since the original library is focused on functioning and setting up through Node and we plan to use plain old Vanilla JavaScript in this guide, we opted to create a fork of the Numerous library. This GitHub fork comments out a few Node-related codes in the Numerous library and replaces them with Vanilla JS code letting the pluralization in this guide work using Vanilla JavaScript.

Let’s download the ZIP file of the Numerous library fork and extract it to the root folder of our PluralizationJS project:

Important Note: Note that only the code used in this guide is fittingly modified in this Numerous fork. Hence, avoid using this fork for your production-level code and resort to the original Numerous library.

Use Numerous library

Given that there’ll be a considerable amount of code and JavaScript module imports, it’d be cleaner for us to write all Numerous library-related code as a separate module. Therefore, as our third step, let’s create a “numerous_pluralization.js” file inside our PluralizationJS project’s root folder with some initial imports:

import * as numerous from "./numerous-master/lib/numerous.js";
import enLocale from "./numerous-master/locales/en.js";
import ruLocale from "./numerous-master/locales/ru.js";

Numerous asks us to load all the locales we plan to use before we use its pluralization features. So, we’ll go ahead and register the English and Russian locales inside our numerous_pluralization module:

.
numerous.registerLocale(enLocale);
numerous.registerLocale(ruLocale);

The library uses CLDR and is hence aware of CLDR plural rules, but it relies on us to provide all the plural variants, unlike the Pluralize library. This being the case, let’s add a const to our numerous_pluralization module to hold localized plural form variants for a count of apples:

.
const pluralFormVariants = {
    en: {
        one: 'apple',
        other: 'apples'
    },
    ru: {
        one: 'яблоко',
        few: 'яблока',
        many: 'яблок'
    }
};

Next up, let’s add a pluralizeUsingNumerous function to the numerous_pluralization module:

.
function pluralizeUsingNumerous(langChoice) {  // 1
    document.getElementById("apple_count_zero").innerHTML
        = 0 + " " + numerous.pluralize(langChoice, 0, pluralFormVariants[langChoice]);  // 2
    document.getElementById("apple_count_one").innerHTML
        = 1 + " " + numerous.pluralize(langChoice, 1, pluralFormVariants[langChoice]);
    document.getElementById("apple_count_few").innerHTML
        = 2 + " " + numerous.pluralize(langChoice, 2, pluralFormVariants[langChoice]);
    document.getElementById("apple_count_many").innerHTML
        = 5 + " " + numerous.pluralize(langChoice, 5, pluralFormVariants[langChoice]);
}
  1. Create a pluralizeUsingNumerous function that accepts a langChoice parameter.
  2. Call the numerous.pluralize function, consecutively passing in the langChoice argument, an apple count of 0, and an extracted plural form variant object for the given langChoice from the pluralFormVariants const. Set the returned value on the HTML element with an ID of “apple_count_zero”.

Similarly, call the numerous.pluralize function for the rest of the plural form variants and set the returned value on the appropriate HTML elements.

Then, let us add event listeners in our numerous_pluralization module for the HTML buttons we placed in the previous section:

.
document.getElementById('lang_choice_en').addEventListener('click', function() {
    pluralizeUsingNumerous("en");  // 1
});
document.getElementById('lang_choice_ru').addEventListener('click', function() {
    pluralizeUsingNumerous("ru");  // 2
});
  1. Call the pluralizeUsingNumerous function with an “en” argument when the element with ID “lang_choice_en” is clicked.
  2. Call the pluralizeUsingNumerous function with an “ru” argument when the element with ID “lang_choice_ru” is clicked.

Finally, let’s not forget to import this numerous_pluralization module into our PluralizationJS project’s index file. We can perform this import simply by adding the following line in the <head> tag of the “index.html” file:

<head>
.
<script type="module" src="numerous_pluralization.js"></script>
</head>
view raw index.html hosted with ❤ by GitHub

Test it out

Running our PluralizationJS application lets us retrieve a pluralized apple count in the English locale and also in the Russian locale:

In English:

In Russian:

Java pluralization

Much like front-end programming languages, their counterparts, back-end languages, require methods for string pluralization all the same. So, let’s explore how Java tackles string pluralization.

The source code is available on GitHub.

Basic Java project setup

First off, let’s create a simple Java application to use as the stage for trying out our pluralizations. For this, we’ll open up our favorite Java IDE and create a PluralizationJava Maven project inside it with this configuration:

GroupId: com.lokalise
ArtifactId: pluralization-java
Version: 1.0-SNAPSHOT

Note: These configurations are placed as guidelines only. Hence, feel free to set them up as you prefer.

Secondly, let us create a Main class holding a main method inside our PluralizationJava project’s src/main/java folder:

.
public class Main {
    public static void main(String[] args) {}
}

Pluralization with ICU

The native string pluralization method Java currently provides surely leaves a lot to be desired. As we covered in our Java internationalization basics article, Java asks us to resort to the ChoiceFormat class for pluralization. This method theoretically works but ends up requiring hundreds of String and double arrays, making our application quite cumbersome to modify and manage.

Exploring more practical ways of pluralization, the decades-matured ICU and its Java variant, the ICU4J library, prove to be our best bet! Why don’t we set up this ICU4J library in our PluralizationJava project and see for ourselves how mature it actually is?

Set up ICU4J library

Let us simply head over to our PluralizationJava project’s pom.xml file and add the latest ICU4J library as a dependency:

.
<dependencies>
    <dependency>
        <groupId>com.ibm.icu</groupId>
        <artifactId>icu4j</artifactId>
        <version>70.1</version>
    </dependency>
</dependencies>

Note: The mentioned ICU4J library version was simply the latest one available in the Maven repository at the time of writing and is therefore subject to change over time.

Enter ICU MessageFormat

Although Java natively brings out a MessageFormat class, it unfortunately lacks any sort of pluralization support. But, admiringly, ICU supplies its own MessageFormat class which knows how to handle plurals. Moreover, ICU’s MessageFormat inherits from the native java.text.Format class consequently exposing all its methods to the ICU MessageFormat itself.

MessageFormat(String pattern, ULocale locale) constructor explanation

We will use this MessageFormat constructor to initialize MessageFormat objects in the coming sections. This is because it allows a ULocale input, letting us define the locale we plan to localize our string in.

MessageFormat expects us to provide a pattern string with a specific syntax. Since we’re planning to pluralize our strings, the pattern syntax we must attend to would be:

pluralArg = '{' argNameOrNumber ',' "plural" ',' pluralStyle '}'

The first parameter, argNameOrNumber, is where we should pass in the quantity or count for MessageFormat to pluralize on. This parameter accepts one of two options:

  • A map argument name that holds the count as its value.
  • An array index that holds the count.

This map or array which contains the particular count argument or index is passed in when calling the MessageFormat object’s format method.

The second parameter, plural, simply informs MessageFormat that this is a plural pattern.

The third parameter, pluralStyle, obtains all the data for the plural forms according to the pluralStyle syntax in PluralFormat.

Pluralize with MessageFormat

Firstly, let’s introduce a new static method to our PluralizationJava project’s Main class:

private static void pluralizeUsingMessageFormat() {  // 1
    MessageFormat pluralMessageFormat = new MessageFormat(  // 2
                                            "{quantity, plural, " +
                                            "=0{There are no apples.}" +
                                            "=1{There is one apple.}" +
                                            "other{There are # apples.}" +
                                            "}",
                                            ULocale.ENGLISH);  // 3

    Map patternArgs = new HashMap();  // 4
    patternArgs.put("quantity", 0);
    System.out.println(pluralMessageFormat.format(patternArgs));
    patternArgs.put("quantity", 1);
    System.out.println(pluralMessageFormat.format(patternArgs));
    patternArgs.put("quantity", 2);
    System.out.println(pluralMessageFormat.format(patternArgs));
    patternArgs.put("quantity", 5);
    System.out.println(pluralMessageFormat.format(patternArgs));
}
  1. Create a pluralizeUsingMessageFormat method. The method is kept as static to allow it to be called from the main method later on.
  2. Initialize a MessageFormat named “pluralMessageFormat”. As the first argument to the constructor, pass in an array holding:
    • a map key value of “quantity”.
    • an instruction that it’s a plural pattern.
    • sentences in plural forms in compliance with the PluralFormat syntax.
  3. For the second argument to the MessageFormat constructor, provide a ULocale of the English language.
  4. Create a HashMap named patternArgs, place different values for its “quantity” key, and call the inherited format method of pluralMessageFormat, passing in the patternArgs map to it as an argument.

Secondly, let’s not forget to call this pluralizeUsingMessageFormat method inside our PluralizationJava project’s main method:

public static void main(String[] args) {
    pluralizeUsingMessageFormat();
}
Test it out

Let’s run our PluralizationJava app and see if the ICU4J MessageFormat can count our apples properly!

Pluralize in French

What if we need to pluralize in another locale? With MessageFormat, it boils down to a single MessageFormat initialization.

Let’s head over to our pluralizeUsingMessageFormat method and change its MessageFormat initialization as follows:

MessageFormat pluralMessageFormat = new MessageFormat(  // 1
                                        "{quantity, plural, " +
                                        "=0{Il n'y a pas de pommes.}" +
                                        "=1{Il y a une pomme.}" +
                                        "other{Il y a # pommes.}" +
                                        "}",
                                        ULocale.FRENCH);  // 2
  1. Initialize pluralMessageFormat with a MessageFormat object holding a French plural pattern as its first argument.
  2. Pass a ULocale of the French language for the 2nd argument.
Test it out

Running our PluralizationJava application again shows us the correctly pluralized apple counts—but this time in French!

Load plural pattern externally

Suppose we needed our app to successfully count apples in hundreds of locales. Technically, we could write thousands of lines inside our application’s classes, but it’d only bog down the whole application, don’t you think? And, in fact, with ChoiceFormat we would have been forced to do exactly that. But, thanks to ICU MessageFormat patterns and their serializable pattern syntaxes, we can safely place all our plural patterns for all locales inside Java properties files and call it a day! Let’s find out how to do this, shall we?

Firstly, let’s navigate to our PluralizationJava project’s src/main/resources directory and add a “pattern_en.properties” file inside it:

applecount={quantity, plural, =0{There are no apples.}=1{There is one apple.}other{There are # apples.}}

Note: It’s safe to create a “resources” directory in the mentioned path if it doesn’t already exist.

Necessarily, we placed the same English plural pattern we set in the previous section as a property value this time around, along with an “applecount” property key.

Likewise, secondly, let’s add a “pattern_fr.properties” file to hold the French locale counterparts right next to the previous properties file:

applecount={quantity, plural, =0{Il n'y a pas de pommes.}=1{Il y a une pomme.}other{Il y a # pommes.}}

Thirdly, we’ll add a static method to the Main class of our PluralizationJava project:

private static void pluralizeWithExternalPluralPattern() {  // 1
    ResourceBundle resourceBundleEn = ResourceBundle.getBundle("pattern", Locale.ENGLISH);  // 2
    String patternEn = resourceBundleEn.getString("applecount");  // 3
    MessageFormat pluralMessageFormat = new MessageFormat(patternEn, ULocale.ENGLISH);  // 4

    Map patternArgs = new HashMap();  // 5
    patternArgs.put("quantity", 0);
    System.out.println(pluralMessageFormat.format(patternArgs));
    patternArgs.put("quantity", 1);
    System.out.println(pluralMessageFormat.format(patternArgs));
    patternArgs.put("quantity", 2);
    System.out.println(pluralMessageFormat.format(patternArgs));
    patternArgs.put("quantity", 5);
    System.out.println(pluralMessageFormat.format(patternArgs));
}
  1. Add a static pluralizeWithExternalPluralPattern method.
  2. Use ResourceBundle.getBundle() to retrieve the resource bundle with a base name of “pattern” and a Locale of English. In our case, ResourceBundle will load the resource bundle in the “pattern_en.properties” file. Save the loaded resource bundle in a “resourceBundleEn” ResourceBundle object.
  3. Ask resourceBundleEn to get a string value for an “applecount” key from the resource bundle it’s holding. Store the received string value in a “patternEn” String object.
  4. Initialize pluralMessageFormat with a MessageFormat object holding patternEn as its plural pattern and a ULocale of English.
  5. Create a HashMap named patternArgs, place different values for its “quantity” key, and call the inherited format method of pluralMessageFormat, passing in the patternArgs map to it as an argument.

Fourthly, let’s call this pluralizeWithExternalPluralPattern method inside our PluralizationJava project’s main method:

public static void main(String[] args) {
    pluralizeWithExternalPluralPattern();
}
Test it out

That’s it! Running our PluralizationJava app will show us the same result we achieved earlier. But don’t forget! This time the whole plural pattern was taken from an easily modifiable resource file:

Pluralize in French

Just like the last time, pluralizing in another locale requires hardly any changes to the code.

Let’s navigate to our pluralizeWithExternalPluralPattern method and change the first few lines, like so:

private static void pluralizeWithExternalPluralPattern() {
    ResourceBundle resourceBundleFr = ResourceBundle.getBundle("pattern", Locale.FRENCH);  // 1
    String patternFr = resourceBundleFr.getString("applecount");  // 2
    MessageFormat pluralMessageFormat = new MessageFormat(patternFr, ULocale.FRENCH);  // 3
    .
    .
}
  1. Use ResourceBundle.getBundle() to get the resource bundle with a base name of “pattern” and a Locale of French. This time around, ResourceBundle will load the resource bundle in the “pattern_fr.properties” file. Store the loaded resource bundle in a “resourceBundleFr” ResourceBundle object.
  2. Ask resourceBundleFr to get a string value for an “applecount” key from the resource bundle it’s holding. Store the received string value in a “patternFr” String object.
  3. Initialize pluralMessageFormat with a MessageFormat object holding patternFr as its plural pattern and a ULocale of French.
Test it out

That’s all it takes! Let’s run our PluralizationJava application to see the apple count delightfully pluralized in French:

Some pluralization extras

At this point, we have explored ways to pluralize strings in multiple languages—both front-end and back-end. How about we take things a bit further and learn a few more pluralization-related tricks while we’re at it?

Set placeholders using Pluralize

Venturing back toward the front end, let’s discover how we can use placeholders when pluralizing our PluralizationJS application.

Firstly, we’ll head over to the “index.html” file of our PluralizationJS project and code a new function inside its <head> tag:

.
<script>
function getCountWithPlaceholdersUsingPluralizeLib(name, item, count) {  // 1
    if (count >= 0) {  // 2
        let pluralizedItemCountText = pluralize(item, count, true);  // 3
        return name + " had " + pluralizedItemCountText;  // 4
    } else {
        return "That's surely an invalid count!";  // 5
    }
}
</script>
  1. Create a getCountWithPlaceholdersUsingPluralizeLib function that accepts the parameters:
    • name – holds a name input from the user.
    • item – keeps an item input that the user wishes to pluralize.
    • count – holds the number of items the user wishes to pluralize for their previously provided item.
  2. Check if the count value is greater than or equal to zero to avoid uncountable number inputs.
  3. Call the Pluralize library’s pluralize function. As its arguments, consecutively pass in item, count, and a boolean indicating prefixing of the result with the item count. Save the returned pluralization result in a pluralizedItemCountText variable.
  4. Return a string concatenating the name argument with the pluralized result in pluralizedItemCountText.
  5. If the condition in step 2 isn’t met, return a string informing of the invalid input.

Secondly, let’s add some empty HTML elements inside the <body> tag of our project’s “index.html” file:

<table>
    <tr>  // 1
        <td><label for="name_input">Name: </label></td>
        <td><input type="text" id="name_input"></td>
    </tr>
    <tr>
        <td><label for="item_input">Item: </label></td>
        <td><input type="text" id="item_input"></td>
    </tr>
    <tr>
        <td><label for="item_count_input">Item count: </label></td>
        <td><input type="text" id="item_count_input"></td>
        <td><button id="placeholder_submit">Submit</button></td>  // 2
    </tr>
</table>

<p id="placeholder_output"></p>  // 3
  1. Add HTML table rows to get the user inputs required by the getCountWithPlaceholdersUsingPluralizeLib function.
  2. Add an HTML button with an ID of “placeholder_submit” to bind with an event handler later on.
  3. Put in an empty HTML paragraph element with an ID of “placeholder_output” to display the pluralization result.

Thirdly, let’s add an event handler script right below the HTML table we previously scripted:

.
<script>
    document.getElementById("placeholder_submit").onclick = function() {  // 1
        let countWithPlaceholders = getCountWithPlaceholdersUsingPluralizeLib(  // 2
            document.getElementById('name_input').value,
            document.getElementById('item_input').value,
            +document.getElementById('item_count_input').value
        );

        document.getElementById("placeholder_output").innerHTML = countWithPlaceholders;  // 3
    };
</script>
  1. Place a JavaScript onclick event handler to trigger on the click of the placeholder_submit button.
  2. Call getCountWithPlaceholdersUsingPluralizeLib, passing the user input values for its arguments. Store the returned value in a countWithPlaceholders variable. Notice that The 3rd argument is prefixed with a unary plus operator to convert the value document.getElementById returns into a number.
  3. Set the value of the “placeholder_output” element to the value in countWithPlaceholders.

Test it out

This time we’re not restricted to apples! Let’s hypothetically count the exes Joey and Chandler had in Friends. Let’s run our PluralizationJS application and input some values for the placeholders:

Although a die-hard Friends fan might whack us on our way home for those incorrect numbers, we’ve successfully placed placeholders while pluralizing.

MessageFormat arguments as placeholders

Moving back to the back end, ICU MessageFormat and its arguments don’t let us down when it comes to placeholders. Let’s see how we can set up placeholders when pluralizing strings in our Java applications.

Imagine our PluralizationJava application serves for an apple farm distributed worldwide. Assume we need to print the count of apples available on specific farms. Let’s find out how we can pass in these locations as placeholder values alongside the apple counts.

Firstly, we’ll open up our PluralizationJava project’s Main class and add a static method inside it:

private static void pluralizeUsingMessageFormatArguments() {  // 1
    MessageFormat pluralMessageFormatWithArgs = new MessageFormat(  // 2
                                                    "{quantity, plural, " +
                                                    "=0{There are no apples in the {location} farm.}" +
                                                    "=1{There is one apple in the {location} farm.}" +
                                                    "other{There are # apples in the {location} farm.}" +
                                                    "}",
                                                    ULocale.ENGLISH);  // 3

    Map patternArgs = new HashMap();  // 4
    patternArgs.put("quantity", 0);
    patternArgs.put("location", "Normandy");
    System.out.println(pluralMessageFormatWithArgs.format(patternArgs));
    patternArgs.put("quantity", 2);
    patternArgs.put("location", "Washington");
    System.out.println(pluralMessageFormatWithArgs.format(patternArgs));
}
  1. Create a pluralizeUsingMessageFormatArguments static method.
  2. Initialize a MessageFormat named “pluralMessageFormatWithArgs”. As the first argument to the constructor, pass in an array bearing:
    • a map key value of “quantity”.
    • an indication that it’s a plural pattern.
    • sentences in plural forms in compliance with the PluralFormat syntax. “{location}” marks a placeholder with a map record key name of “location”. The current MessageFormat object will access this map record from the map passed in when calling its format method.
  3. Pass an English ULocale as the 2nd argument to the MessageFormat constructor.
  4. Create a HashMap named patternArgs, place different values for its “quantity” key, put different placeholder values for the map record keyed “location”, and call the pluralMessageFormat.format method, passing in the patternArgs map to it as an argument.

Secondly, let’s make sure to call this pluralizeUsingMessageFormatArguments method inside the main method of our PluralizationJava app:

public static void main(String[] args) {
    pluralizeUsingMessageFormatArguments();
}

Test it out

Let’s run our PluralizationJava application and see if it works! We should now be able to see pluralization taking place while swiftly placing the provided placeholder values alongside them.

Pluralize with Lokalise

As we discovered, the seemingly effortless task of pluralization becomes a challenge to conquer the moment we add multiple locales to our project. But, at the end of the day, unless you’re coding for ‘Pluralization’ coursework at university, or your organization is focused exclusively on pluralization, you might reasonably hesitate to devote so many hours of work just to setting up pluralization in your application.

But, what if I told you there’s a much simpler, 1000x faster, and a million times more favorable way to handle string pluralization in any of your applications—both front-end and back-end?

Meet Lokalise, the translation management system that takes care of all your applications’ string pluralization wants and needs. With features like:

  • Easy integration with various other services
  • Collaborative translations
  • Quality assurance tools for translations
  • Easy management of your translations through a central dashboard
  • Plus, loads of others

Lokalise will make your life a whole lot easier by letting you expand your properly pluralized applications to all the locales you’ll ever plan to reach.

Your plurals handled automatically

With Lokalise, the whole jargon of pluralization is simplified to the mere click of a Plural switch.

 

So, is there anything left to ponder at this point? Start with Lokalise in just a few steps:

  • Sign up for a free trial (no credit card information required).
  • Log in to your account.
  • Create a new project under any name you like.
  • Upload your translation files and edit them as required.

There you go! Almost before you could pluralize the word “hippopotamus” in your head, you have already completed the baby steps toward Lokalise-ing your application. See the Getting Started section for a collection of articles that will provide all the help you’ll need to kick-start the Lokalise journey. Also, refer to Lokalise API Documentation for a complete list of REST commands you can call on your Lokalise internationalization project.

Conclusion

In this step-by-step guide, we explored how some front-end and back-end languages—namely, JavaScript and Java—handle string pluralization. We created a basic JavaScript project and performed hardcoded pluralization on it. Then, we integrated a Pluralize third-party library to pluralize our English locale strings. Subsequently, we employed the help of another third-party library called Numerous to pluralize strings in multiple locales. Additionally, we looked into using Pluralize for placeholders.

Moving on to the back end, we created a basic Java project and used the MessageFormat variant from ICU to pluralize strings. We explored how MessageFormat uses plural patterns and arguments passed to it to use as placeholder values.

So, the time has come for me to vaporize, so that you can go and pluralize. And, before it’s too late to apologize, make sure those hands are sanitized!

Related posts

Learn something new every week

Get the latest in localization delivered straight to your inbox.

Read also
Localization made easy. Why wait?
The preferred localization tool of 2000+ companies