/** * General purpose inflector class that {@link #pluralize pluralizes}, * {@link #singularize singularizes} and {@link #ordinalize ordinalizes} words. Sample usage: * * //turning singular words into plurals * Ext.util.Inflector.pluralize('word'); //'words' * Ext.util.Inflector.pluralize('person'); //'people' * Ext.util.Inflector.pluralize('sheep'); //'sheep' * * //turning plurals into singulars * Ext.util.Inflector.singularize('words'); //'word' * Ext.util.Inflector.singularize('people'); //'person' * Ext.util.Inflector.singularize('sheep'); //'sheep' * * //ordinalizing numbers * Ext.util.Inflector.ordinalize(11); //"11th" * Ext.util.Inflector.ordinalize(21); //"21st" * Ext.util.Inflector.ordinalize(1043); //"1043rd" * * # Customization * * The Inflector comes with a default set of US English pluralization rules. These can be augmented * with additional rules if the default rules do not meet your application's requirements, * or swapped out entirely for other languages. Here is how we might add a rule that pluralizes * "ox" to "oxen": * * Ext.util.Inflector.plural(/^(ox)$/i, "$1en"); * * Each rule consists of two items - a regular expression that matches one or more rules, * and a replacement string. In this case, the regular expression will only match the string "ox", * and will replace that match with "oxen". Here's how we could add the inverse rule: * * Ext.util.Inflector.singular(/^(ox)en$/i, "$1"); * * Note that the ox/oxen rules are present by default. */Ext.define('Ext.util.Inflector', { /* Begin Definitions */ singleton: true, /* End Definitions */ /* eslint-disable no-multi-spaces */ /** * @private * The registered plural tuples. Each item in the array should contain two items - the first * must be a regular expression that matchers the singular form of a word, the second must be * a String that replaces the matched part of the regular expression. This is managed by the * {@link #plural} method. * @property {Array} plurals */ plurals: [ [(/(quiz)$/i), "$1zes" ], [(/^(ox)$/i), "$1en" ], [(/([m|l])ouse$/i), "$1ice" ], [(/(matr|vert|ind)ix|ex$/i), "$1ices" ], [(/(x|ch|ss|sh)$/i), "$1es" ], [(/([^aeiouy]|qu)y$/i), "$1ies" ], [(/(hive)$/i), "$1s" ], [(/(?:([^f])fe|([lr])f)$/i), "$1$2ves"], [(/sis$/i), "ses" ], [(/([ti])um$/i), "$1a" ], [(/(buffal|tomat|potat)o$/i), "$1oes" ], [(/(bu)s$/i), "$1ses" ], [(/(alias|status|sex)$/i), "$1es" ], [(/(octop|vir)us$/i), "$1i" ], [(/(ax|test)is$/i), "$1es" ], [(/^(p)erson$/i), "$1eople"], [(/^(m)an$/i), "$1en" ], [(/(.*)(child)(ren)?$/i), "$1$2ren"], [(/s$/i), "s" ], [(/$/), "s" ] ], /** * @private * The set of registered singular matchers. Each item in the array should contain two items - * the first must be a regular expression that matches the plural form of a word, the second * must be a String that replaces the matched part of the regular expression. This is managed * by the {@link #singular} method. * @property {Array} singulars */ singulars: [ [(/(address)$/i), "$1" ], [(/(quiz)zes$/i), "$1" ], [(/(matr)ices$/i), "$1ix" ], [(/(vert|ind)ices$/i), "$1ex" ], [(/^(ox)en/i), "$1" ], [(/(alias|status)es$/i), "$1" ], [(/(octop|vir)i$/i), "$1us" ], [(/(cris|ax|test)es$/i), "$1is" ], [(/(shoe)s$/i), "$1" ], [(/(o)es$/i), "$1" ], [(/(bus)es$/i), "$1" ], [(/([m|l])ice$/i), "$1ouse" ], [(/(x|ch|ss|sh)es$/i), "$1" ], [(/(m)ovies$/i), "$1ovie" ], [(/(s)eries$/i), "$1eries"], [(/([^aeiouy]|qu)ies$/i), "$1y" ], [(/([lr])ves$/i), "$1f" ], [(/(tive)s$/i), "$1" ], [(/(hive)s$/i), "$1" ], [(/([^f])ves$/i), "$1fe" ], [(/(^analy)ses$/i), "$1sis" ], [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"], [(/([ti])a$/i), "$1um" ], [(/(n)ews$/i), "$1ews" ], [(/(p)eople$/i), "$1erson"], [(/s$/i), "" ] ], /* eslint-enable no-multi-spaces */ /** * @private * The registered uncountable words * @property {String[]} uncountable */ uncountable: [ "sheep", "fish", "series", "species", "money", "rice", "information", "equipment", "grass", "mud", "offspring", "deer", "means" ], /** * Adds a new singularization rule to the Inflector. See the intro docs for more information * @param {RegExp} matcher The matcher regex * @param {String} replacer The replacement string, which can reference matches from the matcher * argument */ singular: function(matcher, replacer) { this.singulars.unshift([matcher, replacer]); }, /** * Adds a new pluralization rule to the Inflector. See the intro docs for more information * @param {RegExp} matcher The matcher regex * @param {String} replacer The replacement string, which can reference matches from the matcher * argument */ plural: function(matcher, replacer) { this.plurals.unshift([matcher, replacer]); }, /** * Removes all registered singularization rules */ clearSingulars: function() { this.singulars = []; }, /** * Removes all registered pluralization rules */ clearPlurals: function() { this.plurals = []; }, /** * Returns true if the given word is transnumeral (the word is its own singular and * plural form - e.g. sheep, fish) * @param {String} word The word to test * @return {Boolean} True if the word is transnumeral */ isTransnumeral: function(word) { return Ext.Array.indexOf(this.uncountable, word) !== -1; }, /** * Returns the pluralized form of a word (e.g. Ext.util.Inflector.pluralize('word') * returns 'words') * @param {String} word The word to pluralize * @return {String} The pluralized form of the word */ pluralize: function(word) { if (this.isTransnumeral(word)) { return word; } // eslint-disable-next-line vars-on-top var plurals = this.plurals, length = plurals.length, tuple, regex, i; for (i = 0; i < length; i++) { tuple = plurals[i]; regex = tuple[0]; // eslint-disable-next-line eqeqeq if (regex == word || (regex.test && regex.test(word))) { return word.replace(regex, tuple[1]); } } return word; }, /** * Returns the singularized form of a word (e.g. Ext.util.Inflector.singularize('words') * returns 'word') * @param {String} word The word to singularize * @return {String} The singularized form of the word */ singularize: function(word) { if (this.isTransnumeral(word)) { return word; } // eslint-disable-next-line vars-on-top var singulars = this.singulars, length = singulars.length, tuple, regex, i; for (i = 0; i < length; i++) { tuple = singulars[i]; regex = tuple[0]; // eslint-disable-next-line eqeqeq if (regex == word || (regex.test && regex.test(word))) { return word.replace(regex, tuple[1]); } } return word; }, /** * Returns the correct {@link Ext.data.Model Model} name for a given string. Mostly used * internally by the data * package * @param {String} word The word to classify * @return {String} The classified version of the word */ classify: function(word) { return Ext.String.capitalize(this.singularize(word)); }, /** * Ordinalizes a given number by adding a prefix such as 'st', 'nd', 'rd' or 'th' based on * the last digit of the number. 21 -> 21st, 22 -> 22nd, 23 -> 23rd, 24 -> 24th etc * @param {Number} number The number to ordinalize * @return {String} The ordinalized number */ ordinalize: function(number) { var parsed = parseInt(number, 10), mod10 = parsed % 10, mod100 = parsed % 100; // 11 through 13 are a special case if (11 <= mod100 && mod100 <= 13) { return number + "th"; } else { switch (mod10) { case 1 : return number + "st"; case 2 : return number + "nd"; case 3 : return number + "rd"; default: return number + "th"; } } }}, function() { // aside from the rules above, there are a number of words that have irregular pluralization // so we add them here var singular, irregulars = { alumnus: 'alumni', cactus: 'cacti', focus: 'foci', nucleus: 'nuclei', radius: 'radii', stimulus: 'stimuli', ellipsis: 'ellipses', paralysis: 'paralyses', oasis: 'oases', appendix: 'appendices', index: 'indexes', beau: 'beaux', bureau: 'bureaux', tableau: 'tableaux', woman: 'women', child: 'children', man: 'men', corpus: 'corpora', criterion: 'criteria', curriculum: 'curricula', genus: 'genera', memorandum: 'memoranda', phenomenon: 'phenomena', foot: 'feet', goose: 'geese', tooth: 'teeth', antenna: 'antennae', formula: 'formulae', nebula: 'nebulae', vertebra: 'vertebrae', vita: 'vitae' }; for (singular in irregulars) { if (irregulars.hasOwnProperty(singular)) { this.plural(singular, irregulars[singular]); this.singular(irregulars[singular], singular); } }});