Permalink
Browse files

added inflector to JS SDK

  • Loading branch information...
1 parent 2ffb2bd commit ef4eee96450531ee98a35dd7c03331fc61febf7d @berk committed Apr 3, 2012
@@ -1,5 +1,5 @@
/****************************************************************************
- Copyright (c) 2010-2011 Michael Berkovich, Ian McDaniel
+ Copyright (c) 2010-2012 Michael Berkovich, Ian McDaniel
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -23,6 +23,8 @@
/****************************************************************************
**** Tr8n Generic Helper Functions
+****
+**** Tr8n does not rely on any library and is 100% fully self-contained
****************************************************************************/
document.createElement('tr8n');
@@ -38,7 +40,7 @@ var Tr8n = Tr8n || {
};
/****************************************************************************
-**** Tr8n Effects Helper Functions - Can be overloaded by JS frameworks
+**** Tr8n Effects Helper Functions - Can be overloaded by any JS frameworks
****************************************************************************/
Tr8n.Effects = {
@@ -240,11 +240,8 @@ Tr8n.Proxy.prototype = {
var tr8nElement = Tr8n.element(translation_key_data.key);
if (tr8nElement && missing_key_data.translation_key) {
- tr8nElement.innerHTML = missing_key_data.translation_key.translate(this.language, missing_key_data.token_values, {skip_decorations:true});
tr8nElement.setAttribute('translation_key_id', translation_key_data['id']);
- if (this.inline_translations_enabled) {
- tr8nElement.className = 'tr8n_translatable tr8n_not_translated';
- }
+ tr8nElement.innerHTML = missing_key_data.translation_key.translate(this.language, missing_key_data.token_values);
}
delete this.missing_translation_keys[missing_key_data.translation_key.key];
@@ -500,7 +497,10 @@ Tr8n.Proxy.NumericRule.prototype = new Tr8n.Proxy.LanguageRule();
// {count | person, people}
Tr8n.Proxy.NumericRule.transform = function(count, values) {
if (count == 1) return values[0];
- return values[1];
+ if (values.length == 2) {
+ return values[1];
+ }
+ return values[0].pluralize();
}
Tr8n.Proxy.NumericRule.prototype.evaluate = function(token_name, token_values){
@@ -997,9 +997,17 @@ Tr8n.Proxy.Logger.prototype = {
this.append(str);
},
debug: function(msg) {
+ if (!this.options['proxy'].logger_enabled) return;
+ if (window.console && console.log) {
+ console.log(msg);
+ }
this.log("<span style='color:grey'>" + msg + "</span>");
},
error: function(msg) {
+ if (!this.options['proxy'].logger_enabled) return;
+ if (window.console && console.error) {
+ console.error(msg);
+ }
this.log("<span style='color:red'>" + msg + "</span>");
},
S4: function() {
@@ -1266,8 +1274,10 @@ Tr8n.Proxy.Utils = {
/****************************************************************************
***
*** MD5 (Message-Digest Algorithm)
-*** http://www.webtoolkit.info/
+*** http://www.webtoolkit.info/javascript-md5.html
***
+*** MD5 was developed by Professor Ronald L. Rivest in 1994.
+*** Its 128 bit (16 byte) message digest makes it a faster implementation than SHA-1.
****************************************************************************/
var MD5 = function (string) {
@@ -1469,4 +1479,317 @@ var MD5 = function (string) {
var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
return temp.toLowerCase();
-}
+}
+
+
+/*
+Copyright (c) 2010 Ryan Schuft (ryan.schuft@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/*
+ This code is based in part on the work done in Ruby to support
+ infection as part of Ruby on Rails in the ActiveSupport's Inflector
+ and Inflections classes. It was initally ported to Javascript by
+ Ryan Schuft (ryan.schuft@gmail.com) in 2007.
+
+ The code is available at http://code.google.com/p/inflection-js/
+
+ The basic usage is:
+ 1. Include this script on your web page.
+ 2. Call functions on any String object in Javascript
+
+ Currently implemented functions:
+
+ String.pluralize(plural) == String
+ renders a singular English language noun into its plural form
+ normal results can be overridden by passing in an alternative
+
+ String.singularize(singular) == String
+ renders a plural English language noun into its singular form
+ normal results can be overridden by passing in an alterative
+*/
+
+/*
+ This sets up a container for some constants in its own namespace
+ We use the window (if available) to enable dynamic loading of this script
+ Window won't necessarily exist for non-browsers.
+*/
+if (window && !window.InflectionJS)
+{
+ window.InflectionJS = null;
+}
+
+/*
+ This sets up some constants for later use
+ This should use the window namespace variable if available
+*/
+InflectionJS =
+{
+ /*
+ This is a list of nouns that use the same form for both singular and plural.
+ This list should remain entirely in lower case to correctly match Strings.
+ */
+ uncountable_words: [
+ 'equipment', 'information', 'rice', 'money', 'species', 'series',
+ 'fish', 'sheep', 'moose', 'deer', 'news'
+ ],
+
+ /*
+ These rules translate from the singular form of a noun to its plural form.
+ */
+ plural_rules: [
+ [new RegExp('(m)an$', 'gi'), '$1en'],
+ [new RegExp('(pe)rson$', 'gi'), '$1ople'],
+ [new RegExp('(child)$', 'gi'), '$1ren'],
+ [new RegExp('^(ox)$', 'gi'), '$1en'],
+ [new RegExp('(ax|test)is$', 'gi'), '$1es'],
+ [new RegExp('(octop|vir)us$', 'gi'), '$1i'],
+ [new RegExp('(alias|status)$', 'gi'), '$1es'],
+ [new RegExp('(bu)s$', 'gi'), '$1ses'],
+ [new RegExp('(buffal|tomat|potat)o$', 'gi'), '$1oes'],
+ [new RegExp('([ti])um$', 'gi'), '$1a'],
+ [new RegExp('sis$', 'gi'), 'ses'],
+ [new RegExp('(?:([^f])fe|([lr])f)$', 'gi'), '$1$2ves'],
+ [new RegExp('(hive)$', 'gi'), '$1s'],
+ [new RegExp('([^aeiouy]|qu)y$', 'gi'), '$1ies'],
+ [new RegExp('(x|ch|ss|sh)$', 'gi'), '$1es'],
+ [new RegExp('(matr|vert|ind)ix|ex$', 'gi'), '$1ices'],
+ [new RegExp('([m|l])ouse$', 'gi'), '$1ice'],
+ [new RegExp('(quiz)$', 'gi'), '$1zes'],
+ [new RegExp('s$', 'gi'), 's'],
+ [new RegExp('$', 'gi'), 's']
+ ],
+
+ /*
+ These rules translate from the plural form of a noun to its singular form.
+ */
+ singular_rules: [
+ [new RegExp('(m)en$', 'gi'), '$1an'],
+ [new RegExp('(pe)ople$', 'gi'), '$1rson'],
+ [new RegExp('(child)ren$', 'gi'), '$1'],
+ [new RegExp('([ti])a$', 'gi'), '$1um'],
+ [new RegExp('((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$','gi'), '$1$2sis'],
+ [new RegExp('(hive)s$', 'gi'), '$1'],
+ [new RegExp('(tive)s$', 'gi'), '$1'],
+ [new RegExp('(curve)s$', 'gi'), '$1'],
+ [new RegExp('([lr])ves$', 'gi'), '$1f'],
+ [new RegExp('([^fo])ves$', 'gi'), '$1fe'],
+ [new RegExp('([^aeiouy]|qu)ies$', 'gi'), '$1y'],
+ [new RegExp('(s)eries$', 'gi'), '$1eries'],
+ [new RegExp('(m)ovies$', 'gi'), '$1ovie'],
+ [new RegExp('(x|ch|ss|sh)es$', 'gi'), '$1'],
+ [new RegExp('([m|l])ice$', 'gi'), '$1ouse'],
+ [new RegExp('(bus)es$', 'gi'), '$1'],
+ [new RegExp('(o)es$', 'gi'), '$1'],
+ [new RegExp('(shoe)s$', 'gi'), '$1'],
+ [new RegExp('(cris|ax|test)es$', 'gi'), '$1is'],
+ [new RegExp('(octop|vir)i$', 'gi'), '$1us'],
+ [new RegExp('(alias|status)es$', 'gi'), '$1'],
+ [new RegExp('^(ox)en', 'gi'), '$1'],
+ [new RegExp('(vert|ind)ices$', 'gi'), '$1ex'],
+ [new RegExp('(matr)ices$', 'gi'), '$1ix'],
+ [new RegExp('(quiz)zes$', 'gi'), '$1'],
+ [new RegExp('s$', 'gi'), '']
+ ],
+
+ /*
+ This is a list of words that should not be capitalized for title case
+ */
+ non_titlecased_words: [
+ 'and', 'or', 'nor', 'a', 'an', 'the', 'so', 'but', 'to', 'of', 'at',
+ 'by', 'from', 'into', 'on', 'onto', 'off', 'out', 'in', 'over',
+ 'with', 'for'
+ ],
+
+ /*
+ These are regular expressions used for converting between String formats
+ */
+ id_suffix: new RegExp('(_ids|_id)$', 'g'),
+ underbar: new RegExp('_', 'g'),
+ space_or_underbar: new RegExp('[\ _]', 'g'),
+ uppercase: new RegExp('([A-Z])', 'g'),
+ underbar_prefix: new RegExp('^_'),
+
+ /*
+ This is a helper method that applies rules based replacement to a String
+ Signature:
+ InflectionJS.apply_rules(str, rules, skip, override) == String
+ Arguments:
+ str - String - String to modify and return based on the passed rules
+ rules - Array: [RegExp, String] - Regexp to match paired with String to use for replacement
+ skip - Array: [String] - Strings to skip if they match
+ override - String (optional) - String to return as though this method succeeded (used to conform to APIs)
+ Returns:
+ String - passed String modified by passed rules
+ Examples:
+ InflectionJS.apply_rules("cows", InflectionJs.singular_rules) === 'cow'
+ */
+ apply_rules: function(str, rules, skip, override)
+ {
+ if (override)
+ {
+ str = override;
+ }
+ else
+ {
+ var ignore = (skip.indexOf(str.toLowerCase()) > -1);
+ if (!ignore)
+ {
+ for (var x = 0; x < rules.length; x++)
+ {
+ if (str.match(rules[x][0]))
+ {
+ str = str.replace(rules[x][0], rules[x][1]);
+ break;
+ }
+ }
+ }
+ }
+ return str;
+ }
+};
+
+/*
+ This lets us detect if an Array contains a given element
+ Signature:
+ Array.indexOf(item, fromIndex, compareFunc) == Integer
+ Arguments:
+ item - Object - object to locate in the Array
+ fromIndex - Integer (optional) - starts checking from this position in the Array
+ compareFunc - Function (optional) - function used to compare Array item vs passed item
+ Returns:
+ Integer - index position in the Array of the passed item
+ Examples:
+ ['hi','there'].indexOf("guys") === -1
+ ['hi','there'].indexOf("hi") === 0
+*/
+if (!Array.prototype.indexOf)
+{
+ Array.prototype.indexOf = function(item, fromIndex, compareFunc)
+ {
+ if (!fromIndex)
+ {
+ fromIndex = -1;
+ }
+ var index = -1;
+ for (var i = fromIndex; i < this.length; i++)
+ {
+ if (this[i] === item || compareFunc && compareFunc(this[i], item))
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ };
+}
+
+/*
+ You can override this list for all Strings or just one depending on if you
+ set the new values on prototype or on a given String instance.
+*/
+if (!String.prototype._uncountable_words)
+{
+ String.prototype._uncountable_words = InflectionJS.uncountable_words;
+}
+
+/*
+ You can override this list for all Strings or just one depending on if you
+ set the new values on prototype or on a given String instance.
+*/
+if (!String.prototype._plural_rules)
+{
+ String.prototype._plural_rules = InflectionJS.plural_rules;
+}
+
+/*
+ You can override this list for all Strings or just one depending on if you
+ set the new values on prototype or on a given String instance.
+*/
+if (!String.prototype._singular_rules)
+{
+ String.prototype._singular_rules = InflectionJS.singular_rules;
+}
+
+/*
+ You can override this list for all Strings or just one depending on if you
+ set the new values on prototype or on a given String instance.
+*/
+if (!String.prototype._non_titlecased_words)
+{
+ String.prototype._non_titlecased_words = InflectionJS.non_titlecased_words;
+}
+
+/*
+ This function adds plurilization support to every String object
+ Signature:
+ String.pluralize(plural) == String
+ Arguments:
+ plural - String (optional) - overrides normal output with said String
+ Returns:
+ String - singular English language nouns are returned in plural form
+ Examples:
+ "person".pluralize() == "people"
+ "octopus".pluralize() == "octopi"
+ "Hat".pluralize() == "Hats"
+ "person".pluralize("guys") == "guys"
+*/
+if (!String.prototype.pluralize)
+{
+ String.prototype.pluralize = function(plural)
+ {
+ return InflectionJS.apply_rules(
+ this,
+ this._plural_rules,
+ this._uncountable_words,
+ plural
+ );
+ };
+}
+
+/*
+ This function adds singularization support to every String object
+ Signature:
+ String.singularize(singular) == String
+ Arguments:
+ singular - String (optional) - overrides normal output with said String
+ Returns:
+ String - plural English language nouns are returned in singular form
+ Examples:
+ "people".singularize() == "person"
+ "octopi".singularize() == "octopus"
+ "Hats".singularize() == "Hat"
+ "guys".singularize("person") == "person"
+*/
+if (!String.prototype.singularize)
+{
+ String.prototype.singularize = function(singular)
+ {
+ return InflectionJS.apply_rules(
+ this,
+ this._singular_rules,
+ this._uncountable_words,
+ singular
+ );
+ };
+}
+
+
Oops, something went wrong.

0 comments on commit ef4eee9

Please sign in to comment.