pmrotule
pmrotule

Reputation: 9692

JavaScript pluralize an english string

In PHP, I use Kuwamoto's class to pluralize nouns in my strings. I didn't find something as good as this script in javascript except for some plugins. So, it would be great to have a javascript function based on Kuwamoto's class.

http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/

Upvotes: 88

Views: 124849

Answers (19)

Maksim Nesterenko
Maksim Nesterenko

Reputation: 6233

Just use Intl.PluralRules.

If you care about English only you can use this code:

/**
 * As English only has two forms for cardinal numbers,
 * the select() method returns only two tags:
 * "one" for the singular case, and "other" for all other cardinal numbers.
 */
export const createEnglishPluralizer = (wordForms: {
  one: string;
  other: string;
}) => {
  const enCardinalRules = new Intl.PluralRules('en-US');

  return (number: number) => {
    const rule = enCardinalRules.select(number) as 'one' | 'other';

    return wordForms[rule];
  };
};

Test

import { createEnglishPluralizer } from './createEnglishPluralizer';

describe('createEnglishPluralizer', () => {
  it('pluralizes', () => {
    const pluralizeNodes = createEnglishPluralizer({
      one: 'node',
      other: 'nodes',
    });

    expect(pluralizeNodes(0)).toBe('nodes');
    expect(pluralizeNodes(1)).toBe('node');
    expect(pluralizeNodes(2)).toBe('nodes');
    // ...
    expect(pluralizeNodes(9)).toBe('nodes');
    expect(pluralizeNodes(10)).toBe('nodes');
    expect(pluralizeNodes(11)).toBe('nodes');
    expect(pluralizeNodes(12)).toBe('nodes');
    expect(pluralizeNodes(13)).toBe('nodes');
    // ...
    expect(pluralizeNodes(19)).toBe('nodes');
    expect(pluralizeNodes(20)).toBe('nodes');
    expect(pluralizeNodes(21)).toBe('nodes');
    expect(pluralizeNodes(22)).toBe('nodes');
    expect(pluralizeNodes(23)).toBe('nodes');
    // ...
    expect(pluralizeNodes(100)).toBe('nodes');
    expect(pluralizeNodes(101)).toBe('nodes');
  });
});

for other languages, you'll need different pluaralizers that use different tags. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules

Upvotes: 0

vsync
vsync

Reputation: 130730

Using the native Intl.PluralRules:

Intl.PluralRules is better than a simple count > 1 check because it handles complex pluralization rules for different languages. English pluralization rules are very easy but it isn't the case for other languages.

const getPlural = (locale = navigator.language) => (count, singular, plural) => {
  const rules = new Intl.PluralRules(locale);
  const pluralCategory = rules.select(count);
  
  if (pluralCategory === "one") return singular;
  
  if (!plural) {
    // fallback for English locales. You can add other languages' fallbacks (see German below)
    if (locale.toLowerCase().startsWith("en")) return `${singular}s`;

    // example for an automatic German fallback
    if (locale.toLowerCase().startsWith("de")) {
      // Common German plural endings
      if (singular.endsWith("e")) return `${singular}n`;  
      if (singular.endsWith("er") || 
          singular.endsWith("el") || 
          singular.endsWith("en")) return singular;       
      return `${singular}e`;
    }
  }
  
  return plural || singular;
}

// English examples
const pluralize = getPlural("en-US"); // when initialized with "English" 

console.log(`1 ${pluralize(1, 'item')}`) // "1 item"
console.log(`2 ${pluralize(2, 'item')}`) // "2 items"
console.log(`3 ${pluralize(2, 'child', 'children')}`) // "3 children"

// German examples
console.log(`1 ${getPlural("DE")(1, 'buch')}`) // "1 book"
console.log(`2 ${getPlural("DE")(2, 'buch')}`) // "2 items"

// Russian
console.log(`2 ${getPlural("RU")(2, 'книга', 'книги')}`) // (books)

enter image description here

Upvotes: 1

srghma
srghma

Reputation: 5353

// 1 - apple
// 2 - apples
const pluralize_noun = (count, noun, suffix = 's') =>
  `${noun}${count !== 1 ? suffix : ''}`;

// 1 - (apple) gives
// 2 - (apples) give
// `This package includes ${package_.person_amount} ${pluralize_noun(package_.person_amount, "ticket")} that ${pluralize_verb(package_.person_amount, "give")} access to ${package_.person_amount} ${pluralize_noun(package_.person_amount, "seat")}.`
const pluralize_verb = (count, verb, suffix = 's') =>
  `${verb}${count !== 1 ? '' : suffix}`;

