I18n = (function(){
	
	var _translations = {},
		_locale = App.lang || "en";
	
	return {
		setLocale: function(locale){
			_locale = locale;
		},
		addTranslation: function(locale, translations){
			if (typeof locale == "string" && typeof translations == "object"){
				if (typeof _translations[locale] == "undefined"){
					_translations[locale] = {};
				}
				Object.extend(_translations[locale], translations);
			}
		},
		translate: function(messageId, messagePlural, count, locale){
			if (typeof messagePlural != "undefined" && typeof count != "number") {
	            locale = messagePlural;
	            messagePlural = null;
	            count = null;
	        }
	        if (typeof locale != "string") {
	            locale = _locale;
	        }
	        
	        var plurals = 0;
	        
	        if (typeof count == "number" && !(plurals = this.getPlural(count, locale))) {
				if (count != 1) {
					plurals = 1;
				}
			}
			
	        if (typeof _translations[locale] != "undefined" && typeof _translations[locale][messageId] != "undefined") {
	        	var trans;
				if ((trans = _translations[locale][messageId]) || (plurals) && (trans = _translations[locale][messagePlural])) {
					if (trans != null && typeof trans == "object" && 'splice' in trans && 'join' in trans) { // trans - array
						trans = trans[plurals];
					}
					if (typeof trans == "string" && trans.length > 0) { // trans - string
						return trans;
					}
				}
			}
			
			// no translation found, return original
			if (plurals > 0) {
				return messagePlural;
			}
			return messageId;  
		},
		getPlural: function(n, locale){
			switch(locale) {
	            case 'bo':
	            case 'dz':
	            case 'id':
	            case 'ja':
	            case 'jv':
	            case 'ka':
	            case 'km':
	            case 'kn':
	            case 'ko':
	            case 'ms':
	            case 'th':
	            case 'tr':
	            case 'vi':
	                return 0;
	                break;
	
	            case 'af':
	            case 'az':
	            case 'bn':
	            case 'bg':
	            case 'ca':
	            case 'da':
	            case 'de':
	            case 'el':
	            case 'en':
	            case 'eo':
	            case 'es':
	            case 'et':
	            case 'eu':
	            case 'fa':
	            case 'fi':
	            case 'fo':
	            case 'fur':
	            case 'fy':
	            case 'gl':
	            case 'gu':
	            case 'ha':
	            case 'he':
	            case 'hu':
	            case 'is':
	            case 'it':
	            case 'ku':
	            case 'lb':
	            case 'ml':
	            case 'mn':
	            case 'mr':
	            case 'nah':
	            case 'nb':
	            case 'ne':
	            case 'nl':
	            case 'nn':
	            case 'no':
	            case 'om':
	            case 'or':
	            case 'pa':
	            case 'pap':
	            case 'ps':
	            case 'pt':
	            case 'so':
	            case 'sq':
	            case 'sv':
	            case 'sw':
	            case 'ta':
	            case 'te':
	            case 'tk':
	            case 'ur':
	            case 'zh':
	            case 'zu':
	                return n != 1 ? 1 : 0; 
	
	            case 'am':
	            case 'bh':
	            case 'fil':
	            case 'fr':
	            case 'gun':
	            case 'hi':
	            case 'ln':
	            case 'mg':
	            case 'nso':
	            case 'xbr':
	            case 'ti':
	            case 'wa':
		            throw("Plural formula not implemented for '"+locale+"' language!");
	                //return ((n == 0) || (n == 1)) ? 1 : 0;
	
	            case 'be':
	            case 'bs':
	            case 'hr':
	            case 'ru':
	            case 'sr':
	            case 'uk':
	                return n % 10 == 1 && n % 100 != 11 ? 0 : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); 
	
	            case 'cs':
	            case 'sk':
	                return n == 1 ? 0 : (n >= 2 && n <= 4 ? 1 : 2); 
	
	            case 'ga':
	                return n == 1 ? 0 : (n == 2 ? 1 : 2); 
	
	            case 'lt':
	                return n % 10 == 1 && n % 100 != 11 ? 0 : (n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); 
	
	            case 'sl':
	                return n % 100 == 1 ? 0 : (n % 100 == 2 ? 1 : (n % 100 == 3 || n % 100 == 4 ? 2 : 3)); 
	
	            case 'mk':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n % 10 == 1) ? 1 : 0;
	
	            case 'mt':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n == 1) ? 1 : ((n == 0) || ((n % 100 > 1) && (n % 100 < 11))) ? 2 : ((n % 100 > 10) && (n % 100 < 20)) ? 3 : 0;
	
	            case 'lv':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n == 0) ? 1 : ((n % 10 == 1) && (n % 100 != 11)) ? 2 : 0;
	
	            case 'pl':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n == 1) ? 1 : ((n % 10 >= 2) && (n % 10 <= 4) && ((n % 100 < 10) || (n % 100 > 29))) ? 2 : 0;
	
	            case 'cy':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n == 1) ? 1 : (n == 2) ? 2 : ((n == 8) || (n == 11)) ? 3 : 0;
	
	            case 'ro':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n == 1) ? 1 : ((n == 0) || ((n % 100 > 0) && (n % 100 < 20))) ? 2 : 0;
	
	            case 'ar':
	            	throw("Plural formula not implemented for '"+locale+"' language!");
	                //return (n == 0) ? 1 : (n == 1) ? 2 : (n == 2) ? 3 : ((n >= 3) && (n <= 10)) ? 4 : ((n >= 11) && (n <= 99)) ? 5 : 0;
	
	            default:
	                return null;
			}
		}
	}

})();

/**
 * Returns a translated string if one is found, or the submitted message if not found.
 *
 * @param  {String} messageId The text to translate
 * @param  {String} locale
 * 
 * @return {String} Translated text
 */
function __(messageId, locale){
	return I18n.translate(messageId, locale);
}

/**
 * Returns correct plural form of message identified by $singular and $plural for count $count.
 * Some languages have more than one form for plural messages dependent on the count.
 *
 * @param  {String}  messageId     Singular text to translate
 * @param  {String}  messagePlural Plural text
 * @param  {Integer} count         Count
 * @param  {String}  locale
 * @return {String}  Plural form of translated string
 */
function __n(messageId, messagePlural, count, locale){
	return I18n.translate(messageId, messagePlural, count, locale);
}
