3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * General purpose inflector class that {@link #pluralize pluralizes}, {@link #singularize singularizes} and
17 * {@link #ordinalize ordinalizes} words. Sample usage:
19 * //turning singular words into plurals
20 * Ext.util.Inflector.pluralize('word'); //'words'
21 * Ext.util.Inflector.pluralize('person'); //'people'
22 * Ext.util.Inflector.pluralize('sheep'); //'sheep'
24 * //turning plurals into singulars
25 * Ext.util.Inflector.singularize('words'); //'word'
26 * Ext.util.Inflector.singularize('people'); //'person'
27 * Ext.util.Inflector.singularize('sheep'); //'sheep'
29 * //ordinalizing numbers
30 * Ext.util.Inflector.ordinalize(11); //"11th"
31 * Ext.util.Inflector.ordinalize(21); //"21th"
32 * Ext.util.Inflector.ordinalize(1043); //"1043rd"
36 * The Inflector comes with a default set of US English pluralization rules. These can be augmented with additional
37 * rules if the default rules do not meet your application's requirements, or swapped out entirely for other languages.
38 * Here is how we might add a rule that pluralizes "ox" to "oxen":
40 * Ext.util.Inflector.plural(/^(ox)$/i, "$1en");
42 * Each rule consists of two items - a regular expression that matches one or more rules, and a replacement string. In
43 * this case, the regular expression will only match the string "ox", and will replace that match with "oxen". Here's
44 * how we could add the inverse rule:
46 * Ext.util.Inflector.singular(/^(ox)en$/i, "$1");
48 * Note that the ox/oxen rules are present by default.
50 Ext.define('Ext.util.Inflector', {
52 /* Begin Definitions */
60 * The registered plural tuples. Each item in the array should contain two items - the first must be a regular
61 * expression that matchers the singular form of a word, the second must be a String that replaces the matched
62 * part of the regular expression. This is managed by the {@link #plural} method.
63 * @property {Array} plurals
66 [(/(quiz)$/i), "$1zes" ],
67 [(/^(ox)$/i), "$1en" ],
68 [(/([m|l])ouse$/i), "$1ice" ],
69 [(/(matr|vert|ind)ix|ex$/i), "$1ices" ],
70 [(/(x|ch|ss|sh)$/i), "$1es" ],
71 [(/([^aeiouy]|qu)y$/i), "$1ies" ],
72 [(/(hive)$/i), "$1s" ],
73 [(/(?:([^f])fe|([lr])f)$/i), "$1$2ves"],
75 [(/([ti])um$/i), "$1a" ],
76 [(/(buffal|tomat|potat)o$/i), "$1oes" ],
77 [(/(bu)s$/i), "$1ses" ],
78 [(/(alias|status|sex)$/i), "$1es" ],
79 [(/(octop|vir)us$/i), "$1i" ],
80 [(/(ax|test)is$/i), "$1es" ],
81 [(/^person$/), "people" ],
83 [(/^(child)$/), "$1ren" ],
90 * The set of registered singular matchers. Each item in the array should contain two items - the first must be a
91 * regular expression that matches the plural form of a word, the second must be a String that replaces the
92 * matched part of the regular expression. This is managed by the {@link #singular} method.
93 * @property {Array} singulars
96 [(/(quiz)zes$/i), "$1" ],
97 [(/(matr)ices$/i), "$1ix" ],
98 [(/(vert|ind)ices$/i), "$1ex" ],
99 [(/^(ox)en/i), "$1" ],
100 [(/(alias|status)es$/i), "$1" ],
101 [(/(octop|vir)i$/i), "$1us" ],
102 [(/(cris|ax|test)es$/i), "$1is" ],
103 [(/(shoe)s$/i), "$1" ],
104 [(/(o)es$/i), "$1" ],
105 [(/(bus)es$/i), "$1" ],
106 [(/([m|l])ice$/i), "$1ouse" ],
107 [(/(x|ch|ss|sh)es$/i), "$1" ],
108 [(/(m)ovies$/i), "$1ovie" ],
109 [(/(s)eries$/i), "$1eries"],
110 [(/([^aeiouy]|qu)ies$/i), "$1y" ],
111 [(/([lr])ves$/i), "$1f" ],
112 [(/(tive)s$/i), "$1" ],
113 [(/(hive)s$/i), "$1" ],
114 [(/([^f])ves$/i), "$1fe" ],
115 [(/(^analy)ses$/i), "$1sis" ],
116 [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
117 [(/([ti])a$/i), "$1um" ],
118 [(/(n)ews$/i), "$1ews" ],
119 [(/people$/i), "person" ],
125 * The registered uncountable words
126 * @property {String[]} uncountable
145 * Adds a new singularization rule to the Inflector. See the intro docs for more information
146 * @param {RegExp} matcher The matcher regex
147 * @param {String} replacer The replacement string, which can reference matches from the matcher argument
149 singular: function(matcher, replacer) {
150 this.singulars.unshift([matcher, replacer]);
154 * Adds a new pluralization rule to the Inflector. See the intro docs for more information
155 * @param {RegExp} matcher The matcher regex
156 * @param {String} replacer The replacement string, which can reference matches from the matcher argument
158 plural: function(matcher, replacer) {
159 this.plurals.unshift([matcher, replacer]);
163 * Removes all registered singularization rules
165 clearSingulars: function() {
170 * Removes all registered pluralization rules
172 clearPlurals: function() {
177 * Returns true if the given word is transnumeral (the word is its own singular and plural form - e.g. sheep, fish)
178 * @param {String} word The word to test
179 * @return {Boolean} True if the word is transnumeral
181 isTransnumeral: function(word) {
182 return Ext.Array.indexOf(this.uncountable, word) != -1;
186 * Returns the pluralized form of a word (e.g. Ext.util.Inflector.pluralize('word') returns 'words')
187 * @param {String} word The word to pluralize
188 * @return {String} The pluralized form of the word
190 pluralize: function(word) {
191 if (this.isTransnumeral(word)) {
195 var plurals = this.plurals,
196 length = plurals.length,
199 for (i = 0; i < length; i++) {
203 if (regex == word || (regex.test && regex.test(word))) {
204 return word.replace(regex, tuple[1]);
212 * Returns the singularized form of a word (e.g. Ext.util.Inflector.singularize('words') returns 'word')
213 * @param {String} word The word to singularize
214 * @return {String} The singularized form of the word
216 singularize: function(word) {
217 if (this.isTransnumeral(word)) {
221 var singulars = this.singulars,
222 length = singulars.length,
225 for (i = 0; i < length; i++) {
226 tuple = singulars[i];
229 if (regex == word || (regex.test && regex.test(word))) {
230 return word.replace(regex, tuple[1]);
238 * Returns the correct {@link Ext.data.Model Model} name for a given string. Mostly used internally by the data
240 * @param {String} word The word to classify
241 * @return {String} The classified version of the word
243 classify: function(word) {
244 return Ext.String.capitalize(this.singularize(word));
248 * Ordinalizes a given number by adding a prefix such as 'st', 'nd', 'rd' or 'th' based on the last digit of the
249 * number. 21 -> 21st, 22 -> 22nd, 23 -> 23rd, 24 -> 24th etc
250 * @param {Number} number The number to ordinalize
251 * @return {String} The ordinalized number
253 ordinalize: function(number) {
254 var parsed = parseInt(number, 10),
256 mod100 = parsed % 100;
258 //11 through 13 are a special case
259 if (11 <= mod100 && mod100 <= 13) {
260 return number + "th";
263 case 1 : return number + "st";
264 case 2 : return number + "nd";
265 case 3 : return number + "rd";
266 default: return number + "th";
271 //aside from the rules above, there are a number of words that have irregular pluralization so we add them here
279 ellipsis: 'ellipses',
280 paralysis: 'paralyses',
282 appendix: 'appendices',
291 criterion: 'criteria',
292 curriculum: 'curricula',
294 memorandum: 'memoranda',
295 phenomenon: 'phenomena',
302 vertebra: 'vertebrae',
307 for (singular in irregulars) {
308 this.plural(singular, irregulars[singular]);
309 this.singular(irregulars[singular], singular);