Upvotes: 0

Tushar Garg
Tushar Garg

Reputation: 9

In my company we were initially using the most voted answer on this thread https://stackoverflow.com/a/39835908/14204063.

Kudos to him for coming up with this algorithm.

Although there is a common missed case for this.

Consider plurals for words like company -> companies, category -> categories cannot be handled with that algorithm.

Thus I came up with this algorithm, please have a look at this.

const maybePluralize = ({ count, noun, suffix = "s", pluralNoun }) => {
  if (count <= 1) {
    return `${count} ${noun}`;
  }

  const pluralForm = pluralNoun ? `${pluralNoun}` : `${noun}${suffix}`;
  return `${count} ${pluralForm}`;
};

Example:

word: category

maybepluralize({count: 1, noun: category}) -> category

maybepluralize({count: 10, noun: category, pluralNoun: "categories"}) -> categories

Upvotes: 0

Oded Breiner
Oded Breiner

Reputation: 29759

In case the singular/plural word is not dynamic and you just want to add an "s" if there's more than one:

`${x} minute${x - 1 ? 's' : ''}`

Upvotes: -1

Must Impress
Must Impress

Reputation: 347

I'm a bit late to this party but this works nicely with very minimal code:

const pluralize = (count, single, plural) => `${count} ${count !== 1 ? plural || single+'s' : single}`;

Provide either a single word:

pluralize(1, 'house');
// Output: 1 house

pluralize(2, 'house');
// Output: 2 houses

or, 2 strings for words with different endings:

pluralize(1, 'company', 'companies');
// Output: 1 company

pluralize(2, 'company', 'companies');
// Output: 2 companies

pluralize(100000, "fish", "fish");
// Output: 100000 fish

pluralize(2, "piece of furniture", "pieces of furniture");
// Output: 2 pieces of furniture

Upvotes: -2

Pepe El Toro
Pepe El Toro

Reputation: 31

I am late to the party too, but this will work for English words or Spanish:

String.prototype.pluralize = function(count, plural = 's') {
  return count === 1 ? this : plural.length > 2 ? plural : this + plural
};

This way you can use any string like so:

"Apple".pluralize(1) // Apple
"Apple".pluralize(2) // Apples
"Company".pluralize(1, "Companies") // Company
"Company".pluralize(5, "Companies") // Companies
"Tooth".pluralize(1, "Teeth") // Tooth
"Tooth".pluralize(2, "Teeth") // Teeth 

Some Spanish:

"arbol".pluralize(1,"es")  // arbol
"arbol".pluralize(2,"es")  // arboles
"manzana".pluralize(1) // manzana
"manzana".pluralize(2) // manzanas

Upvotes: 0

Kabir Sarin
Kabir Sarin

Reputation: 18556

Simple version (ES6):

const pluralize = (count, noun, suffix = 's') =>
  `${count} ${noun}${count !== 1 ? suffix : ''}`;

Typescript:

const pluralize = (count: number, noun: string, suffix = 's') =>
  `${count} ${noun}${count !== 1 ? suffix : ''}`;

Usage:

pluralize(0, 'turtle'); // 0 turtles
pluralize(1, 'turtle'); // 1 turtle
pluralize(2, 'turtle'); // 2 turtles
pluralize(3, 'fox', 'es'); // 3 foxes

This obviously doesn't support all english edge-cases, but it's suitable for most purposes

Upvotes: 113

Nirvana
Nirvana

Reputation: 643

Use -ies or -s (depending on the second-to-last letter) if the word ends in a y, use -es if the word ends in a ‑s, -ss, -sh, -ch, -x, or -z, use a lookup table if the world is an irregular plural, and use -s otherwise.

