    google.load("language", "1");
	
	var translator = true;
	
	function init(){
		var str = $("source").innerHTML;
		var language = jar.get('language');
		
		//var triggerCollection = $("langSelect").select("li");
		//triggerCollection.invoke("observe", "click", handleTriggerClick);
		translator = new Translator("source", "span");

		translator.addEventListener("complete", function(obj){
			//console.log("The translation has finished %o", obj);
		});
		translator.addEventListener("begin", function(obj){
			//console.log("Translation has begun! %o", obj);		
		});
		if(language)
		translator.translate(language.name);
		//console.log(translator.textNodeCollection);
	}
	function handleTriggerClick(e){
		var lang = e.element().getAttribute("lang");
		jar.put('language', {name: lang});
		var str = $("source").innerHTML;
		translator.translate(lang);
	}
	
	function insertToForeign(obj){		
		$("source").innerHTML = obj.translation;		
	}
	
	
	google.setOnLoadCallback(init);
	
	var Translator = Class.create(EventDispatcher, { 
		initialize : function(element, selector, config){ 
			this.element = $(element);
			this.preservedHTML = this.element.innerHTML;
			this.config = Object.extend(this.getDefaultConfig(), config);			
			this.textNodeCollection = this.collectChildren(selector);
			this.preservedParentHash = {};
			this.placeHolderHash = {};
			this.entityWasher = new Element("div"); 
			this.textNodeCollection = this.textNodeCollection.findAll(this.purifyTextNode);
		},
		purifyTextNode : function(node){
			try{
				if(!node)
					return false; 
				return node.nodeType == 3;
			}
			catch(e){
				return false;
			}		
		},
		getDefaultConfig : function(){
			return { maxLength : 2500, srcLang : "en", recursive : true, type : "text" };	
		},
		collectChildren : function(selector){
			return this.element.select(selector).collect(this.collectTextNodes.bind(this)).flatten();
		},
		collectTextNodes : function(element){
			var self = this;
			var stack = $A(element.childNodes).collect(function(child){
				if(child.nodeType == 3  && child.nodeValue.length < self.config.maxLength && child.nodeValue.search(/^\s+$/g) == -1)
					return child;
				else if(child.nodeType == 3  && child.nodeValue.length > self.config.maxLength)
					return self.splitTextNode(child);
				else if(child.nodeType == 1 && self.config.recursive)
					return self.collectTextNodes(child);
					
			});	
			return stack;
		},
		splitStringByMax : function(text){
			var offset = 0;
			var textArr = [];
			while(text.length > this.config.maxLength){				
				var tmp = text.substr(0, this.config.maxLength);
				offset = tmp.lastIndexOf(" ");
				var subText = text.substr(0, offset);				
				text = text.substr(offset);
				textArr.push(subText);				
			}
			textArr.push(text);
			return textArr;
		},
		splitTextNode : function(node){
			var nodeStack = [];
			var textArr = this.splitStringByMax(node.nodeValue);
			
			var prevNode = false;
			textArr.each(function(text, itr){
				var newNode = document.createTextNode(text);
				nodeStack.push(newNode);		
				if(node.nextSibling != null && !prevNode)
					node.parentNode.insertBefore(newNode, node.nextSibling);
				else if(prevNode && prevNode.nextSibling != null)
					node.parentNode.insertBefore(newNode, prevNode.nextSibling);
				else 
					node.parentNode.appendChild(newNode);
				prevNode = newNode;
			});
			node.parentNode.removeChild(node);
			
			return nodeStack;
		},
		getEventBeginObject : function(destLang){
			return { 
				destLang : destLang,
				srcLang : this.config.srcLang,
				srcLangNodes : this.textNodeCollection,
				srcHTML : this.preservedHTML
			}	
		},
		getEventCompleteObject : function(result){
			return {
				srcLangNodes : this.textNodeCollection,
				destLangNodes : this.translationStack,
				destLangHTML : this.element.innerHTML,
				srcLangHTML : this.preservedHTML,
				result : result,
				resultStack : this.resultStack			
			}		
		},
		finishTranslation : function(result){
			this.translating = false;
			this.dispatchEvent("complete", this.getEventCompleteObject(result));
		
		},
		translate : function(destLang){
			if(this.translating)
				return false;
			var self = this;
			this.dispatchEvent("begin", this.getEventBeginObject(destLang));
			this.textNodeCount = this.textNodeCollection.length;
			this.translationStack = [];
			this.resultStack = [];
			this.textNodeCollection.each(function(node, index){
				self.translating = true;
				google.language.translate(node.nodeValue, self.config.srcLang, destLang, self.handleTranslation.bind(self, node, index));
			});
			return true;	
		},
		getPreservedParent : function(node, index){
			if(this.preservedParentHash[index])
				return this.preservedParentHash[index];
			return this.preservedParentHash[index] = node.parentNode;
		},
		getPlaceHolder : function(index){
			return this.placeHolderHash[index] || false;		
		},
		setPlaceHolder : function(node, index){
			this.placeHolderHash[index] = node;		
		},
/*		html_entity_decode : function (str) {
			  var tarea=content.document.createElement('textarea'); // the "content" part is needed in buttons
			  tarea.innerHTML = str;
			  return tarea.value;
		},*/
		handleTranslation : function(node, index, obj){
			try{
				var parent = this.getPreservedParent(node, index);
				
				this.entityWasher.innerHTML = obj.translation;
				var translatedText = this.entityWasher.innerHTML;
				if(node.nodeValue.search(/^\s/) > -1)
					translatedText = " " + translatedText;
				if(node.nodeValue.search(/\s$/) > -1)
					translatedText = translatedText + " ";
				//	alert(translatedText);
				//translatedText = 	this.html_entity_decode(translatedText);
				var tarea	=	document.createElement('textarea');
				tarea.innerHTML = translatedText;
				translatedText = tarea.value;
						
				var newText = document.createTextNode(translatedText);
							
				if(this.getPlaceHolder(index))
					parent.replaceChild(newText, this.getPlaceHolder(index));
				else
					parent.replaceChild(newText, node);

				this.setPlaceHolder(newText, index);
				this.translationStack.push(newText);
				this.resultStack.push(obj);
				this.textNodeCount--;
				if(this.textNodeCount <= 0)
					this.finishTranslation(obj);
			}
			catch(e){
				console.log("Error has occured with handling translation error = %o arguments = %o", e, arguments);
			}
		}
	
	});