var pluralize = (function () {
    const vowels = "aeiou";

    const irregulars = { "addendum": "addenda", "aircraft": "aircraft", "alumna": "alumnae", "alumnus": "alumni", "analysis": "analyses", "antenna": "antennae", "antithesis": "antitheses", "apex": "apices", "appendix": "appendices", "axis": "axes", "bacillus": "bacilli", "bacterium": "bacteria", "basis": "bases", "beau": "beaux", "bison": "bison", "bureau": "bureaux", "cactus": "cacti", "château": "châteaux", "child": "children", "codex": "codices", "concerto": "concerti", "corpus": "corpora", "crisis": "crises", "criterion": "criteria", "curriculum": "curricula", "datum": "data", "deer": "deer", "diagnosis": "diagnoses", "die": "dice", "dwarf": "dwarves", "ellipsis": "ellipses", "erratum": "errata", "faux pas": "faux pas", "fez": "fezzes", "fish": "fish", "focus": "foci", "foot": "feet", "formula": "formulae", "fungus": "fungi", "genus": "genera", "goose": "geese", "graffito": "graffiti", "grouse": "grouse", "half": "halves", "hoof": "hooves", "hypothesis": "hypotheses", "index": "indices", "larva": "larvae", "libretto": "libretti", "loaf": "loaves", "locus": "loci", "louse": "lice", "man": "men", "matrix": "matrices", "medium": "media", "memorandum": "memoranda", "minutia": "minutiae", "moose": "moose", "mouse": "mice", "nebula": "nebulae", "nucleus": "nuclei", "oasis": "oases", "offspring": "offspring", "opus": "opera", "ovum": "ova", "ox": "oxen", "parenthesis": "parentheses", "phenomenon": "phenomena", "phylum": "phyla", "quiz": "quizzes", "radius": "radii", "referendum": "referenda", "salmon": "salmon", "scarf": "scarves", "self": "selves", "series": "series", "sheep": "sheep", "shrimp": "shrimp", "species": "species", "stimulus": "stimuli", "stratum": "strata", "swine": "swine", "syllabus": "syllabi", "symposium": "symposia", "synopsis": "synopses", "tableau": "tableaux", "thesis": "theses", "thief": "thieves", "tooth": "teeth", "trout": "trout", "tuna": "tuna", "vertebra": "vertebrae", "vertex": "vertices", "vita": "vitae", "vortex": "vortices", "wharf": "wharves", "wife": "wives", "wolf": "wolves", "woman": "women", "guy": "guys", "buy": "buys", "person": "people" };

    function pluralize(word) {
        word = word.toLowerCase();


        if (irregulars[word]) {
            return irregulars[word];
        }

        if (word.length >= 2 && vowels.includes(word[word.length - 2])) {
            return word + "s";
        }

        if (word.endsWith("s") || word.endsWith("sh") || word.endsWith("ch") || word.endsWith("x") || word.endsWith("z")) {
            return word + "es";
        }

        if (word.endsWith("y")) {
            return word.slice(0, -1) + "ies";
        }


        return word + "s";
    }

    return pluralize;
})();

////////////////////////////////////////
console.log(pluralize("dog"));
console.log(pluralize("cat"));
console.log(pluralize("fox"));
console.log(pluralize("dwarf"));
console.log(pluralize("guy"));
console.log(pluralize("play"));

Obviously, this can't support all English edge-cases, but it has the most common ones.

Upvotes: 5

kmypwn
kmypwn

Reputation: 487

To provide a simple and readable option (ES6):

export function pluralizeAndStringify(value, word, suffix = 's'){
   if (value == 1){
    return value + ' ' + word;
   }
   else {
    return value + ' ' + word + suffix;
   }
}

If you gave something like pluralizeAndStringify(5, 'dog') you'd get "5 dogs" as your output.

Upvotes: 2

Tudor Morar
Tudor Morar

Reputation: 3868

I use this simple inline statement

const number = 2;
const string = `${number} trutle${number === 1 ? "" : "s"}`; //this one
console.log(string)

Upvotes: 7

Erik Campobadal
Erik Campobadal

Reputation: 917

Based on @pmrotule answer with some typescript magic and some additions to the uncountable array. I add here the plural and singular functions.

The plural version:

/**
 * Returns the plural of an English word.
 *
 * @export
 * @param {string} word
 * @param {number} [amount]
 * @returns {string}
 */
export function plural(word: string, amount?: number): string {
    if (amount !== undefined && amount === 1) {
        return word
    }
    const plural: { [key: string]: string } = {
        '(quiz)$'               : "$1zes",
        '^(ox)$'                : "$1en",
        '([m|l])ouse$'          : "$1ice",
        '(matr|vert|ind)ix|ex$' : "$1ices",
        '(x|ch|ss|sh)$'         : "$1es",
        '([^aeiouy]|qu)y$'      : "$1ies",
        '(hive)$'               : "$1s",
        '(?:([^f])fe|([lr])f)$' : "$1$2ves",
        '(shea|lea|loa|thie)f$' : "$1ves",
        'sis$'                  : "ses",
        '([ti])um$'             : "$1a",
        '(tomat|potat|ech|her|vet)o$': "$1oes",
        '(bu)s$'                : "$1ses",
        '(alias)$'              : "$1es",
        '(octop)us$'            : "$1i",
        '(ax|test)is$'          : "$1es",
        '(us)$'                 : "$1es",
        '([^s]+)$'              : "$1s"
    }
    const irregular: { [key: string]: string } = {
        'move'   : 'moves',
        'foot'   : 'feet',
        'goose'  : 'geese',
        'sex'    : 'sexes',
        'child'  : 'children',
        'man'    : 'men',
        'tooth'  : 'teeth',
        'person' : 'people'
    }
    const uncountable: string[] = [
        'sheep',
        'fish',
        'deer',
        'moose',
        'series',
        'species',
        'money',
        'rice',
        'information',
        'equipment',
        'bison',
        'cod',
        'offspring',
        'pike',
        'salmon',
        'shrimp',
        'swine',
        'trout',
        'aircraft',
        'hovercraft',
        'spacecraft',
        'sugar',
        'tuna',
        'you',
        'wood'
    ]
    // save some time in the case that singular and plural are the same
    if (uncountable.indexOf(word.toLowerCase()) >= 0) {
        return word
    }
    // check for irregular forms
    for (const w in irregular) {
        const pattern = new RegExp(`${w}$`, 'i')
        const replace = irregular[w]
        if (pattern.test(word)) {
            return word.replace(pattern, replace)
        }
    }
    // check for matches using regular expressions
    for (const reg in plural) {
        const pattern = new RegExp(reg, 'i')
        if (pattern.test(word)) {
            return word.replace(pattern, plural[reg])
        }
    }
    return word
}

And the singular version:

/**
 * Returns the singular of an English word.
 *
 * @export
 * @param {string} word
 * @param {number} [amount]
 * @returns {string}
 */
export function singular(word: string, amount?: number): string {
    if (amount !== undefined && amount !== 1) {
        return word
    }
    const singular: { [key: string]: string } = {
        '(quiz)zes$'             : "$1",
        '(matr)ices$'            : "$1ix",
        '(vert|ind)ices$'        : "$1ex",
        '^(ox)en$'               : "$1",
        '(alias)es$'             : "$1",
        '(octop|vir)i$'          : "$1us",
        '(cris|ax|test)es$'      : "$1is",
        '(shoe)s$'               : "$1",
        '(o)es$'                 : "$1",
        '(bus)es$'               : "$1",
        '([m|l])ice$'            : "$1ouse",
        '(x|ch|ss|sh)es$'        : "$1",
        '(m)ovies$'              : "$1ovie",
        '(s)eries$'              : "$1eries",
        '([^aeiouy]|qu)ies$'     : "$1y",
        '([lr])ves$'             : "$1f",
        '(tive)s$'               : "$1",
        '(hive)s$'               : "$1",
        '(li|wi|kni)ves$'        : "$1fe",
        '(shea|loa|lea|thie)ves$': "$1f",
        '(^analy)ses$'           : "$1sis",
        '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$': "$1$2sis",
        '([ti])a$'               : "$1um",
        '(n)ews$'                : "$1ews",
        '(h|bl)ouses$'           : "$1ouse",
        '(corpse)s$'             : "$1",
        '(us)es$'                : "$1",
        's$'                     : ""
    }
    const irregular: { [key: string]: string } = {
        'move'   : 'moves',
        'foot'   : 'feet',
        'goose'  : 'geese',
        'sex'    : 'sexes',
        'child'  : 'children',
        'man'    : 'men',
        'tooth'  : 'teeth',
        'person' : 'people'
    }
    const uncountable: string[] = [
        'sheep',
        'fish',
        'deer',
        'moose',
        'series',
        'species',
        'money',
        'rice',
        'information',
        'equipment',
        'bison',
        'cod',
        'offspring',
        'pike',
        'salmon',
        'shrimp',
        'swine',
        'trout',
        'aircraft',
        'hovercraft',
        'spacecraft',
        'sugar',
        'tuna',
        'you',
        'wood'
    ]
    // save some time in the case that singular and plural are the same
    if (uncountable.indexOf(word.toLowerCase()) >= 0) {
        return word
    }
    // check for irregular forms
    for (const w in irregular) {
        const pattern = new RegExp(`${irregular[w]}$`, 'i')
        const replace = w
        if (pattern.test(word)) {
            return word.replace(pattern, replace)
        }
    }
    // check for matches using regular expressions
    for (const reg in singular) {
        const pattern = new RegExp(reg, 'i')
        if (pattern.test(word)) {
            return word.replace(pattern, singular[reg])
        }
    }
    return word
}

Upvotes: 26

Chintan Bhatt
Chintan Bhatt

Reputation: 181

Using @sarink's answer, I made a function to create a string using key value pairs data and pluralizing the keys. Here's the snippet:

// Function to create a string from given key value pairs and pluralize keys
const stringPluralize = function(data){
    var suffix = 's';
    var str = '';
    $.each(data, function(key, val){
        if(str != ''){
            str += val>0 ? ` and ${val} ${key}${val !== 1 ? suffix : ''}` : '';
        }
        else{
            str = val>0 ? `${val} ${key}${val !== 1 ? suffix : ''}` : '';
        }
    });
    return str;
}
var leftDays = '1';
var leftHours = '12';
var str = stringPluralize({day:leftDays, hour:leftHours});
console.log(str) // Gives 1 day and 12 hours

Upvotes: 0

barncat
barncat

Reputation: 85

function pluralize( /* n, [ n2, n3, ... ] str */ ) {
    var n = Array.prototype.slice.call( arguments ) ;
    var str = n.pop(), iMax = n.length - 1, i = -1, j ;
    str = str.replace( /\$\$|\$(\d+)/g,
        function( m, p1 ) { return m == '$$' ? '$' : n[+p1-1] }
    ) ;
    return str.replace( /[(](.*?)([+-])(\d*)(?:,([^,)]*))?(?:,([^)]*))?[)]/g,
        function( match, one, sign, abs, not1, zero ) {
            // if abs, use indicated element in the array of numbers
            // instead of using the next element in sequence
            abs ? ( j = +abs - 1 ) : ( i < iMax && i++, j = i ) ;
            if ( zero != undefined && n[j] == 0 ) return zero ;
            return ( n[j] != 1 ) == ( sign == '+' ) ? ( not1 || 's' ) : one ;
        }
    ) ;  
}

console.log( pluralize( 1, 'the cat(+) live(-) outside' ) ) ;
// the cat lives outside
console.log( pluralize( 2, 'the child(+,ren) (is+,are) inside' ) ) ;
// the children are inside
console.log( pluralize( 0, '$1 dog(+), ($1+,$1,no) dog(+), ($1+,$1,no) dog(+,,)' ) ) ;
// 0 dogs, no dogs, no dog
console.log( pluralize( 100, 1, '$1 penn(y+,ies) make(-1) $$$2' ) ) ;
// 100 pennies make $1
console.log( pluralize( 1, 0.01, '$1 penn(y+,ies) make(-1) $$$2' ) ) ;
// 1 penny makes $0.01

Upvotes: 0

Sergio Tapia
Sergio Tapia

Reputation: 9825

Taken from my blog: https://sergiotapia.me/pluralizing-strings-in-javascript-es6-b5d4d651d403


You can use the pluralize library for this.

NPM:
npm install pluralize --save

Yarn:
yarn add pluralize

Wherever you want to use the lib, you can require it easily.

var pluralize = require('pluralize')

I like to add it to the window object so I can just invoke pluralize() wherever I need it. Within my application.js root file:

window.pluralize = require('pluralize')

Then you can just use it anywhere, React components, or just plain Javascript:

<span className="pull-left">
  {`${item.score} ${pluralize('point', item.score)}`}
</span>

console.log(pluralize('point', item.score))

Upvotes: 7

Joshua Pinter
Joshua Pinter

Reputation: 47621

Use Pluralize

There's a great little library called Pluralize that's packaged in npm and bower.

This is what it looks like to use:

import Pluralize from 'pluralize';

Pluralize( 'Towel', 42 );       // "Towels"

Pluralize( 'Towel', 42, true ); // "42 Towels"

And you can get it here:

https://github.com/blakeembrey/pluralize

Upvotes: 87

Slava Fomin II
Slava Fomin II

Reputation: 28661

I’ve created a very simple library that can be used for words pluralization in JavaScript. It transparently uses CLDR database for multiple locales, so it supports almost any language you would like to use. It’s API is very minimalistic and integration is extremely simple. It’s called Numerous.

I’ve also written a small introduction article to it: «How to pluralize any word in different languages using JavaScript?».

Feel free to use it in your project. I will also be glad for your feedback on it.

Upvotes: 2

gasolin
gasolin

Reputation: 2334

The new intl API spec from ECMA will provide the plural rules function, https://github.com/tc39/proposal-intl-plural-rules

Here's the polyfill that can be used today https://github.com/eemeli/IntlPluralRules

Upvotes: 8

pmrotule
pmrotule

Reputation: 9692

So, I answer my own question by sharing my translation in javascript of Kuwamoto's PHP class.

String.prototype.plural = function(revert){

    var plural = {
        '(quiz)$'               : "$1zes",
        '^(ox)$'                : "$1en",
        '([m|l])ouse$'          : "$1ice",
        '(matr|vert|ind)ix|ex$' : "$1ices",
        '(x|ch|ss|sh)$'         : "$1es",
        '([^aeiouy]|qu)y$'      : "$1ies",
        '(hive)$'               : "$1s",
        '(?:([^f])fe|([lr])f)$' : "$1$2ves",
        '(shea|lea|loa|thie)f$' : "$1ves",
        'sis$'                  : "ses",
        '([ti])um$'             : "$1a",
        '(tomat|potat|ech|her|vet)o$': "$1oes",
        '(bu)s$'                : "$1ses",
        '(alias)$'              : "$1es",
        '(octop)us$'            : "$1i",
        '(ax|test)is$'          : "$1es",
        '(us)$'                 : "$1es",
        '([^s]+)$'              : "$1s"
    };

    var singular = {
        '(quiz)zes$'             : "$1",
        '(matr)ices$'            : "$1ix",
        '(vert|ind)ices$'        : "$1ex",
        '^(ox)en$'               : "$1",
        '(alias)es$'             : "$1",
        '(octop|vir)i$'          : "$1us",
        '(cris|ax|test)es$'      : "$1is",
        '(shoe)s$'               : "$1",
        '(o)es$'                 : "$1",
        '(bus)es$'               : "$1",
        '([m|l])ice$'            : "$1ouse",
        '(x|ch|ss|sh)es$'        : "$1",
        '(m)ovies$'              : "$1ovie",
        '(s)eries$'              : "$1eries",
        '([^aeiouy]|qu)ies$'     : "$1y",
        '([lr])ves$'             : "$1f",
        '(tive)s$'               : "$1",
        '(hive)s$'               : "$1",
        '(li|wi|kni)ves$'        : "$1fe",
        '(shea|loa|lea|thie)ves$': "$1f",
        '(^analy)ses$'           : "$1sis",
        '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$': "$1$2sis",        
        '([ti])a$'               : "$1um",
        '(n)ews$'                : "$1ews",
        '(h|bl)ouses$'           : "$1ouse",
        '(corpse)s$'             : "$1",
        '(us)es$'                : "$1",
        's$'                     : ""
    };

    var irregular = {
        'move'   : 'moves',
        'foot'   : 'feet',
        'goose'  : 'geese',
        'sex'    : 'sexes',
        'child'  : 'children',
        'man'    : 'men',
        'tooth'  : 'teeth',
        'person' : 'people'
    };

    var uncountable = [
        'sheep', 
        'fish',
        'deer',
        'moose',
        'series',
        'species',
        'money',
        'rice',
        'information',
        'equipment'
    ];

    // save some time in the case that singular and plural are the same
    if(uncountable.indexOf(this.toLowerCase()) >= 0)
      return this;

    // check for irregular forms
    for(word in irregular){

      if(revert){
              var pattern = new RegExp(irregular[word]+'$', 'i');
              var replace = word;
      } else{ var pattern = new RegExp(word+'$', 'i');
              var replace = irregular[word];
      }
      if(pattern.test(this))
        return this.replace(pattern, replace);
    }

    if(revert) var array = singular;
         else  var array = plural;

    // check for matches using regular expressions
    for(reg in array){

      var pattern = new RegExp(reg, 'i');

      if(pattern.test(this))
        return this.replace(pattern, array[reg]);
    }

    return this;
}

Easy to use:

alert("page".plural()); // return plural form => pages
alert("mouse".plural()); // return plural form => mice
alert("women".plural(true)); // return singular form => woman

DEMO

Upvotes: 47

Related Questions