Return to Snippet

Revision: 39557
at January 19, 2011 05:50 by mavrikicecool


Updated Code
Read from top to Bottom see for **** especially.... /* ignore the spelling mistakes */

Make an application multi lingual by using google API....
This process can even be implemented by an web service, but i have made use of google API
Please follow the steps and make changes accordingly 

PHP(make use of div's and apply to the id's), ASP(Apply to all labesl)...and the rest of the languages follow up the same procedure accoringly......

*****************Add these 2 scripts tags into u r header and make it common for the pages so that it includes in each and everything***
<!--<script type="text/javascript" src="Translate/googlelanguage.js"></script>
<script type="text/javascript" src="Translate/translate.js"></script>-->
****************Better to add these 2 into head section of u r html or asp or jsp pages********************************************
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
************Add this thing into the body section where ever u wish to or u wanna Place the option for selection*******************
 <!-- <div><font size="+1">Select Language</font></div>
  <div id="mlt_languagelist"> </div>-->
  
  -->Steps:
  	1) As the page is loaded the the 2nd div gets activated and gets processed through the api and data is fetched from the tranlate.js script....check in the line number 166 the function getLangs() gets called and executed.just go through the function and understand the parameters passed u will know better whats happening.
	
	2) G to line number 85 there u will come to know how the langues get changed based upon u r request.
	3)	if(GL_curLang == "orig") {
			refresh();
			return;
		}
	
	find th this block and add few more langues based upon ICANN standards for language notations in google.soon after the above block by dumping more conditions to the above block u can select the langues aby your choice
	
	Add:
		else if(GL_curLang == "es") { //spanish
			refresh();
			return;
		}	
		else if(GL_curLang == "ja") { //japanese
			refresh();
			return;
		} 
		
		
	4) So add according to u r choice all this has to be followed aftr line number 888 for the 3 point.
	
	6) And now get to start of the page translate.js and point towards line 52, there you gonna find a an array assigned toa  variable with various elements within the array, present with other elements within it for the converion usuage.
	for all required labels in asp or the div or span's which u find the page, assign them which are to be changed upon request.
	
	7) rename those elements name by u r own names which u want, use those div's which are present in all front end pages .for each and every text item or asp with label tags, assign these id's one for all those text items(i.e the div's of each and every text item)..and u r almost done
	
	8)save all changes and start using this applicationits gonna work i am sure.....if there is anything lemme know.post it on the comments section i will reply back.
	
	5)By this way the combo box is set with languages which you require to make the application multi lingual
	
	6)this particual api support 64 recognised languages , check the info in google for this particual api.
	
  
********************************************************************************************************************************* 
</body>
</html>


*******************Save it as translate.js***************************

/* Multi-Language Translation Script:
*
*  Automatically translates a webpage (containing text in more than one language) into any single language
*  requested by the user. Particularly useful for sites involving a lot of user-generated content (which
*  might have originally been written in different languages) - e.g. blogs, forums, or other community sites. 
*  Harnesses the Google AJAX Language API to perform translation and language detection.
*
*  Version: 0.2.5 [2010-01-22]
*  Author: Patrick Hathway, OdinLab, University of Reading.
*  For Documentation and Updates: See http://code.google.com/p/multi-language-translation/
*  Licence: MIT License - see http://opensource.org/licenses/mit-license.php for full terms. Also check 
*  the script Documentation for more information, and for details of one important consideration.
*
*  Some minor configuration is required for this script to work on your website. Follow the instructions
*  below, or see the Documentation for full details and examples...   */

/* 1. Specify the 'Base Language' for your website: */

var GL_baseLang = "en";

/* 2. Specify the IDs for all major regions (i.e. HTML elements) in your site that should have their 
*  contents translated. Note that an ID can only be used to identify a single element on a page (for 
*  elements which appear multiple times, use Class Names instead - see below). The script will translate
*  each element separately; any elements that cannot be found on a page will be ignored:   */

var GL_classIds = [
	["navigation"],	
	["navigation", "", true],  
	["quick-id", "", true],  
	["c-quote", "", true],  
	["c-need-quote", "", true],  
	["c-index", "", true],   
	["c-about", "", true],  
	["c-exper", "", true],  
	["c-solution", "", true],
	["c-product", "", true],  
	["c-contact", "", true],  
	["c-indian-add", "", true],  
	["c-work", "", true],  
	["c-contact", "", true],  
	["c-contactinf", "", true],
	["c-usa-add", "", true],  
	["c-warning", "", true],  
	["right_sidebar", "fr", true], 
	["footer"]
];

/* 3. Specify the Class Names of all major regions (i.e. HTML elements) in your site that should have their 
*  their contents translated. Multiple elements may appear on a page with the same class name; the script
*  will locate each occurrance (if present) and translate them separately:   */

var GL_classNames = [
	["entry_baselang"],
	["entry_french", "fr"],
	["index-class", "", true],
	["about-class", "", true],	
	["association-class", "", true],
	["building-class", "", true],
	["career-class", "", true],
	["college-class", "", true],
	["construction-class", "", true],
	["contact-class", "", true], 
	["entry_baselang", "", true], 
	["education-class", "", true], 
	["entry", "", true], 
	["expertise-class", "", true], 
	["description", "", true], 
	["list-custom_website", "", true], 
	["list-beautiful_graphic", "", true], 
	["list-using_nature", "", true],
	["list-css_xhtml", "", true],
	["description", "", true], 
	["list-branding_your", "", true], 
	["list-green_branding", "", true], 
	["list-who_are", "", true], 
	["list-long_term", "", true], 
	["list-the_importance", "", true], 
	["list-flow", "", true], 
	["list-click_through", "", true], 
	["list-scale", "", true], 
	["description", "", true], 
	["list-google_rank", "", true], 
	["list-ppc", "", true], 
	["list-custom_icon", "", true], 
	["list-why_use", "", true], 
	["list-web_standard", "", true], 
	["list-promoting_your", "", true], 
	["list-business_cards", "", true], 
	["fashin-class", "", true], 
	["right", "", true],  
	["web_portfolio", "", true], 
	["interior-class", "", true],
	["manufacture-class", "", true], 
	["news-class", "", true], 
	["medical-class", "", true], 
	["opening-class", "", true], 
	["ourclass-class", "", true], 	
	["portfolio-class", "", true], 	
	["ecommerce-class", "", true], 	
	["mobile-class", "", true], 
	["webdesign-class", "", true], 
	["product-class", "", true], 
	["professional-class", "", true], 
	["real-class", "", true], 
	["realestate-class", "", true], 
	["request-class", "", true],   
	["form_entry", "", true],
	["request-id", "", true],
	["requestquote-class", "", true],
	["consumer-class", "", true],
	["software-class", "", true],
	["solutions-class", "", true],
	["list-why_use", "", true],
	["list-west_coast", "", true], 
	["list-custom_icon", "", true],
	["list-crisp_graphics", "", true],
	["list-scalable_across", "", true],
	["testimonials-class", "", true],  
	["testimonials", "", true],
	["tourism-class", "", true],
	["trade-class", "", true], 
	["transport-class", "", true], 
	["levonsys-class", "", true],  
	["working-levonsys-class", "", true],    
	["quick", "", true], 
	["entry_french", "", true], 
	["quotes", "de", true]
];


/* 4. Specify the default language for new visitors (leave blank to auto-detect using browser/system settings) */

var GL_curLang = "";

/* The rest of the Script should not be modified; unless you want to alter the functionality!
*  ------------------------------------------------------------------------------------------ */

// Global variables:
var GL_srcContent;             // array containing all content on the page to be translated, split up into chunks
var GL_transContent = [];      // array containing all chunks which have been translated
var GL_chunksTotal = 0;        // total number of chunks to translate
var GL_curChunk;               // ID of current chunk being translated
var GL_errors;                 // array containing details of all errors that occur (if applicable)
var GL_errSrcTxt;              // array containing all source text that causes errors (if applicable)
var GL_miniTransItems = [];    // array containing element IDs/class names which contain minor items to translate

google.load("language", "1");  // load v1 of google ajax language api

// run when page loads
function initialise() {
	addTransMsgs();        // append elements (which will display translation status messages) to page
	buildChunkedContent(); // create a local 'cache' of chunked content to be translated
	getLangCookie();       // find out the current site language (if known)
	getLangs();            // display listbox containing all languages the site can be translated into

	// if the original languages should be shown, end function.
	if(GL_curLang == "orig") {
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// display listbox containing all languages the site can be translated into (so that one can be selected by user)
function getLangs() {
	// create listbox within script so that it won't appear if JavaScript is disabled
	document.getElementById("mlt_languagelist").innerHTML = '<select id="mlt_language" onchange="changeLang()" style="width:150px; height:20px;"></select>';
	// +	'<div id="mlt_langattr"></div>'
	var langItems = document.getElementById("mlt_language").options;

	// add option to top of listbox allowing user to view the site in its original (i.e. un-translated) languages
	langItems.add(new Option("Original Languages", "orig", true));

	// loop through list of currently available languages and add each to listbox
	for(var lang in google.language.Languages) {
		// find out the 2 character Google language code
		
		var langCode = google.language.Languages[lang];
		// convert language string to title case
		var langString = lang.substr(0,1) + lang.substr(1).toLowerCase();
		// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
		langString = langString.split("_").join(" - ");

		// check that Google can translate content into the current language
		if ((google.language.isTranslatable(langCode)) && (langCode != "")) {
			// if so, add to listbox and translate, so native speakers of that language can find it
			if(langCode=="ar")
			{
				langItems.add(new Option(langString, langCode));
				miniTranslate(langItems[(langItems.length-1)],langCode);
			}
			
		}
	}

	document.getElementById("mlt_language").value = GL_curLang; // change listbox to display current site language
	google.language.getBranding("mlt_langattr");  // display Google attribution below listbox (as required by TOS)
}

// start the translation
function startTranslation() {
	// reset global variables
	GL_curChunk = 0; GL_errors = []; GL_errSrcTxt = [];
	
	// check if all content has already been translated into current language since page loaded.
	if(chkLangTrans()) {
		return; // if so, don't need to translate content again
	} 
	
	// sanity check - can google actually translate into the current site language?
	if (!(google.language.isTranslatable(GL_curLang)) || (GL_curLang == "")) {
		return; // if not, end translation
	} // Otherwise, send content to google to be translated:
	
	// show the 'Translating...' block
	document.getElementById("mlt_translatemsg").innerHTML = 'Translating... <span id="mlt_perc">0%</span>';
	miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	document.getElementById("mlt_translatemsg").style.display='block';

	// find out the ID of the destination language
	var curLangNo = document.getElementById("mlt_language").selectedIndex;
	var k = 0;
	
	// create sub-array to hold all translations for current language
	GL_transContent[GL_transContent.length]        = new Array(3);
	GL_transContent[(GL_transContent.length-1)][0] = []; // this array will contain all translated chunks
	GL_transContent[(GL_transContent.length-1)][1] = GL_curLang; // store current language
	GL_transContent[(GL_transContent.length-1)][2] = false; // mark translation of language as incomplete

	// loop through all the chunks to be translated, send to google...
	for(var i = 0; i < GL_srcContent.length; i++) {
		// find out the source language for the current element to be translated
		var srcLang = GL_srcContent[i][GL_srcContent[i].length - 1];

		for(var j = 0; j < (GL_srcContent[i].length - 1); j++) {
			/* AJAX is used to return translated chunks, so they MAY be returned in any order.
		   	To solve, include current chunk id, destination language + separators at start of each
		   	string. This is a bit of a 'hack', so try to find a better solution! */
			var srcText = curLangNo + "<br />" + k + "<br />" + GL_srcContent[i][j];

			// send current chunk to google translate; when translated, call function translateChunk
			google.language.translate(srcText, srcLang, GL_curLang, translateChunk);
			k++;
		}
	}

	setTimeout("checkTransStatus()", 1000); // run function to check translation status after 1 second
}

// check if page content has already been translated into current language since page loaded.
function chkLangTrans() {
	// loop through the list of languages the page has been translated into
	for(var i = 0; i < GL_transContent.length; i++) {
		// check if a translation for current language exists, and if so, whether it is complete.
		if((GL_transContent[i][1] == GL_curLang) && (GL_transContent[i][2] == true)){
			/* if so, don't need to send content to google again, just assemble the pre-translated content.
			This will *dramatically* reduce the translation time for this language! */
			endTranslation(i);
			return true;
		} 
	}
	return false; // otherwise, all relevant page content must be submitted to google for translation.
}

// This runs after each chunk has been translated...
function translateChunk(result) {
	// handle translation errors gracefully by storing error details but allowing translation to continue
	if (result.error) {
		GL_errors[GL_errors.length] = result.error.message;
	}
	else {

	/* Translated chunks may be returned in any order, so we need a method to assemble the chunks
	   in the correct order:
	   * Start of each chunk has a destination language id and a chunk id followed by separators.
	   * Separator is a <br /> HTML tag, as these always appear to retain position after translation...
	   * The destination language id is used to ensure the translated text is now in the correct language.
	   * Each chunk is stored in the position of the 'GL_transContent' array corresponding to the current chunk id.
	   * The ids + separators should not be shown, and are discarded from the chunk when it's stored in array.
	*/
	
		// split into array based on separator, so we know the id & destination language of translated chunk
		var transChunk = result.translation.split("<br />");
		// [find out length of substring to chop off from start of chunk]
		var chunkSubStr = 12 + transChunk[0].length + transChunk[1].length;
		// remove whitespace from chunk id & destination language (a problem with some translations)
		transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
		transChunk[1] = transChunk[1].replace(/^\s+|\s+$/g,"");

		/* If the translated chunk has a different destination language to the current site language, discard
		translation & end function. This may happen if user changes language whilst translation is in progress */
		if(transChunk[0] != document.getElementById("mlt_language").selectedIndex) {
			return;
		}

		// store translated chunk in current language array, along with detected source language (if known)
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]] = new Array(3);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][0] = result.translation.substr(chunkSubStr);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][1] = result.detectedSourceLanguage;
	}

	GL_curChunk++; // increment current chunk ID every time function is called

	// calculate and display percentage of translation completed, based on number of chunks remaining
	var perc = (GL_curChunk / GL_chunksTotal)*100;
	document.getElementById("mlt_perc").innerHTML = Math.round(perc) + "%";

	// when all chunks have been translated, run the 'endTranslation' function...
	if(GL_curChunk >= GL_chunksTotal) {
		endTranslation((GL_transContent.length-1)); // [final array element holds current language content!]
	}
}

/* runs once a second whilst translation is in progress, updating contents of all elements that have already
   been completely translated. Also shows 'timeout' messages if translation not completed within 30 seconds... */
function checkTransStatus() {
	// 'static' member variables to keep track of how many times function has run, as well as current language:
	if((typeof checkTransStatus.chkStatusCount == 'undefined') || (checkTransStatus.curTransLang != GL_curLang)) {
		// reset variables if not defined yet, or if site language has changed since last function call
        	checkTransStatus.chkStatusCount = 0;
		checkTransStatus.curTransLang = GL_curLang;
	}

	// if translation is now complete, end function.
	if(GL_curChunk >= GL_chunksTotal) {
		return;
	}
	
	checkTransStatus.chkStatusCount++; // increment Translation Status counter

	// Store the list of languages in case they are replaced during translation
	var langList = document.getElementById("mlt_languagelist").innerHTML;

	var curElement; var curTransChunk = 0; var curClass = 0; var curTransLang = GL_transContent.length-1;

	// loop through all element IDs (as specified at script top), searching for ones with completed translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,false);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), searching for completed translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],false);
				curClass++; // move to next element Class Name
			}
		}
	}

	// if listbox containing all languages has been removed as a result of translation, display it again
	if(document.getElementById("mlt_languagelist").innerHTML == "") {
		document.getElementById("mlt_languagelist").innerHTML = langList;
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to show current language
	}

	/* if translation still isn't complete after 30 seconds, update translation message. Note: there is no
	   need to halt the current translation completely, but we will allow user to restart it if desired! */
	if(checkTransStatus.chkStatusCount == 30) {
		// calculate and display percentage of translation completed, based on number of chunks remaining
		var perc = Math.round((GL_curChunk / GL_chunksTotal)*100) + "%";
		// update translation status message
		document.getElementById("mlt_translatemsg").innerHTML = 'Translating (Slowly!)... ' +
		'<span id="mlt_perc">' + perc + '</span> - <a href="javascript:refresh()">Retry</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	}

	setTimeout("checkTransStatus()", 1000); // check translation status again after another second
}

// runs after all translations have been completed; displaying the results on screen in place of previous content
function endTranslation(curTransLang) {
	var curElement;
	var curTransChunk = 0; var curClass = 0;

	// loop through all element IDs (as specified at script top), replacing current contents with translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,true,GL_classIds[i]);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), so contents can be replaced by translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],true,GL_classNames[i]);
				curClass++; // move to next element Class Name
			}
		}
	}

	// Perform translations of all content added by the script (e.g. language strings and error messages)
	transAddedText();

	// Re-create listbox containing all languages, in case it has been removed as a result of translation
	getLangs();

	// translate the 'Original Languages' listbox item to equivalent in current site language
	miniTranslate(document.getElementById("mlt_language").options[0],GL_curLang,"Original Languages");
	
	// if any errors occured during translation, display warning message at top of screen and end function 
	if(GL_errors.length != 0) {
		document.getElementById("mlt_translatemsg").innerHTML = GL_errors.length + ' Problems(s) Occurred During Translation: ' +
		'<a href="javascript:refresh()">Retry</a> - <a href="javascript:showErrDetails()">Details</a> - ' +
		'<a href="javascript:hideTransMsg()">Hide</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate warning message into current site language
		return;
	}
	
	// mark translation of page into current language as complete, so that translation can be quicker next time.
	GL_transContent[curTransLang][2] = true;

	hideTransMsg(); // otherwise, hide 'Translating...' message
}

// assemble and display translated chunks for current element on page
function unpackTransChunks(curTransLang,curTransChunk,curClassNum,curElement,transComplete,curClass) {
	// 'static' member variable to keep track of how many times function has run
	if(typeof unpackTransChunks.curLinkId == 'undefined') {
		// reset curLinkId variable if not defined yet - it's used to identify the correct 'show source text' link
        	unpackTransChunks.curLinkId = 0;
	} unpackTransChunks.curLinkId++; var j = unpackTransChunks.curLinkId; // increment current link id, j is an alias

	var curContent = ""; // reset translated contents of current element
	var initTransChunk = curTransChunk; // store initial chunk id of current element

	// loop through all translated chunks, assembling all translated content for current element
	for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
		// if current chunk does not exist, translation is not complete or errors occurred
		if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == false)) {
			break; // stop looping through chunks if full translation has not yet been completed
		} else if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == true)) {
			// if full translation IS complete, show warning message and a link to show source text (in red)
			curContent += '<div style="color: red;" id="mlt_srctxt' + j + '">[<span class="mlt_transerrtxt">' +
			'<em style="text-transform: uppercase;">THIS SECTION COULD NOT BE TRANSLATED</em> - '+
			'<a id="mlt_srctxtlnk' + j + '" href="javascript:showSrcTxt(' + j + ',' + curClassNum + ',' + (i+1) + 
			')">View Source Text [+]</a></span><span id="mlt_srctxtbracket' + j + '">]</span></div>';
			GL_errSrcTxt[GL_errSrcTxt.length] = GL_srcContent[curClassNum][i]; // store affected source text
			unpackTransChunks.curLinkId++; j = unpackTransChunks.curLinkId; // increment current link id		
		} else {
			// otherwise append current translated chunk to translated content string
			curContent += GL_transContent[curTransLang][0][curTransChunk][0];
		}
		curTransChunk++; // move to next chunk
	}

	// if translation is complete, replace contents of current element with translated text
	if(transComplete == true) {
		curElement.innerHTML = curContent;
		// append a language string to bottom of current element if desired
		getLangString(curTransLang,curElement,curClass,initTransChunk,(GL_srcContent[curClassNum].length - 1),j,curClassNum);
	// otherwise, check if all translated chunks for current element were assembled
	} else if((i == (GL_srcContent[curClassNum].length - 1)) && (GL_transContent[curTransLang][0][initTransChunk][2] != true)) {			
		// if so (and current element translation is not yet marked as complete), replace contents with translation
		curElement.innerHTML = curContent;
		GL_transContent[curTransLang][0][initTransChunk][2] = true; // mark current element translation as complete
	}

	return curTransChunk; // return current chunk id to calling function
}

// If required, find and append a string containing the Source Language to the bottom of the specified element
function getLangString(curTransLang,curElement,curClass,curTransChunk,transChunksLen,j,curClassNum) {
	
	var detectedLang = "";

	// if the current element does not need a language string appended, end function
	if(curClass[2] != true) {
		return;
	}

	// if source language for current element has already been manually specified, set this as detected language
	if(curClass[1] != "") {
		detectedLang = curClass[1];
	}
	// otherwise find out language based on the detected source languages for translated chunks in current element 
	else {
		detectedLang = findDetectedLang(curTransLang,curTransChunk,transChunksLen);
	}

	// if detected language is same as site language, there is no need to display language string, so end function
	if(detectedLang == GL_curLang){
			return;
	}

	var srcLangString = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string 

	// append language string to current element...
//	curElement.innerHTML += '<div style="color: green;" id="mlt_srctxt' + j + '"></div>';
}

// convert a google language code into a formatted string containing the language name
function getFmtLangStr(lang) {
	// loop through list of supported languages and retrieve names
	for(var l in google.language.Languages) {
		if(google.language.Languages[l] == lang) {
			// convert language string into title case
			var lang = l.substr(0,1) + l.substr(1).toLowerCase();
			// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
			lang = lang.split("_").join(" - ");
			break; // stop loop (don't need to continue searching for languages)
		}
	}
	// if language cannot be found in list of supported languages, set language to 'unknown'
	if(typeof lang == "undefined") {
		lang = "An Unknown Language";
	}
	return lang; // return formatted language string
}

// find out the most common detected language for all translated chunks in current element, to appear in language string
function findDetectedLang(curTransLang,curTransChunk,transChunksLen) {
	var chunkLangs = []; langCounter = 0;

	// loop through all translated chunks in current element
	for(var i = 0; i < transChunksLen; i++) {
		// bugfix: set detected language to 'undefined' if an error occurred during translation... 
		if(GL_transContent[curTransLang][0][curTransChunk] == null) {
			GL_transContent[curTransLang][0][curTransChunk] = new Array(3);
			GL_transContent[curTransLang][0][curTransChunk][1] = "undefined";	
		}
		// loop through array of detected languages to see if current chunk has an existing detected language
		for(var j = 0; j < chunkLangs.length; j++) {
			if(chunkLangs[j][0] == GL_transContent[curTransLang][0][curTransChunk][1]) {
				// if so, increment counter containing the total number of chunks with that language
				chunkLangs[j][1]++;
				break; // halt loop
			}
		}
		// if current chunk has a language not yet detected, add it to end of detected languages array
		if(j == chunkLangs.length) {
			chunkLangs[j] = new Array(2);
			chunkLangs[j][0] = GL_transContent[curTransLang][0][curTransChunk][1]; // name of detected language
			chunkLangs[j][1] = 1; // total number of chunks with that language
		}
		curTransChunk++; // move to next chunk
	}

	/* once array has been created containing all detected languages in current element, loop through it
	to find the most common detected language - language string should contain this */
	for(i = 0; i < chunkLangs.length; i++) {
		if(chunkLangs[i][1] > langCounter) {
			/* if current language was detected more times than all previous languages, store language
			and number of times detected - so that next language can be compared against this total */
			var detectedLang = chunkLangs[i][0];
			langCounter = chunkLangs[i][1];
		}		
	}
	
	return detectedLang; // return the most common detected language
}

// Auto-translate all text added previously by the script (including language strings and error messages)
function transAddedText() {
	var allElements = document.getElementsByTagName("*"); // get all elements on page, so relevant ones can be translated
	var foundElements = [];

	// loop through all elements to find any of class 'mlt_langstring' or 'mlt_transerrtxt' 
	for(var i=0; i<allElements.length; i++) {
		if((allElements[i].className == "mlt_langstring") || (allElements[i].className == "mlt_transerrtxt")) {
			foundElements[foundElements.length] = allElements[i];
		}
	}

	// translate all located elements (runs separately from above code to prevent infinite loop as items are translated)
	for(i = 0; i < foundElements.length; i++) {
		miniTranslate(foundElements[i]); // translate current element
	}
}

/* this function runs before any translation takes place, and creates a local 'cache' of all content to be translated (in chunks)
   - meaning the content can be submitted to Google more rapidly, and the resulting translations can then be sorted reliably */
function buildChunkedContent() {
	var curElement; GL_srcContent = []; var j = 0;

	/* loop through all applicable element IDs (as specified at script top), converting the contents of each into chunks,
	   and storing each chunk in an array */
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element
		// check that element actually exists on the page - if not, ignore it
		if(curElement != null) {
			GL_srcContent[j] = createChunks(curElement); // separate the content of current element into chunks
			GL_chunksTotal += GL_srcContent[j].length;   // store a running total of the number of chunks created

			// if a Source Language is not specified for current element, store Base Language in array instead
			if(GL_classIds[i].length == 1) {
				GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
			} else {
				// otherwise store the specified language (or a blank string if this is to be auto-detected)
				GL_srcContent[j][GL_srcContent[j].length] = GL_classIds[i][1];
			}
			j++;
		}
	}

	// get all elements on page, so that the ones specified can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all applicable element IDs (as specified at script top), converting into chunks and storing in array
	for(var i = 0; i < GL_classNames.length; i++) {
		// find all elements which have the current class name
		for(var k = 0; k < allElements.length; k++) { 
			if(allElements[k].className == GL_classNames[i][0]) {
				// separate the content of current element into chunks
				GL_srcContent[j] = createChunks(allElements[k]);
				// store a running total of the number of chunks created
				GL_chunksTotal += GL_srcContent[j].length;

				// if a Source Language is not specified for current element, store Base Language in array
				if(GL_classNames[i].length == 1) {
					GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
				} else {
					// otherwise store specified language (or a blank string if auto-detected)
					GL_srcContent[j][GL_srcContent[j].length] = GL_classNames[i][1];
				}
				j++;
			}
		}
	}
}

/* Web browsers (and Google) limit the amount of text translated per request, so split contents of current element into chunks.
   The aim is to achieve this whilst maintaining the translation integrity */
function createChunks(srcContent) {	
	var chars = 1000; // number of characters to allow per chunk.

	/* We do NOT want the content inside any HTML tag to be split between chunks (as this could cause 
	rendering problems), so create 2 arrays storing tags and textual content of current div separately */
	var tags = srcContent.innerHTML.match(/<.*?>/g);
	var text = srcContent.innerHTML.split(/<.*?>/g);
	if(tags == null) {
		tags = new Array();} // handle content containing no tags

	var curchar = 0; var tagnum = 0; var textnum = 0; var contTotal = tags.length + text.length;
	// create an array containing content to be chunked, with tags + text separately re-assembled (in order)
	var content = new Array(contTotal);
	// loop through content of current div
	for(var i=0; i < contTotal; i++) {
		// if current position in content is the start of a tag char, add appropriate tag to content array
		if(srcContent.innerHTML.substr(curchar,1) == "<") {
			content[i] = tags[tagnum];
			curchar += tags[tagnum].length;
			tagnum++;
		// if it is a text string, add the corresponding text to the curent element in content array
		} else {
			content[i] = text[textnum];
			curchar += text[textnum].length;
			textnum++;
		}
	}

	// Create the chunks - don't split either tags or words (to ensure as high translation quality as possible)
	var chunks = []; var curChunk = 0;
	chunks[0]="";
	for (i = 0; i < contTotal; i++) {
		// if next content item (tag or textual) won't exceed length of current chunk, add it to chunk
		if((chunks[curChunk].length + content[i].length) < chars) {
			chunks[curChunk] += content[i];
		} else {
			// otherwise, proceed to next chunk.
			curChunk++;
			// add the entire content item to this chunk if possible (to ensure better translation)
			if(content[i].length < chars) {
				chunks[curChunk] = content[i];
			}
			else {
				// only split further in rare cases where text length exceeds maximum chunk size
				var curPos = 0;
				do {
					// retrieve the maximum amount of text that can fit in this chunk
					var subContent = content[i].substr(curPos,chars);
					// find out how many words are in this substring
					var words = subContent.split(" ");
					// chop off final word, so words aren't split up between chunks
					var lastWordPos = subContent.length - words[(words.length-1)].length;
					if(subContent.length < chars) { // [bugfix: prevent word cut-off on final iteration]
						lastWordPos = subContent.length}
					chunks[curChunk] = subContent.substr(0,lastWordPos); // store in chunk
					curChunk++; // remainder of text will go in next chunk
					curPos+=lastWordPos; // store current position in text, for further processing
				} while(subContent.length >= chars); // repeat until all this text has been chunked
				curChunk--; // because there may still be space in the current chunk!
			}
		}
	}		
	
	return chunks; // return chunked content to calling function...
}

// Append elements to page (will be used to display translation messages), and specify their css styles.
function addTransMsgs() {
	// add element to page which will contain translation messages
	var transCont = document.createElement("div");
	document.body.appendChild(transCont);
	
	// add element to container created above - this will display the translation messages
	var translateMsg = document.createElement("div");
	translateMsg.id = "mlt_translatemsg";
	transCont.appendChild(translateMsg);

	// define visual styles for translation messages displayed on screen
	translateMsg.style.backgroundColor = "silver";
	translateMsg.style.border = "3px green solid";
	translateMsg.style.padding = "5px";
	translateMsg.style.fontSize = "large";
	translateMsg.style.fontWeight = "bold";
	translateMsg.style.textAlign = "left";
	translateMsg.style.color = "black";

	// more translation message styles (these should not need editing!)
	translateMsg.style.left = "-50%";
	translateMsg.style.position = "relative";
	translateMsg.style.display = "none";
	
	// define the styles for the container element
	transCont.style.left = "50%";
	transCont.style.zIndex = "1000";
	if(!(/MSIE 6/i.test(navigator.userAgent))) {
		// styles for all browsers except IE6
		transCont.style.position = "fixed";
		transCont.style.top = "0px";
	}
	else {
		// styles for IE6
		transCont.style.position = "absolute";
		transCont.style.setExpression("top", "(i = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
	}
}

// Hide 'Translating...' message (or translation error message) - runs at end of translation, or if user dismisses error message
function hideTransMsg() {
	document.getElementById("mlt_translatemsg").innerHTML = "";
	document.getElementById("mlt_translatemsg").style.display='none';
}

// if the user clicks on the 'Details' link [after error(s) occurred], show details of all errors on screen
function showErrDetails() {
	// continue to show original error message (but remove 'Details' link)
	document.getElementById("mlt_translatemsg").innerHTML = '<span id="mlt_transerrmsg1">' + GL_errors.length + 
	' Problems(s) Occurred During Translation: ' + '<a href="javascript:refresh()">Retry</a> - ' +
	'<a href="javascript:hideTransMsg()">Hide</a>... <br /><em>Error(s) Reported:</em></span>' +
	'<ul style="margin: 0px; padding: 0px;" id="mlt_transerrlist"></ul>';

	// Loop through array containing details of all errors, and show them as a list on screen
	for(var i = 0; i < GL_errors.length; i++) {
		document.getElementById("mlt_transerrlist").innerHTML += '<li style="margin-left: 15px;">' + GL_errors[i] + '.</li> ';	
	}

	/* create a textarea - this will show the original source text of all affected sections (as HTML) to aid debugging
	   Note: because translations are returned using AJAX, the affected sections are not NECESSARILY in the same order as
	   the errors reported (though in many cases, they will be!) */
	document.getElementById("mlt_translatemsg").innerHTML += '<em id="mlt_transerrmsg2">Section(s) Affected:</em><br />' +
	'<textarea id="mlt_errsrctxt" rows="8" readonly="readonly" style="width: 99%; background-color: silver; border: 1px gray solid;">' +
	'</textarea>';

	// Loop through Source Text array, appending to textarea.
	for(var i = 0; i < GL_errSrcTxt.length; i++) {
		document.getElementById("mlt_errsrctxt").value += "Affected Section " + (i+1) + ":\n" + GL_errSrcTxt[i] + "\n\n";
	}

	// Translate the entire contents of the Translation Errors box (with the exception of the text inside the textarea)
	miniTranslate(document.getElementById("mlt_transerrmsg1")); miniTranslate(document.getElementById("mlt_transerrlist"));
	miniTranslate(document.getElementById("mlt_transerrmsg2"));
}

// function runs when the user clicks on a link to view the original source text for a translated element / chunk
function showSrcTxt(curLinkId,curClassNum,curChunkId) {
	// if the current chunk should be shown only, display chunk on screen
	if((curChunkId-1) != -1) {
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+GL_srcContent[curClassNum][(curChunkId-1)]+']</div>';
	} else {
	// otherwise assemble all chunks for current element, and display on screen
		var srcTxt = "";
		for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
			srcTxt +=  GL_srcContent[curClassNum][i];
		}
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+srcTxt+']</div>';
	}	

	// update Source Text link so that when clicked in future, the source text will be hidden instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "Hide Source Text [-]";
	srcTxtLnk.href = 'javascript:hideSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = ""; // hide bracket after link
}

// function runs when the user clicks on a link to hide the original source text for a translated element / chunk
function hideSrcTxt(curLinkId,curClassNum,curChunkId) {
	// remove the element containing the original source text
	srcTxtContent = document.getElementById("mlt_srctxtcontent"+curLinkId);
	document.getElementById("mlt_srctxt"+curLinkId).removeChild(srcTxtContent);

	// update Source Text link so that when clicked in future, the source text will be shown instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "View Source Text [+]";
	srcTxtLnk.href = 'javascript:showSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = "]"; // show bracket after link
}

// translate small non crucial items of text into current site language
function miniTranslate(item,destLang,srcTxt) {
	if(typeof destLang == "undefined") {
		var destLang = GL_curLang; // if the destLang argument was not specified, use the current site language
	}
	if(typeof srcTxt == "undefined") {
		var srcTxt = item.innerHTML; // if the srcText argument was not specified, use the current item contents
	}

	// loop through translated items array to see if a translation for current text already exists since page loaded
	for(var i = 0; i < GL_miniTransItems.length; i++) {
		// check if source text and destination language match a translated item (and a completed translation exists for it)
		if((GL_miniTransItems[i][1] == srcTxt) && (GL_miniTransItems[i][2] == destLang) && (GL_miniTransItems[i][3] != "")) {
			item.innerHTML = GL_miniTransItems[i][3]; // if so, display existing translation in item
			item.title = srcTxt.split(/<.*?>/g).join(""); // display English source text as a tooltip (strip HTML first)
			return; // Don't need to send a translation request to Google, so end function.
		}
	}

	// store item to be translated in global array for access by callback function
	GL_miniTransItems[GL_miniTransItems.length]	   = new Array(4);
	GL_miniTransItems[(GL_miniTransItems.length-1)][0] = item;
	GL_miniTransItems[(GL_miniTransItems.length-1)][1] = srcTxt;
	GL_miniTransItems[(GL_miniTransItems.length-1)][2] = destLang;
	GL_miniTransItems[(GL_miniTransItems.length-1)][3] = "";

	// create source text by adding current item ID to start of item text (ID will ensure correct item is translated)
	srcTxt = (GL_miniTransItems.length-1) + "<br />" + srcTxt;

	google.language.translate(srcTxt, "en", destLang, function(result) {
        	if (!result.error) {
			// split into array based on separator, so we know the id of translated item
			var transChunk = result.translation.split("<br />");
			// [find out length of substring to chop off from start of item]
			var chunkSubStr = 6 + transChunk[0].length;
			// remove whitespace from item id (a problem with some translations)
			transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");

			// display english source text of translated item (with HTML stripped) if user hovers mouse over it
			var strippedSrcTxt = GL_miniTransItems[transChunk[0]][1].split(/<.*?>/g).join("");
			GL_miniTransItems[transChunk[0]][0].title = "[" + strippedSrcTxt  + "]";

			// store and display translation of specified item (stripping item ID from start of text)
			GL_miniTransItems[transChunk[0]][3] = result.translation.substr(chunkSubStr);
			GL_miniTransItems[transChunk[0]][0].innerHTML = GL_miniTransItems[transChunk[0]][3];
        	}
	});
}

// runs when the user changes the site language
function changeLang(destLang) {
	if(typeof destLang != "undefined") {
		GL_curLang = destLang; // if the destLang argument was specified, set new site language to this
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to display new site language
	} else {
		// otherwise get the new language requested by user
		GL_curLang = document.getElementById("mlt_language").value;
	}

	// store the requested language in a cookie
	setLangCookie();
	
	// if the original site languages should be shown, refresh the page.
	if(GL_curLang == "orig") {
		refresh();
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// find out the value of the language cookie (if it exists)
function getLangCookie() {
	var curStoredLang;
	// retrieve a list of cookies for this page, split into array elements (separated by ; if multiple cookies)
	var getCurLang=document.cookie.split(";");
	// loop through all array elements (i.e. cookies) until one with name 'lang' is found.
	for(var i=0; i < getCurLang.length; i++) {

		// remove whitespace from cookies (a problem if there are multiple cookies)
		var lngCookie = getCurLang[i].replace(/^\s+|\s+$/g,"");

		if(lngCookie.indexOf("lang=") == 0) {
			// find out value of lang
			curStoredLang = lngCookie.substring(5);
		}
	}
	
	// if language cookie exists, set current site language to stored value
	if(typeof curStoredLang != "undefined") {
		GL_curLang = curStoredLang;
	// otherwise, check if an initial language has been specified
	} else if((GL_curLang == "") || (typeof GL_curLang == "undefined")) {
		detectUserLang(); // if not, find out user's language based on their settings, and offer to translate into that language
		GL_curLang = "orig"; // show site using original languages for now
		return; // don't want to store language in cookie until one has been specified, so end function
	}

	setLangCookie(); // if valid cookie exists or initial language was specified, set/renew cookie (to store new expiry date)
}

// If a new user has not specified a language yet, offer to translate page into their current browser / system language
function detectUserLang(){
	/* detect user's current language (if they are using IE this will be based on the regional settings on their system; 
	   otherwise it will be based on the default language of their current browser) */
	var detectedLang = (navigator.language) ? navigator.language : navigator.userLanguage;
	
	// if language cannot be detected for some reason, end function.
	if((typeof detectedLang == "undefined") || (detectedLang == ""))  {
		return;
	}
	
	// if language is regional dialect (e.g. "en-gb"), check last 2 letters are upper case - for google compatibility.
	if(detectedLang.length == 5) {
		detectedLang = detectedLang.substr(0,3) + detectedLang.substr(3).toUpperCase();
	}
	
	// check that Google can translate content into detected language
	if (!google.language.isTranslatable(detectedLang)) {
		// if not, check if language is a regional dialect (e.g. "en-GB")
		if(detectedLang.length == 5) {
			// if so, Google may still be able to translate into a non-regional equivalent (e.g. "en")
			detectedLang = detectedLang.substr(0,2);
			if (!google.language.isTranslatable(detectedLang)) {
				return; // google cannot translate into non-regional equivalent, so end function
			}
		// language is not a regional dialect, and google cannot translate into it, so end function
		} else {
			return;
		}
	}
	
	var detectedLangStr = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
	
	/*
	// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  'Translate this page into ' + detectedLangStr + '? ' +
	'<a href="javascript:changeLang(\'' + detectedLang + '\')">Yes</a> | <a href="javascript:changeLang(\'orig\')">No</a>';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='block'; // show the question on screen
	*/
	
	
		// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  '';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='none'; // show the question on screen
}

// create a cookie to store the current site language
function setLangCookie() {
	// expire previous cookie (if it exists)
	document.cookie = "lang=; expires=-1; path=/";

	// cookie will expire after 90 days.
	var expdate = new Date();
	expdate.setTime(expdate.getTime()+7776000000);

	// create the cookie
	document.cookie = "lang=" + GL_curLang + "; expires=" + expdate.toGMTString() + "; path=/";
}

// refresh the current page [runs if the Original Languages option was selected, or if requested by user after error(s)]
function refresh() {
	hideTransMsg();
	window.location.reload(true);
}

// run the 'initialise' function once the page has loaded.
google.setOnLoadCallback(initialise);

****************The End*****************************


*****************Save it as googlelanguage.js******************


if (!window['google']) {
window['google'] = {};
}
if (!window['google']['loader']) {
window['google']['loader'] = {};
google.loader.ServiceBase = 'http://www.google.com/uds';
google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax';
google.loader.ApiKey = 'notsupplied';
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.Secure = false;
google.loader.GoogleLocale = 'www.google.com';
google.loader.ClientLocation = {"latitude":17.385044,"longitude":78.486671,"address":{"city":"Hyderabad","region":"Andhra Pradesh","country":"India","country_code":"IN"}};
google.loader.AdditionalParams = '';
(function() {var d=true,g=null,h=false,j=encodeURIComponent,l=window,n=undefined,o=document;function p(a,b){return a.load=b}var q="push",r="replace",s="charAt",t="ServiceBase",u="name",v="getTime",w="length",x="prototype",y="setTimeout",z="loader",A="substring",B="join",C="toLowerCase";function D(a){if(a in E)return E[a];return E[a]=navigator.userAgent[C]().indexOf(a)!=-1}var E={};function F(a,b){var c=function(){};c.prototype=b[x];a.Q=b[x];a.prototype=new c}
function G(a,b){var c=Array[x].slice.call(arguments,2)||[];return function(){var e=c.concat(Array[x].slice.call(arguments));return a.apply(b,e)}}function H(a){a=Error(a);a.toString=function(){return this.message};return a}function I(a,b){for(var c=a.split(/\./),e=l,f=0;f<c[w]-1;f++){e[c[f]]||(e[c[f]]={});e=e[c[f]]}e[c[c[w]-1]]=b}function J(a,b,c){a[b]=c}if(!K)var K=I;if(!L)var L=J;google[z].t={};K("google.loader.callbacks",google[z].t);var M={},N={};google[z].eval={};K("google.loader.eval",google[z].eval);
p(google,function(a,b,c){function e(k){var m=k.split(".");if(m[w]>2)throw H("Module: '"+k+"' not found!");else if(typeof m[1]!="undefined"){f=m[0];c.packages=c.packages||[];c.packages[q](m[1])}}var f=a;c=c||{};if(a instanceof Array||a&&typeof a=="object"&&typeof a[B]=="function"&&typeof a.reverse=="function")for(var i=0;i<a[w];i++)e(a[i]);else e(a);if(a=M[":"+f]){if(c&&!c.language&&c.locale)c.language=c.locale;if(c&&typeof c.callback=="string"){i=c.callback;if(i.match(/^[[\]A-Za-z0-9._]+$/)){i=l.eval(i);
c.callback=i}}if((i=c&&c.callback!=g)&&!a.s(b))throw H("Module: '"+f+"' must be loaded before DOM onLoad!");else if(i)a.m(b,c)?l[y](c.callback,0):a.load(b,c);else a.m(b,c)||a.load(b,c)}else throw H("Module: '"+f+"' not found!");});K("google.load",google.load);
google.P=function(a,b){if(b){if(O[w]==0){P(l,"load",Q);if(!D("msie")&&!(D("safari")||D("konqueror"))&&D("mozilla")||l.opera)l.addEventListener("DOMContentLoaded",Q,h);else if(D("msie"))o.write("<script defer onreadystatechange='google.loader.domReady()' src=//:><\/script>");else(D("safari")||D("konqueror"))&&l[y](S,10)}O[q](a)}else P(l,"load",a)};K("google.setOnLoadCallback",google.P);
function P(a,b,c){if(a.addEventListener)a.addEventListener(b,c,h);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var e=a["on"+b];a["on"+b]=e!=g?aa([c,e]):c}}function aa(a){return function(){for(var b=0;b<a[w];b++)a[b]()}}var O=[];google[z].K=function(){var a=l.event.srcElement;if(a.readyState=="complete"){a.onreadystatechange=g;a.parentNode.removeChild(a);Q()}};K("google.loader.domReady",google[z].K);var ba={loaded:d,complete:d};function S(){if(ba[o.readyState])Q();else O[w]>0&&l[y](S,10)}
function Q(){for(var a=0;a<O[w];a++)O[a]();O.length=0}
google[z].d=function(a,b,c){if(c){var e;if(a=="script"){e=o.createElement("script");e.type="text/javascript";e.src=b}else if(a=="css"){e=o.createElement("link");e.type="text/css";e.href=b;e.rel="stylesheet"}(a=o.getElementsByTagName("head")[0])||(a=o.body.parentNode.appendChild(o.createElement("head")));a.appendChild(e)}else if(a=="script")o.write('<script src="'+b+'" type="text/javascript"><\/script>');else a=="css"&&o.write('<link href="'+b+'" type="text/css" rel="stylesheet"></link>')};
K("google.loader.writeLoadTag",google[z].d);google[z].M=function(a){N=a};K("google.loader.rfm",google[z].M);google[z].O=function(a){for(var b in a)if(typeof b=="string"&&b&&b[s](0)==":"&&!M[b])M[b]=new T(b[A](1),a[b])};K("google.loader.rpl",google[z].O);google[z].N=function(a){if((a=a.specs)&&a[w])for(var b=0;b<a[w];++b){var c=a[b];if(typeof c=="string")M[":"+c]=new U(c);else{c=new V(c[u],c.baseSpec,c.customSpecs);M[":"+c[u]]=c}}};K("google.loader.rm",google[z].N);
google[z].loaded=function(a){M[":"+a.module].k(a)};K("google.loader.loaded",google[z].loaded);google[z].J=function(){return"qid="+((new Date)[v]().toString(16)+Math.floor(Math.random()*1E7).toString(16))};K("google.loader.createGuidArg_",google[z].J);I("google_exportSymbol",I);I("google_exportProperty",J);google[z].b={};K("google.loader.themes",google[z].b);google[z].b.z="http://www.google.com/cse/style/look/bubblegum.css";L(google[z].b,"BUBBLEGUM",google[z].b.z);google[z].b.B="http://www.google.com/cse/style/look/greensky.css";
L(google[z].b,"GREENSKY",google[z].b.B);google[z].b.A="http://www.google.com/cse/style/look/espresso.css";L(google[z].b,"ESPRESSO",google[z].b.A);google[z].b.D="http://www.google.com/cse/style/look/shiny.css";L(google[z].b,"SHINY",google[z].b.D);google[z].b.C="http://www.google.com/cse/style/look/minimalist.css";L(google[z].b,"MINIMALIST",google[z].b.C);function U(a){this.a=a;this.q=[];this.p={};this.i={};this.e={};this.l=d;this.c=-1}
U[x].g=function(a,b){var c="";if(b!=n){if(b.language!=n)c+="&hl="+j(b.language);if(b.nocss!=n)c+="&output="+j("nocss="+b.nocss);if(b.nooldnames!=n)c+="&nooldnames="+j(b.nooldnames);if(b.packages!=n)c+="&packages="+j(b.packages);if(b.callback!=g)c+="&async=2";if(b.style!=n)c+="&style="+j(b.style);if(b.other_params!=n)c+="&"+b.other_params}if(!this.l){if(google[this.a]&&google[this.a].JSHash)c+="&sig="+j(google[this.a].JSHash);var e=[];for(var f in this.p)f[s](0)==":"&&e[q](f[A](1));for(f in this.i)f[s](0)==
":"&&this.i[f]&&e[q](f[A](1));c+="&have="+j(e[B](","))}return google[z][t]+"/?file="+this.a+"&v="+a+google[z].AdditionalParams+c};U[x].v=function(a){var b=g;if(a)b=a.packages;var c=g;if(b)if(typeof b=="string")c=[a.packages];else if(b[w]){c=[];for(a=0;a<b[w];a++)typeof b[a]=="string"&&c[q](b[a][r](/^\s*|\s*$/,"")[C]())}c||(c=["default"]);b=[];for(a=0;a<c[w];a++)this.p[":"+c[a]]||b[q](c[a]);return b};
p(U[x],function(a,b){var c=this.v(b),e=b&&b.callback!=g;if(e)var f=new W(b.callback);for(var i=[],k=c[w]-1;k>=0;k--){var m=c[k];e&&f.F(m);if(this.i[":"+m]){c.splice(k,1);e&&this.e[":"+m][q](f)}else i[q](m)}if(c[w]){if(b&&b.packages)b.packages=c.sort()[B](",");for(k=0;k<i[w];k++){m=i[k];this.e[":"+m]=[];e&&this.e[":"+m][q](f)}if(!b&&N[":"+this.a]!=g&&N[":"+this.a].versions[":"+a]!=g&&!google[z].AdditionalParams&&this.l){c=N[":"+this.a];google[this.a]=google[this.a]||{};for(var R in c.properties)if(R&&
R[s](0)==":")google[this.a][R[A](1)]=c.properties[R];google[z].d("script",google[z][t]+c.path+c.js,e);c.css&&google[z].d("css",google[z][t]+c.path+c.css,e)}else if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),e);if(this.l){this.l=h;this.c=(new Date)[v]();if(this.c%100!=1)this.c=-1}for(k=0;k<i[w];k++){m=i[k];this.i[":"+m]=d}}});
U[x].k=function(a){if(this.c!=-1){X("al_"+this.a,"jl."+((new Date)[v]()-this.c),d);this.c=-1}this.q=this.q.concat(a.components);google[z][this.a]||(google[z][this.a]={});google[z][this.a].packages=this.q.slice(0);for(var b=0;b<a.components[w];b++){this.p[":"+a.components[b]]=d;this.i[":"+a.components[b]]=h;var c=this.e[":"+a.components[b]];if(c){for(var e=0;e<c[w];e++)c[e].I(a.components[b]);delete this.e[":"+a.components[b]]}}X("hl",this.a)};U[x].m=function(a,b){return this.v(b)[w]==0};U[x].s=function(){return d};
function W(a){this.H=a;this.n={};this.r=0}W[x].F=function(a){this.r++;this.n[":"+a]=d};W[x].I=function(a){if(this.n[":"+a]){this.n[":"+a]=h;this.r--;this.r==0&&l[y](this.H,0)}};function V(a,b,c){this.name=a;this.G=b;this.o=c;this.u=this.h=h;this.j=[];google[z].t[this[u]]=G(this.k,this)}F(V,U);p(V[x],function(a,b){var c=b&&b.callback!=g;if(c){this.j[q](b.callback);b.callback="google.loader.callbacks."+this[u]}else this.h=d;if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),c);X("el",this[u])});V[x].m=function(a,b){return b&&b.callback!=g?this.u:this.h};V[x].k=function(){this.u=d;for(var a=0;a<this.j[w];a++)l[y](this.j[a],0);this.j=[]};
var Y=function(a,b){return a.string?j(a.string)+"="+j(b):a.regex?b[r](/(^.*$)/,a.regex):""};V[x].g=function(a,b){return this.L(this.w(a),a,b)};
V[x].L=function(a,b,c){var e="";if(a.key)e+="&"+Y(a.key,google[z].ApiKey);if(a.version)e+="&"+Y(a.version,b);b=google[z].Secure&&a.ssl?a.ssl:a.uri;if(c!=g)for(var f in c)if(a.params[f])e+="&"+Y(a.params[f],c[f]);else if(f=="other_params")e+="&"+c[f];else if(f=="base_domain")b="http://"+c[f]+a.uri[A](a.uri.indexOf("/",7));google[this[u]]={};if(b.indexOf("?")==-1&&e)e="?"+e[A](1);return b+e};V[x].s=function(a){return this.w(a).deferred};
V[x].w=function(a){if(this.o)for(var b=0;b<this.o[w];++b){var c=this.o[b];if(RegExp(c.pattern).test(a))return c}return this.G};function T(a,b){this.a=a;this.f=b;this.h=h}F(T,U);p(T[x],function(a,b){this.h=d;google[z].d("script",this.g(a,b),h)});T[x].m=function(){return this.h};T[x].k=function(){};
T[x].g=function(a,b){if(!this.f.versions[":"+a]){if(this.f.aliases){var c=this.f.aliases[":"+a];if(c)a=c}if(!this.f.versions[":"+a])throw H("Module: '"+this.a+"' with version '"+a+"' not found!");}c=google[z].GoogleApisBase+"/libs/"+this.a+"/"+a+"/"+this.f.versions[":"+a][b&&b.uncompressed?"uncompressed":"compressed"];X("el",this.a);return c};T[x].s=function(){return h};var ca=h,Z=[],da=(new Date)[v](),X=function(a,b,c){if(!ca){P(l,"unload",ea);ca=d}if(c){if(!google[z].Secure&&(!google[z].Options||google[z].Options.csi===h)){a=a[C]()[r](/[^a-z0-9_.]+/g,"_");b=b[C]()[r](/[^a-z0-9_.]+/g,"_");l[y](G($,g,"http://csi.gstatic.com/csi?s=uds&v=2&action="+j(a)+"&it="+j(b)),1E4)}}else{Z[q]("r"+Z[w]+"="+j(a+(b?"|"+b:"")));l[y](ea,Z[w]>5?0:15E3)}},ea=function(){if(Z[w]){$(google[z][t]+"/stats?"+Z[B]("&")+"&nc="+(new Date)[v]()+"_"+((new Date)[v]()-da));Z.length=0}},$=function(a){var b=
new Image,c=fa++;ga[c]=b;b.onload=b.onerror=function(){delete ga[c]};b.src=a;b=g},ga={},fa=0;I("google.loader.recordStat",X);I("google.loader.createImageForLogging",$);

}) ();google.loader.rm({"specs":[{"name":"books","baseSpec":{"uri":"http://books.google.com/books/api.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}}}},"feeds",{"name":"friendconnect","baseSpec":{"uri":"http://www.google.com/friendconnect/script/friendconnect.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{}}},"spreadsheets","gdata","visualization",{"name":"sharing","baseSpec":{"uri":"http://www.google.com/s2/sharing/js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{"language":{"string":"hl"}}}},"search",{"name":"maps","baseSpec":{"uri":"http://maps.google.com/maps?file\u003dgoogleapi","ssl":"https://maps-api-ssl.google.com/maps?file\u003dgoogleapi","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"regex":"callback\u003d$1\u0026async\u003d2"},"language":{"string":"hl"}}},"customSpecs":[{"uri":"http://maps.google.com/maps/api/js","ssl":"https://maps-api-ssl.google.com/maps/api/js","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}},"pattern":"^(3|3..*)$"}]},"annotations_v2","wave","orkut",{"name":"annotations","baseSpec":{"uri":"http://www.google.com/reviews/scripts/annotations_bootstrap.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"},"country":{"string":"gl"}}}},"language","earth","ads","elements"]});
google.loader.rfm({":search":{"versions":{":1":"1",":1.0":"1"},"path":"/api/search/1.0/2a8ff2a70ad0b091ae9dfd8b5e832141/","js":"default+en.I.js","css":"default.css","properties":{":JSHash":"2a8ff2a70ad0b091ae9dfd8b5e832141",":NoOldNames":false,":Version":"1.0"}},":language":{"versions":{":1":"1",":1.0":"1"},"path":"/api/language/1.0/62c64af2122d2da7dcb0087852fa7396/","js":"default+en.I.js","properties":{":JSHash":"62c64af2122d2da7dcb0087852fa7396",":Version":"1.0"}},":wave":{"versions":{":1":"1",":1.0":"1"},"path":"/api/wave/1.0/3b6f7573ff78da6602dda5e09c9025bf/","js":"default.I.js","properties":{":JSHash":"3b6f7573ff78da6602dda5e09c9025bf",":Version":"1.0"}},":spreadsheets":{"versions":{":0":"1",":0.3":"1"},"path":"/api/spreadsheets/0.3/8331b0bbcc74776270648505340e9200/","js":"default.I.js","properties":{":JSHash":"8331b0bbcc74776270648505340e9200",":Version":"0.3"}},":earth":{"versions":{":1":"1",":1.0":"1"},"path":"/api/earth/1.0/819ffbf1e363d238791231792a2e0a90/","js":"default.I.js","properties":{":JSHash":"819ffbf1e363d238791231792a2e0a90",":Version":"1.0"}},":annotations":{"versions":{":1":"1",":1.0":"1"},"path":"/api/annotations/1.0/11cfaf30c00ca64601d09fcac7dd8bc7/","js":"default+en.I.js","properties":{":JSHash":"11cfaf30c00ca64601d09fcac7dd8bc7",":Version":"1.0"}}});
google.loader.rpl({":scriptaculous":{"versions":{":1.8.3":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.2":{"uncompre

Revision: 39556
at January 19, 2011 05:48 by mavrikicecool


Updated Code
Read from top to Bottom see for **** especially....

Make an application multi lingual by using google API....
This process can even be implemented by an web service, but i have made use of google API
Please follow the steps and make changes accordingly 

PHP(make use of div's and apply to the id's), ASP(Apply to all labesl)...and the rest of the languages follow up the same procedure accoringly......

*****************Add these 2 scripts tags into u r header and make it common for the pages so that it includes in each and everything***
<!--<script type="text/javascript" src="Translate/googlelanguage.js"></script>
<script type="text/javascript" src="Translate/translate.js"></script>-->
****************Better to add these 2 into head section of u r html or asp or jsp pages********************************************
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
************Add this thing into the body section where ever u wish to or u wanna Place the option for selection*******************
 <!-- <div><font size="+1">Select Language</font></div>
  <div id="mlt_languagelist"> </div>-->
  
  -->Steps:
  	1) As the page is loaded the the 2nd div gets activated and gets processed through the api and data is fetched from the tranlate.js script....check in the line number 166 the function getLangs() gets called and executed.just go through the function and understand the parameters passed u will know better whats happening.
	
	2) G to line number 85 there u will come to know how the langues get changed based upon u r request.
	3)	if(GL_curLang == "orig") {
			refresh();
			return;
		}
	
	find th this block and add few more langues based upon ICANN standards for language notations in google.soon after the above block by dumping more conditions to the above block u can select the langues aby your choice
	
	Add:
		else if(GL_curLang == "es") { //spanish
			refresh();
			return;
		}	
		else if(GL_curLang == "ja") { //japanese
			refresh();
			return;
		} 
		
		
	4) So add according to u r choice all this has to be followed aftr line number 888 for the 3 point.
	
	6) And now get to start of the page translate.js and point towards line 52, there you gonna find a an array assigned toa  variable with various elements within the array, present with other elements within it for the converion usuage.
	for all required labels in asp or the div or span's which u find the page, assign them which are to be changed upon request.
	
	7) rename those elements name by u r own names which u want, use those div's which are present in all front end pages .for each and every text item or asp with label tags, assign these id's one for all those text items(i.e the div's of each and every text item)..and u r almost done
	
	8)save all changes and start using this applicationits gonna work i am sure.....if there is anything lemme know.post it on the comments section i will reply back.
	
	5)By this way the combo box is set with languages which you require to make the application multi lingual
	
	6)this particual api support 64 recognised languages , check the info in google for this particual api.
	
  
********************************************************************************************************************************* 
</body>
</html>


*******************Save it as translate.js***************************

/* Multi-Language Translation Script:
*
*  Automatically translates a webpage (containing text in more than one language) into any single language
*  requested by the user. Particularly useful for sites involving a lot of user-generated content (which
*  might have originally been written in different languages) - e.g. blogs, forums, or other community sites. 
*  Harnesses the Google AJAX Language API to perform translation and language detection.
*
*  Version: 0.2.5 [2010-01-22]
*  Author: Patrick Hathway, OdinLab, University of Reading.
*  For Documentation and Updates: See http://code.google.com/p/multi-language-translation/
*  Licence: MIT License - see http://opensource.org/licenses/mit-license.php for full terms. Also check 
*  the script Documentation for more information, and for details of one important consideration.
*
*  Some minor configuration is required for this script to work on your website. Follow the instructions
*  below, or see the Documentation for full details and examples...   */

/* 1. Specify the 'Base Language' for your website: */

var GL_baseLang = "en";

/* 2. Specify the IDs for all major regions (i.e. HTML elements) in your site that should have their 
*  contents translated. Note that an ID can only be used to identify a single element on a page (for 
*  elements which appear multiple times, use Class Names instead - see below). The script will translate
*  each element separately; any elements that cannot be found on a page will be ignored:   */

var GL_classIds = [
	["navigation"],	
	["navigation", "", true],  
	["quick-id", "", true],  
	["c-quote", "", true],  
	["c-need-quote", "", true],  
	["c-index", "", true],   
	["c-about", "", true],  
	["c-exper", "", true],  
	["c-solution", "", true],
	["c-product", "", true],  
	["c-contact", "", true],  
	["c-indian-add", "", true],  
	["c-work", "", true],  
	["c-contact", "", true],  
	["c-contactinf", "", true],
	["c-usa-add", "", true],  
	["c-warning", "", true],  
	["right_sidebar", "fr", true], 
	["footer"]
];

/* 3. Specify the Class Names of all major regions (i.e. HTML elements) in your site that should have their 
*  their contents translated. Multiple elements may appear on a page with the same class name; the script
*  will locate each occurrance (if present) and translate them separately:   */

var GL_classNames = [
	["entry_baselang"],
	["entry_french", "fr"],
	["index-class", "", true],
	["about-class", "", true],	
	["association-class", "", true],
	["building-class", "", true],
	["career-class", "", true],
	["college-class", "", true],
	["construction-class", "", true],
	["contact-class", "", true], 
	["entry_baselang", "", true], 
	["education-class", "", true], 
	["entry", "", true], 
	["expertise-class", "", true], 
	["description", "", true], 
	["list-custom_website", "", true], 
	["list-beautiful_graphic", "", true], 
	["list-using_nature", "", true],
	["list-css_xhtml", "", true],
	["description", "", true], 
	["list-branding_your", "", true], 
	["list-green_branding", "", true], 
	["list-who_are", "", true], 
	["list-long_term", "", true], 
	["list-the_importance", "", true], 
	["list-flow", "", true], 
	["list-click_through", "", true], 
	["list-scale", "", true], 
	["description", "", true], 
	["list-google_rank", "", true], 
	["list-ppc", "", true], 
	["list-custom_icon", "", true], 
	["list-why_use", "", true], 
	["list-web_standard", "", true], 
	["list-promoting_your", "", true], 
	["list-business_cards", "", true], 
	["fashin-class", "", true], 
	["right", "", true],  
	["web_portfolio", "", true], 
	["interior-class", "", true],
	["manufacture-class", "", true], 
	["news-class", "", true], 
	["medical-class", "", true], 
	["opening-class", "", true], 
	["ourclass-class", "", true], 	
	["portfolio-class", "", true], 	
	["ecommerce-class", "", true], 	
	["mobile-class", "", true], 
	["webdesign-class", "", true], 
	["product-class", "", true], 
	["professional-class", "", true], 
	["real-class", "", true], 
	["realestate-class", "", true], 
	["request-class", "", true],   
	["form_entry", "", true],
	["request-id", "", true],
	["requestquote-class", "", true],
	["consumer-class", "", true],
	["software-class", "", true],
	["solutions-class", "", true],
	["list-why_use", "", true],
	["list-west_coast", "", true], 
	["list-custom_icon", "", true],
	["list-crisp_graphics", "", true],
	["list-scalable_across", "", true],
	["testimonials-class", "", true],  
	["testimonials", "", true],
	["tourism-class", "", true],
	["trade-class", "", true], 
	["transport-class", "", true], 
	["levonsys-class", "", true],  
	["working-levonsys-class", "", true],    
	["quick", "", true], 
	["entry_french", "", true], 
	["quotes", "de", true]
];


/* 4. Specify the default language for new visitors (leave blank to auto-detect using browser/system settings) */

var GL_curLang = "";

/* The rest of the Script should not be modified; unless you want to alter the functionality!
*  ------------------------------------------------------------------------------------------ */

// Global variables:
var GL_srcContent;             // array containing all content on the page to be translated, split up into chunks
var GL_transContent = [];      // array containing all chunks which have been translated
var GL_chunksTotal = 0;        // total number of chunks to translate
var GL_curChunk;               // ID of current chunk being translated
var GL_errors;                 // array containing details of all errors that occur (if applicable)
var GL_errSrcTxt;              // array containing all source text that causes errors (if applicable)
var GL_miniTransItems = [];    // array containing element IDs/class names which contain minor items to translate

google.load("language", "1");  // load v1 of google ajax language api

// run when page loads
function initialise() {
	addTransMsgs();        // append elements (which will display translation status messages) to page
	buildChunkedContent(); // create a local 'cache' of chunked content to be translated
	getLangCookie();       // find out the current site language (if known)
	getLangs();            // display listbox containing all languages the site can be translated into

	// if the original languages should be shown, end function.
	if(GL_curLang == "orig") {
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// display listbox containing all languages the site can be translated into (so that one can be selected by user)
function getLangs() {
	// create listbox within script so that it won't appear if JavaScript is disabled
	document.getElementById("mlt_languagelist").innerHTML = '<select id="mlt_language" onchange="changeLang()" style="width:150px; height:20px;"></select>';
	// +	'<div id="mlt_langattr"></div>'
	var langItems = document.getElementById("mlt_language").options;

	// add option to top of listbox allowing user to view the site in its original (i.e. un-translated) languages
	langItems.add(new Option("Original Languages", "orig", true));

	// loop through list of currently available languages and add each to listbox
	for(var lang in google.language.Languages) {
		// find out the 2 character Google language code
		
		var langCode = google.language.Languages[lang];
		// convert language string to title case
		var langString = lang.substr(0,1) + lang.substr(1).toLowerCase();
		// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
		langString = langString.split("_").join(" - ");

		// check that Google can translate content into the current language
		if ((google.language.isTranslatable(langCode)) && (langCode != "")) {
			// if so, add to listbox and translate, so native speakers of that language can find it
			if(langCode=="ar")
			{
				langItems.add(new Option(langString, langCode));
				miniTranslate(langItems[(langItems.length-1)],langCode);
			}
			
		}
	}

	document.getElementById("mlt_language").value = GL_curLang; // change listbox to display current site language
	google.language.getBranding("mlt_langattr");  // display Google attribution below listbox (as required by TOS)
}

// start the translation
function startTranslation() {
	// reset global variables
	GL_curChunk = 0; GL_errors = []; GL_errSrcTxt = [];
	
	// check if all content has already been translated into current language since page loaded.
	if(chkLangTrans()) {
		return; // if so, don't need to translate content again
	} 
	
	// sanity check - can google actually translate into the current site language?
	if (!(google.language.isTranslatable(GL_curLang)) || (GL_curLang == "")) {
		return; // if not, end translation
	} // Otherwise, send content to google to be translated:
	
	// show the 'Translating...' block
	document.getElementById("mlt_translatemsg").innerHTML = 'Translating... <span id="mlt_perc">0%</span>';
	miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	document.getElementById("mlt_translatemsg").style.display='block';

	// find out the ID of the destination language
	var curLangNo = document.getElementById("mlt_language").selectedIndex;
	var k = 0;
	
	// create sub-array to hold all translations for current language
	GL_transContent[GL_transContent.length]        = new Array(3);
	GL_transContent[(GL_transContent.length-1)][0] = []; // this array will contain all translated chunks
	GL_transContent[(GL_transContent.length-1)][1] = GL_curLang; // store current language
	GL_transContent[(GL_transContent.length-1)][2] = false; // mark translation of language as incomplete

	// loop through all the chunks to be translated, send to google...
	for(var i = 0; i < GL_srcContent.length; i++) {
		// find out the source language for the current element to be translated
		var srcLang = GL_srcContent[i][GL_srcContent[i].length - 1];

		for(var j = 0; j < (GL_srcContent[i].length - 1); j++) {
			/* AJAX is used to return translated chunks, so they MAY be returned in any order.
		   	To solve, include current chunk id, destination language + separators at start of each
		   	string. This is a bit of a 'hack', so try to find a better solution! */
			var srcText = curLangNo + "<br />" + k + "<br />" + GL_srcContent[i][j];

			// send current chunk to google translate; when translated, call function translateChunk
			google.language.translate(srcText, srcLang, GL_curLang, translateChunk);
			k++;
		}
	}

	setTimeout("checkTransStatus()", 1000); // run function to check translation status after 1 second
}

// check if page content has already been translated into current language since page loaded.
function chkLangTrans() {
	// loop through the list of languages the page has been translated into
	for(var i = 0; i < GL_transContent.length; i++) {
		// check if a translation for current language exists, and if so, whether it is complete.
		if((GL_transContent[i][1] == GL_curLang) && (GL_transContent[i][2] == true)){
			/* if so, don't need to send content to google again, just assemble the pre-translated content.
			This will *dramatically* reduce the translation time for this language! */
			endTranslation(i);
			return true;
		} 
	}
	return false; // otherwise, all relevant page content must be submitted to google for translation.
}

// This runs after each chunk has been translated...
function translateChunk(result) {
	// handle translation errors gracefully by storing error details but allowing translation to continue
	if (result.error) {
		GL_errors[GL_errors.length] = result.error.message;
	}
	else {

	/* Translated chunks may be returned in any order, so we need a method to assemble the chunks
	   in the correct order:
	   * Start of each chunk has a destination language id and a chunk id followed by separators.
	   * Separator is a <br /> HTML tag, as these always appear to retain position after translation...
	   * The destination language id is used to ensure the translated text is now in the correct language.
	   * Each chunk is stored in the position of the 'GL_transContent' array corresponding to the current chunk id.
	   * The ids + separators should not be shown, and are discarded from the chunk when it's stored in array.
	*/
	
		// split into array based on separator, so we know the id & destination language of translated chunk
		var transChunk = result.translation.split("<br />");
		// [find out length of substring to chop off from start of chunk]
		var chunkSubStr = 12 + transChunk[0].length + transChunk[1].length;
		// remove whitespace from chunk id & destination language (a problem with some translations)
		transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
		transChunk[1] = transChunk[1].replace(/^\s+|\s+$/g,"");

		/* If the translated chunk has a different destination language to the current site language, discard
		translation & end function. This may happen if user changes language whilst translation is in progress */
		if(transChunk[0] != document.getElementById("mlt_language").selectedIndex) {
			return;
		}

		// store translated chunk in current language array, along with detected source language (if known)
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]] = new Array(3);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][0] = result.translation.substr(chunkSubStr);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][1] = result.detectedSourceLanguage;
	}

	GL_curChunk++; // increment current chunk ID every time function is called

	// calculate and display percentage of translation completed, based on number of chunks remaining
	var perc = (GL_curChunk / GL_chunksTotal)*100;
	document.getElementById("mlt_perc").innerHTML = Math.round(perc) + "%";

	// when all chunks have been translated, run the 'endTranslation' function...
	if(GL_curChunk >= GL_chunksTotal) {
		endTranslation((GL_transContent.length-1)); // [final array element holds current language content!]
	}
}

/* runs once a second whilst translation is in progress, updating contents of all elements that have already
   been completely translated. Also shows 'timeout' messages if translation not completed within 30 seconds... */
function checkTransStatus() {
	// 'static' member variables to keep track of how many times function has run, as well as current language:
	if((typeof checkTransStatus.chkStatusCount == 'undefined') || (checkTransStatus.curTransLang != GL_curLang)) {
		// reset variables if not defined yet, or if site language has changed since last function call
        	checkTransStatus.chkStatusCount = 0;
		checkTransStatus.curTransLang = GL_curLang;
	}

	// if translation is now complete, end function.
	if(GL_curChunk >= GL_chunksTotal) {
		return;
	}
	
	checkTransStatus.chkStatusCount++; // increment Translation Status counter

	// Store the list of languages in case they are replaced during translation
	var langList = document.getElementById("mlt_languagelist").innerHTML;

	var curElement; var curTransChunk = 0; var curClass = 0; var curTransLang = GL_transContent.length-1;

	// loop through all element IDs (as specified at script top), searching for ones with completed translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,false);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), searching for completed translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],false);
				curClass++; // move to next element Class Name
			}
		}
	}

	// if listbox containing all languages has been removed as a result of translation, display it again
	if(document.getElementById("mlt_languagelist").innerHTML == "") {
		document.getElementById("mlt_languagelist").innerHTML = langList;
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to show current language
	}

	/* if translation still isn't complete after 30 seconds, update translation message. Note: there is no
	   need to halt the current translation completely, but we will allow user to restart it if desired! */
	if(checkTransStatus.chkStatusCount == 30) {
		// calculate and display percentage of translation completed, based on number of chunks remaining
		var perc = Math.round((GL_curChunk / GL_chunksTotal)*100) + "%";
		// update translation status message
		document.getElementById("mlt_translatemsg").innerHTML = 'Translating (Slowly!)... ' +
		'<span id="mlt_perc">' + perc + '</span> - <a href="javascript:refresh()">Retry</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	}

	setTimeout("checkTransStatus()", 1000); // check translation status again after another second
}

// runs after all translations have been completed; displaying the results on screen in place of previous content
function endTranslation(curTransLang) {
	var curElement;
	var curTransChunk = 0; var curClass = 0;

	// loop through all element IDs (as specified at script top), replacing current contents with translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,true,GL_classIds[i]);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), so contents can be replaced by translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],true,GL_classNames[i]);
				curClass++; // move to next element Class Name
			}
		}
	}

	// Perform translations of all content added by the script (e.g. language strings and error messages)
	transAddedText();

	// Re-create listbox containing all languages, in case it has been removed as a result of translation
	getLangs();

	// translate the 'Original Languages' listbox item to equivalent in current site language
	miniTranslate(document.getElementById("mlt_language").options[0],GL_curLang,"Original Languages");
	
	// if any errors occured during translation, display warning message at top of screen and end function 
	if(GL_errors.length != 0) {
		document.getElementById("mlt_translatemsg").innerHTML = GL_errors.length + ' Problems(s) Occurred During Translation: ' +
		'<a href="javascript:refresh()">Retry</a> - <a href="javascript:showErrDetails()">Details</a> - ' +
		'<a href="javascript:hideTransMsg()">Hide</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate warning message into current site language
		return;
	}
	
	// mark translation of page into current language as complete, so that translation can be quicker next time.
	GL_transContent[curTransLang][2] = true;

	hideTransMsg(); // otherwise, hide 'Translating...' message
}

// assemble and display translated chunks for current element on page
function unpackTransChunks(curTransLang,curTransChunk,curClassNum,curElement,transComplete,curClass) {
	// 'static' member variable to keep track of how many times function has run
	if(typeof unpackTransChunks.curLinkId == 'undefined') {
		// reset curLinkId variable if not defined yet - it's used to identify the correct 'show source text' link
        	unpackTransChunks.curLinkId = 0;
	} unpackTransChunks.curLinkId++; var j = unpackTransChunks.curLinkId; // increment current link id, j is an alias

	var curContent = ""; // reset translated contents of current element
	var initTransChunk = curTransChunk; // store initial chunk id of current element

	// loop through all translated chunks, assembling all translated content for current element
	for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
		// if current chunk does not exist, translation is not complete or errors occurred
		if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == false)) {
			break; // stop looping through chunks if full translation has not yet been completed
		} else if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == true)) {
			// if full translation IS complete, show warning message and a link to show source text (in red)
			curContent += '<div style="color: red;" id="mlt_srctxt' + j + '">[<span class="mlt_transerrtxt">' +
			'<em style="text-transform: uppercase;">THIS SECTION COULD NOT BE TRANSLATED</em> - '+
			'<a id="mlt_srctxtlnk' + j + '" href="javascript:showSrcTxt(' + j + ',' + curClassNum + ',' + (i+1) + 
			')">View Source Text [+]</a></span><span id="mlt_srctxtbracket' + j + '">]</span></div>';
			GL_errSrcTxt[GL_errSrcTxt.length] = GL_srcContent[curClassNum][i]; // store affected source text
			unpackTransChunks.curLinkId++; j = unpackTransChunks.curLinkId; // increment current link id		
		} else {
			// otherwise append current translated chunk to translated content string
			curContent += GL_transContent[curTransLang][0][curTransChunk][0];
		}
		curTransChunk++; // move to next chunk
	}

	// if translation is complete, replace contents of current element with translated text
	if(transComplete == true) {
		curElement.innerHTML = curContent;
		// append a language string to bottom of current element if desired
		getLangString(curTransLang,curElement,curClass,initTransChunk,(GL_srcContent[curClassNum].length - 1),j,curClassNum);
	// otherwise, check if all translated chunks for current element were assembled
	} else if((i == (GL_srcContent[curClassNum].length - 1)) && (GL_transContent[curTransLang][0][initTransChunk][2] != true)) {			
		// if so (and current element translation is not yet marked as complete), replace contents with translation
		curElement.innerHTML = curContent;
		GL_transContent[curTransLang][0][initTransChunk][2] = true; // mark current element translation as complete
	}

	return curTransChunk; // return current chunk id to calling function
}

// If required, find and append a string containing the Source Language to the bottom of the specified element
function getLangString(curTransLang,curElement,curClass,curTransChunk,transChunksLen,j,curClassNum) {
	
	var detectedLang = "";

	// if the current element does not need a language string appended, end function
	if(curClass[2] != true) {
		return;
	}

	// if source language for current element has already been manually specified, set this as detected language
	if(curClass[1] != "") {
		detectedLang = curClass[1];
	}
	// otherwise find out language based on the detected source languages for translated chunks in current element 
	else {
		detectedLang = findDetectedLang(curTransLang,curTransChunk,transChunksLen);
	}

	// if detected language is same as site language, there is no need to display language string, so end function
	if(detectedLang == GL_curLang){
			return;
	}

	var srcLangString = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string 

	// append language string to current element...
//	curElement.innerHTML += '<div style="color: green;" id="mlt_srctxt' + j + '"></div>';
}

// convert a google language code into a formatted string containing the language name
function getFmtLangStr(lang) {
	// loop through list of supported languages and retrieve names
	for(var l in google.language.Languages) {
		if(google.language.Languages[l] == lang) {
			// convert language string into title case
			var lang = l.substr(0,1) + l.substr(1).toLowerCase();
			// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
			lang = lang.split("_").join(" - ");
			break; // stop loop (don't need to continue searching for languages)
		}
	}
	// if language cannot be found in list of supported languages, set language to 'unknown'
	if(typeof lang == "undefined") {
		lang = "An Unknown Language";
	}
	return lang; // return formatted language string
}

// find out the most common detected language for all translated chunks in current element, to appear in language string
function findDetectedLang(curTransLang,curTransChunk,transChunksLen) {
	var chunkLangs = []; langCounter = 0;

	// loop through all translated chunks in current element
	for(var i = 0; i < transChunksLen; i++) {
		// bugfix: set detected language to 'undefined' if an error occurred during translation... 
		if(GL_transContent[curTransLang][0][curTransChunk] == null) {
			GL_transContent[curTransLang][0][curTransChunk] = new Array(3);
			GL_transContent[curTransLang][0][curTransChunk][1] = "undefined";	
		}
		// loop through array of detected languages to see if current chunk has an existing detected language
		for(var j = 0; j < chunkLangs.length; j++) {
			if(chunkLangs[j][0] == GL_transContent[curTransLang][0][curTransChunk][1]) {
				// if so, increment counter containing the total number of chunks with that language
				chunkLangs[j][1]++;
				break; // halt loop
			}
		}
		// if current chunk has a language not yet detected, add it to end of detected languages array
		if(j == chunkLangs.length) {
			chunkLangs[j] = new Array(2);
			chunkLangs[j][0] = GL_transContent[curTransLang][0][curTransChunk][1]; // name of detected language
			chunkLangs[j][1] = 1; // total number of chunks with that language
		}
		curTransChunk++; // move to next chunk
	}

	/* once array has been created containing all detected languages in current element, loop through it
	to find the most common detected language - language string should contain this */
	for(i = 0; i < chunkLangs.length; i++) {
		if(chunkLangs[i][1] > langCounter) {
			/* if current language was detected more times than all previous languages, store language
			and number of times detected - so that next language can be compared against this total */
			var detectedLang = chunkLangs[i][0];
			langCounter = chunkLangs[i][1];
		}		
	}
	
	return detectedLang; // return the most common detected language
}

// Auto-translate all text added previously by the script (including language strings and error messages)
function transAddedText() {
	var allElements = document.getElementsByTagName("*"); // get all elements on page, so relevant ones can be translated
	var foundElements = [];

	// loop through all elements to find any of class 'mlt_langstring' or 'mlt_transerrtxt' 
	for(var i=0; i<allElements.length; i++) {
		if((allElements[i].className == "mlt_langstring") || (allElements[i].className == "mlt_transerrtxt")) {
			foundElements[foundElements.length] = allElements[i];
		}
	}

	// translate all located elements (runs separately from above code to prevent infinite loop as items are translated)
	for(i = 0; i < foundElements.length; i++) {
		miniTranslate(foundElements[i]); // translate current element
	}
}

/* this function runs before any translation takes place, and creates a local 'cache' of all content to be translated (in chunks)
   - meaning the content can be submitted to Google more rapidly, and the resulting translations can then be sorted reliably */
function buildChunkedContent() {
	var curElement; GL_srcContent = []; var j = 0;

	/* loop through all applicable element IDs (as specified at script top), converting the contents of each into chunks,
	   and storing each chunk in an array */
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element
		// check that element actually exists on the page - if not, ignore it
		if(curElement != null) {
			GL_srcContent[j] = createChunks(curElement); // separate the content of current element into chunks
			GL_chunksTotal += GL_srcContent[j].length;   // store a running total of the number of chunks created

			// if a Source Language is not specified for current element, store Base Language in array instead
			if(GL_classIds[i].length == 1) {
				GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
			} else {
				// otherwise store the specified language (or a blank string if this is to be auto-detected)
				GL_srcContent[j][GL_srcContent[j].length] = GL_classIds[i][1];
			}
			j++;
		}
	}

	// get all elements on page, so that the ones specified can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all applicable element IDs (as specified at script top), converting into chunks and storing in array
	for(var i = 0; i < GL_classNames.length; i++) {
		// find all elements which have the current class name
		for(var k = 0; k < allElements.length; k++) { 
			if(allElements[k].className == GL_classNames[i][0]) {
				// separate the content of current element into chunks
				GL_srcContent[j] = createChunks(allElements[k]);
				// store a running total of the number of chunks created
				GL_chunksTotal += GL_srcContent[j].length;

				// if a Source Language is not specified for current element, store Base Language in array
				if(GL_classNames[i].length == 1) {
					GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
				} else {
					// otherwise store specified language (or a blank string if auto-detected)
					GL_srcContent[j][GL_srcContent[j].length] = GL_classNames[i][1];
				}
				j++;
			}
		}
	}
}

/* Web browsers (and Google) limit the amount of text translated per request, so split contents of current element into chunks.
   The aim is to achieve this whilst maintaining the translation integrity */
function createChunks(srcContent) {	
	var chars = 1000; // number of characters to allow per chunk.

	/* We do NOT want the content inside any HTML tag to be split between chunks (as this could cause 
	rendering problems), so create 2 arrays storing tags and textual content of current div separately */
	var tags = srcContent.innerHTML.match(/<.*?>/g);
	var text = srcContent.innerHTML.split(/<.*?>/g);
	if(tags == null) {
		tags = new Array();} // handle content containing no tags

	var curchar = 0; var tagnum = 0; var textnum = 0; var contTotal = tags.length + text.length;
	// create an array containing content to be chunked, with tags + text separately re-assembled (in order)
	var content = new Array(contTotal);
	// loop through content of current div
	for(var i=0; i < contTotal; i++) {
		// if current position in content is the start of a tag char, add appropriate tag to content array
		if(srcContent.innerHTML.substr(curchar,1) == "<") {
			content[i] = tags[tagnum];
			curchar += tags[tagnum].length;
			tagnum++;
		// if it is a text string, add the corresponding text to the curent element in content array
		} else {
			content[i] = text[textnum];
			curchar += text[textnum].length;
			textnum++;
		}
	}

	// Create the chunks - don't split either tags or words (to ensure as high translation quality as possible)
	var chunks = []; var curChunk = 0;
	chunks[0]="";
	for (i = 0; i < contTotal; i++) {
		// if next content item (tag or textual) won't exceed length of current chunk, add it to chunk
		if((chunks[curChunk].length + content[i].length) < chars) {
			chunks[curChunk] += content[i];
		} else {
			// otherwise, proceed to next chunk.
			curChunk++;
			// add the entire content item to this chunk if possible (to ensure better translation)
			if(content[i].length < chars) {
				chunks[curChunk] = content[i];
			}
			else {
				// only split further in rare cases where text length exceeds maximum chunk size
				var curPos = 0;
				do {
					// retrieve the maximum amount of text that can fit in this chunk
					var subContent = content[i].substr(curPos,chars);
					// find out how many words are in this substring
					var words = subContent.split(" ");
					// chop off final word, so words aren't split up between chunks
					var lastWordPos = subContent.length - words[(words.length-1)].length;
					if(subContent.length < chars) { // [bugfix: prevent word cut-off on final iteration]
						lastWordPos = subContent.length}
					chunks[curChunk] = subContent.substr(0,lastWordPos); // store in chunk
					curChunk++; // remainder of text will go in next chunk
					curPos+=lastWordPos; // store current position in text, for further processing
				} while(subContent.length >= chars); // repeat until all this text has been chunked
				curChunk--; // because there may still be space in the current chunk!
			}
		}
	}		
	
	return chunks; // return chunked content to calling function...
}

// Append elements to page (will be used to display translation messages), and specify their css styles.
function addTransMsgs() {
	// add element to page which will contain translation messages
	var transCont = document.createElement("div");
	document.body.appendChild(transCont);
	
	// add element to container created above - this will display the translation messages
	var translateMsg = document.createElement("div");
	translateMsg.id = "mlt_translatemsg";
	transCont.appendChild(translateMsg);

	// define visual styles for translation messages displayed on screen
	translateMsg.style.backgroundColor = "silver";
	translateMsg.style.border = "3px green solid";
	translateMsg.style.padding = "5px";
	translateMsg.style.fontSize = "large";
	translateMsg.style.fontWeight = "bold";
	translateMsg.style.textAlign = "left";
	translateMsg.style.color = "black";

	// more translation message styles (these should not need editing!)
	translateMsg.style.left = "-50%";
	translateMsg.style.position = "relative";
	translateMsg.style.display = "none";
	
	// define the styles for the container element
	transCont.style.left = "50%";
	transCont.style.zIndex = "1000";
	if(!(/MSIE 6/i.test(navigator.userAgent))) {
		// styles for all browsers except IE6
		transCont.style.position = "fixed";
		transCont.style.top = "0px";
	}
	else {
		// styles for IE6
		transCont.style.position = "absolute";
		transCont.style.setExpression("top", "(i = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
	}
}

// Hide 'Translating...' message (or translation error message) - runs at end of translation, or if user dismisses error message
function hideTransMsg() {
	document.getElementById("mlt_translatemsg").innerHTML = "";
	document.getElementById("mlt_translatemsg").style.display='none';
}

// if the user clicks on the 'Details' link [after error(s) occurred], show details of all errors on screen
function showErrDetails() {
	// continue to show original error message (but remove 'Details' link)
	document.getElementById("mlt_translatemsg").innerHTML = '<span id="mlt_transerrmsg1">' + GL_errors.length + 
	' Problems(s) Occurred During Translation: ' + '<a href="javascript:refresh()">Retry</a> - ' +
	'<a href="javascript:hideTransMsg()">Hide</a>... <br /><em>Error(s) Reported:</em></span>' +
	'<ul style="margin: 0px; padding: 0px;" id="mlt_transerrlist"></ul>';

	// Loop through array containing details of all errors, and show them as a list on screen
	for(var i = 0; i < GL_errors.length; i++) {
		document.getElementById("mlt_transerrlist").innerHTML += '<li style="margin-left: 15px;">' + GL_errors[i] + '.</li> ';	
	}

	/* create a textarea - this will show the original source text of all affected sections (as HTML) to aid debugging
	   Note: because translations are returned using AJAX, the affected sections are not NECESSARILY in the same order as
	   the errors reported (though in many cases, they will be!) */
	document.getElementById("mlt_translatemsg").innerHTML += '<em id="mlt_transerrmsg2">Section(s) Affected:</em><br />' +
	'<textarea id="mlt_errsrctxt" rows="8" readonly="readonly" style="width: 99%; background-color: silver; border: 1px gray solid;">' +
	'</textarea>';

	// Loop through Source Text array, appending to textarea.
	for(var i = 0; i < GL_errSrcTxt.length; i++) {
		document.getElementById("mlt_errsrctxt").value += "Affected Section " + (i+1) + ":\n" + GL_errSrcTxt[i] + "\n\n";
	}

	// Translate the entire contents of the Translation Errors box (with the exception of the text inside the textarea)
	miniTranslate(document.getElementById("mlt_transerrmsg1")); miniTranslate(document.getElementById("mlt_transerrlist"));
	miniTranslate(document.getElementById("mlt_transerrmsg2"));
}

// function runs when the user clicks on a link to view the original source text for a translated element / chunk
function showSrcTxt(curLinkId,curClassNum,curChunkId) {
	// if the current chunk should be shown only, display chunk on screen
	if((curChunkId-1) != -1) {
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+GL_srcContent[curClassNum][(curChunkId-1)]+']</div>';
	} else {
	// otherwise assemble all chunks for current element, and display on screen
		var srcTxt = "";
		for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
			srcTxt +=  GL_srcContent[curClassNum][i];
		}
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+srcTxt+']</div>';
	}	

	// update Source Text link so that when clicked in future, the source text will be hidden instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "Hide Source Text [-]";
	srcTxtLnk.href = 'javascript:hideSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = ""; // hide bracket after link
}

// function runs when the user clicks on a link to hide the original source text for a translated element / chunk
function hideSrcTxt(curLinkId,curClassNum,curChunkId) {
	// remove the element containing the original source text
	srcTxtContent = document.getElementById("mlt_srctxtcontent"+curLinkId);
	document.getElementById("mlt_srctxt"+curLinkId).removeChild(srcTxtContent);

	// update Source Text link so that when clicked in future, the source text will be shown instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "View Source Text [+]";
	srcTxtLnk.href = 'javascript:showSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = "]"; // show bracket after link
}

// translate small non crucial items of text into current site language
function miniTranslate(item,destLang,srcTxt) {
	if(typeof destLang == "undefined") {
		var destLang = GL_curLang; // if the destLang argument was not specified, use the current site language
	}
	if(typeof srcTxt == "undefined") {
		var srcTxt = item.innerHTML; // if the srcText argument was not specified, use the current item contents
	}

	// loop through translated items array to see if a translation for current text already exists since page loaded
	for(var i = 0; i < GL_miniTransItems.length; i++) {
		// check if source text and destination language match a translated item (and a completed translation exists for it)
		if((GL_miniTransItems[i][1] == srcTxt) && (GL_miniTransItems[i][2] == destLang) && (GL_miniTransItems[i][3] != "")) {
			item.innerHTML = GL_miniTransItems[i][3]; // if so, display existing translation in item
			item.title = srcTxt.split(/<.*?>/g).join(""); // display English source text as a tooltip (strip HTML first)
			return; // Don't need to send a translation request to Google, so end function.
		}
	}

	// store item to be translated in global array for access by callback function
	GL_miniTransItems[GL_miniTransItems.length]	   = new Array(4);
	GL_miniTransItems[(GL_miniTransItems.length-1)][0] = item;
	GL_miniTransItems[(GL_miniTransItems.length-1)][1] = srcTxt;
	GL_miniTransItems[(GL_miniTransItems.length-1)][2] = destLang;
	GL_miniTransItems[(GL_miniTransItems.length-1)][3] = "";

	// create source text by adding current item ID to start of item text (ID will ensure correct item is translated)
	srcTxt = (GL_miniTransItems.length-1) + "<br />" + srcTxt;

	google.language.translate(srcTxt, "en", destLang, function(result) {
        	if (!result.error) {
			// split into array based on separator, so we know the id of translated item
			var transChunk = result.translation.split("<br />");
			// [find out length of substring to chop off from start of item]
			var chunkSubStr = 6 + transChunk[0].length;
			// remove whitespace from item id (a problem with some translations)
			transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");

			// display english source text of translated item (with HTML stripped) if user hovers mouse over it
			var strippedSrcTxt = GL_miniTransItems[transChunk[0]][1].split(/<.*?>/g).join("");
			GL_miniTransItems[transChunk[0]][0].title = "[" + strippedSrcTxt  + "]";

			// store and display translation of specified item (stripping item ID from start of text)
			GL_miniTransItems[transChunk[0]][3] = result.translation.substr(chunkSubStr);
			GL_miniTransItems[transChunk[0]][0].innerHTML = GL_miniTransItems[transChunk[0]][3];
        	}
	});
}

// runs when the user changes the site language
function changeLang(destLang) {
	if(typeof destLang != "undefined") {
		GL_curLang = destLang; // if the destLang argument was specified, set new site language to this
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to display new site language
	} else {
		// otherwise get the new language requested by user
		GL_curLang = document.getElementById("mlt_language").value;
	}

	// store the requested language in a cookie
	setLangCookie();
	
	// if the original site languages should be shown, refresh the page.
	if(GL_curLang == "orig") {
		refresh();
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// find out the value of the language cookie (if it exists)
function getLangCookie() {
	var curStoredLang;
	// retrieve a list of cookies for this page, split into array elements (separated by ; if multiple cookies)
	var getCurLang=document.cookie.split(";");
	// loop through all array elements (i.e. cookies) until one with name 'lang' is found.
	for(var i=0; i < getCurLang.length; i++) {

		// remove whitespace from cookies (a problem if there are multiple cookies)
		var lngCookie = getCurLang[i].replace(/^\s+|\s+$/g,"");

		if(lngCookie.indexOf("lang=") == 0) {
			// find out value of lang
			curStoredLang = lngCookie.substring(5);
		}
	}
	
	// if language cookie exists, set current site language to stored value
	if(typeof curStoredLang != "undefined") {
		GL_curLang = curStoredLang;
	// otherwise, check if an initial language has been specified
	} else if((GL_curLang == "") || (typeof GL_curLang == "undefined")) {
		detectUserLang(); // if not, find out user's language based on their settings, and offer to translate into that language
		GL_curLang = "orig"; // show site using original languages for now
		return; // don't want to store language in cookie until one has been specified, so end function
	}

	setLangCookie(); // if valid cookie exists or initial language was specified, set/renew cookie (to store new expiry date)
}

// If a new user has not specified a language yet, offer to translate page into their current browser / system language
function detectUserLang(){
	/* detect user's current language (if they are using IE this will be based on the regional settings on their system; 
	   otherwise it will be based on the default language of their current browser) */
	var detectedLang = (navigator.language) ? navigator.language : navigator.userLanguage;
	
	// if language cannot be detected for some reason, end function.
	if((typeof detectedLang == "undefined") || (detectedLang == ""))  {
		return;
	}
	
	// if language is regional dialect (e.g. "en-gb"), check last 2 letters are upper case - for google compatibility.
	if(detectedLang.length == 5) {
		detectedLang = detectedLang.substr(0,3) + detectedLang.substr(3).toUpperCase();
	}
	
	// check that Google can translate content into detected language
	if (!google.language.isTranslatable(detectedLang)) {
		// if not, check if language is a regional dialect (e.g. "en-GB")
		if(detectedLang.length == 5) {
			// if so, Google may still be able to translate into a non-regional equivalent (e.g. "en")
			detectedLang = detectedLang.substr(0,2);
			if (!google.language.isTranslatable(detectedLang)) {
				return; // google cannot translate into non-regional equivalent, so end function
			}
		// language is not a regional dialect, and google cannot translate into it, so end function
		} else {
			return;
		}
	}
	
	var detectedLangStr = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
	
	/*
	// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  'Translate this page into ' + detectedLangStr + '? ' +
	'<a href="javascript:changeLang(\'' + detectedLang + '\')">Yes</a> | <a href="javascript:changeLang(\'orig\')">No</a>';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='block'; // show the question on screen
	*/
	
	
		// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  '';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='none'; // show the question on screen
}

// create a cookie to store the current site language
function setLangCookie() {
	// expire previous cookie (if it exists)
	document.cookie = "lang=; expires=-1; path=/";

	// cookie will expire after 90 days.
	var expdate = new Date();
	expdate.setTime(expdate.getTime()+7776000000);

	// create the cookie
	document.cookie = "lang=" + GL_curLang + "; expires=" + expdate.toGMTString() + "; path=/";
}

// refresh the current page [runs if the Original Languages option was selected, or if requested by user after error(s)]
function refresh() {
	hideTransMsg();
	window.location.reload(true);
}

// run the 'initialise' function once the page has loaded.
google.setOnLoadCallback(initialise);

****************The End*****************************


*****************Save it as googlelanguage.js******************


if (!window['google']) {
window['google'] = {};
}
if (!window['google']['loader']) {
window['google']['loader'] = {};
google.loader.ServiceBase = 'http://www.google.com/uds';
google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax';
google.loader.ApiKey = 'notsupplied';
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.Secure = false;
google.loader.GoogleLocale = 'www.google.com';
google.loader.ClientLocation = {"latitude":17.385044,"longitude":78.486671,"address":{"city":"Hyderabad","region":"Andhra Pradesh","country":"India","country_code":"IN"}};
google.loader.AdditionalParams = '';
(function() {var d=true,g=null,h=false,j=encodeURIComponent,l=window,n=undefined,o=document;function p(a,b){return a.load=b}var q="push",r="replace",s="charAt",t="ServiceBase",u="name",v="getTime",w="length",x="prototype",y="setTimeout",z="loader",A="substring",B="join",C="toLowerCase";function D(a){if(a in E)return E[a];return E[a]=navigator.userAgent[C]().indexOf(a)!=-1}var E={};function F(a,b){var c=function(){};c.prototype=b[x];a.Q=b[x];a.prototype=new c}
function G(a,b){var c=Array[x].slice.call(arguments,2)||[];return function(){var e=c.concat(Array[x].slice.call(arguments));return a.apply(b,e)}}function H(a){a=Error(a);a.toString=function(){return this.message};return a}function I(a,b){for(var c=a.split(/\./),e=l,f=0;f<c[w]-1;f++){e[c[f]]||(e[c[f]]={});e=e[c[f]]}e[c[c[w]-1]]=b}function J(a,b,c){a[b]=c}if(!K)var K=I;if(!L)var L=J;google[z].t={};K("google.loader.callbacks",google[z].t);var M={},N={};google[z].eval={};K("google.loader.eval",google[z].eval);
p(google,function(a,b,c){function e(k){var m=k.split(".");if(m[w]>2)throw H("Module: '"+k+"' not found!");else if(typeof m[1]!="undefined"){f=m[0];c.packages=c.packages||[];c.packages[q](m[1])}}var f=a;c=c||{};if(a instanceof Array||a&&typeof a=="object"&&typeof a[B]=="function"&&typeof a.reverse=="function")for(var i=0;i<a[w];i++)e(a[i]);else e(a);if(a=M[":"+f]){if(c&&!c.language&&c.locale)c.language=c.locale;if(c&&typeof c.callback=="string"){i=c.callback;if(i.match(/^[[\]A-Za-z0-9._]+$/)){i=l.eval(i);
c.callback=i}}if((i=c&&c.callback!=g)&&!a.s(b))throw H("Module: '"+f+"' must be loaded before DOM onLoad!");else if(i)a.m(b,c)?l[y](c.callback,0):a.load(b,c);else a.m(b,c)||a.load(b,c)}else throw H("Module: '"+f+"' not found!");});K("google.load",google.load);
google.P=function(a,b){if(b){if(O[w]==0){P(l,"load",Q);if(!D("msie")&&!(D("safari")||D("konqueror"))&&D("mozilla")||l.opera)l.addEventListener("DOMContentLoaded",Q,h);else if(D("msie"))o.write("<script defer onreadystatechange='google.loader.domReady()' src=//:><\/script>");else(D("safari")||D("konqueror"))&&l[y](S,10)}O[q](a)}else P(l,"load",a)};K("google.setOnLoadCallback",google.P);
function P(a,b,c){if(a.addEventListener)a.addEventListener(b,c,h);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var e=a["on"+b];a["on"+b]=e!=g?aa([c,e]):c}}function aa(a){return function(){for(var b=0;b<a[w];b++)a[b]()}}var O=[];google[z].K=function(){var a=l.event.srcElement;if(a.readyState=="complete"){a.onreadystatechange=g;a.parentNode.removeChild(a);Q()}};K("google.loader.domReady",google[z].K);var ba={loaded:d,complete:d};function S(){if(ba[o.readyState])Q();else O[w]>0&&l[y](S,10)}
function Q(){for(var a=0;a<O[w];a++)O[a]();O.length=0}
google[z].d=function(a,b,c){if(c){var e;if(a=="script"){e=o.createElement("script");e.type="text/javascript";e.src=b}else if(a=="css"){e=o.createElement("link");e.type="text/css";e.href=b;e.rel="stylesheet"}(a=o.getElementsByTagName("head")[0])||(a=o.body.parentNode.appendChild(o.createElement("head")));a.appendChild(e)}else if(a=="script")o.write('<script src="'+b+'" type="text/javascript"><\/script>');else a=="css"&&o.write('<link href="'+b+'" type="text/css" rel="stylesheet"></link>')};
K("google.loader.writeLoadTag",google[z].d);google[z].M=function(a){N=a};K("google.loader.rfm",google[z].M);google[z].O=function(a){for(var b in a)if(typeof b=="string"&&b&&b[s](0)==":"&&!M[b])M[b]=new T(b[A](1),a[b])};K("google.loader.rpl",google[z].O);google[z].N=function(a){if((a=a.specs)&&a[w])for(var b=0;b<a[w];++b){var c=a[b];if(typeof c=="string")M[":"+c]=new U(c);else{c=new V(c[u],c.baseSpec,c.customSpecs);M[":"+c[u]]=c}}};K("google.loader.rm",google[z].N);
google[z].loaded=function(a){M[":"+a.module].k(a)};K("google.loader.loaded",google[z].loaded);google[z].J=function(){return"qid="+((new Date)[v]().toString(16)+Math.floor(Math.random()*1E7).toString(16))};K("google.loader.createGuidArg_",google[z].J);I("google_exportSymbol",I);I("google_exportProperty",J);google[z].b={};K("google.loader.themes",google[z].b);google[z].b.z="http://www.google.com/cse/style/look/bubblegum.css";L(google[z].b,"BUBBLEGUM",google[z].b.z);google[z].b.B="http://www.google.com/cse/style/look/greensky.css";
L(google[z].b,"GREENSKY",google[z].b.B);google[z].b.A="http://www.google.com/cse/style/look/espresso.css";L(google[z].b,"ESPRESSO",google[z].b.A);google[z].b.D="http://www.google.com/cse/style/look/shiny.css";L(google[z].b,"SHINY",google[z].b.D);google[z].b.C="http://www.google.com/cse/style/look/minimalist.css";L(google[z].b,"MINIMALIST",google[z].b.C);function U(a){this.a=a;this.q=[];this.p={};this.i={};this.e={};this.l=d;this.c=-1}
U[x].g=function(a,b){var c="";if(b!=n){if(b.language!=n)c+="&hl="+j(b.language);if(b.nocss!=n)c+="&output="+j("nocss="+b.nocss);if(b.nooldnames!=n)c+="&nooldnames="+j(b.nooldnames);if(b.packages!=n)c+="&packages="+j(b.packages);if(b.callback!=g)c+="&async=2";if(b.style!=n)c+="&style="+j(b.style);if(b.other_params!=n)c+="&"+b.other_params}if(!this.l){if(google[this.a]&&google[this.a].JSHash)c+="&sig="+j(google[this.a].JSHash);var e=[];for(var f in this.p)f[s](0)==":"&&e[q](f[A](1));for(f in this.i)f[s](0)==
":"&&this.i[f]&&e[q](f[A](1));c+="&have="+j(e[B](","))}return google[z][t]+"/?file="+this.a+"&v="+a+google[z].AdditionalParams+c};U[x].v=function(a){var b=g;if(a)b=a.packages;var c=g;if(b)if(typeof b=="string")c=[a.packages];else if(b[w]){c=[];for(a=0;a<b[w];a++)typeof b[a]=="string"&&c[q](b[a][r](/^\s*|\s*$/,"")[C]())}c||(c=["default"]);b=[];for(a=0;a<c[w];a++)this.p[":"+c[a]]||b[q](c[a]);return b};
p(U[x],function(a,b){var c=this.v(b),e=b&&b.callback!=g;if(e)var f=new W(b.callback);for(var i=[],k=c[w]-1;k>=0;k--){var m=c[k];e&&f.F(m);if(this.i[":"+m]){c.splice(k,1);e&&this.e[":"+m][q](f)}else i[q](m)}if(c[w]){if(b&&b.packages)b.packages=c.sort()[B](",");for(k=0;k<i[w];k++){m=i[k];this.e[":"+m]=[];e&&this.e[":"+m][q](f)}if(!b&&N[":"+this.a]!=g&&N[":"+this.a].versions[":"+a]!=g&&!google[z].AdditionalParams&&this.l){c=N[":"+this.a];google[this.a]=google[this.a]||{};for(var R in c.properties)if(R&&
R[s](0)==":")google[this.a][R[A](1)]=c.properties[R];google[z].d("script",google[z][t]+c.path+c.js,e);c.css&&google[z].d("css",google[z][t]+c.path+c.css,e)}else if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),e);if(this.l){this.l=h;this.c=(new Date)[v]();if(this.c%100!=1)this.c=-1}for(k=0;k<i[w];k++){m=i[k];this.i[":"+m]=d}}});
U[x].k=function(a){if(this.c!=-1){X("al_"+this.a,"jl."+((new Date)[v]()-this.c),d);this.c=-1}this.q=this.q.concat(a.components);google[z][this.a]||(google[z][this.a]={});google[z][this.a].packages=this.q.slice(0);for(var b=0;b<a.components[w];b++){this.p[":"+a.components[b]]=d;this.i[":"+a.components[b]]=h;var c=this.e[":"+a.components[b]];if(c){for(var e=0;e<c[w];e++)c[e].I(a.components[b]);delete this.e[":"+a.components[b]]}}X("hl",this.a)};U[x].m=function(a,b){return this.v(b)[w]==0};U[x].s=function(){return d};
function W(a){this.H=a;this.n={};this.r=0}W[x].F=function(a){this.r++;this.n[":"+a]=d};W[x].I=function(a){if(this.n[":"+a]){this.n[":"+a]=h;this.r--;this.r==0&&l[y](this.H,0)}};function V(a,b,c){this.name=a;this.G=b;this.o=c;this.u=this.h=h;this.j=[];google[z].t[this[u]]=G(this.k,this)}F(V,U);p(V[x],function(a,b){var c=b&&b.callback!=g;if(c){this.j[q](b.callback);b.callback="google.loader.callbacks."+this[u]}else this.h=d;if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),c);X("el",this[u])});V[x].m=function(a,b){return b&&b.callback!=g?this.u:this.h};V[x].k=function(){this.u=d;for(var a=0;a<this.j[w];a++)l[y](this.j[a],0);this.j=[]};
var Y=function(a,b){return a.string?j(a.string)+"="+j(b):a.regex?b[r](/(^.*$)/,a.regex):""};V[x].g=function(a,b){return this.L(this.w(a),a,b)};
V[x].L=function(a,b,c){var e="";if(a.key)e+="&"+Y(a.key,google[z].ApiKey);if(a.version)e+="&"+Y(a.version,b);b=google[z].Secure&&a.ssl?a.ssl:a.uri;if(c!=g)for(var f in c)if(a.params[f])e+="&"+Y(a.params[f],c[f]);else if(f=="other_params")e+="&"+c[f];else if(f=="base_domain")b="http://"+c[f]+a.uri[A](a.uri.indexOf("/",7));google[this[u]]={};if(b.indexOf("?")==-1&&e)e="?"+e[A](1);return b+e};V[x].s=function(a){return this.w(a).deferred};
V[x].w=function(a){if(this.o)for(var b=0;b<this.o[w];++b){var c=this.o[b];if(RegExp(c.pattern).test(a))return c}return this.G};function T(a,b){this.a=a;this.f=b;this.h=h}F(T,U);p(T[x],function(a,b){this.h=d;google[z].d("script",this.g(a,b),h)});T[x].m=function(){return this.h};T[x].k=function(){};
T[x].g=function(a,b){if(!this.f.versions[":"+a]){if(this.f.aliases){var c=this.f.aliases[":"+a];if(c)a=c}if(!this.f.versions[":"+a])throw H("Module: '"+this.a+"' with version '"+a+"' not found!");}c=google[z].GoogleApisBase+"/libs/"+this.a+"/"+a+"/"+this.f.versions[":"+a][b&&b.uncompressed?"uncompressed":"compressed"];X("el",this.a);return c};T[x].s=function(){return h};var ca=h,Z=[],da=(new Date)[v](),X=function(a,b,c){if(!ca){P(l,"unload",ea);ca=d}if(c){if(!google[z].Secure&&(!google[z].Options||google[z].Options.csi===h)){a=a[C]()[r](/[^a-z0-9_.]+/g,"_");b=b[C]()[r](/[^a-z0-9_.]+/g,"_");l[y](G($,g,"http://csi.gstatic.com/csi?s=uds&v=2&action="+j(a)+"&it="+j(b)),1E4)}}else{Z[q]("r"+Z[w]+"="+j(a+(b?"|"+b:"")));l[y](ea,Z[w]>5?0:15E3)}},ea=function(){if(Z[w]){$(google[z][t]+"/stats?"+Z[B]("&")+"&nc="+(new Date)[v]()+"_"+((new Date)[v]()-da));Z.length=0}},$=function(a){var b=
new Image,c=fa++;ga[c]=b;b.onload=b.onerror=function(){delete ga[c]};b.src=a;b=g},ga={},fa=0;I("google.loader.recordStat",X);I("google.loader.createImageForLogging",$);

}) ();google.loader.rm({"specs":[{"name":"books","baseSpec":{"uri":"http://books.google.com/books/api.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}}}},"feeds",{"name":"friendconnect","baseSpec":{"uri":"http://www.google.com/friendconnect/script/friendconnect.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{}}},"spreadsheets","gdata","visualization",{"name":"sharing","baseSpec":{"uri":"http://www.google.com/s2/sharing/js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{"language":{"string":"hl"}}}},"search",{"name":"maps","baseSpec":{"uri":"http://maps.google.com/maps?file\u003dgoogleapi","ssl":"https://maps-api-ssl.google.com/maps?file\u003dgoogleapi","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"regex":"callback\u003d$1\u0026async\u003d2"},"language":{"string":"hl"}}},"customSpecs":[{"uri":"http://maps.google.com/maps/api/js","ssl":"https://maps-api-ssl.google.com/maps/api/js","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}},"pattern":"^(3|3..*)$"}]},"annotations_v2","wave","orkut",{"name":"annotations","baseSpec":{"uri":"http://www.google.com/reviews/scripts/annotations_bootstrap.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"},"country":{"string":"gl"}}}},"language","earth","ads","elements"]});
google.loader.rfm({":search":{"versions":{":1":"1",":1.0":"1"},"path":"/api/search/1.0/2a8ff2a70ad0b091ae9dfd8b5e832141/","js":"default+en.I.js","css":"default.css","properties":{":JSHash":"2a8ff2a70ad0b091ae9dfd8b5e832141",":NoOldNames":false,":Version":"1.0"}},":language":{"versions":{":1":"1",":1.0":"1"},"path":"/api/language/1.0/62c64af2122d2da7dcb0087852fa7396/","js":"default+en.I.js","properties":{":JSHash":"62c64af2122d2da7dcb0087852fa7396",":Version":"1.0"}},":wave":{"versions":{":1":"1",":1.0":"1"},"path":"/api/wave/1.0/3b6f7573ff78da6602dda5e09c9025bf/","js":"default.I.js","properties":{":JSHash":"3b6f7573ff78da6602dda5e09c9025bf",":Version":"1.0"}},":spreadsheets":{"versions":{":0":"1",":0.3":"1"},"path":"/api/spreadsheets/0.3/8331b0bbcc74776270648505340e9200/","js":"default.I.js","properties":{":JSHash":"8331b0bbcc74776270648505340e9200",":Version":"0.3"}},":earth":{"versions":{":1":"1",":1.0":"1"},"path":"/api/earth/1.0/819ffbf1e363d238791231792a2e0a90/","js":"default.I.js","properties":{":JSHash":"819ffbf1e363d238791231792a2e0a90",":Version":"1.0"}},":annotations":{"versions":{":1":"1",":1.0":"1"},"path":"/api/annotations/1.0/11cfaf30c00ca64601d09fcac7dd8bc7/","js":"default+en.I.js","properties":{":JSHash":"11cfaf30c00ca64601d09fcac7dd8bc7",":Version":"1.0"}}});
google.loader.rpl({":scriptaculous":{"versions":{":1.8.3":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.2":{"uncompre

Revision: 39555
at January 19, 2011 05:47 by mavrikicecool


Updated Code
Read from top to Bottom see for **** especially....and Please don't bother about think about spelling mistakes, as i am little weak in English

Make an application multi lingual by using google API....
This process can even be implemented by an web service, but i have made use of google API
Please follow the steps and make changes accordingly 

PHP(make use of div's and apply to the id's), ASP(Apply to all labesl)...and the rest of the languages follow up the same procedure accoringly......

*****************Add these 2 scripts tags into u r header and make it common for the pages so that it includes in each and everything***
<!--<script type="text/javascript" src="Translate/googlelanguage.js"></script>
<script type="text/javascript" src="Translate/translate.js"></script>-->
****************Better to add these 2 into head section of u r html or asp or jsp pages********************************************
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
************Add this thing into the body section where ever u wish to or u wanna Place the option for selection*******************
 <!-- <div><font size="+1">Select Language</font></div>
  <div id="mlt_languagelist"> </div>-->
  
  -->Steps:
  	1) As the page is loaded the the 2nd div gets activated and gets processed through the api and data is fetched from the tranlate.js script....check in the line number 166 the function getLangs() gets called and executed.just go through the function and understand the parameters passed u will know better whats happening.
	
	2) G to line number 85 there u will come to know how the langues get changed based upon u r request.
	3)	if(GL_curLang == "orig") {
			refresh();
			return;
		}
	
	find th this block and add few more langues based upon ICANN standards for language notations in google.soon after the above block by dumping more conditions to the above block u can select the langues aby your choice
	
	Add:
		else if(GL_curLang == "es") { //spanish
			refresh();
			return;
		}	
		else if(GL_curLang == "ja") { //japanese
			refresh();
			return;
		} 
		
		
	4) So add according to u r choice all this has to be followed aftr line number 888 for the 3 point.
	
	6) And now get to start of the page translate.js and point towards line 52, there you gonna find a an array assigned toa  variable with various elements within the array, present with other elements within it for the converion usuage.
	for all required labels in asp or the div or span's which u find the page, assign them which are to be changed upon request.
	
	7) rename those elements name by u r own names which u want, use those div's which are present in all front end pages .for each and every text item or asp with label tags, assign these id's one for all those text items(i.e the div's of each and every text item)..and u r almost done
	
	8)save all changes and start using this applicationits gonna work i am sure.....if there is anything lemme know.post it on the comments section i will reply back.
	
	5)By this way the combo box is set with languages which you require to make the application multi lingual
	
	6)this particual api support 64 recognised languages , check the info in google for this particual api.
	
  
********************************************************************************************************************************* 
</body>
</html>


*******************Save it as translate.js***************************

/* Multi-Language Translation Script:
*
*  Automatically translates a webpage (containing text in more than one language) into any single language
*  requested by the user. Particularly useful for sites involving a lot of user-generated content (which
*  might have originally been written in different languages) - e.g. blogs, forums, or other community sites. 
*  Harnesses the Google AJAX Language API to perform translation and language detection.
*
*  Version: 0.2.5 [2010-01-22]
*  Author: Patrick Hathway, OdinLab, University of Reading.
*  For Documentation and Updates: See http://code.google.com/p/multi-language-translation/
*  Licence: MIT License - see http://opensource.org/licenses/mit-license.php for full terms. Also check 
*  the script Documentation for more information, and for details of one important consideration.
*
*  Some minor configuration is required for this script to work on your website. Follow the instructions
*  below, or see the Documentation for full details and examples...   */

/* 1. Specify the 'Base Language' for your website: */

var GL_baseLang = "en";

/* 2. Specify the IDs for all major regions (i.e. HTML elements) in your site that should have their 
*  contents translated. Note that an ID can only be used to identify a single element on a page (for 
*  elements which appear multiple times, use Class Names instead - see below). The script will translate
*  each element separately; any elements that cannot be found on a page will be ignored:   */

var GL_classIds = [
	["navigation"],	
	["navigation", "", true],  
	["quick-id", "", true],  
	["c-quote", "", true],  
	["c-need-quote", "", true],  
	["c-index", "", true],   
	["c-about", "", true],  
	["c-exper", "", true],  
	["c-solution", "", true],
	["c-product", "", true],  
	["c-contact", "", true],  
	["c-indian-add", "", true],  
	["c-work", "", true],  
	["c-contact", "", true],  
	["c-contactinf", "", true],
	["c-usa-add", "", true],  
	["c-warning", "", true],  
	["right_sidebar", "fr", true], 
	["footer"]
];

/* 3. Specify the Class Names of all major regions (i.e. HTML elements) in your site that should have their 
*  their contents translated. Multiple elements may appear on a page with the same class name; the script
*  will locate each occurrance (if present) and translate them separately:   */

var GL_classNames = [
	["entry_baselang"],
	["entry_french", "fr"],
	["index-class", "", true],
	["about-class", "", true],	
	["association-class", "", true],
	["building-class", "", true],
	["career-class", "", true],
	["college-class", "", true],
	["construction-class", "", true],
	["contact-class", "", true], 
	["entry_baselang", "", true], 
	["education-class", "", true], 
	["entry", "", true], 
	["expertise-class", "", true], 
	["description", "", true], 
	["list-custom_website", "", true], 
	["list-beautiful_graphic", "", true], 
	["list-using_nature", "", true],
	["list-css_xhtml", "", true],
	["description", "", true], 
	["list-branding_your", "", true], 
	["list-green_branding", "", true], 
	["list-who_are", "", true], 
	["list-long_term", "", true], 
	["list-the_importance", "", true], 
	["list-flow", "", true], 
	["list-click_through", "", true], 
	["list-scale", "", true], 
	["description", "", true], 
	["list-google_rank", "", true], 
	["list-ppc", "", true], 
	["list-custom_icon", "", true], 
	["list-why_use", "", true], 
	["list-web_standard", "", true], 
	["list-promoting_your", "", true], 
	["list-business_cards", "", true], 
	["fashin-class", "", true], 
	["right", "", true],  
	["web_portfolio", "", true], 
	["interior-class", "", true],
	["manufacture-class", "", true], 
	["news-class", "", true], 
	["medical-class", "", true], 
	["opening-class", "", true], 
	["ourclass-class", "", true], 	
	["portfolio-class", "", true], 	
	["ecommerce-class", "", true], 	
	["mobile-class", "", true], 
	["webdesign-class", "", true], 
	["product-class", "", true], 
	["professional-class", "", true], 
	["real-class", "", true], 
	["realestate-class", "", true], 
	["request-class", "", true],   
	["form_entry", "", true],
	["request-id", "", true],
	["requestquote-class", "", true],
	["consumer-class", "", true],
	["software-class", "", true],
	["solutions-class", "", true],
	["list-why_use", "", true],
	["list-west_coast", "", true], 
	["list-custom_icon", "", true],
	["list-crisp_graphics", "", true],
	["list-scalable_across", "", true],
	["testimonials-class", "", true],  
	["testimonials", "", true],
	["tourism-class", "", true],
	["trade-class", "", true], 
	["transport-class", "", true], 
	["levonsys-class", "", true],  
	["working-levonsys-class", "", true],    
	["quick", "", true], 
	["entry_french", "", true], 
	["quotes", "de", true]
];


/* 4. Specify the default language for new visitors (leave blank to auto-detect using browser/system settings) */

var GL_curLang = "";

/* The rest of the Script should not be modified; unless you want to alter the functionality!
*  ------------------------------------------------------------------------------------------ */

// Global variables:
var GL_srcContent;             // array containing all content on the page to be translated, split up into chunks
var GL_transContent = [];      // array containing all chunks which have been translated
var GL_chunksTotal = 0;        // total number of chunks to translate
var GL_curChunk;               // ID of current chunk being translated
var GL_errors;                 // array containing details of all errors that occur (if applicable)
var GL_errSrcTxt;              // array containing all source text that causes errors (if applicable)
var GL_miniTransItems = [];    // array containing element IDs/class names which contain minor items to translate

google.load("language", "1");  // load v1 of google ajax language api

// run when page loads
function initialise() {
	addTransMsgs();        // append elements (which will display translation status messages) to page
	buildChunkedContent(); // create a local 'cache' of chunked content to be translated
	getLangCookie();       // find out the current site language (if known)
	getLangs();            // display listbox containing all languages the site can be translated into

	// if the original languages should be shown, end function.
	if(GL_curLang == "orig") {
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// display listbox containing all languages the site can be translated into (so that one can be selected by user)
function getLangs() {
	// create listbox within script so that it won't appear if JavaScript is disabled
	document.getElementById("mlt_languagelist").innerHTML = '<select id="mlt_language" onchange="changeLang()" style="width:150px; height:20px;"></select>';
	// +	'<div id="mlt_langattr"></div>'
	var langItems = document.getElementById("mlt_language").options;

	// add option to top of listbox allowing user to view the site in its original (i.e. un-translated) languages
	langItems.add(new Option("Original Languages", "orig", true));

	// loop through list of currently available languages and add each to listbox
	for(var lang in google.language.Languages) {
		// find out the 2 character Google language code
		
		var langCode = google.language.Languages[lang];
		// convert language string to title case
		var langString = lang.substr(0,1) + lang.substr(1).toLowerCase();
		// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
		langString = langString.split("_").join(" - ");

		// check that Google can translate content into the current language
		if ((google.language.isTranslatable(langCode)) && (langCode != "")) {
			// if so, add to listbox and translate, so native speakers of that language can find it
			if(langCode=="ar")
			{
				langItems.add(new Option(langString, langCode));
				miniTranslate(langItems[(langItems.length-1)],langCode);
			}
			
		}
	}

	document.getElementById("mlt_language").value = GL_curLang; // change listbox to display current site language
	google.language.getBranding("mlt_langattr");  // display Google attribution below listbox (as required by TOS)
}

// start the translation
function startTranslation() {
	// reset global variables
	GL_curChunk = 0; GL_errors = []; GL_errSrcTxt = [];
	
	// check if all content has already been translated into current language since page loaded.
	if(chkLangTrans()) {
		return; // if so, don't need to translate content again
	} 
	
	// sanity check - can google actually translate into the current site language?
	if (!(google.language.isTranslatable(GL_curLang)) || (GL_curLang == "")) {
		return; // if not, end translation
	} // Otherwise, send content to google to be translated:
	
	// show the 'Translating...' block
	document.getElementById("mlt_translatemsg").innerHTML = 'Translating... <span id="mlt_perc">0%</span>';
	miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	document.getElementById("mlt_translatemsg").style.display='block';

	// find out the ID of the destination language
	var curLangNo = document.getElementById("mlt_language").selectedIndex;
	var k = 0;
	
	// create sub-array to hold all translations for current language
	GL_transContent[GL_transContent.length]        = new Array(3);
	GL_transContent[(GL_transContent.length-1)][0] = []; // this array will contain all translated chunks
	GL_transContent[(GL_transContent.length-1)][1] = GL_curLang; // store current language
	GL_transContent[(GL_transContent.length-1)][2] = false; // mark translation of language as incomplete

	// loop through all the chunks to be translated, send to google...
	for(var i = 0; i < GL_srcContent.length; i++) {
		// find out the source language for the current element to be translated
		var srcLang = GL_srcContent[i][GL_srcContent[i].length - 1];

		for(var j = 0; j < (GL_srcContent[i].length - 1); j++) {
			/* AJAX is used to return translated chunks, so they MAY be returned in any order.
		   	To solve, include current chunk id, destination language + separators at start of each
		   	string. This is a bit of a 'hack', so try to find a better solution! */
			var srcText = curLangNo + "<br />" + k + "<br />" + GL_srcContent[i][j];

			// send current chunk to google translate; when translated, call function translateChunk
			google.language.translate(srcText, srcLang, GL_curLang, translateChunk);
			k++;
		}
	}

	setTimeout("checkTransStatus()", 1000); // run function to check translation status after 1 second
}

// check if page content has already been translated into current language since page loaded.
function chkLangTrans() {
	// loop through the list of languages the page has been translated into
	for(var i = 0; i < GL_transContent.length; i++) {
		// check if a translation for current language exists, and if so, whether it is complete.
		if((GL_transContent[i][1] == GL_curLang) && (GL_transContent[i][2] == true)){
			/* if so, don't need to send content to google again, just assemble the pre-translated content.
			This will *dramatically* reduce the translation time for this language! */
			endTranslation(i);
			return true;
		} 
	}
	return false; // otherwise, all relevant page content must be submitted to google for translation.
}

// This runs after each chunk has been translated...
function translateChunk(result) {
	// handle translation errors gracefully by storing error details but allowing translation to continue
	if (result.error) {
		GL_errors[GL_errors.length] = result.error.message;
	}
	else {

	/* Translated chunks may be returned in any order, so we need a method to assemble the chunks
	   in the correct order:
	   * Start of each chunk has a destination language id and a chunk id followed by separators.
	   * Separator is a <br /> HTML tag, as these always appear to retain position after translation...
	   * The destination language id is used to ensure the translated text is now in the correct language.
	   * Each chunk is stored in the position of the 'GL_transContent' array corresponding to the current chunk id.
	   * The ids + separators should not be shown, and are discarded from the chunk when it's stored in array.
	*/
	
		// split into array based on separator, so we know the id & destination language of translated chunk
		var transChunk = result.translation.split("<br />");
		// [find out length of substring to chop off from start of chunk]
		var chunkSubStr = 12 + transChunk[0].length + transChunk[1].length;
		// remove whitespace from chunk id & destination language (a problem with some translations)
		transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
		transChunk[1] = transChunk[1].replace(/^\s+|\s+$/g,"");

		/* If the translated chunk has a different destination language to the current site language, discard
		translation & end function. This may happen if user changes language whilst translation is in progress */
		if(transChunk[0] != document.getElementById("mlt_language").selectedIndex) {
			return;
		}

		// store translated chunk in current language array, along with detected source language (if known)
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]] = new Array(3);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][0] = result.translation.substr(chunkSubStr);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][1] = result.detectedSourceLanguage;
	}

	GL_curChunk++; // increment current chunk ID every time function is called

	// calculate and display percentage of translation completed, based on number of chunks remaining
	var perc = (GL_curChunk / GL_chunksTotal)*100;
	document.getElementById("mlt_perc").innerHTML = Math.round(perc) + "%";

	// when all chunks have been translated, run the 'endTranslation' function...
	if(GL_curChunk >= GL_chunksTotal) {
		endTranslation((GL_transContent.length-1)); // [final array element holds current language content!]
	}
}

/* runs once a second whilst translation is in progress, updating contents of all elements that have already
   been completely translated. Also shows 'timeout' messages if translation not completed within 30 seconds... */
function checkTransStatus() {
	// 'static' member variables to keep track of how many times function has run, as well as current language:
	if((typeof checkTransStatus.chkStatusCount == 'undefined') || (checkTransStatus.curTransLang != GL_curLang)) {
		// reset variables if not defined yet, or if site language has changed since last function call
        	checkTransStatus.chkStatusCount = 0;
		checkTransStatus.curTransLang = GL_curLang;
	}

	// if translation is now complete, end function.
	if(GL_curChunk >= GL_chunksTotal) {
		return;
	}
	
	checkTransStatus.chkStatusCount++; // increment Translation Status counter

	// Store the list of languages in case they are replaced during translation
	var langList = document.getElementById("mlt_languagelist").innerHTML;

	var curElement; var curTransChunk = 0; var curClass = 0; var curTransLang = GL_transContent.length-1;

	// loop through all element IDs (as specified at script top), searching for ones with completed translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,false);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), searching for completed translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],false);
				curClass++; // move to next element Class Name
			}
		}
	}

	// if listbox containing all languages has been removed as a result of translation, display it again
	if(document.getElementById("mlt_languagelist").innerHTML == "") {
		document.getElementById("mlt_languagelist").innerHTML = langList;
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to show current language
	}

	/* if translation still isn't complete after 30 seconds, update translation message. Note: there is no
	   need to halt the current translation completely, but we will allow user to restart it if desired! */
	if(checkTransStatus.chkStatusCount == 30) {
		// calculate and display percentage of translation completed, based on number of chunks remaining
		var perc = Math.round((GL_curChunk / GL_chunksTotal)*100) + "%";
		// update translation status message
		document.getElementById("mlt_translatemsg").innerHTML = 'Translating (Slowly!)... ' +
		'<span id="mlt_perc">' + perc + '</span> - <a href="javascript:refresh()">Retry</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	}

	setTimeout("checkTransStatus()", 1000); // check translation status again after another second
}

// runs after all translations have been completed; displaying the results on screen in place of previous content
function endTranslation(curTransLang) {
	var curElement;
	var curTransChunk = 0; var curClass = 0;

	// loop through all element IDs (as specified at script top), replacing current contents with translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,true,GL_classIds[i]);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), so contents can be replaced by translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],true,GL_classNames[i]);
				curClass++; // move to next element Class Name
			}
		}
	}

	// Perform translations of all content added by the script (e.g. language strings and error messages)
	transAddedText();

	// Re-create listbox containing all languages, in case it has been removed as a result of translation
	getLangs();

	// translate the 'Original Languages' listbox item to equivalent in current site language
	miniTranslate(document.getElementById("mlt_language").options[0],GL_curLang,"Original Languages");
	
	// if any errors occured during translation, display warning message at top of screen and end function 
	if(GL_errors.length != 0) {
		document.getElementById("mlt_translatemsg").innerHTML = GL_errors.length + ' Problems(s) Occurred During Translation: ' +
		'<a href="javascript:refresh()">Retry</a> - <a href="javascript:showErrDetails()">Details</a> - ' +
		'<a href="javascript:hideTransMsg()">Hide</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate warning message into current site language
		return;
	}
	
	// mark translation of page into current language as complete, so that translation can be quicker next time.
	GL_transContent[curTransLang][2] = true;

	hideTransMsg(); // otherwise, hide 'Translating...' message
}

// assemble and display translated chunks for current element on page
function unpackTransChunks(curTransLang,curTransChunk,curClassNum,curElement,transComplete,curClass) {
	// 'static' member variable to keep track of how many times function has run
	if(typeof unpackTransChunks.curLinkId == 'undefined') {
		// reset curLinkId variable if not defined yet - it's used to identify the correct 'show source text' link
        	unpackTransChunks.curLinkId = 0;
	} unpackTransChunks.curLinkId++; var j = unpackTransChunks.curLinkId; // increment current link id, j is an alias

	var curContent = ""; // reset translated contents of current element
	var initTransChunk = curTransChunk; // store initial chunk id of current element

	// loop through all translated chunks, assembling all translated content for current element
	for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
		// if current chunk does not exist, translation is not complete or errors occurred
		if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == false)) {
			break; // stop looping through chunks if full translation has not yet been completed
		} else if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == true)) {
			// if full translation IS complete, show warning message and a link to show source text (in red)
			curContent += '<div style="color: red;" id="mlt_srctxt' + j + '">[<span class="mlt_transerrtxt">' +
			'<em style="text-transform: uppercase;">THIS SECTION COULD NOT BE TRANSLATED</em> - '+
			'<a id="mlt_srctxtlnk' + j + '" href="javascript:showSrcTxt(' + j + ',' + curClassNum + ',' + (i+1) + 
			')">View Source Text [+]</a></span><span id="mlt_srctxtbracket' + j + '">]</span></div>';
			GL_errSrcTxt[GL_errSrcTxt.length] = GL_srcContent[curClassNum][i]; // store affected source text
			unpackTransChunks.curLinkId++; j = unpackTransChunks.curLinkId; // increment current link id		
		} else {
			// otherwise append current translated chunk to translated content string
			curContent += GL_transContent[curTransLang][0][curTransChunk][0];
		}
		curTransChunk++; // move to next chunk
	}

	// if translation is complete, replace contents of current element with translated text
	if(transComplete == true) {
		curElement.innerHTML = curContent;
		// append a language string to bottom of current element if desired
		getLangString(curTransLang,curElement,curClass,initTransChunk,(GL_srcContent[curClassNum].length - 1),j,curClassNum);
	// otherwise, check if all translated chunks for current element were assembled
	} else if((i == (GL_srcContent[curClassNum].length - 1)) && (GL_transContent[curTransLang][0][initTransChunk][2] != true)) {			
		// if so (and current element translation is not yet marked as complete), replace contents with translation
		curElement.innerHTML = curContent;
		GL_transContent[curTransLang][0][initTransChunk][2] = true; // mark current element translation as complete
	}

	return curTransChunk; // return current chunk id to calling function
}

// If required, find and append a string containing the Source Language to the bottom of the specified element
function getLangString(curTransLang,curElement,curClass,curTransChunk,transChunksLen,j,curClassNum) {
	
	var detectedLang = "";

	// if the current element does not need a language string appended, end function
	if(curClass[2] != true) {
		return;
	}

	// if source language for current element has already been manually specified, set this as detected language
	if(curClass[1] != "") {
		detectedLang = curClass[1];
	}
	// otherwise find out language based on the detected source languages for translated chunks in current element 
	else {
		detectedLang = findDetectedLang(curTransLang,curTransChunk,transChunksLen);
	}

	// if detected language is same as site language, there is no need to display language string, so end function
	if(detectedLang == GL_curLang){
			return;
	}

	var srcLangString = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string 

	// append language string to current element...
//	curElement.innerHTML += '<div style="color: green;" id="mlt_srctxt' + j + '"></div>';
}

// convert a google language code into a formatted string containing the language name
function getFmtLangStr(lang) {
	// loop through list of supported languages and retrieve names
	for(var l in google.language.Languages) {
		if(google.language.Languages[l] == lang) {
			// convert language string into title case
			var lang = l.substr(0,1) + l.substr(1).toLowerCase();
			// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
			lang = lang.split("_").join(" - ");
			break; // stop loop (don't need to continue searching for languages)
		}
	}
	// if language cannot be found in list of supported languages, set language to 'unknown'
	if(typeof lang == "undefined") {
		lang = "An Unknown Language";
	}
	return lang; // return formatted language string
}

// find out the most common detected language for all translated chunks in current element, to appear in language string
function findDetectedLang(curTransLang,curTransChunk,transChunksLen) {
	var chunkLangs = []; langCounter = 0;

	// loop through all translated chunks in current element
	for(var i = 0; i < transChunksLen; i++) {
		// bugfix: set detected language to 'undefined' if an error occurred during translation... 
		if(GL_transContent[curTransLang][0][curTransChunk] == null) {
			GL_transContent[curTransLang][0][curTransChunk] = new Array(3);
			GL_transContent[curTransLang][0][curTransChunk][1] = "undefined";	
		}
		// loop through array of detected languages to see if current chunk has an existing detected language
		for(var j = 0; j < chunkLangs.length; j++) {
			if(chunkLangs[j][0] == GL_transContent[curTransLang][0][curTransChunk][1]) {
				// if so, increment counter containing the total number of chunks with that language
				chunkLangs[j][1]++;
				break; // halt loop
			}
		}
		// if current chunk has a language not yet detected, add it to end of detected languages array
		if(j == chunkLangs.length) {
			chunkLangs[j] = new Array(2);
			chunkLangs[j][0] = GL_transContent[curTransLang][0][curTransChunk][1]; // name of detected language
			chunkLangs[j][1] = 1; // total number of chunks with that language
		}
		curTransChunk++; // move to next chunk
	}

	/* once array has been created containing all detected languages in current element, loop through it
	to find the most common detected language - language string should contain this */
	for(i = 0; i < chunkLangs.length; i++) {
		if(chunkLangs[i][1] > langCounter) {
			/* if current language was detected more times than all previous languages, store language
			and number of times detected - so that next language can be compared against this total */
			var detectedLang = chunkLangs[i][0];
			langCounter = chunkLangs[i][1];
		}		
	}
	
	return detectedLang; // return the most common detected language
}

// Auto-translate all text added previously by the script (including language strings and error messages)
function transAddedText() {
	var allElements = document.getElementsByTagName("*"); // get all elements on page, so relevant ones can be translated
	var foundElements = [];

	// loop through all elements to find any of class 'mlt_langstring' or 'mlt_transerrtxt' 
	for(var i=0; i<allElements.length; i++) {
		if((allElements[i].className == "mlt_langstring") || (allElements[i].className == "mlt_transerrtxt")) {
			foundElements[foundElements.length] = allElements[i];
		}
	}

	// translate all located elements (runs separately from above code to prevent infinite loop as items are translated)
	for(i = 0; i < foundElements.length; i++) {
		miniTranslate(foundElements[i]); // translate current element
	}
}

/* this function runs before any translation takes place, and creates a local 'cache' of all content to be translated (in chunks)
   - meaning the content can be submitted to Google more rapidly, and the resulting translations can then be sorted reliably */
function buildChunkedContent() {
	var curElement; GL_srcContent = []; var j = 0;

	/* loop through all applicable element IDs (as specified at script top), converting the contents of each into chunks,
	   and storing each chunk in an array */
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element
		// check that element actually exists on the page - if not, ignore it
		if(curElement != null) {
			GL_srcContent[j] = createChunks(curElement); // separate the content of current element into chunks
			GL_chunksTotal += GL_srcContent[j].length;   // store a running total of the number of chunks created

			// if a Source Language is not specified for current element, store Base Language in array instead
			if(GL_classIds[i].length == 1) {
				GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
			} else {
				// otherwise store the specified language (or a blank string if this is to be auto-detected)
				GL_srcContent[j][GL_srcContent[j].length] = GL_classIds[i][1];
			}
			j++;
		}
	}

	// get all elements on page, so that the ones specified can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all applicable element IDs (as specified at script top), converting into chunks and storing in array
	for(var i = 0; i < GL_classNames.length; i++) {
		// find all elements which have the current class name
		for(var k = 0; k < allElements.length; k++) { 
			if(allElements[k].className == GL_classNames[i][0]) {
				// separate the content of current element into chunks
				GL_srcContent[j] = createChunks(allElements[k]);
				// store a running total of the number of chunks created
				GL_chunksTotal += GL_srcContent[j].length;

				// if a Source Language is not specified for current element, store Base Language in array
				if(GL_classNames[i].length == 1) {
					GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
				} else {
					// otherwise store specified language (or a blank string if auto-detected)
					GL_srcContent[j][GL_srcContent[j].length] = GL_classNames[i][1];
				}
				j++;
			}
		}
	}
}

/* Web browsers (and Google) limit the amount of text translated per request, so split contents of current element into chunks.
   The aim is to achieve this whilst maintaining the translation integrity */
function createChunks(srcContent) {	
	var chars = 1000; // number of characters to allow per chunk.

	/* We do NOT want the content inside any HTML tag to be split between chunks (as this could cause 
	rendering problems), so create 2 arrays storing tags and textual content of current div separately */
	var tags = srcContent.innerHTML.match(/<.*?>/g);
	var text = srcContent.innerHTML.split(/<.*?>/g);
	if(tags == null) {
		tags = new Array();} // handle content containing no tags

	var curchar = 0; var tagnum = 0; var textnum = 0; var contTotal = tags.length + text.length;
	// create an array containing content to be chunked, with tags + text separately re-assembled (in order)
	var content = new Array(contTotal);
	// loop through content of current div
	for(var i=0; i < contTotal; i++) {
		// if current position in content is the start of a tag char, add appropriate tag to content array
		if(srcContent.innerHTML.substr(curchar,1) == "<") {
			content[i] = tags[tagnum];
			curchar += tags[tagnum].length;
			tagnum++;
		// if it is a text string, add the corresponding text to the curent element in content array
		} else {
			content[i] = text[textnum];
			curchar += text[textnum].length;
			textnum++;
		}
	}

	// Create the chunks - don't split either tags or words (to ensure as high translation quality as possible)
	var chunks = []; var curChunk = 0;
	chunks[0]="";
	for (i = 0; i < contTotal; i++) {
		// if next content item (tag or textual) won't exceed length of current chunk, add it to chunk
		if((chunks[curChunk].length + content[i].length) < chars) {
			chunks[curChunk] += content[i];
		} else {
			// otherwise, proceed to next chunk.
			curChunk++;
			// add the entire content item to this chunk if possible (to ensure better translation)
			if(content[i].length < chars) {
				chunks[curChunk] = content[i];
			}
			else {
				// only split further in rare cases where text length exceeds maximum chunk size
				var curPos = 0;
				do {
					// retrieve the maximum amount of text that can fit in this chunk
					var subContent = content[i].substr(curPos,chars);
					// find out how many words are in this substring
					var words = subContent.split(" ");
					// chop off final word, so words aren't split up between chunks
					var lastWordPos = subContent.length - words[(words.length-1)].length;
					if(subContent.length < chars) { // [bugfix: prevent word cut-off on final iteration]
						lastWordPos = subContent.length}
					chunks[curChunk] = subContent.substr(0,lastWordPos); // store in chunk
					curChunk++; // remainder of text will go in next chunk
					curPos+=lastWordPos; // store current position in text, for further processing
				} while(subContent.length >= chars); // repeat until all this text has been chunked
				curChunk--; // because there may still be space in the current chunk!
			}
		}
	}		
	
	return chunks; // return chunked content to calling function...
}

// Append elements to page (will be used to display translation messages), and specify their css styles.
function addTransMsgs() {
	// add element to page which will contain translation messages
	var transCont = document.createElement("div");
	document.body.appendChild(transCont);
	
	// add element to container created above - this will display the translation messages
	var translateMsg = document.createElement("div");
	translateMsg.id = "mlt_translatemsg";
	transCont.appendChild(translateMsg);

	// define visual styles for translation messages displayed on screen
	translateMsg.style.backgroundColor = "silver";
	translateMsg.style.border = "3px green solid";
	translateMsg.style.padding = "5px";
	translateMsg.style.fontSize = "large";
	translateMsg.style.fontWeight = "bold";
	translateMsg.style.textAlign = "left";
	translateMsg.style.color = "black";

	// more translation message styles (these should not need editing!)
	translateMsg.style.left = "-50%";
	translateMsg.style.position = "relative";
	translateMsg.style.display = "none";
	
	// define the styles for the container element
	transCont.style.left = "50%";
	transCont.style.zIndex = "1000";
	if(!(/MSIE 6/i.test(navigator.userAgent))) {
		// styles for all browsers except IE6
		transCont.style.position = "fixed";
		transCont.style.top = "0px";
	}
	else {
		// styles for IE6
		transCont.style.position = "absolute";
		transCont.style.setExpression("top", "(i = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
	}
}

// Hide 'Translating...' message (or translation error message) - runs at end of translation, or if user dismisses error message
function hideTransMsg() {
	document.getElementById("mlt_translatemsg").innerHTML = "";
	document.getElementById("mlt_translatemsg").style.display='none';
}

// if the user clicks on the 'Details' link [after error(s) occurred], show details of all errors on screen
function showErrDetails() {
	// continue to show original error message (but remove 'Details' link)
	document.getElementById("mlt_translatemsg").innerHTML = '<span id="mlt_transerrmsg1">' + GL_errors.length + 
	' Problems(s) Occurred During Translation: ' + '<a href="javascript:refresh()">Retry</a> - ' +
	'<a href="javascript:hideTransMsg()">Hide</a>... <br /><em>Error(s) Reported:</em></span>' +
	'<ul style="margin: 0px; padding: 0px;" id="mlt_transerrlist"></ul>';

	// Loop through array containing details of all errors, and show them as a list on screen
	for(var i = 0; i < GL_errors.length; i++) {
		document.getElementById("mlt_transerrlist").innerHTML += '<li style="margin-left: 15px;">' + GL_errors[i] + '.</li> ';	
	}

	/* create a textarea - this will show the original source text of all affected sections (as HTML) to aid debugging
	   Note: because translations are returned using AJAX, the affected sections are not NECESSARILY in the same order as
	   the errors reported (though in many cases, they will be!) */
	document.getElementById("mlt_translatemsg").innerHTML += '<em id="mlt_transerrmsg2">Section(s) Affected:</em><br />' +
	'<textarea id="mlt_errsrctxt" rows="8" readonly="readonly" style="width: 99%; background-color: silver; border: 1px gray solid;">' +
	'</textarea>';

	// Loop through Source Text array, appending to textarea.
	for(var i = 0; i < GL_errSrcTxt.length; i++) {
		document.getElementById("mlt_errsrctxt").value += "Affected Section " + (i+1) + ":\n" + GL_errSrcTxt[i] + "\n\n";
	}

	// Translate the entire contents of the Translation Errors box (with the exception of the text inside the textarea)
	miniTranslate(document.getElementById("mlt_transerrmsg1")); miniTranslate(document.getElementById("mlt_transerrlist"));
	miniTranslate(document.getElementById("mlt_transerrmsg2"));
}

// function runs when the user clicks on a link to view the original source text for a translated element / chunk
function showSrcTxt(curLinkId,curClassNum,curChunkId) {
	// if the current chunk should be shown only, display chunk on screen
	if((curChunkId-1) != -1) {
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+GL_srcContent[curClassNum][(curChunkId-1)]+']</div>';
	} else {
	// otherwise assemble all chunks for current element, and display on screen
		var srcTxt = "";
		for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
			srcTxt +=  GL_srcContent[curClassNum][i];
		}
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+srcTxt+']</div>';
	}	

	// update Source Text link so that when clicked in future, the source text will be hidden instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "Hide Source Text [-]";
	srcTxtLnk.href = 'javascript:hideSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = ""; // hide bracket after link
}

// function runs when the user clicks on a link to hide the original source text for a translated element / chunk
function hideSrcTxt(curLinkId,curClassNum,curChunkId) {
	// remove the element containing the original source text
	srcTxtContent = document.getElementById("mlt_srctxtcontent"+curLinkId);
	document.getElementById("mlt_srctxt"+curLinkId).removeChild(srcTxtContent);

	// update Source Text link so that when clicked in future, the source text will be shown instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "View Source Text [+]";
	srcTxtLnk.href = 'javascript:showSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = "]"; // show bracket after link
}

// translate small non crucial items of text into current site language
function miniTranslate(item,destLang,srcTxt) {
	if(typeof destLang == "undefined") {
		var destLang = GL_curLang; // if the destLang argument was not specified, use the current site language
	}
	if(typeof srcTxt == "undefined") {
		var srcTxt = item.innerHTML; // if the srcText argument was not specified, use the current item contents
	}

	// loop through translated items array to see if a translation for current text already exists since page loaded
	for(var i = 0; i < GL_miniTransItems.length; i++) {
		// check if source text and destination language match a translated item (and a completed translation exists for it)
		if((GL_miniTransItems[i][1] == srcTxt) && (GL_miniTransItems[i][2] == destLang) && (GL_miniTransItems[i][3] != "")) {
			item.innerHTML = GL_miniTransItems[i][3]; // if so, display existing translation in item
			item.title = srcTxt.split(/<.*?>/g).join(""); // display English source text as a tooltip (strip HTML first)
			return; // Don't need to send a translation request to Google, so end function.
		}
	}

	// store item to be translated in global array for access by callback function
	GL_miniTransItems[GL_miniTransItems.length]	   = new Array(4);
	GL_miniTransItems[(GL_miniTransItems.length-1)][0] = item;
	GL_miniTransItems[(GL_miniTransItems.length-1)][1] = srcTxt;
	GL_miniTransItems[(GL_miniTransItems.length-1)][2] = destLang;
	GL_miniTransItems[(GL_miniTransItems.length-1)][3] = "";

	// create source text by adding current item ID to start of item text (ID will ensure correct item is translated)
	srcTxt = (GL_miniTransItems.length-1) + "<br />" + srcTxt;

	google.language.translate(srcTxt, "en", destLang, function(result) {
        	if (!result.error) {
			// split into array based on separator, so we know the id of translated item
			var transChunk = result.translation.split("<br />");
			// [find out length of substring to chop off from start of item]
			var chunkSubStr = 6 + transChunk[0].length;
			// remove whitespace from item id (a problem with some translations)
			transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");

			// display english source text of translated item (with HTML stripped) if user hovers mouse over it
			var strippedSrcTxt = GL_miniTransItems[transChunk[0]][1].split(/<.*?>/g).join("");
			GL_miniTransItems[transChunk[0]][0].title = "[" + strippedSrcTxt  + "]";

			// store and display translation of specified item (stripping item ID from start of text)
			GL_miniTransItems[transChunk[0]][3] = result.translation.substr(chunkSubStr);
			GL_miniTransItems[transChunk[0]][0].innerHTML = GL_miniTransItems[transChunk[0]][3];
        	}
	});
}

// runs when the user changes the site language
function changeLang(destLang) {
	if(typeof destLang != "undefined") {
		GL_curLang = destLang; // if the destLang argument was specified, set new site language to this
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to display new site language
	} else {
		// otherwise get the new language requested by user
		GL_curLang = document.getElementById("mlt_language").value;
	}

	// store the requested language in a cookie
	setLangCookie();
	
	// if the original site languages should be shown, refresh the page.
	if(GL_curLang == "orig") {
		refresh();
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// find out the value of the language cookie (if it exists)
function getLangCookie() {
	var curStoredLang;
	// retrieve a list of cookies for this page, split into array elements (separated by ; if multiple cookies)
	var getCurLang=document.cookie.split(";");
	// loop through all array elements (i.e. cookies) until one with name 'lang' is found.
	for(var i=0; i < getCurLang.length; i++) {

		// remove whitespace from cookies (a problem if there are multiple cookies)
		var lngCookie = getCurLang[i].replace(/^\s+|\s+$/g,"");

		if(lngCookie.indexOf("lang=") == 0) {
			// find out value of lang
			curStoredLang = lngCookie.substring(5);
		}
	}
	
	// if language cookie exists, set current site language to stored value
	if(typeof curStoredLang != "undefined") {
		GL_curLang = curStoredLang;
	// otherwise, check if an initial language has been specified
	} else if((GL_curLang == "") || (typeof GL_curLang == "undefined")) {
		detectUserLang(); // if not, find out user's language based on their settings, and offer to translate into that language
		GL_curLang = "orig"; // show site using original languages for now
		return; // don't want to store language in cookie until one has been specified, so end function
	}

	setLangCookie(); // if valid cookie exists or initial language was specified, set/renew cookie (to store new expiry date)
}

// If a new user has not specified a language yet, offer to translate page into their current browser / system language
function detectUserLang(){
	/* detect user's current language (if they are using IE this will be based on the regional settings on their system; 
	   otherwise it will be based on the default language of their current browser) */
	var detectedLang = (navigator.language) ? navigator.language : navigator.userLanguage;
	
	// if language cannot be detected for some reason, end function.
	if((typeof detectedLang == "undefined") || (detectedLang == ""))  {
		return;
	}
	
	// if language is regional dialect (e.g. "en-gb"), check last 2 letters are upper case - for google compatibility.
	if(detectedLang.length == 5) {
		detectedLang = detectedLang.substr(0,3) + detectedLang.substr(3).toUpperCase();
	}
	
	// check that Google can translate content into detected language
	if (!google.language.isTranslatable(detectedLang)) {
		// if not, check if language is a regional dialect (e.g. "en-GB")
		if(detectedLang.length == 5) {
			// if so, Google may still be able to translate into a non-regional equivalent (e.g. "en")
			detectedLang = detectedLang.substr(0,2);
			if (!google.language.isTranslatable(detectedLang)) {
				return; // google cannot translate into non-regional equivalent, so end function
			}
		// language is not a regional dialect, and google cannot translate into it, so end function
		} else {
			return;
		}
	}
	
	var detectedLangStr = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
	
	/*
	// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  'Translate this page into ' + detectedLangStr + '? ' +
	'<a href="javascript:changeLang(\'' + detectedLang + '\')">Yes</a> | <a href="javascript:changeLang(\'orig\')">No</a>';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='block'; // show the question on screen
	*/
	
	
		// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  '';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='none'; // show the question on screen
}

// create a cookie to store the current site language
function setLangCookie() {
	// expire previous cookie (if it exists)
	document.cookie = "lang=; expires=-1; path=/";

	// cookie will expire after 90 days.
	var expdate = new Date();
	expdate.setTime(expdate.getTime()+7776000000);

	// create the cookie
	document.cookie = "lang=" + GL_curLang + "; expires=" + expdate.toGMTString() + "; path=/";
}

// refresh the current page [runs if the Original Languages option was selected, or if requested by user after error(s)]
function refresh() {
	hideTransMsg();
	window.location.reload(true);
}

// run the 'initialise' function once the page has loaded.
google.setOnLoadCallback(initialise);

****************The End*****************************


*****************Save it as googlelanguage.js******************


if (!window['google']) {
window['google'] = {};
}
if (!window['google']['loader']) {
window['google']['loader'] = {};
google.loader.ServiceBase = 'http://www.google.com/uds';
google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax';
google.loader.ApiKey = 'notsupplied';
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.Secure = false;
google.loader.GoogleLocale = 'www.google.com';
google.loader.ClientLocation = {"latitude":17.385044,"longitude":78.486671,"address":{"city":"Hyderabad","region":"Andhra Pradesh","country":"India","country_code":"IN"}};
google.loader.AdditionalParams = '';
(function() {var d=true,g=null,h=false,j=encodeURIComponent,l=window,n=undefined,o=document;function p(a,b){return a.load=b}var q="push",r="replace",s="charAt",t="ServiceBase",u="name",v="getTime",w="length",x="prototype",y="setTimeout",z="loader",A="substring",B="join",C="toLowerCase";function D(a){if(a in E)return E[a];return E[a]=navigator.userAgent[C]().indexOf(a)!=-1}var E={};function F(a,b){var c=function(){};c.prototype=b[x];a.Q=b[x];a.prototype=new c}
function G(a,b){var c=Array[x].slice.call(arguments,2)||[];return function(){var e=c.concat(Array[x].slice.call(arguments));return a.apply(b,e)}}function H(a){a=Error(a);a.toString=function(){return this.message};return a}function I(a,b){for(var c=a.split(/\./),e=l,f=0;f<c[w]-1;f++){e[c[f]]||(e[c[f]]={});e=e[c[f]]}e[c[c[w]-1]]=b}function J(a,b,c){a[b]=c}if(!K)var K=I;if(!L)var L=J;google[z].t={};K("google.loader.callbacks",google[z].t);var M={},N={};google[z].eval={};K("google.loader.eval",google[z].eval);
p(google,function(a,b,c){function e(k){var m=k.split(".");if(m[w]>2)throw H("Module: '"+k+"' not found!");else if(typeof m[1]!="undefined"){f=m[0];c.packages=c.packages||[];c.packages[q](m[1])}}var f=a;c=c||{};if(a instanceof Array||a&&typeof a=="object"&&typeof a[B]=="function"&&typeof a.reverse=="function")for(var i=0;i<a[w];i++)e(a[i]);else e(a);if(a=M[":"+f]){if(c&&!c.language&&c.locale)c.language=c.locale;if(c&&typeof c.callback=="string"){i=c.callback;if(i.match(/^[[\]A-Za-z0-9._]+$/)){i=l.eval(i);
c.callback=i}}if((i=c&&c.callback!=g)&&!a.s(b))throw H("Module: '"+f+"' must be loaded before DOM onLoad!");else if(i)a.m(b,c)?l[y](c.callback,0):a.load(b,c);else a.m(b,c)||a.load(b,c)}else throw H("Module: '"+f+"' not found!");});K("google.load",google.load);
google.P=function(a,b){if(b){if(O[w]==0){P(l,"load",Q);if(!D("msie")&&!(D("safari")||D("konqueror"))&&D("mozilla")||l.opera)l.addEventListener("DOMContentLoaded",Q,h);else if(D("msie"))o.write("<script defer onreadystatechange='google.loader.domReady()' src=//:><\/script>");else(D("safari")||D("konqueror"))&&l[y](S,10)}O[q](a)}else P(l,"load",a)};K("google.setOnLoadCallback",google.P);
function P(a,b,c){if(a.addEventListener)a.addEventListener(b,c,h);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var e=a["on"+b];a["on"+b]=e!=g?aa([c,e]):c}}function aa(a){return function(){for(var b=0;b<a[w];b++)a[b]()}}var O=[];google[z].K=function(){var a=l.event.srcElement;if(a.readyState=="complete"){a.onreadystatechange=g;a.parentNode.removeChild(a);Q()}};K("google.loader.domReady",google[z].K);var ba={loaded:d,complete:d};function S(){if(ba[o.readyState])Q();else O[w]>0&&l[y](S,10)}
function Q(){for(var a=0;a<O[w];a++)O[a]();O.length=0}
google[z].d=function(a,b,c){if(c){var e;if(a=="script"){e=o.createElement("script");e.type="text/javascript";e.src=b}else if(a=="css"){e=o.createElement("link");e.type="text/css";e.href=b;e.rel="stylesheet"}(a=o.getElementsByTagName("head")[0])||(a=o.body.parentNode.appendChild(o.createElement("head")));a.appendChild(e)}else if(a=="script")o.write('<script src="'+b+'" type="text/javascript"><\/script>');else a=="css"&&o.write('<link href="'+b+'" type="text/css" rel="stylesheet"></link>')};
K("google.loader.writeLoadTag",google[z].d);google[z].M=function(a){N=a};K("google.loader.rfm",google[z].M);google[z].O=function(a){for(var b in a)if(typeof b=="string"&&b&&b[s](0)==":"&&!M[b])M[b]=new T(b[A](1),a[b])};K("google.loader.rpl",google[z].O);google[z].N=function(a){if((a=a.specs)&&a[w])for(var b=0;b<a[w];++b){var c=a[b];if(typeof c=="string")M[":"+c]=new U(c);else{c=new V(c[u],c.baseSpec,c.customSpecs);M[":"+c[u]]=c}}};K("google.loader.rm",google[z].N);
google[z].loaded=function(a){M[":"+a.module].k(a)};K("google.loader.loaded",google[z].loaded);google[z].J=function(){return"qid="+((new Date)[v]().toString(16)+Math.floor(Math.random()*1E7).toString(16))};K("google.loader.createGuidArg_",google[z].J);I("google_exportSymbol",I);I("google_exportProperty",J);google[z].b={};K("google.loader.themes",google[z].b);google[z].b.z="http://www.google.com/cse/style/look/bubblegum.css";L(google[z].b,"BUBBLEGUM",google[z].b.z);google[z].b.B="http://www.google.com/cse/style/look/greensky.css";
L(google[z].b,"GREENSKY",google[z].b.B);google[z].b.A="http://www.google.com/cse/style/look/espresso.css";L(google[z].b,"ESPRESSO",google[z].b.A);google[z].b.D="http://www.google.com/cse/style/look/shiny.css";L(google[z].b,"SHINY",google[z].b.D);google[z].b.C="http://www.google.com/cse/style/look/minimalist.css";L(google[z].b,"MINIMALIST",google[z].b.C);function U(a){this.a=a;this.q=[];this.p={};this.i={};this.e={};this.l=d;this.c=-1}
U[x].g=function(a,b){var c="";if(b!=n){if(b.language!=n)c+="&hl="+j(b.language);if(b.nocss!=n)c+="&output="+j("nocss="+b.nocss);if(b.nooldnames!=n)c+="&nooldnames="+j(b.nooldnames);if(b.packages!=n)c+="&packages="+j(b.packages);if(b.callback!=g)c+="&async=2";if(b.style!=n)c+="&style="+j(b.style);if(b.other_params!=n)c+="&"+b.other_params}if(!this.l){if(google[this.a]&&google[this.a].JSHash)c+="&sig="+j(google[this.a].JSHash);var e=[];for(var f in this.p)f[s](0)==":"&&e[q](f[A](1));for(f in this.i)f[s](0)==
":"&&this.i[f]&&e[q](f[A](1));c+="&have="+j(e[B](","))}return google[z][t]+"/?file="+this.a+"&v="+a+google[z].AdditionalParams+c};U[x].v=function(a){var b=g;if(a)b=a.packages;var c=g;if(b)if(typeof b=="string")c=[a.packages];else if(b[w]){c=[];for(a=0;a<b[w];a++)typeof b[a]=="string"&&c[q](b[a][r](/^\s*|\s*$/,"")[C]())}c||(c=["default"]);b=[];for(a=0;a<c[w];a++)this.p[":"+c[a]]||b[q](c[a]);return b};
p(U[x],function(a,b){var c=this.v(b),e=b&&b.callback!=g;if(e)var f=new W(b.callback);for(var i=[],k=c[w]-1;k>=0;k--){var m=c[k];e&&f.F(m);if(this.i[":"+m]){c.splice(k,1);e&&this.e[":"+m][q](f)}else i[q](m)}if(c[w]){if(b&&b.packages)b.packages=c.sort()[B](",");for(k=0;k<i[w];k++){m=i[k];this.e[":"+m]=[];e&&this.e[":"+m][q](f)}if(!b&&N[":"+this.a]!=g&&N[":"+this.a].versions[":"+a]!=g&&!google[z].AdditionalParams&&this.l){c=N[":"+this.a];google[this.a]=google[this.a]||{};for(var R in c.properties)if(R&&
R[s](0)==":")google[this.a][R[A](1)]=c.properties[R];google[z].d("script",google[z][t]+c.path+c.js,e);c.css&&google[z].d("css",google[z][t]+c.path+c.css,e)}else if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),e);if(this.l){this.l=h;this.c=(new Date)[v]();if(this.c%100!=1)this.c=-1}for(k=0;k<i[w];k++){m=i[k];this.i[":"+m]=d}}});
U[x].k=function(a){if(this.c!=-1){X("al_"+this.a,"jl."+((new Date)[v]()-this.c),d);this.c=-1}this.q=this.q.concat(a.components);google[z][this.a]||(google[z][this.a]={});google[z][this.a].packages=this.q.slice(0);for(var b=0;b<a.components[w];b++){this.p[":"+a.components[b]]=d;this.i[":"+a.components[b]]=h;var c=this.e[":"+a.components[b]];if(c){for(var e=0;e<c[w];e++)c[e].I(a.components[b]);delete this.e[":"+a.components[b]]}}X("hl",this.a)};U[x].m=function(a,b){return this.v(b)[w]==0};U[x].s=function(){return d};
function W(a){this.H=a;this.n={};this.r=0}W[x].F=function(a){this.r++;this.n[":"+a]=d};W[x].I=function(a){if(this.n[":"+a]){this.n[":"+a]=h;this.r--;this.r==0&&l[y](this.H,0)}};function V(a,b,c){this.name=a;this.G=b;this.o=c;this.u=this.h=h;this.j=[];google[z].t[this[u]]=G(this.k,this)}F(V,U);p(V[x],function(a,b){var c=b&&b.callback!=g;if(c){this.j[q](b.callback);b.callback="google.loader.callbacks."+this[u]}else this.h=d;if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),c);X("el",this[u])});V[x].m=function(a,b){return b&&b.callback!=g?this.u:this.h};V[x].k=function(){this.u=d;for(var a=0;a<this.j[w];a++)l[y](this.j[a],0);this.j=[]};
var Y=function(a,b){return a.string?j(a.string)+"="+j(b):a.regex?b[r](/(^.*$)/,a.regex):""};V[x].g=function(a,b){return this.L(this.w(a),a,b)};
V[x].L=function(a,b,c){var e="";if(a.key)e+="&"+Y(a.key,google[z].ApiKey);if(a.version)e+="&"+Y(a.version,b);b=google[z].Secure&&a.ssl?a.ssl:a.uri;if(c!=g)for(var f in c)if(a.params[f])e+="&"+Y(a.params[f],c[f]);else if(f=="other_params")e+="&"+c[f];else if(f=="base_domain")b="http://"+c[f]+a.uri[A](a.uri.indexOf("/",7));google[this[u]]={};if(b.indexOf("?")==-1&&e)e="?"+e[A](1);return b+e};V[x].s=function(a){return this.w(a).deferred};
V[x].w=function(a){if(this.o)for(var b=0;b<this.o[w];++b){var c=this.o[b];if(RegExp(c.pattern).test(a))return c}return this.G};function T(a,b){this.a=a;this.f=b;this.h=h}F(T,U);p(T[x],function(a,b){this.h=d;google[z].d("script",this.g(a,b),h)});T[x].m=function(){return this.h};T[x].k=function(){};
T[x].g=function(a,b){if(!this.f.versions[":"+a]){if(this.f.aliases){var c=this.f.aliases[":"+a];if(c)a=c}if(!this.f.versions[":"+a])throw H("Module: '"+this.a+"' with version '"+a+"' not found!");}c=google[z].GoogleApisBase+"/libs/"+this.a+"/"+a+"/"+this.f.versions[":"+a][b&&b.uncompressed?"uncompressed":"compressed"];X("el",this.a);return c};T[x].s=function(){return h};var ca=h,Z=[],da=(new Date)[v](),X=function(a,b,c){if(!ca){P(l,"unload",ea);ca=d}if(c){if(!google[z].Secure&&(!google[z].Options||google[z].Options.csi===h)){a=a[C]()[r](/[^a-z0-9_.]+/g,"_");b=b[C]()[r](/[^a-z0-9_.]+/g,"_");l[y](G($,g,"http://csi.gstatic.com/csi?s=uds&v=2&action="+j(a)+"&it="+j(b)),1E4)}}else{Z[q]("r"+Z[w]+"="+j(a+(b?"|"+b:"")));l[y](ea,Z[w]>5?0:15E3)}},ea=function(){if(Z[w]){$(google[z][t]+"/stats?"+Z[B]("&")+"&nc="+(new Date)[v]()+"_"+((new Date)[v]()-da));Z.length=0}},$=function(a){var b=
new Image,c=fa++;ga[c]=b;b.onload=b.onerror=function(){delete ga[c]};b.src=a;b=g},ga={},fa=0;I("google.loader.recordStat",X);I("google.loader.createImageForLogging",$);

}) ();google.loader.rm({"specs":[{"name":"books","baseSpec":{"uri":"http://books.google.com/books/api.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}}}},"feeds",{"name":"friendconnect","baseSpec":{"uri":"http://www.google.com/friendconnect/script/friendconnect.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{}}},"spreadsheets","gdata","visualization",{"name":"sharing","baseSpec":{"uri":"http://www.google.com/s2/sharing/js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{"language":{"string":"hl"}}}},"search",{"name":"maps","baseSpec":{"uri":"http://maps.google.com/maps?file\u003dgoogleapi","ssl":"https://maps-api-ssl.google.com/maps?file\u003dgoogleapi","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"regex":"callback\u003d$1\u0026async\u003d2"},"language":{"string":"hl"}}},"customSpecs":[{"uri":"http://maps.google.com/maps/api/js","ssl":"https://maps-api-ssl.google.com/maps/api/js","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}},"pattern":"^(3|3..*)$"}]},"annotations_v2","wave","orkut",{"name":"annotations","baseSpec":{"uri":"http://www.google.com/reviews/scripts/annotations_bootstrap.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"},"country":{"string":"gl"}}}},"language","earth","ads","elements"]});
google.loader.rfm({":search":{"versions":{":1":"1",":1.0":"1"},"path":"/api/search/1.0/2a8ff2a70ad0b091ae9dfd8b5e832141/","js":"default+en.I.js","css":"default.css","properties":{":JSHash":"2a8ff2a70ad0b091ae9dfd8b5e832141",":NoOldNames":false,":Version":"1.0"}},":language":{"versions":{":1":"1",":1.0":"1"},"path":"/api/language/1.0/62c64af2122d2da7dcb0087852fa7396/","js":"default+en.I.js","properties":{":JSHash":"62c64af2122d2da7dcb0087852fa7396",":Version":"1.0"}},":wave":{"versions":{":1":"1",":1.0":"1"},"path":"/api/wave/1.0/3b6f7573ff78da6602dda5e09c9025bf/","js":"default.I.js","properties":{":JSHash":"3b6f7573ff78da6602dda5e09c9025bf",":Version":"1.0"}},":spreadsheets":{"versions":{":0":"1",":0.3":"1"},"path":"/api/spreadsheets/0.3/8331b0bbcc74776270648505340e9200/","js":"default.I.js","properties":{":JSHash":"8331b0bbcc74776270648505340e9200",":Version":"0.3"}},":earth":{"versions":{":1":"1",":1.0":"1"},"path":"/api/earth/1.0/819ffbf1e363d238791231792a2e0a90/","js":"default.I.js","properties":{":JSHash":"819ffbf1e363d238791231792a2e0a90",":Version":"1.0"}},":annotations":{"versions":{":1":"1",":1.0":"1"},"path":"/api/annotations/1.0/11cfaf30c00ca64601d09fcac7dd8bc7/","js":"default+en.I.js","properties":{":JSHash":"11cfaf30c00ca64601d09fcac7dd8bc7",":Version":"1.0"}}});
google.loader.rpl({":scriptaculous":{"versions":{":1.8.3":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.2":{"uncompre

Revision: 39554
at January 19, 2011 05:47 by mavrikicecool


Updated Code
Read from top to Bottom see for **** especially....and Please don't bother about think about spelling mistakes, as i am little weak in English

Make an application multi lingual by using google API....
This process can even be implemented by an web service, but i have made use of google API
Please follow the steps and make changes accordingly 

PHP(make use of div's and apply to the id's), ASP(Apply to all labesl)...and the rest of the languages follow up the same procedure accoringly......

*****************Add these 2 scripts into u r header and make it common for the pages so that it includes in each and everything***
<!--<script type="text/javascript" src="Translate/googlelanguage.js"></script>
<script type="text/javascript" src="Translate/translate.js"></script>-->
****************Better to add these 2 into head section of u r html or asp or jsp pages********************************************
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
************Add this thing into the body section where ever u wish to or u wanna Place the option for selection*******************
 <!-- <div><font size="+1">Select Language</font></div>
  <div id="mlt_languagelist"> </div>-->
  
  -->Steps:
  	1) As the page is loaded the the 2nd div gets activated and gets processed through the api and data is fetched from the tranlate.js script....check in the line number 166 the function getLangs() gets called and executed.just go through the function and understand the parameters passed u will know better whats happening.
	
	2) G to line number 85 there u will come to know how the langues get changed based upon u r request.
	3)	if(GL_curLang == "orig") {
			refresh();
			return;
		}
	
	find th this block and add few more langues based upon ICANN standards for language notations in google.soon after the above block by dumping more conditions to the above block u can select the langues aby your choice
	
	Add:
		else if(GL_curLang == "es") { //spanish
			refresh();
			return;
		}	
		else if(GL_curLang == "ja") { //japanese
			refresh();
			return;
		} 
		
		
	4) So add according to u r choice all this has to be followed aftr line number 888 for the 3 point.
	
	6) And now get to start of the page translate.js and point towards line 52, there you gonna find a an array assigned toa  variable with various elements within the array, present with other elements within it for the converion usuage.
	for all required labels in asp or the div or span's which u find the page, assign them which are to be changed upon request.
	
	7) rename those elements name by u r own names which u want, use those div's which are present in all front end pages .for each and every text item or asp with label tags, assign these id's one for all those text items(i.e the div's of each and every text item)..and u r almost done
	
	8)save all changes and start using this applicationits gonna work i am sure.....if there is anything lemme know.post it on the comments section i will reply back.
	
	5)By this way the combo box is set with languages which you require to make the application multi lingual
	
	6)this particual api support 64 recognised languages , check the info in google for this particual api.
	
  
********************************************************************************************************************************* 
</body>
</html>


*******************Save it as translate.js***************************

/* Multi-Language Translation Script:
*
*  Automatically translates a webpage (containing text in more than one language) into any single language
*  requested by the user. Particularly useful for sites involving a lot of user-generated content (which
*  might have originally been written in different languages) - e.g. blogs, forums, or other community sites. 
*  Harnesses the Google AJAX Language API to perform translation and language detection.
*
*  Version: 0.2.5 [2010-01-22]
*  Author: Patrick Hathway, OdinLab, University of Reading.
*  For Documentation and Updates: See http://code.google.com/p/multi-language-translation/
*  Licence: MIT License - see http://opensource.org/licenses/mit-license.php for full terms. Also check 
*  the script Documentation for more information, and for details of one important consideration.
*
*  Some minor configuration is required for this script to work on your website. Follow the instructions
*  below, or see the Documentation for full details and examples...   */

/* 1. Specify the 'Base Language' for your website: */

var GL_baseLang = "en";

/* 2. Specify the IDs for all major regions (i.e. HTML elements) in your site that should have their 
*  contents translated. Note that an ID can only be used to identify a single element on a page (for 
*  elements which appear multiple times, use Class Names instead - see below). The script will translate
*  each element separately; any elements that cannot be found on a page will be ignored:   */

var GL_classIds = [
	["navigation"],	
	["navigation", "", true],  
	["quick-id", "", true],  
	["c-quote", "", true],  
	["c-need-quote", "", true],  
	["c-index", "", true],   
	["c-about", "", true],  
	["c-exper", "", true],  
	["c-solution", "", true],
	["c-product", "", true],  
	["c-contact", "", true],  
	["c-indian-add", "", true],  
	["c-work", "", true],  
	["c-contact", "", true],  
	["c-contactinf", "", true],
	["c-usa-add", "", true],  
	["c-warning", "", true],  
	["right_sidebar", "fr", true], 
	["footer"]
];

/* 3. Specify the Class Names of all major regions (i.e. HTML elements) in your site that should have their 
*  their contents translated. Multiple elements may appear on a page with the same class name; the script
*  will locate each occurrance (if present) and translate them separately:   */

var GL_classNames = [
	["entry_baselang"],
	["entry_french", "fr"],
	["index-class", "", true],
	["about-class", "", true],	
	["association-class", "", true],
	["building-class", "", true],
	["career-class", "", true],
	["college-class", "", true],
	["construction-class", "", true],
	["contact-class", "", true], 
	["entry_baselang", "", true], 
	["education-class", "", true], 
	["entry", "", true], 
	["expertise-class", "", true], 
	["description", "", true], 
	["list-custom_website", "", true], 
	["list-beautiful_graphic", "", true], 
	["list-using_nature", "", true],
	["list-css_xhtml", "", true],
	["description", "", true], 
	["list-branding_your", "", true], 
	["list-green_branding", "", true], 
	["list-who_are", "", true], 
	["list-long_term", "", true], 
	["list-the_importance", "", true], 
	["list-flow", "", true], 
	["list-click_through", "", true], 
	["list-scale", "", true], 
	["description", "", true], 
	["list-google_rank", "", true], 
	["list-ppc", "", true], 
	["list-custom_icon", "", true], 
	["list-why_use", "", true], 
	["list-web_standard", "", true], 
	["list-promoting_your", "", true], 
	["list-business_cards", "", true], 
	["fashin-class", "", true], 
	["right", "", true],  
	["web_portfolio", "", true], 
	["interior-class", "", true],
	["manufacture-class", "", true], 
	["news-class", "", true], 
	["medical-class", "", true], 
	["opening-class", "", true], 
	["ourclass-class", "", true], 	
	["portfolio-class", "", true], 	
	["ecommerce-class", "", true], 	
	["mobile-class", "", true], 
	["webdesign-class", "", true], 
	["product-class", "", true], 
	["professional-class", "", true], 
	["real-class", "", true], 
	["realestate-class", "", true], 
	["request-class", "", true],   
	["form_entry", "", true],
	["request-id", "", true],
	["requestquote-class", "", true],
	["consumer-class", "", true],
	["software-class", "", true],
	["solutions-class", "", true],
	["list-why_use", "", true],
	["list-west_coast", "", true], 
	["list-custom_icon", "", true],
	["list-crisp_graphics", "", true],
	["list-scalable_across", "", true],
	["testimonials-class", "", true],  
	["testimonials", "", true],
	["tourism-class", "", true],
	["trade-class", "", true], 
	["transport-class", "", true], 
	["levonsys-class", "", true],  
	["working-levonsys-class", "", true],    
	["quick", "", true], 
	["entry_french", "", true], 
	["quotes", "de", true]
];


/* 4. Specify the default language for new visitors (leave blank to auto-detect using browser/system settings) */

var GL_curLang = "";

/* The rest of the Script should not be modified; unless you want to alter the functionality!
*  ------------------------------------------------------------------------------------------ */

// Global variables:
var GL_srcContent;             // array containing all content on the page to be translated, split up into chunks
var GL_transContent = [];      // array containing all chunks which have been translated
var GL_chunksTotal = 0;        // total number of chunks to translate
var GL_curChunk;               // ID of current chunk being translated
var GL_errors;                 // array containing details of all errors that occur (if applicable)
var GL_errSrcTxt;              // array containing all source text that causes errors (if applicable)
var GL_miniTransItems = [];    // array containing element IDs/class names which contain minor items to translate

google.load("language", "1");  // load v1 of google ajax language api

// run when page loads
function initialise() {
	addTransMsgs();        // append elements (which will display translation status messages) to page
	buildChunkedContent(); // create a local 'cache' of chunked content to be translated
	getLangCookie();       // find out the current site language (if known)
	getLangs();            // display listbox containing all languages the site can be translated into

	// if the original languages should be shown, end function.
	if(GL_curLang == "orig") {
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// display listbox containing all languages the site can be translated into (so that one can be selected by user)
function getLangs() {
	// create listbox within script so that it won't appear if JavaScript is disabled
	document.getElementById("mlt_languagelist").innerHTML = '<select id="mlt_language" onchange="changeLang()" style="width:150px; height:20px;"></select>';
	// +	'<div id="mlt_langattr"></div>'
	var langItems = document.getElementById("mlt_language").options;

	// add option to top of listbox allowing user to view the site in its original (i.e. un-translated) languages
	langItems.add(new Option("Original Languages", "orig", true));

	// loop through list of currently available languages and add each to listbox
	for(var lang in google.language.Languages) {
		// find out the 2 character Google language code
		
		var langCode = google.language.Languages[lang];
		// convert language string to title case
		var langString = lang.substr(0,1) + lang.substr(1).toLowerCase();
		// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
		langString = langString.split("_").join(" - ");

		// check that Google can translate content into the current language
		if ((google.language.isTranslatable(langCode)) && (langCode != "")) {
			// if so, add to listbox and translate, so native speakers of that language can find it
			if(langCode=="ar")
			{
				langItems.add(new Option(langString, langCode));
				miniTranslate(langItems[(langItems.length-1)],langCode);
			}
			
		}
	}

	document.getElementById("mlt_language").value = GL_curLang; // change listbox to display current site language
	google.language.getBranding("mlt_langattr");  // display Google attribution below listbox (as required by TOS)
}

// start the translation
function startTranslation() {
	// reset global variables
	GL_curChunk = 0; GL_errors = []; GL_errSrcTxt = [];
	
	// check if all content has already been translated into current language since page loaded.
	if(chkLangTrans()) {
		return; // if so, don't need to translate content again
	} 
	
	// sanity check - can google actually translate into the current site language?
	if (!(google.language.isTranslatable(GL_curLang)) || (GL_curLang == "")) {
		return; // if not, end translation
	} // Otherwise, send content to google to be translated:
	
	// show the 'Translating...' block
	document.getElementById("mlt_translatemsg").innerHTML = 'Translating... <span id="mlt_perc">0%</span>';
	miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	document.getElementById("mlt_translatemsg").style.display='block';

	// find out the ID of the destination language
	var curLangNo = document.getElementById("mlt_language").selectedIndex;
	var k = 0;
	
	// create sub-array to hold all translations for current language
	GL_transContent[GL_transContent.length]        = new Array(3);
	GL_transContent[(GL_transContent.length-1)][0] = []; // this array will contain all translated chunks
	GL_transContent[(GL_transContent.length-1)][1] = GL_curLang; // store current language
	GL_transContent[(GL_transContent.length-1)][2] = false; // mark translation of language as incomplete

	// loop through all the chunks to be translated, send to google...
	for(var i = 0; i < GL_srcContent.length; i++) {
		// find out the source language for the current element to be translated
		var srcLang = GL_srcContent[i][GL_srcContent[i].length - 1];

		for(var j = 0; j < (GL_srcContent[i].length - 1); j++) {
			/* AJAX is used to return translated chunks, so they MAY be returned in any order.
		   	To solve, include current chunk id, destination language + separators at start of each
		   	string. This is a bit of a 'hack', so try to find a better solution! */
			var srcText = curLangNo + "<br />" + k + "<br />" + GL_srcContent[i][j];

			// send current chunk to google translate; when translated, call function translateChunk
			google.language.translate(srcText, srcLang, GL_curLang, translateChunk);
			k++;
		}
	}

	setTimeout("checkTransStatus()", 1000); // run function to check translation status after 1 second
}

// check if page content has already been translated into current language since page loaded.
function chkLangTrans() {
	// loop through the list of languages the page has been translated into
	for(var i = 0; i < GL_transContent.length; i++) {
		// check if a translation for current language exists, and if so, whether it is complete.
		if((GL_transContent[i][1] == GL_curLang) && (GL_transContent[i][2] == true)){
			/* if so, don't need to send content to google again, just assemble the pre-translated content.
			This will *dramatically* reduce the translation time for this language! */
			endTranslation(i);
			return true;
		} 
	}
	return false; // otherwise, all relevant page content must be submitted to google for translation.
}

// This runs after each chunk has been translated...
function translateChunk(result) {
	// handle translation errors gracefully by storing error details but allowing translation to continue
	if (result.error) {
		GL_errors[GL_errors.length] = result.error.message;
	}
	else {

	/* Translated chunks may be returned in any order, so we need a method to assemble the chunks
	   in the correct order:
	   * Start of each chunk has a destination language id and a chunk id followed by separators.
	   * Separator is a <br /> HTML tag, as these always appear to retain position after translation...
	   * The destination language id is used to ensure the translated text is now in the correct language.
	   * Each chunk is stored in the position of the 'GL_transContent' array corresponding to the current chunk id.
	   * The ids + separators should not be shown, and are discarded from the chunk when it's stored in array.
	*/
	
		// split into array based on separator, so we know the id & destination language of translated chunk
		var transChunk = result.translation.split("<br />");
		// [find out length of substring to chop off from start of chunk]
		var chunkSubStr = 12 + transChunk[0].length + transChunk[1].length;
		// remove whitespace from chunk id & destination language (a problem with some translations)
		transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
		transChunk[1] = transChunk[1].replace(/^\s+|\s+$/g,"");

		/* If the translated chunk has a different destination language to the current site language, discard
		translation & end function. This may happen if user changes language whilst translation is in progress */
		if(transChunk[0] != document.getElementById("mlt_language").selectedIndex) {
			return;
		}

		// store translated chunk in current language array, along with detected source language (if known)
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]] = new Array(3);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][0] = result.translation.substr(chunkSubStr);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][1] = result.detectedSourceLanguage;
	}

	GL_curChunk++; // increment current chunk ID every time function is called

	// calculate and display percentage of translation completed, based on number of chunks remaining
	var perc = (GL_curChunk / GL_chunksTotal)*100;
	document.getElementById("mlt_perc").innerHTML = Math.round(perc) + "%";

	// when all chunks have been translated, run the 'endTranslation' function...
	if(GL_curChunk >= GL_chunksTotal) {
		endTranslation((GL_transContent.length-1)); // [final array element holds current language content!]
	}
}

/* runs once a second whilst translation is in progress, updating contents of all elements that have already
   been completely translated. Also shows 'timeout' messages if translation not completed within 30 seconds... */
function checkTransStatus() {
	// 'static' member variables to keep track of how many times function has run, as well as current language:
	if((typeof checkTransStatus.chkStatusCount == 'undefined') || (checkTransStatus.curTransLang != GL_curLang)) {
		// reset variables if not defined yet, or if site language has changed since last function call
        	checkTransStatus.chkStatusCount = 0;
		checkTransStatus.curTransLang = GL_curLang;
	}

	// if translation is now complete, end function.
	if(GL_curChunk >= GL_chunksTotal) {
		return;
	}
	
	checkTransStatus.chkStatusCount++; // increment Translation Status counter

	// Store the list of languages in case they are replaced during translation
	var langList = document.getElementById("mlt_languagelist").innerHTML;

	var curElement; var curTransChunk = 0; var curClass = 0; var curTransLang = GL_transContent.length-1;

	// loop through all element IDs (as specified at script top), searching for ones with completed translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,false);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), searching for completed translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],false);
				curClass++; // move to next element Class Name
			}
		}
	}

	// if listbox containing all languages has been removed as a result of translation, display it again
	if(document.getElementById("mlt_languagelist").innerHTML == "") {
		document.getElementById("mlt_languagelist").innerHTML = langList;
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to show current language
	}

	/* if translation still isn't complete after 30 seconds, update translation message. Note: there is no
	   need to halt the current translation completely, but we will allow user to restart it if desired! */
	if(checkTransStatus.chkStatusCount == 30) {
		// calculate and display percentage of translation completed, based on number of chunks remaining
		var perc = Math.round((GL_curChunk / GL_chunksTotal)*100) + "%";
		// update translation status message
		document.getElementById("mlt_translatemsg").innerHTML = 'Translating (Slowly!)... ' +
		'<span id="mlt_perc">' + perc + '</span> - <a href="javascript:refresh()">Retry</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	}

	setTimeout("checkTransStatus()", 1000); // check translation status again after another second
}

// runs after all translations have been completed; displaying the results on screen in place of previous content
function endTranslation(curTransLang) {
	var curElement;
	var curTransChunk = 0; var curClass = 0;

	// loop through all element IDs (as specified at script top), replacing current contents with translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,true,GL_classIds[i]);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), so contents can be replaced by translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],true,GL_classNames[i]);
				curClass++; // move to next element Class Name
			}
		}
	}

	// Perform translations of all content added by the script (e.g. language strings and error messages)
	transAddedText();

	// Re-create listbox containing all languages, in case it has been removed as a result of translation
	getLangs();

	// translate the 'Original Languages' listbox item to equivalent in current site language
	miniTranslate(document.getElementById("mlt_language").options[0],GL_curLang,"Original Languages");
	
	// if any errors occured during translation, display warning message at top of screen and end function 
	if(GL_errors.length != 0) {
		document.getElementById("mlt_translatemsg").innerHTML = GL_errors.length + ' Problems(s) Occurred During Translation: ' +
		'<a href="javascript:refresh()">Retry</a> - <a href="javascript:showErrDetails()">Details</a> - ' +
		'<a href="javascript:hideTransMsg()">Hide</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate warning message into current site language
		return;
	}
	
	// mark translation of page into current language as complete, so that translation can be quicker next time.
	GL_transContent[curTransLang][2] = true;

	hideTransMsg(); // otherwise, hide 'Translating...' message
}

// assemble and display translated chunks for current element on page
function unpackTransChunks(curTransLang,curTransChunk,curClassNum,curElement,transComplete,curClass) {
	// 'static' member variable to keep track of how many times function has run
	if(typeof unpackTransChunks.curLinkId == 'undefined') {
		// reset curLinkId variable if not defined yet - it's used to identify the correct 'show source text' link
        	unpackTransChunks.curLinkId = 0;
	} unpackTransChunks.curLinkId++; var j = unpackTransChunks.curLinkId; // increment current link id, j is an alias

	var curContent = ""; // reset translated contents of current element
	var initTransChunk = curTransChunk; // store initial chunk id of current element

	// loop through all translated chunks, assembling all translated content for current element
	for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
		// if current chunk does not exist, translation is not complete or errors occurred
		if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == false)) {
			break; // stop looping through chunks if full translation has not yet been completed
		} else if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == true)) {
			// if full translation IS complete, show warning message and a link to show source text (in red)
			curContent += '<div style="color: red;" id="mlt_srctxt' + j + '">[<span class="mlt_transerrtxt">' +
			'<em style="text-transform: uppercase;">THIS SECTION COULD NOT BE TRANSLATED</em> - '+
			'<a id="mlt_srctxtlnk' + j + '" href="javascript:showSrcTxt(' + j + ',' + curClassNum + ',' + (i+1) + 
			')">View Source Text [+]</a></span><span id="mlt_srctxtbracket' + j + '">]</span></div>';
			GL_errSrcTxt[GL_errSrcTxt.length] = GL_srcContent[curClassNum][i]; // store affected source text
			unpackTransChunks.curLinkId++; j = unpackTransChunks.curLinkId; // increment current link id		
		} else {
			// otherwise append current translated chunk to translated content string
			curContent += GL_transContent[curTransLang][0][curTransChunk][0];
		}
		curTransChunk++; // move to next chunk
	}

	// if translation is complete, replace contents of current element with translated text
	if(transComplete == true) {
		curElement.innerHTML = curContent;
		// append a language string to bottom of current element if desired
		getLangString(curTransLang,curElement,curClass,initTransChunk,(GL_srcContent[curClassNum].length - 1),j,curClassNum);
	// otherwise, check if all translated chunks for current element were assembled
	} else if((i == (GL_srcContent[curClassNum].length - 1)) && (GL_transContent[curTransLang][0][initTransChunk][2] != true)) {			
		// if so (and current element translation is not yet marked as complete), replace contents with translation
		curElement.innerHTML = curContent;
		GL_transContent[curTransLang][0][initTransChunk][2] = true; // mark current element translation as complete
	}

	return curTransChunk; // return current chunk id to calling function
}

// If required, find and append a string containing the Source Language to the bottom of the specified element
function getLangString(curTransLang,curElement,curClass,curTransChunk,transChunksLen,j,curClassNum) {
	
	var detectedLang = "";

	// if the current element does not need a language string appended, end function
	if(curClass[2] != true) {
		return;
	}

	// if source language for current element has already been manually specified, set this as detected language
	if(curClass[1] != "") {
		detectedLang = curClass[1];
	}
	// otherwise find out language based on the detected source languages for translated chunks in current element 
	else {
		detectedLang = findDetectedLang(curTransLang,curTransChunk,transChunksLen);
	}

	// if detected language is same as site language, there is no need to display language string, so end function
	if(detectedLang == GL_curLang){
			return;
	}

	var srcLangString = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string 

	// append language string to current element...
//	curElement.innerHTML += '<div style="color: green;" id="mlt_srctxt' + j + '"></div>';
}

// convert a google language code into a formatted string containing the language name
function getFmtLangStr(lang) {
	// loop through list of supported languages and retrieve names
	for(var l in google.language.Languages) {
		if(google.language.Languages[l] == lang) {
			// convert language string into title case
			var lang = l.substr(0,1) + l.substr(1).toLowerCase();
			// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
			lang = lang.split("_").join(" - ");
			break; // stop loop (don't need to continue searching for languages)
		}
	}
	// if language cannot be found in list of supported languages, set language to 'unknown'
	if(typeof lang == "undefined") {
		lang = "An Unknown Language";
	}
	return lang; // return formatted language string
}

// find out the most common detected language for all translated chunks in current element, to appear in language string
function findDetectedLang(curTransLang,curTransChunk,transChunksLen) {
	var chunkLangs = []; langCounter = 0;

	// loop through all translated chunks in current element
	for(var i = 0; i < transChunksLen; i++) {
		// bugfix: set detected language to 'undefined' if an error occurred during translation... 
		if(GL_transContent[curTransLang][0][curTransChunk] == null) {
			GL_transContent[curTransLang][0][curTransChunk] = new Array(3);
			GL_transContent[curTransLang][0][curTransChunk][1] = "undefined";	
		}
		// loop through array of detected languages to see if current chunk has an existing detected language
		for(var j = 0; j < chunkLangs.length; j++) {
			if(chunkLangs[j][0] == GL_transContent[curTransLang][0][curTransChunk][1]) {
				// if so, increment counter containing the total number of chunks with that language
				chunkLangs[j][1]++;
				break; // halt loop
			}
		}
		// if current chunk has a language not yet detected, add it to end of detected languages array
		if(j == chunkLangs.length) {
			chunkLangs[j] = new Array(2);
			chunkLangs[j][0] = GL_transContent[curTransLang][0][curTransChunk][1]; // name of detected language
			chunkLangs[j][1] = 1; // total number of chunks with that language
		}
		curTransChunk++; // move to next chunk
	}

	/* once array has been created containing all detected languages in current element, loop through it
	to find the most common detected language - language string should contain this */
	for(i = 0; i < chunkLangs.length; i++) {
		if(chunkLangs[i][1] > langCounter) {
			/* if current language was detected more times than all previous languages, store language
			and number of times detected - so that next language can be compared against this total */
			var detectedLang = chunkLangs[i][0];
			langCounter = chunkLangs[i][1];
		}		
	}
	
	return detectedLang; // return the most common detected language
}

// Auto-translate all text added previously by the script (including language strings and error messages)
function transAddedText() {
	var allElements = document.getElementsByTagName("*"); // get all elements on page, so relevant ones can be translated
	var foundElements = [];

	// loop through all elements to find any of class 'mlt_langstring' or 'mlt_transerrtxt' 
	for(var i=0; i<allElements.length; i++) {
		if((allElements[i].className == "mlt_langstring") || (allElements[i].className == "mlt_transerrtxt")) {
			foundElements[foundElements.length] = allElements[i];
		}
	}

	// translate all located elements (runs separately from above code to prevent infinite loop as items are translated)
	for(i = 0; i < foundElements.length; i++) {
		miniTranslate(foundElements[i]); // translate current element
	}
}

/* this function runs before any translation takes place, and creates a local 'cache' of all content to be translated (in chunks)
   - meaning the content can be submitted to Google more rapidly, and the resulting translations can then be sorted reliably */
function buildChunkedContent() {
	var curElement; GL_srcContent = []; var j = 0;

	/* loop through all applicable element IDs (as specified at script top), converting the contents of each into chunks,
	   and storing each chunk in an array */
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element
		// check that element actually exists on the page - if not, ignore it
		if(curElement != null) {
			GL_srcContent[j] = createChunks(curElement); // separate the content of current element into chunks
			GL_chunksTotal += GL_srcContent[j].length;   // store a running total of the number of chunks created

			// if a Source Language is not specified for current element, store Base Language in array instead
			if(GL_classIds[i].length == 1) {
				GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
			} else {
				// otherwise store the specified language (or a blank string if this is to be auto-detected)
				GL_srcContent[j][GL_srcContent[j].length] = GL_classIds[i][1];
			}
			j++;
		}
	}

	// get all elements on page, so that the ones specified can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all applicable element IDs (as specified at script top), converting into chunks and storing in array
	for(var i = 0; i < GL_classNames.length; i++) {
		// find all elements which have the current class name
		for(var k = 0; k < allElements.length; k++) { 
			if(allElements[k].className == GL_classNames[i][0]) {
				// separate the content of current element into chunks
				GL_srcContent[j] = createChunks(allElements[k]);
				// store a running total of the number of chunks created
				GL_chunksTotal += GL_srcContent[j].length;

				// if a Source Language is not specified for current element, store Base Language in array
				if(GL_classNames[i].length == 1) {
					GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
				} else {
					// otherwise store specified language (or a blank string if auto-detected)
					GL_srcContent[j][GL_srcContent[j].length] = GL_classNames[i][1];
				}
				j++;
			}
		}
	}
}

/* Web browsers (and Google) limit the amount of text translated per request, so split contents of current element into chunks.
   The aim is to achieve this whilst maintaining the translation integrity */
function createChunks(srcContent) {	
	var chars = 1000; // number of characters to allow per chunk.

	/* We do NOT want the content inside any HTML tag to be split between chunks (as this could cause 
	rendering problems), so create 2 arrays storing tags and textual content of current div separately */
	var tags = srcContent.innerHTML.match(/<.*?>/g);
	var text = srcContent.innerHTML.split(/<.*?>/g);
	if(tags == null) {
		tags = new Array();} // handle content containing no tags

	var curchar = 0; var tagnum = 0; var textnum = 0; var contTotal = tags.length + text.length;
	// create an array containing content to be chunked, with tags + text separately re-assembled (in order)
	var content = new Array(contTotal);
	// loop through content of current div
	for(var i=0; i < contTotal; i++) {
		// if current position in content is the start of a tag char, add appropriate tag to content array
		if(srcContent.innerHTML.substr(curchar,1) == "<") {
			content[i] = tags[tagnum];
			curchar += tags[tagnum].length;
			tagnum++;
		// if it is a text string, add the corresponding text to the curent element in content array
		} else {
			content[i] = text[textnum];
			curchar += text[textnum].length;
			textnum++;
		}
	}

	// Create the chunks - don't split either tags or words (to ensure as high translation quality as possible)
	var chunks = []; var curChunk = 0;
	chunks[0]="";
	for (i = 0; i < contTotal; i++) {
		// if next content item (tag or textual) won't exceed length of current chunk, add it to chunk
		if((chunks[curChunk].length + content[i].length) < chars) {
			chunks[curChunk] += content[i];
		} else {
			// otherwise, proceed to next chunk.
			curChunk++;
			// add the entire content item to this chunk if possible (to ensure better translation)
			if(content[i].length < chars) {
				chunks[curChunk] = content[i];
			}
			else {
				// only split further in rare cases where text length exceeds maximum chunk size
				var curPos = 0;
				do {
					// retrieve the maximum amount of text that can fit in this chunk
					var subContent = content[i].substr(curPos,chars);
					// find out how many words are in this substring
					var words = subContent.split(" ");
					// chop off final word, so words aren't split up between chunks
					var lastWordPos = subContent.length - words[(words.length-1)].length;
					if(subContent.length < chars) { // [bugfix: prevent word cut-off on final iteration]
						lastWordPos = subContent.length}
					chunks[curChunk] = subContent.substr(0,lastWordPos); // store in chunk
					curChunk++; // remainder of text will go in next chunk
					curPos+=lastWordPos; // store current position in text, for further processing
				} while(subContent.length >= chars); // repeat until all this text has been chunked
				curChunk--; // because there may still be space in the current chunk!
			}
		}
	}		
	
	return chunks; // return chunked content to calling function...
}

// Append elements to page (will be used to display translation messages), and specify their css styles.
function addTransMsgs() {
	// add element to page which will contain translation messages
	var transCont = document.createElement("div");
	document.body.appendChild(transCont);
	
	// add element to container created above - this will display the translation messages
	var translateMsg = document.createElement("div");
	translateMsg.id = "mlt_translatemsg";
	transCont.appendChild(translateMsg);

	// define visual styles for translation messages displayed on screen
	translateMsg.style.backgroundColor = "silver";
	translateMsg.style.border = "3px green solid";
	translateMsg.style.padding = "5px";
	translateMsg.style.fontSize = "large";
	translateMsg.style.fontWeight = "bold";
	translateMsg.style.textAlign = "left";
	translateMsg.style.color = "black";

	// more translation message styles (these should not need editing!)
	translateMsg.style.left = "-50%";
	translateMsg.style.position = "relative";
	translateMsg.style.display = "none";
	
	// define the styles for the container element
	transCont.style.left = "50%";
	transCont.style.zIndex = "1000";
	if(!(/MSIE 6/i.test(navigator.userAgent))) {
		// styles for all browsers except IE6
		transCont.style.position = "fixed";
		transCont.style.top = "0px";
	}
	else {
		// styles for IE6
		transCont.style.position = "absolute";
		transCont.style.setExpression("top", "(i = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
	}
}

// Hide 'Translating...' message (or translation error message) - runs at end of translation, or if user dismisses error message
function hideTransMsg() {
	document.getElementById("mlt_translatemsg").innerHTML = "";
	document.getElementById("mlt_translatemsg").style.display='none';
}

// if the user clicks on the 'Details' link [after error(s) occurred], show details of all errors on screen
function showErrDetails() {
	// continue to show original error message (but remove 'Details' link)
	document.getElementById("mlt_translatemsg").innerHTML = '<span id="mlt_transerrmsg1">' + GL_errors.length + 
	' Problems(s) Occurred During Translation: ' + '<a href="javascript:refresh()">Retry</a> - ' +
	'<a href="javascript:hideTransMsg()">Hide</a>... <br /><em>Error(s) Reported:</em></span>' +
	'<ul style="margin: 0px; padding: 0px;" id="mlt_transerrlist"></ul>';

	// Loop through array containing details of all errors, and show them as a list on screen
	for(var i = 0; i < GL_errors.length; i++) {
		document.getElementById("mlt_transerrlist").innerHTML += '<li style="margin-left: 15px;">' + GL_errors[i] + '.</li> ';	
	}

	/* create a textarea - this will show the original source text of all affected sections (as HTML) to aid debugging
	   Note: because translations are returned using AJAX, the affected sections are not NECESSARILY in the same order as
	   the errors reported (though in many cases, they will be!) */
	document.getElementById("mlt_translatemsg").innerHTML += '<em id="mlt_transerrmsg2">Section(s) Affected:</em><br />' +
	'<textarea id="mlt_errsrctxt" rows="8" readonly="readonly" style="width: 99%; background-color: silver; border: 1px gray solid;">' +
	'</textarea>';

	// Loop through Source Text array, appending to textarea.
	for(var i = 0; i < GL_errSrcTxt.length; i++) {
		document.getElementById("mlt_errsrctxt").value += "Affected Section " + (i+1) + ":\n" + GL_errSrcTxt[i] + "\n\n";
	}

	// Translate the entire contents of the Translation Errors box (with the exception of the text inside the textarea)
	miniTranslate(document.getElementById("mlt_transerrmsg1")); miniTranslate(document.getElementById("mlt_transerrlist"));
	miniTranslate(document.getElementById("mlt_transerrmsg2"));
}

// function runs when the user clicks on a link to view the original source text for a translated element / chunk
function showSrcTxt(curLinkId,curClassNum,curChunkId) {
	// if the current chunk should be shown only, display chunk on screen
	if((curChunkId-1) != -1) {
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+GL_srcContent[curClassNum][(curChunkId-1)]+']</div>';
	} else {
	// otherwise assemble all chunks for current element, and display on screen
		var srcTxt = "";
		for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
			srcTxt +=  GL_srcContent[curClassNum][i];
		}
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+srcTxt+']</div>';
	}	

	// update Source Text link so that when clicked in future, the source text will be hidden instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "Hide Source Text [-]";
	srcTxtLnk.href = 'javascript:hideSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = ""; // hide bracket after link
}

// function runs when the user clicks on a link to hide the original source text for a translated element / chunk
function hideSrcTxt(curLinkId,curClassNum,curChunkId) {
	// remove the element containing the original source text
	srcTxtContent = document.getElementById("mlt_srctxtcontent"+curLinkId);
	document.getElementById("mlt_srctxt"+curLinkId).removeChild(srcTxtContent);

	// update Source Text link so that when clicked in future, the source text will be shown instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "View Source Text [+]";
	srcTxtLnk.href = 'javascript:showSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = "]"; // show bracket after link
}

// translate small non crucial items of text into current site language
function miniTranslate(item,destLang,srcTxt) {
	if(typeof destLang == "undefined") {
		var destLang = GL_curLang; // if the destLang argument was not specified, use the current site language
	}
	if(typeof srcTxt == "undefined") {
		var srcTxt = item.innerHTML; // if the srcText argument was not specified, use the current item contents
	}

	// loop through translated items array to see if a translation for current text already exists since page loaded
	for(var i = 0; i < GL_miniTransItems.length; i++) {
		// check if source text and destination language match a translated item (and a completed translation exists for it)
		if((GL_miniTransItems[i][1] == srcTxt) && (GL_miniTransItems[i][2] == destLang) && (GL_miniTransItems[i][3] != "")) {
			item.innerHTML = GL_miniTransItems[i][3]; // if so, display existing translation in item
			item.title = srcTxt.split(/<.*?>/g).join(""); // display English source text as a tooltip (strip HTML first)
			return; // Don't need to send a translation request to Google, so end function.
		}
	}

	// store item to be translated in global array for access by callback function
	GL_miniTransItems[GL_miniTransItems.length]	   = new Array(4);
	GL_miniTransItems[(GL_miniTransItems.length-1)][0] = item;
	GL_miniTransItems[(GL_miniTransItems.length-1)][1] = srcTxt;
	GL_miniTransItems[(GL_miniTransItems.length-1)][2] = destLang;
	GL_miniTransItems[(GL_miniTransItems.length-1)][3] = "";

	// create source text by adding current item ID to start of item text (ID will ensure correct item is translated)
	srcTxt = (GL_miniTransItems.length-1) + "<br />" + srcTxt;

	google.language.translate(srcTxt, "en", destLang, function(result) {
        	if (!result.error) {
			// split into array based on separator, so we know the id of translated item
			var transChunk = result.translation.split("<br />");
			// [find out length of substring to chop off from start of item]
			var chunkSubStr = 6 + transChunk[0].length;
			// remove whitespace from item id (a problem with some translations)
			transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");

			// display english source text of translated item (with HTML stripped) if user hovers mouse over it
			var strippedSrcTxt = GL_miniTransItems[transChunk[0]][1].split(/<.*?>/g).join("");
			GL_miniTransItems[transChunk[0]][0].title = "[" + strippedSrcTxt  + "]";

			// store and display translation of specified item (stripping item ID from start of text)
			GL_miniTransItems[transChunk[0]][3] = result.translation.substr(chunkSubStr);
			GL_miniTransItems[transChunk[0]][0].innerHTML = GL_miniTransItems[transChunk[0]][3];
        	}
	});
}

// runs when the user changes the site language
function changeLang(destLang) {
	if(typeof destLang != "undefined") {
		GL_curLang = destLang; // if the destLang argument was specified, set new site language to this
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to display new site language
	} else {
		// otherwise get the new language requested by user
		GL_curLang = document.getElementById("mlt_language").value;
	}

	// store the requested language in a cookie
	setLangCookie();
	
	// if the original site languages should be shown, refresh the page.
	if(GL_curLang == "orig") {
		refresh();
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// find out the value of the language cookie (if it exists)
function getLangCookie() {
	var curStoredLang;
	// retrieve a list of cookies for this page, split into array elements (separated by ; if multiple cookies)
	var getCurLang=document.cookie.split(";");
	// loop through all array elements (i.e. cookies) until one with name 'lang' is found.
	for(var i=0; i < getCurLang.length; i++) {

		// remove whitespace from cookies (a problem if there are multiple cookies)
		var lngCookie = getCurLang[i].replace(/^\s+|\s+$/g,"");

		if(lngCookie.indexOf("lang=") == 0) {
			// find out value of lang
			curStoredLang = lngCookie.substring(5);
		}
	}
	
	// if language cookie exists, set current site language to stored value
	if(typeof curStoredLang != "undefined") {
		GL_curLang = curStoredLang;
	// otherwise, check if an initial language has been specified
	} else if((GL_curLang == "") || (typeof GL_curLang == "undefined")) {
		detectUserLang(); // if not, find out user's language based on their settings, and offer to translate into that language
		GL_curLang = "orig"; // show site using original languages for now
		return; // don't want to store language in cookie until one has been specified, so end function
	}

	setLangCookie(); // if valid cookie exists or initial language was specified, set/renew cookie (to store new expiry date)
}

// If a new user has not specified a language yet, offer to translate page into their current browser / system language
function detectUserLang(){
	/* detect user's current language (if they are using IE this will be based on the regional settings on their system; 
	   otherwise it will be based on the default language of their current browser) */
	var detectedLang = (navigator.language) ? navigator.language : navigator.userLanguage;
	
	// if language cannot be detected for some reason, end function.
	if((typeof detectedLang == "undefined") || (detectedLang == ""))  {
		return;
	}
	
	// if language is regional dialect (e.g. "en-gb"), check last 2 letters are upper case - for google compatibility.
	if(detectedLang.length == 5) {
		detectedLang = detectedLang.substr(0,3) + detectedLang.substr(3).toUpperCase();
	}
	
	// check that Google can translate content into detected language
	if (!google.language.isTranslatable(detectedLang)) {
		// if not, check if language is a regional dialect (e.g. "en-GB")
		if(detectedLang.length == 5) {
			// if so, Google may still be able to translate into a non-regional equivalent (e.g. "en")
			detectedLang = detectedLang.substr(0,2);
			if (!google.language.isTranslatable(detectedLang)) {
				return; // google cannot translate into non-regional equivalent, so end function
			}
		// language is not a regional dialect, and google cannot translate into it, so end function
		} else {
			return;
		}
	}
	
	var detectedLangStr = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
	
	/*
	// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  'Translate this page into ' + detectedLangStr + '? ' +
	'<a href="javascript:changeLang(\'' + detectedLang + '\')">Yes</a> | <a href="javascript:changeLang(\'orig\')">No</a>';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='block'; // show the question on screen
	*/
	
	
		// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  '';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='none'; // show the question on screen
}

// create a cookie to store the current site language
function setLangCookie() {
	// expire previous cookie (if it exists)
	document.cookie = "lang=; expires=-1; path=/";

	// cookie will expire after 90 days.
	var expdate = new Date();
	expdate.setTime(expdate.getTime()+7776000000);

	// create the cookie
	document.cookie = "lang=" + GL_curLang + "; expires=" + expdate.toGMTString() + "; path=/";
}

// refresh the current page [runs if the Original Languages option was selected, or if requested by user after error(s)]
function refresh() {
	hideTransMsg();
	window.location.reload(true);
}

// run the 'initialise' function once the page has loaded.
google.setOnLoadCallback(initialise);

****************The End*****************************


*****************Save it as googlelanguage.js******************


if (!window['google']) {
window['google'] = {};
}
if (!window['google']['loader']) {
window['google']['loader'] = {};
google.loader.ServiceBase = 'http://www.google.com/uds';
google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax';
google.loader.ApiKey = 'notsupplied';
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.Secure = false;
google.loader.GoogleLocale = 'www.google.com';
google.loader.ClientLocation = {"latitude":17.385044,"longitude":78.486671,"address":{"city":"Hyderabad","region":"Andhra Pradesh","country":"India","country_code":"IN"}};
google.loader.AdditionalParams = '';
(function() {var d=true,g=null,h=false,j=encodeURIComponent,l=window,n=undefined,o=document;function p(a,b){return a.load=b}var q="push",r="replace",s="charAt",t="ServiceBase",u="name",v="getTime",w="length",x="prototype",y="setTimeout",z="loader",A="substring",B="join",C="toLowerCase";function D(a){if(a in E)return E[a];return E[a]=navigator.userAgent[C]().indexOf(a)!=-1}var E={};function F(a,b){var c=function(){};c.prototype=b[x];a.Q=b[x];a.prototype=new c}
function G(a,b){var c=Array[x].slice.call(arguments,2)||[];return function(){var e=c.concat(Array[x].slice.call(arguments));return a.apply(b,e)}}function H(a){a=Error(a);a.toString=function(){return this.message};return a}function I(a,b){for(var c=a.split(/\./),e=l,f=0;f<c[w]-1;f++){e[c[f]]||(e[c[f]]={});e=e[c[f]]}e[c[c[w]-1]]=b}function J(a,b,c){a[b]=c}if(!K)var K=I;if(!L)var L=J;google[z].t={};K("google.loader.callbacks",google[z].t);var M={},N={};google[z].eval={};K("google.loader.eval",google[z].eval);
p(google,function(a,b,c){function e(k){var m=k.split(".");if(m[w]>2)throw H("Module: '"+k+"' not found!");else if(typeof m[1]!="undefined"){f=m[0];c.packages=c.packages||[];c.packages[q](m[1])}}var f=a;c=c||{};if(a instanceof Array||a&&typeof a=="object"&&typeof a[B]=="function"&&typeof a.reverse=="function")for(var i=0;i<a[w];i++)e(a[i]);else e(a);if(a=M[":"+f]){if(c&&!c.language&&c.locale)c.language=c.locale;if(c&&typeof c.callback=="string"){i=c.callback;if(i.match(/^[[\]A-Za-z0-9._]+$/)){i=l.eval(i);
c.callback=i}}if((i=c&&c.callback!=g)&&!a.s(b))throw H("Module: '"+f+"' must be loaded before DOM onLoad!");else if(i)a.m(b,c)?l[y](c.callback,0):a.load(b,c);else a.m(b,c)||a.load(b,c)}else throw H("Module: '"+f+"' not found!");});K("google.load",google.load);
google.P=function(a,b){if(b){if(O[w]==0){P(l,"load",Q);if(!D("msie")&&!(D("safari")||D("konqueror"))&&D("mozilla")||l.opera)l.addEventListener("DOMContentLoaded",Q,h);else if(D("msie"))o.write("<script defer onreadystatechange='google.loader.domReady()' src=//:><\/script>");else(D("safari")||D("konqueror"))&&l[y](S,10)}O[q](a)}else P(l,"load",a)};K("google.setOnLoadCallback",google.P);
function P(a,b,c){if(a.addEventListener)a.addEventListener(b,c,h);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var e=a["on"+b];a["on"+b]=e!=g?aa([c,e]):c}}function aa(a){return function(){for(var b=0;b<a[w];b++)a[b]()}}var O=[];google[z].K=function(){var a=l.event.srcElement;if(a.readyState=="complete"){a.onreadystatechange=g;a.parentNode.removeChild(a);Q()}};K("google.loader.domReady",google[z].K);var ba={loaded:d,complete:d};function S(){if(ba[o.readyState])Q();else O[w]>0&&l[y](S,10)}
function Q(){for(var a=0;a<O[w];a++)O[a]();O.length=0}
google[z].d=function(a,b,c){if(c){var e;if(a=="script"){e=o.createElement("script");e.type="text/javascript";e.src=b}else if(a=="css"){e=o.createElement("link");e.type="text/css";e.href=b;e.rel="stylesheet"}(a=o.getElementsByTagName("head")[0])||(a=o.body.parentNode.appendChild(o.createElement("head")));a.appendChild(e)}else if(a=="script")o.write('<script src="'+b+'" type="text/javascript"><\/script>');else a=="css"&&o.write('<link href="'+b+'" type="text/css" rel="stylesheet"></link>')};
K("google.loader.writeLoadTag",google[z].d);google[z].M=function(a){N=a};K("google.loader.rfm",google[z].M);google[z].O=function(a){for(var b in a)if(typeof b=="string"&&b&&b[s](0)==":"&&!M[b])M[b]=new T(b[A](1),a[b])};K("google.loader.rpl",google[z].O);google[z].N=function(a){if((a=a.specs)&&a[w])for(var b=0;b<a[w];++b){var c=a[b];if(typeof c=="string")M[":"+c]=new U(c);else{c=new V(c[u],c.baseSpec,c.customSpecs);M[":"+c[u]]=c}}};K("google.loader.rm",google[z].N);
google[z].loaded=function(a){M[":"+a.module].k(a)};K("google.loader.loaded",google[z].loaded);google[z].J=function(){return"qid="+((new Date)[v]().toString(16)+Math.floor(Math.random()*1E7).toString(16))};K("google.loader.createGuidArg_",google[z].J);I("google_exportSymbol",I);I("google_exportProperty",J);google[z].b={};K("google.loader.themes",google[z].b);google[z].b.z="http://www.google.com/cse/style/look/bubblegum.css";L(google[z].b,"BUBBLEGUM",google[z].b.z);google[z].b.B="http://www.google.com/cse/style/look/greensky.css";
L(google[z].b,"GREENSKY",google[z].b.B);google[z].b.A="http://www.google.com/cse/style/look/espresso.css";L(google[z].b,"ESPRESSO",google[z].b.A);google[z].b.D="http://www.google.com/cse/style/look/shiny.css";L(google[z].b,"SHINY",google[z].b.D);google[z].b.C="http://www.google.com/cse/style/look/minimalist.css";L(google[z].b,"MINIMALIST",google[z].b.C);function U(a){this.a=a;this.q=[];this.p={};this.i={};this.e={};this.l=d;this.c=-1}
U[x].g=function(a,b){var c="";if(b!=n){if(b.language!=n)c+="&hl="+j(b.language);if(b.nocss!=n)c+="&output="+j("nocss="+b.nocss);if(b.nooldnames!=n)c+="&nooldnames="+j(b.nooldnames);if(b.packages!=n)c+="&packages="+j(b.packages);if(b.callback!=g)c+="&async=2";if(b.style!=n)c+="&style="+j(b.style);if(b.other_params!=n)c+="&"+b.other_params}if(!this.l){if(google[this.a]&&google[this.a].JSHash)c+="&sig="+j(google[this.a].JSHash);var e=[];for(var f in this.p)f[s](0)==":"&&e[q](f[A](1));for(f in this.i)f[s](0)==
":"&&this.i[f]&&e[q](f[A](1));c+="&have="+j(e[B](","))}return google[z][t]+"/?file="+this.a+"&v="+a+google[z].AdditionalParams+c};U[x].v=function(a){var b=g;if(a)b=a.packages;var c=g;if(b)if(typeof b=="string")c=[a.packages];else if(b[w]){c=[];for(a=0;a<b[w];a++)typeof b[a]=="string"&&c[q](b[a][r](/^\s*|\s*$/,"")[C]())}c||(c=["default"]);b=[];for(a=0;a<c[w];a++)this.p[":"+c[a]]||b[q](c[a]);return b};
p(U[x],function(a,b){var c=this.v(b),e=b&&b.callback!=g;if(e)var f=new W(b.callback);for(var i=[],k=c[w]-1;k>=0;k--){var m=c[k];e&&f.F(m);if(this.i[":"+m]){c.splice(k,1);e&&this.e[":"+m][q](f)}else i[q](m)}if(c[w]){if(b&&b.packages)b.packages=c.sort()[B](",");for(k=0;k<i[w];k++){m=i[k];this.e[":"+m]=[];e&&this.e[":"+m][q](f)}if(!b&&N[":"+this.a]!=g&&N[":"+this.a].versions[":"+a]!=g&&!google[z].AdditionalParams&&this.l){c=N[":"+this.a];google[this.a]=google[this.a]||{};for(var R in c.properties)if(R&&
R[s](0)==":")google[this.a][R[A](1)]=c.properties[R];google[z].d("script",google[z][t]+c.path+c.js,e);c.css&&google[z].d("css",google[z][t]+c.path+c.css,e)}else if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),e);if(this.l){this.l=h;this.c=(new Date)[v]();if(this.c%100!=1)this.c=-1}for(k=0;k<i[w];k++){m=i[k];this.i[":"+m]=d}}});
U[x].k=function(a){if(this.c!=-1){X("al_"+this.a,"jl."+((new Date)[v]()-this.c),d);this.c=-1}this.q=this.q.concat(a.components);google[z][this.a]||(google[z][this.a]={});google[z][this.a].packages=this.q.slice(0);for(var b=0;b<a.components[w];b++){this.p[":"+a.components[b]]=d;this.i[":"+a.components[b]]=h;var c=this.e[":"+a.components[b]];if(c){for(var e=0;e<c[w];e++)c[e].I(a.components[b]);delete this.e[":"+a.components[b]]}}X("hl",this.a)};U[x].m=function(a,b){return this.v(b)[w]==0};U[x].s=function(){return d};
function W(a){this.H=a;this.n={};this.r=0}W[x].F=function(a){this.r++;this.n[":"+a]=d};W[x].I=function(a){if(this.n[":"+a]){this.n[":"+a]=h;this.r--;this.r==0&&l[y](this.H,0)}};function V(a,b,c){this.name=a;this.G=b;this.o=c;this.u=this.h=h;this.j=[];google[z].t[this[u]]=G(this.k,this)}F(V,U);p(V[x],function(a,b){var c=b&&b.callback!=g;if(c){this.j[q](b.callback);b.callback="google.loader.callbacks."+this[u]}else this.h=d;if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),c);X("el",this[u])});V[x].m=function(a,b){return b&&b.callback!=g?this.u:this.h};V[x].k=function(){this.u=d;for(var a=0;a<this.j[w];a++)l[y](this.j[a],0);this.j=[]};
var Y=function(a,b){return a.string?j(a.string)+"="+j(b):a.regex?b[r](/(^.*$)/,a.regex):""};V[x].g=function(a,b){return this.L(this.w(a),a,b)};
V[x].L=function(a,b,c){var e="";if(a.key)e+="&"+Y(a.key,google[z].ApiKey);if(a.version)e+="&"+Y(a.version,b);b=google[z].Secure&&a.ssl?a.ssl:a.uri;if(c!=g)for(var f in c)if(a.params[f])e+="&"+Y(a.params[f],c[f]);else if(f=="other_params")e+="&"+c[f];else if(f=="base_domain")b="http://"+c[f]+a.uri[A](a.uri.indexOf("/",7));google[this[u]]={};if(b.indexOf("?")==-1&&e)e="?"+e[A](1);return b+e};V[x].s=function(a){return this.w(a).deferred};
V[x].w=function(a){if(this.o)for(var b=0;b<this.o[w];++b){var c=this.o[b];if(RegExp(c.pattern).test(a))return c}return this.G};function T(a,b){this.a=a;this.f=b;this.h=h}F(T,U);p(T[x],function(a,b){this.h=d;google[z].d("script",this.g(a,b),h)});T[x].m=function(){return this.h};T[x].k=function(){};
T[x].g=function(a,b){if(!this.f.versions[":"+a]){if(this.f.aliases){var c=this.f.aliases[":"+a];if(c)a=c}if(!this.f.versions[":"+a])throw H("Module: '"+this.a+"' with version '"+a+"' not found!");}c=google[z].GoogleApisBase+"/libs/"+this.a+"/"+a+"/"+this.f.versions[":"+a][b&&b.uncompressed?"uncompressed":"compressed"];X("el",this.a);return c};T[x].s=function(){return h};var ca=h,Z=[],da=(new Date)[v](),X=function(a,b,c){if(!ca){P(l,"unload",ea);ca=d}if(c){if(!google[z].Secure&&(!google[z].Options||google[z].Options.csi===h)){a=a[C]()[r](/[^a-z0-9_.]+/g,"_");b=b[C]()[r](/[^a-z0-9_.]+/g,"_");l[y](G($,g,"http://csi.gstatic.com/csi?s=uds&v=2&action="+j(a)+"&it="+j(b)),1E4)}}else{Z[q]("r"+Z[w]+"="+j(a+(b?"|"+b:"")));l[y](ea,Z[w]>5?0:15E3)}},ea=function(){if(Z[w]){$(google[z][t]+"/stats?"+Z[B]("&")+"&nc="+(new Date)[v]()+"_"+((new Date)[v]()-da));Z.length=0}},$=function(a){var b=
new Image,c=fa++;ga[c]=b;b.onload=b.onerror=function(){delete ga[c]};b.src=a;b=g},ga={},fa=0;I("google.loader.recordStat",X);I("google.loader.createImageForLogging",$);

}) ();google.loader.rm({"specs":[{"name":"books","baseSpec":{"uri":"http://books.google.com/books/api.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}}}},"feeds",{"name":"friendconnect","baseSpec":{"uri":"http://www.google.com/friendconnect/script/friendconnect.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{}}},"spreadsheets","gdata","visualization",{"name":"sharing","baseSpec":{"uri":"http://www.google.com/s2/sharing/js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{"language":{"string":"hl"}}}},"search",{"name":"maps","baseSpec":{"uri":"http://maps.google.com/maps?file\u003dgoogleapi","ssl":"https://maps-api-ssl.google.com/maps?file\u003dgoogleapi","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"regex":"callback\u003d$1\u0026async\u003d2"},"language":{"string":"hl"}}},"customSpecs":[{"uri":"http://maps.google.com/maps/api/js","ssl":"https://maps-api-ssl.google.com/maps/api/js","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}},"pattern":"^(3|3..*)$"}]},"annotations_v2","wave","orkut",{"name":"annotations","baseSpec":{"uri":"http://www.google.com/reviews/scripts/annotations_bootstrap.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"},"country":{"string":"gl"}}}},"language","earth","ads","elements"]});
google.loader.rfm({":search":{"versions":{":1":"1",":1.0":"1"},"path":"/api/search/1.0/2a8ff2a70ad0b091ae9dfd8b5e832141/","js":"default+en.I.js","css":"default.css","properties":{":JSHash":"2a8ff2a70ad0b091ae9dfd8b5e832141",":NoOldNames":false,":Version":"1.0"}},":language":{"versions":{":1":"1",":1.0":"1"},"path":"/api/language/1.0/62c64af2122d2da7dcb0087852fa7396/","js":"default+en.I.js","properties":{":JSHash":"62c64af2122d2da7dcb0087852fa7396",":Version":"1.0"}},":wave":{"versions":{":1":"1",":1.0":"1"},"path":"/api/wave/1.0/3b6f7573ff78da6602dda5e09c9025bf/","js":"default.I.js","properties":{":JSHash":"3b6f7573ff78da6602dda5e09c9025bf",":Version":"1.0"}},":spreadsheets":{"versions":{":0":"1",":0.3":"1"},"path":"/api/spreadsheets/0.3/8331b0bbcc74776270648505340e9200/","js":"default.I.js","properties":{":JSHash":"8331b0bbcc74776270648505340e9200",":Version":"0.3"}},":earth":{"versions":{":1":"1",":1.0":"1"},"path":"/api/earth/1.0/819ffbf1e363d238791231792a2e0a90/","js":"default.I.js","properties":{":JSHash":"819ffbf1e363d238791231792a2e0a90",":Version":"1.0"}},":annotations":{"versions":{":1":"1",":1.0":"1"},"path":"/api/annotations/1.0/11cfaf30c00ca64601d09fcac7dd8bc7/","js":"default+en.I.js","properties":{":JSHash":"11cfaf30c00ca64601d09fcac7dd8bc7",":Version":"1.0"}}});
google.loader.rpl({":scriptaculous":{"versions":{":1.8.3":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.2":{"uncompressed"

Revision: 39553
at January 18, 2011 07:33 by mavrikicecool


Initial Code
Read from top to Bottom see for **** especially

Make an application multi lingual by using google API....
This process can even be implemented by an web service, but i have made use of google API
Please follow the steps and make changes accorindly

PHP(make use of div's and apply to the id's), ASP(Apply to all labesl)...and the rest of the languages follow up the same procedure accoringly......

*****************Add these 2 scripts into u r header and make it common for the pages so that it includes in each and everything***
<!--<script type="text/javascript" src="Translate/googlelanguage.js"></script>
<script type="text/javascript" src="Translate/translate.js"></script>-->
****************Better to add these 2 into head section of u r html or asp or jsp pages********************************************
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
************Add this thing into the body section where ever u wish to or u wanna Place the option for selection*******************
 <!-- <div><font size="+1">Select Language</font></div>
  <div id="mlt_languagelist"> </div>-->
  
  -->Steps:
  	1) As the page is loaded the the 2nd div gets activated and gets processed through the api and data is fetched from the tranlate.js script....check in the line number 166 the function getLangs() gets called and executed.just go through the function and understand the parameters passed u will know better whats happening.
	
	2) G to line number 85 there u will come to know how the langues get changed based upon u r request.
	3)	if(GL_curLang == "orig") {
			refresh();
			return;
		}
	
	find th this block and add few more langues based upon ICANN standards for language notations in google.soon after the above block by dumping more conditions to the above block u can select the langues aby your choice
	
	Add:
		else if(GL_curLang == "es") { //spanish
			refresh();
			return;
		}	
		else if(GL_curLang == "ja") { //japanese
			refresh();
			return;
		} 
		
		
	4) So add according to u r choice all this has to be followed aftr line number 888 for the 3 point.
	
	6) And now get to start of the page translate.js and point towards line 52, there you gonna find a an array assigned toa  variable with various elements within the array, present with other elements within it for the converion usuage.
	for all required labels in asp or the div or span's which u find the page, assign them which are to be changed upon request.
	
	7) rename those elements name by u r own names which u want, use those div's which are present in all front end pages .for each and every text item or asp with label tags, assign these id's one for all those text items(i.e the div's of each and every text item)..and u r almost done
	
	8)save all changes and start using this applicationits gonna work i am sure.....if there is anything lemme know.post it on the comments section i will reply back.
	
	5)By this way the combo box is set with languages which you require to make the application multi lingual
	
	6)this particual api support 64 recognised languages , check the info in google for this particual api.
	
  
********************************************************************************************************************************* 
</body>
</html>


*******************Save it as translate.js***************************

/* Multi-Language Translation Script:
*
*  Automatically translates a webpage (containing text in more than one language) into any single language
*  requested by the user. Particularly useful for sites involving a lot of user-generated content (which
*  might have originally been written in different languages) - e.g. blogs, forums, or other community sites. 
*  Harnesses the Google AJAX Language API to perform translation and language detection.
*
*  Version: 0.2.5 [2010-01-22]
*  Author: Patrick Hathway, OdinLab, University of Reading.
*  For Documentation and Updates: See http://code.google.com/p/multi-language-translation/
*  Licence: MIT License - see http://opensource.org/licenses/mit-license.php for full terms. Also check 
*  the script Documentation for more information, and for details of one important consideration.
*
*  Some minor configuration is required for this script to work on your website. Follow the instructions
*  below, or see the Documentation for full details and examples...   */

/* 1. Specify the 'Base Language' for your website: */

var GL_baseLang = "en";

/* 2. Specify the IDs for all major regions (i.e. HTML elements) in your site that should have their 
*  contents translated. Note that an ID can only be used to identify a single element on a page (for 
*  elements which appear multiple times, use Class Names instead - see below). The script will translate
*  each element separately; any elements that cannot be found on a page will be ignored:   */

var GL_classIds = [
	["navigation"],	
	["navigation", "", true],  
	["quick-id", "", true],  
	["c-quote", "", true],  
	["c-need-quote", "", true],  
	["c-index", "", true],   
	["c-about", "", true],  
	["c-exper", "", true],  
	["c-solution", "", true],
	["c-product", "", true],  
	["c-contact", "", true],  
	["c-indian-add", "", true],  
	["c-work", "", true],  
	["c-contact", "", true],  
	["c-contactinf", "", true],
	["c-usa-add", "", true],  
	["c-warning", "", true],  
	["right_sidebar", "fr", true], 
	["footer"]
];

/* 3. Specify the Class Names of all major regions (i.e. HTML elements) in your site that should have their 
*  their contents translated. Multiple elements may appear on a page with the same class name; the script
*  will locate each occurrance (if present) and translate them separately:   */

var GL_classNames = [
	["entry_baselang"],
	["entry_french", "fr"],
	["index-class", "", true],
	["about-class", "", true],	
	["association-class", "", true],
	["building-class", "", true],
	["career-class", "", true],
	["college-class", "", true],
	["construction-class", "", true],
	["contact-class", "", true], 
	["entry_baselang", "", true], 
	["education-class", "", true], 
	["entry", "", true], 
	["expertise-class", "", true], 
	["description", "", true], 
	["list-custom_website", "", true], 
	["list-beautiful_graphic", "", true], 
	["list-using_nature", "", true],
	["list-css_xhtml", "", true],
	["description", "", true], 
	["list-branding_your", "", true], 
	["list-green_branding", "", true], 
	["list-who_are", "", true], 
	["list-long_term", "", true], 
	["list-the_importance", "", true], 
	["list-flow", "", true], 
	["list-click_through", "", true], 
	["list-scale", "", true], 
	["description", "", true], 
	["list-google_rank", "", true], 
	["list-ppc", "", true], 
	["list-custom_icon", "", true], 
	["list-why_use", "", true], 
	["list-web_standard", "", true], 
	["list-promoting_your", "", true], 
	["list-business_cards", "", true], 
	["fashin-class", "", true], 
	["right", "", true],  
	["web_portfolio", "", true], 
	["interior-class", "", true],
	["manufacture-class", "", true], 
	["news-class", "", true], 
	["medical-class", "", true], 
	["opening-class", "", true], 
	["ourclass-class", "", true], 	
	["portfolio-class", "", true], 	
	["ecommerce-class", "", true], 	
	["mobile-class", "", true], 
	["webdesign-class", "", true], 
	["product-class", "", true], 
	["professional-class", "", true], 
	["real-class", "", true], 
	["realestate-class", "", true], 
	["request-class", "", true],   
	["form_entry", "", true],
	["request-id", "", true],
	["requestquote-class", "", true],
	["consumer-class", "", true],
	["software-class", "", true],
	["solutions-class", "", true],
	["list-why_use", "", true],
	["list-west_coast", "", true], 
	["list-custom_icon", "", true],
	["list-crisp_graphics", "", true],
	["list-scalable_across", "", true],
	["testimonials-class", "", true],  
	["testimonials", "", true],
	["tourism-class", "", true],
	["trade-class", "", true], 
	["transport-class", "", true], 
	["levonsys-class", "", true],  
	["working-levonsys-class", "", true],    
	["quick", "", true], 
	["entry_french", "", true], 
	["quotes", "de", true]
];


/* 4. Specify the default language for new visitors (leave blank to auto-detect using browser/system settings) */

var GL_curLang = "";

/* The rest of the Script should not be modified; unless you want to alter the functionality!
*  ------------------------------------------------------------------------------------------ */

// Global variables:
var GL_srcContent;             // array containing all content on the page to be translated, split up into chunks
var GL_transContent = [];      // array containing all chunks which have been translated
var GL_chunksTotal = 0;        // total number of chunks to translate
var GL_curChunk;               // ID of current chunk being translated
var GL_errors;                 // array containing details of all errors that occur (if applicable)
var GL_errSrcTxt;              // array containing all source text that causes errors (if applicable)
var GL_miniTransItems = [];    // array containing element IDs/class names which contain minor items to translate

google.load("language", "1");  // load v1 of google ajax language api

// run when page loads
function initialise() {
	addTransMsgs();        // append elements (which will display translation status messages) to page
	buildChunkedContent(); // create a local 'cache' of chunked content to be translated
	getLangCookie();       // find out the current site language (if known)
	getLangs();            // display listbox containing all languages the site can be translated into

	// if the original languages should be shown, end function.
	if(GL_curLang == "orig") {
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// display listbox containing all languages the site can be translated into (so that one can be selected by user)
function getLangs() {
	// create listbox within script so that it won't appear if JavaScript is disabled
	document.getElementById("mlt_languagelist").innerHTML = '<select id="mlt_language" onchange="changeLang()" style="width:150px; height:20px;"></select>';
	// +	'<div id="mlt_langattr"></div>'
	var langItems = document.getElementById("mlt_language").options;

	// add option to top of listbox allowing user to view the site in its original (i.e. un-translated) languages
	langItems.add(new Option("Original Languages", "orig", true));

	// loop through list of currently available languages and add each to listbox
	for(var lang in google.language.Languages) {
		// find out the 2 character Google language code
		
		var langCode = google.language.Languages[lang];
		// convert language string to title case
		var langString = lang.substr(0,1) + lang.substr(1).toLowerCase();
		// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
		langString = langString.split("_").join(" - ");

		// check that Google can translate content into the current language
		if ((google.language.isTranslatable(langCode)) && (langCode != "")) {
			// if so, add to listbox and translate, so native speakers of that language can find it
			if(langCode=="ar")
			{
				langItems.add(new Option(langString, langCode));
				miniTranslate(langItems[(langItems.length-1)],langCode);
			}
			
		}
	}

	document.getElementById("mlt_language").value = GL_curLang; // change listbox to display current site language
	google.language.getBranding("mlt_langattr");  // display Google attribution below listbox (as required by TOS)
}

// start the translation
function startTranslation() {
	// reset global variables
	GL_curChunk = 0; GL_errors = []; GL_errSrcTxt = [];
	
	// check if all content has already been translated into current language since page loaded.
	if(chkLangTrans()) {
		return; // if so, don't need to translate content again
	} 
	
	// sanity check - can google actually translate into the current site language?
	if (!(google.language.isTranslatable(GL_curLang)) || (GL_curLang == "")) {
		return; // if not, end translation
	} // Otherwise, send content to google to be translated:
	
	// show the 'Translating...' block
	document.getElementById("mlt_translatemsg").innerHTML = 'Translating... <span id="mlt_perc">0%</span>';
	miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	document.getElementById("mlt_translatemsg").style.display='block';

	// find out the ID of the destination language
	var curLangNo = document.getElementById("mlt_language").selectedIndex;
	var k = 0;
	
	// create sub-array to hold all translations for current language
	GL_transContent[GL_transContent.length]        = new Array(3);
	GL_transContent[(GL_transContent.length-1)][0] = []; // this array will contain all translated chunks
	GL_transContent[(GL_transContent.length-1)][1] = GL_curLang; // store current language
	GL_transContent[(GL_transContent.length-1)][2] = false; // mark translation of language as incomplete

	// loop through all the chunks to be translated, send to google...
	for(var i = 0; i < GL_srcContent.length; i++) {
		// find out the source language for the current element to be translated
		var srcLang = GL_srcContent[i][GL_srcContent[i].length - 1];

		for(var j = 0; j < (GL_srcContent[i].length - 1); j++) {
			/* AJAX is used to return translated chunks, so they MAY be returned in any order.
		   	To solve, include current chunk id, destination language + separators at start of each
		   	string. This is a bit of a 'hack', so try to find a better solution! */
			var srcText = curLangNo + "<br />" + k + "<br />" + GL_srcContent[i][j];

			// send current chunk to google translate; when translated, call function translateChunk
			google.language.translate(srcText, srcLang, GL_curLang, translateChunk);
			k++;
		}
	}

	setTimeout("checkTransStatus()", 1000); // run function to check translation status after 1 second
}

// check if page content has already been translated into current language since page loaded.
function chkLangTrans() {
	// loop through the list of languages the page has been translated into
	for(var i = 0; i < GL_transContent.length; i++) {
		// check if a translation for current language exists, and if so, whether it is complete.
		if((GL_transContent[i][1] == GL_curLang) && (GL_transContent[i][2] == true)){
			/* if so, don't need to send content to google again, just assemble the pre-translated content.
			This will *dramatically* reduce the translation time for this language! */
			endTranslation(i);
			return true;
		} 
	}
	return false; // otherwise, all relevant page content must be submitted to google for translation.
}

// This runs after each chunk has been translated...
function translateChunk(result) {
	// handle translation errors gracefully by storing error details but allowing translation to continue
	if (result.error) {
		GL_errors[GL_errors.length] = result.error.message;
	}
	else {

	/* Translated chunks may be returned in any order, so we need a method to assemble the chunks
	   in the correct order:
	   * Start of each chunk has a destination language id and a chunk id followed by separators.
	   * Separator is a <br /> HTML tag, as these always appear to retain position after translation...
	   * The destination language id is used to ensure the translated text is now in the correct language.
	   * Each chunk is stored in the position of the 'GL_transContent' array corresponding to the current chunk id.
	   * The ids + separators should not be shown, and are discarded from the chunk when it's stored in array.
	*/
	
		// split into array based on separator, so we know the id & destination language of translated chunk
		var transChunk = result.translation.split("<br />");
		// [find out length of substring to chop off from start of chunk]
		var chunkSubStr = 12 + transChunk[0].length + transChunk[1].length;
		// remove whitespace from chunk id & destination language (a problem with some translations)
		transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
		transChunk[1] = transChunk[1].replace(/^\s+|\s+$/g,"");

		/* If the translated chunk has a different destination language to the current site language, discard
		translation & end function. This may happen if user changes language whilst translation is in progress */
		if(transChunk[0] != document.getElementById("mlt_language").selectedIndex) {
			return;
		}

		// store translated chunk in current language array, along with detected source language (if known)
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]] = new Array(3);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][0] = result.translation.substr(chunkSubStr);
		GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][1] = result.detectedSourceLanguage;
	}

	GL_curChunk++; // increment current chunk ID every time function is called

	// calculate and display percentage of translation completed, based on number of chunks remaining
	var perc = (GL_curChunk / GL_chunksTotal)*100;
	document.getElementById("mlt_perc").innerHTML = Math.round(perc) + "%";

	// when all chunks have been translated, run the 'endTranslation' function...
	if(GL_curChunk >= GL_chunksTotal) {
		endTranslation((GL_transContent.length-1)); // [final array element holds current language content!]
	}
}

/* runs once a second whilst translation is in progress, updating contents of all elements that have already
   been completely translated. Also shows 'timeout' messages if translation not completed within 30 seconds... */
function checkTransStatus() {
	// 'static' member variables to keep track of how many times function has run, as well as current language:
	if((typeof checkTransStatus.chkStatusCount == 'undefined') || (checkTransStatus.curTransLang != GL_curLang)) {
		// reset variables if not defined yet, or if site language has changed since last function call
        	checkTransStatus.chkStatusCount = 0;
		checkTransStatus.curTransLang = GL_curLang;
	}

	// if translation is now complete, end function.
	if(GL_curChunk >= GL_chunksTotal) {
		return;
	}
	
	checkTransStatus.chkStatusCount++; // increment Translation Status counter

	// Store the list of languages in case they are replaced during translation
	var langList = document.getElementById("mlt_languagelist").innerHTML;

	var curElement; var curTransChunk = 0; var curClass = 0; var curTransLang = GL_transContent.length-1;

	// loop through all element IDs (as specified at script top), searching for ones with completed translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,false);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), searching for completed translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],false);
				curClass++; // move to next element Class Name
			}
		}
	}

	// if listbox containing all languages has been removed as a result of translation, display it again
	if(document.getElementById("mlt_languagelist").innerHTML == "") {
		document.getElementById("mlt_languagelist").innerHTML = langList;
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to show current language
	}

	/* if translation still isn't complete after 30 seconds, update translation message. Note: there is no
	   need to halt the current translation completely, but we will allow user to restart it if desired! */
	if(checkTransStatus.chkStatusCount == 30) {
		// calculate and display percentage of translation completed, based on number of chunks remaining
		var perc = Math.round((GL_curChunk / GL_chunksTotal)*100) + "%";
		// update translation status message
		document.getElementById("mlt_translatemsg").innerHTML = 'Translating (Slowly!)... ' +
		'<span id="mlt_perc">' + perc + '</span> - <a href="javascript:refresh()">Retry</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
	}

	setTimeout("checkTransStatus()", 1000); // check translation status again after another second
}

// runs after all translations have been completed; displaying the results on screen in place of previous content
function endTranslation(curTransLang) {
	var curElement;
	var curTransChunk = 0; var curClass = 0;

	// loop through all element IDs (as specified at script top), replacing current contents with translations
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element

		// if current element ID exists on the page, replace contents with translated chunks
		if(curElement != null) {
			// assemble and display translated chunks for current element
			curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,true,GL_classIds[i]);
			curClass++; // move to next element ID
		}
	}

	// Get all elements on the page, so that ones with the specified class names can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all element class names (as specified at script top), so contents can be replaced by translations
	for(var i = 0; i < GL_classNames.length; i++) {
		// loop through all elements, so that any with the current class name can be identified
		for(var j = 0; j < allElements.length; j++) {
			if(allElements[j].className == GL_classNames[i][0]) {
				// assemble and display translated chunks for current element
				curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],true,GL_classNames[i]);
				curClass++; // move to next element Class Name
			}
		}
	}

	// Perform translations of all content added by the script (e.g. language strings and error messages)
	transAddedText();

	// Re-create listbox containing all languages, in case it has been removed as a result of translation
	getLangs();

	// translate the 'Original Languages' listbox item to equivalent in current site language
	miniTranslate(document.getElementById("mlt_language").options[0],GL_curLang,"Original Languages");
	
	// if any errors occured during translation, display warning message at top of screen and end function 
	if(GL_errors.length != 0) {
		document.getElementById("mlt_translatemsg").innerHTML = GL_errors.length + ' Problems(s) Occurred During Translation: ' +
		'<a href="javascript:refresh()">Retry</a> - <a href="javascript:showErrDetails()">Details</a> - ' +
		'<a href="javascript:hideTransMsg()">Hide</a>';
		miniTranslate(document.getElementById("mlt_translatemsg")); // translate warning message into current site language
		return;
	}
	
	// mark translation of page into current language as complete, so that translation can be quicker next time.
	GL_transContent[curTransLang][2] = true;

	hideTransMsg(); // otherwise, hide 'Translating...' message
}

// assemble and display translated chunks for current element on page
function unpackTransChunks(curTransLang,curTransChunk,curClassNum,curElement,transComplete,curClass) {
	// 'static' member variable to keep track of how many times function has run
	if(typeof unpackTransChunks.curLinkId == 'undefined') {
		// reset curLinkId variable if not defined yet - it's used to identify the correct 'show source text' link
        	unpackTransChunks.curLinkId = 0;
	} unpackTransChunks.curLinkId++; var j = unpackTransChunks.curLinkId; // increment current link id, j is an alias

	var curContent = ""; // reset translated contents of current element
	var initTransChunk = curTransChunk; // store initial chunk id of current element

	// loop through all translated chunks, assembling all translated content for current element
	for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
		// if current chunk does not exist, translation is not complete or errors occurred
		if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == false)) {
			break; // stop looping through chunks if full translation has not yet been completed
		} else if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == true)) {
			// if full translation IS complete, show warning message and a link to show source text (in red)
			curContent += '<div style="color: red;" id="mlt_srctxt' + j + '">[<span class="mlt_transerrtxt">' +
			'<em style="text-transform: uppercase;">THIS SECTION COULD NOT BE TRANSLATED</em> - '+
			'<a id="mlt_srctxtlnk' + j + '" href="javascript:showSrcTxt(' + j + ',' + curClassNum + ',' + (i+1) + 
			')">View Source Text [+]</a></span><span id="mlt_srctxtbracket' + j + '">]</span></div>';
			GL_errSrcTxt[GL_errSrcTxt.length] = GL_srcContent[curClassNum][i]; // store affected source text
			unpackTransChunks.curLinkId++; j = unpackTransChunks.curLinkId; // increment current link id		
		} else {
			// otherwise append current translated chunk to translated content string
			curContent += GL_transContent[curTransLang][0][curTransChunk][0];
		}
		curTransChunk++; // move to next chunk
	}

	// if translation is complete, replace contents of current element with translated text
	if(transComplete == true) {
		curElement.innerHTML = curContent;
		// append a language string to bottom of current element if desired
		getLangString(curTransLang,curElement,curClass,initTransChunk,(GL_srcContent[curClassNum].length - 1),j,curClassNum);
	// otherwise, check if all translated chunks for current element were assembled
	} else if((i == (GL_srcContent[curClassNum].length - 1)) && (GL_transContent[curTransLang][0][initTransChunk][2] != true)) {			
		// if so (and current element translation is not yet marked as complete), replace contents with translation
		curElement.innerHTML = curContent;
		GL_transContent[curTransLang][0][initTransChunk][2] = true; // mark current element translation as complete
	}

	return curTransChunk; // return current chunk id to calling function
}

// If required, find and append a string containing the Source Language to the bottom of the specified element
function getLangString(curTransLang,curElement,curClass,curTransChunk,transChunksLen,j,curClassNum) {
	
	var detectedLang = "";

	// if the current element does not need a language string appended, end function
	if(curClass[2] != true) {
		return;
	}

	// if source language for current element has already been manually specified, set this as detected language
	if(curClass[1] != "") {
		detectedLang = curClass[1];
	}
	// otherwise find out language based on the detected source languages for translated chunks in current element 
	else {
		detectedLang = findDetectedLang(curTransLang,curTransChunk,transChunksLen);
	}

	// if detected language is same as site language, there is no need to display language string, so end function
	if(detectedLang == GL_curLang){
			return;
	}

	var srcLangString = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string 

	// append language string to current element...
//	curElement.innerHTML += '<div style="color: green;" id="mlt_srctxt' + j + '"></div>';
}

// convert a google language code into a formatted string containing the language name
function getFmtLangStr(lang) {
	// loop through list of supported languages and retrieve names
	for(var l in google.language.Languages) {
		if(google.language.Languages[l] == lang) {
			// convert language string into title case
			var lang = l.substr(0,1) + l.substr(1).toLowerCase();
			// improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
			lang = lang.split("_").join(" - ");
			break; // stop loop (don't need to continue searching for languages)
		}
	}
	// if language cannot be found in list of supported languages, set language to 'unknown'
	if(typeof lang == "undefined") {
		lang = "An Unknown Language";
	}
	return lang; // return formatted language string
}

// find out the most common detected language for all translated chunks in current element, to appear in language string
function findDetectedLang(curTransLang,curTransChunk,transChunksLen) {
	var chunkLangs = []; langCounter = 0;

	// loop through all translated chunks in current element
	for(var i = 0; i < transChunksLen; i++) {
		// bugfix: set detected language to 'undefined' if an error occurred during translation... 
		if(GL_transContent[curTransLang][0][curTransChunk] == null) {
			GL_transContent[curTransLang][0][curTransChunk] = new Array(3);
			GL_transContent[curTransLang][0][curTransChunk][1] = "undefined";	
		}
		// loop through array of detected languages to see if current chunk has an existing detected language
		for(var j = 0; j < chunkLangs.length; j++) {
			if(chunkLangs[j][0] == GL_transContent[curTransLang][0][curTransChunk][1]) {
				// if so, increment counter containing the total number of chunks with that language
				chunkLangs[j][1]++;
				break; // halt loop
			}
		}
		// if current chunk has a language not yet detected, add it to end of detected languages array
		if(j == chunkLangs.length) {
			chunkLangs[j] = new Array(2);
			chunkLangs[j][0] = GL_transContent[curTransLang][0][curTransChunk][1]; // name of detected language
			chunkLangs[j][1] = 1; // total number of chunks with that language
		}
		curTransChunk++; // move to next chunk
	}

	/* once array has been created containing all detected languages in current element, loop through it
	to find the most common detected language - language string should contain this */
	for(i = 0; i < chunkLangs.length; i++) {
		if(chunkLangs[i][1] > langCounter) {
			/* if current language was detected more times than all previous languages, store language
			and number of times detected - so that next language can be compared against this total */
			var detectedLang = chunkLangs[i][0];
			langCounter = chunkLangs[i][1];
		}		
	}
	
	return detectedLang; // return the most common detected language
}

// Auto-translate all text added previously by the script (including language strings and error messages)
function transAddedText() {
	var allElements = document.getElementsByTagName("*"); // get all elements on page, so relevant ones can be translated
	var foundElements = [];

	// loop through all elements to find any of class 'mlt_langstring' or 'mlt_transerrtxt' 
	for(var i=0; i<allElements.length; i++) {
		if((allElements[i].className == "mlt_langstring") || (allElements[i].className == "mlt_transerrtxt")) {
			foundElements[foundElements.length] = allElements[i];
		}
	}

	// translate all located elements (runs separately from above code to prevent infinite loop as items are translated)
	for(i = 0; i < foundElements.length; i++) {
		miniTranslate(foundElements[i]); // translate current element
	}
}

/* this function runs before any translation takes place, and creates a local 'cache' of all content to be translated (in chunks)
   - meaning the content can be submitted to Google more rapidly, and the resulting translations can then be sorted reliably */
function buildChunkedContent() {
	var curElement; GL_srcContent = []; var j = 0;

	/* loop through all applicable element IDs (as specified at script top), converting the contents of each into chunks,
	   and storing each chunk in an array */
	for(var i = 0; i < GL_classIds.length; i++) {
		curElement = document.getElementById(GL_classIds[i][0]); // find out current element
		// check that element actually exists on the page - if not, ignore it
		if(curElement != null) {
			GL_srcContent[j] = createChunks(curElement); // separate the content of current element into chunks
			GL_chunksTotal += GL_srcContent[j].length;   // store a running total of the number of chunks created

			// if a Source Language is not specified for current element, store Base Language in array instead
			if(GL_classIds[i].length == 1) {
				GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
			} else {
				// otherwise store the specified language (or a blank string if this is to be auto-detected)
				GL_srcContent[j][GL_srcContent[j].length] = GL_classIds[i][1];
			}
			j++;
		}
	}

	// get all elements on page, so that the ones specified can be located
	var allElements = document.getElementsByTagName("*");
	// loop through all applicable element IDs (as specified at script top), converting into chunks and storing in array
	for(var i = 0; i < GL_classNames.length; i++) {
		// find all elements which have the current class name
		for(var k = 0; k < allElements.length; k++) { 
			if(allElements[k].className == GL_classNames[i][0]) {
				// separate the content of current element into chunks
				GL_srcContent[j] = createChunks(allElements[k]);
				// store a running total of the number of chunks created
				GL_chunksTotal += GL_srcContent[j].length;

				// if a Source Language is not specified for current element, store Base Language in array
				if(GL_classNames[i].length == 1) {
					GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
				} else {
					// otherwise store specified language (or a blank string if auto-detected)
					GL_srcContent[j][GL_srcContent[j].length] = GL_classNames[i][1];
				}
				j++;
			}
		}
	}
}

/* Web browsers (and Google) limit the amount of text translated per request, so split contents of current element into chunks.
   The aim is to achieve this whilst maintaining the translation integrity */
function createChunks(srcContent) {	
	var chars = 1000; // number of characters to allow per chunk.

	/* We do NOT want the content inside any HTML tag to be split between chunks (as this could cause 
	rendering problems), so create 2 arrays storing tags and textual content of current div separately */
	var tags = srcContent.innerHTML.match(/<.*?>/g);
	var text = srcContent.innerHTML.split(/<.*?>/g);
	if(tags == null) {
		tags = new Array();} // handle content containing no tags

	var curchar = 0; var tagnum = 0; var textnum = 0; var contTotal = tags.length + text.length;
	// create an array containing content to be chunked, with tags + text separately re-assembled (in order)
	var content = new Array(contTotal);
	// loop through content of current div
	for(var i=0; i < contTotal; i++) {
		// if current position in content is the start of a tag char, add appropriate tag to content array
		if(srcContent.innerHTML.substr(curchar,1) == "<") {
			content[i] = tags[tagnum];
			curchar += tags[tagnum].length;
			tagnum++;
		// if it is a text string, add the corresponding text to the curent element in content array
		} else {
			content[i] = text[textnum];
			curchar += text[textnum].length;
			textnum++;
		}
	}

	// Create the chunks - don't split either tags or words (to ensure as high translation quality as possible)
	var chunks = []; var curChunk = 0;
	chunks[0]="";
	for (i = 0; i < contTotal; i++) {
		// if next content item (tag or textual) won't exceed length of current chunk, add it to chunk
		if((chunks[curChunk].length + content[i].length) < chars) {
			chunks[curChunk] += content[i];
		} else {
			// otherwise, proceed to next chunk.
			curChunk++;
			// add the entire content item to this chunk if possible (to ensure better translation)
			if(content[i].length < chars) {
				chunks[curChunk] = content[i];
			}
			else {
				// only split further in rare cases where text length exceeds maximum chunk size
				var curPos = 0;
				do {
					// retrieve the maximum amount of text that can fit in this chunk
					var subContent = content[i].substr(curPos,chars);
					// find out how many words are in this substring
					var words = subContent.split(" ");
					// chop off final word, so words aren't split up between chunks
					var lastWordPos = subContent.length - words[(words.length-1)].length;
					if(subContent.length < chars) { // [bugfix: prevent word cut-off on final iteration]
						lastWordPos = subContent.length}
					chunks[curChunk] = subContent.substr(0,lastWordPos); // store in chunk
					curChunk++; // remainder of text will go in next chunk
					curPos+=lastWordPos; // store current position in text, for further processing
				} while(subContent.length >= chars); // repeat until all this text has been chunked
				curChunk--; // because there may still be space in the current chunk!
			}
		}
	}		
	
	return chunks; // return chunked content to calling function...
}

// Append elements to page (will be used to display translation messages), and specify their css styles.
function addTransMsgs() {
	// add element to page which will contain translation messages
	var transCont = document.createElement("div");
	document.body.appendChild(transCont);
	
	// add element to container created above - this will display the translation messages
	var translateMsg = document.createElement("div");
	translateMsg.id = "mlt_translatemsg";
	transCont.appendChild(translateMsg);

	// define visual styles for translation messages displayed on screen
	translateMsg.style.backgroundColor = "silver";
	translateMsg.style.border = "3px green solid";
	translateMsg.style.padding = "5px";
	translateMsg.style.fontSize = "large";
	translateMsg.style.fontWeight = "bold";
	translateMsg.style.textAlign = "left";
	translateMsg.style.color = "black";

	// more translation message styles (these should not need editing!)
	translateMsg.style.left = "-50%";
	translateMsg.style.position = "relative";
	translateMsg.style.display = "none";
	
	// define the styles for the container element
	transCont.style.left = "50%";
	transCont.style.zIndex = "1000";
	if(!(/MSIE 6/i.test(navigator.userAgent))) {
		// styles for all browsers except IE6
		transCont.style.position = "fixed";
		transCont.style.top = "0px";
	}
	else {
		// styles for IE6
		transCont.style.position = "absolute";
		transCont.style.setExpression("top", "(i = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
	}
}

// Hide 'Translating...' message (or translation error message) - runs at end of translation, or if user dismisses error message
function hideTransMsg() {
	document.getElementById("mlt_translatemsg").innerHTML = "";
	document.getElementById("mlt_translatemsg").style.display='none';
}

// if the user clicks on the 'Details' link [after error(s) occurred], show details of all errors on screen
function showErrDetails() {
	// continue to show original error message (but remove 'Details' link)
	document.getElementById("mlt_translatemsg").innerHTML = '<span id="mlt_transerrmsg1">' + GL_errors.length + 
	' Problems(s) Occurred During Translation: ' + '<a href="javascript:refresh()">Retry</a> - ' +
	'<a href="javascript:hideTransMsg()">Hide</a>... <br /><em>Error(s) Reported:</em></span>' +
	'<ul style="margin: 0px; padding: 0px;" id="mlt_transerrlist"></ul>';

	// Loop through array containing details of all errors, and show them as a list on screen
	for(var i = 0; i < GL_errors.length; i++) {
		document.getElementById("mlt_transerrlist").innerHTML += '<li style="margin-left: 15px;">' + GL_errors[i] + '.</li> ';	
	}

	/* create a textarea - this will show the original source text of all affected sections (as HTML) to aid debugging
	   Note: because translations are returned using AJAX, the affected sections are not NECESSARILY in the same order as
	   the errors reported (though in many cases, they will be!) */
	document.getElementById("mlt_translatemsg").innerHTML += '<em id="mlt_transerrmsg2">Section(s) Affected:</em><br />' +
	'<textarea id="mlt_errsrctxt" rows="8" readonly="readonly" style="width: 99%; background-color: silver; border: 1px gray solid;">' +
	'</textarea>';

	// Loop through Source Text array, appending to textarea.
	for(var i = 0; i < GL_errSrcTxt.length; i++) {
		document.getElementById("mlt_errsrctxt").value += "Affected Section " + (i+1) + ":\n" + GL_errSrcTxt[i] + "\n\n";
	}

	// Translate the entire contents of the Translation Errors box (with the exception of the text inside the textarea)
	miniTranslate(document.getElementById("mlt_transerrmsg1")); miniTranslate(document.getElementById("mlt_transerrlist"));
	miniTranslate(document.getElementById("mlt_transerrmsg2"));
}

// function runs when the user clicks on a link to view the original source text for a translated element / chunk
function showSrcTxt(curLinkId,curClassNum,curChunkId) {
	// if the current chunk should be shown only, display chunk on screen
	if((curChunkId-1) != -1) {
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+GL_srcContent[curClassNum][(curChunkId-1)]+']</div>';
	} else {
	// otherwise assemble all chunks for current element, and display on screen
		var srcTxt = "";
		for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
			srcTxt +=  GL_srcContent[curClassNum][i];
		}
		document.getElementById("mlt_srctxt"+curLinkId).innerHTML += 
		'<div id="mlt_srctxtcontent' + curLinkId + '">'+srcTxt+']</div>';
	}	

	// update Source Text link so that when clicked in future, the source text will be hidden instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "Hide Source Text [-]";
	srcTxtLnk.href = 'javascript:hideSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = ""; // hide bracket after link
}

// function runs when the user clicks on a link to hide the original source text for a translated element / chunk
function hideSrcTxt(curLinkId,curClassNum,curChunkId) {
	// remove the element containing the original source text
	srcTxtContent = document.getElementById("mlt_srctxtcontent"+curLinkId);
	document.getElementById("mlt_srctxt"+curLinkId).removeChild(srcTxtContent);

	// update Source Text link so that when clicked in future, the source text will be shown instead...
	srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
	srcTxtLnk.innerHTML = "View Source Text [+]";
	srcTxtLnk.href = 'javascript:showSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
	miniTranslate(srcTxtLnk); // translate link text
	document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = "]"; // show bracket after link
}

// translate small non crucial items of text into current site language
function miniTranslate(item,destLang,srcTxt) {
	if(typeof destLang == "undefined") {
		var destLang = GL_curLang; // if the destLang argument was not specified, use the current site language
	}
	if(typeof srcTxt == "undefined") {
		var srcTxt = item.innerHTML; // if the srcText argument was not specified, use the current item contents
	}

	// loop through translated items array to see if a translation for current text already exists since page loaded
	for(var i = 0; i < GL_miniTransItems.length; i++) {
		// check if source text and destination language match a translated item (and a completed translation exists for it)
		if((GL_miniTransItems[i][1] == srcTxt) && (GL_miniTransItems[i][2] == destLang) && (GL_miniTransItems[i][3] != "")) {
			item.innerHTML = GL_miniTransItems[i][3]; // if so, display existing translation in item
			item.title = srcTxt.split(/<.*?>/g).join(""); // display English source text as a tooltip (strip HTML first)
			return; // Don't need to send a translation request to Google, so end function.
		}
	}

	// store item to be translated in global array for access by callback function
	GL_miniTransItems[GL_miniTransItems.length]	   = new Array(4);
	GL_miniTransItems[(GL_miniTransItems.length-1)][0] = item;
	GL_miniTransItems[(GL_miniTransItems.length-1)][1] = srcTxt;
	GL_miniTransItems[(GL_miniTransItems.length-1)][2] = destLang;
	GL_miniTransItems[(GL_miniTransItems.length-1)][3] = "";

	// create source text by adding current item ID to start of item text (ID will ensure correct item is translated)
	srcTxt = (GL_miniTransItems.length-1) + "<br />" + srcTxt;

	google.language.translate(srcTxt, "en", destLang, function(result) {
        	if (!result.error) {
			// split into array based on separator, so we know the id of translated item
			var transChunk = result.translation.split("<br />");
			// [find out length of substring to chop off from start of item]
			var chunkSubStr = 6 + transChunk[0].length;
			// remove whitespace from item id (a problem with some translations)
			transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");

			// display english source text of translated item (with HTML stripped) if user hovers mouse over it
			var strippedSrcTxt = GL_miniTransItems[transChunk[0]][1].split(/<.*?>/g).join("");
			GL_miniTransItems[transChunk[0]][0].title = "[" + strippedSrcTxt  + "]";

			// store and display translation of specified item (stripping item ID from start of text)
			GL_miniTransItems[transChunk[0]][3] = result.translation.substr(chunkSubStr);
			GL_miniTransItems[transChunk[0]][0].innerHTML = GL_miniTransItems[transChunk[0]][3];
        	}
	});
}

// runs when the user changes the site language
function changeLang(destLang) {
	if(typeof destLang != "undefined") {
		GL_curLang = destLang; // if the destLang argument was specified, set new site language to this
		document.getElementById("mlt_language").value = GL_curLang; // change listbox to display new site language
	} else {
		// otherwise get the new language requested by user
		GL_curLang = document.getElementById("mlt_language").value;
	}

	// store the requested language in a cookie
	setLangCookie();
	
	// if the original site languages should be shown, refresh the page.
	if(GL_curLang == "orig") {
		refresh();
		return;
	}
	
	// otherwise, start the translation
	startTranslation();
}

// find out the value of the language cookie (if it exists)
function getLangCookie() {
	var curStoredLang;
	// retrieve a list of cookies for this page, split into array elements (separated by ; if multiple cookies)
	var getCurLang=document.cookie.split(";");
	// loop through all array elements (i.e. cookies) until one with name 'lang' is found.
	for(var i=0; i < getCurLang.length; i++) {

		// remove whitespace from cookies (a problem if there are multiple cookies)
		var lngCookie = getCurLang[i].replace(/^\s+|\s+$/g,"");

		if(lngCookie.indexOf("lang=") == 0) {
			// find out value of lang
			curStoredLang = lngCookie.substring(5);
		}
	}
	
	// if language cookie exists, set current site language to stored value
	if(typeof curStoredLang != "undefined") {
		GL_curLang = curStoredLang;
	// otherwise, check if an initial language has been specified
	} else if((GL_curLang == "") || (typeof GL_curLang == "undefined")) {
		detectUserLang(); // if not, find out user's language based on their settings, and offer to translate into that language
		GL_curLang = "orig"; // show site using original languages for now
		return; // don't want to store language in cookie until one has been specified, so end function
	}

	setLangCookie(); // if valid cookie exists or initial language was specified, set/renew cookie (to store new expiry date)
}

// If a new user has not specified a language yet, offer to translate page into their current browser / system language
function detectUserLang(){
	/* detect user's current language (if they are using IE this will be based on the regional settings on their system; 
	   otherwise it will be based on the default language of their current browser) */
	var detectedLang = (navigator.language) ? navigator.language : navigator.userLanguage;
	
	// if language cannot be detected for some reason, end function.
	if((typeof detectedLang == "undefined") || (detectedLang == ""))  {
		return;
	}
	
	// if language is regional dialect (e.g. "en-gb"), check last 2 letters are upper case - for google compatibility.
	if(detectedLang.length == 5) {
		detectedLang = detectedLang.substr(0,3) + detectedLang.substr(3).toUpperCase();
	}
	
	// check that Google can translate content into detected language
	if (!google.language.isTranslatable(detectedLang)) {
		// if not, check if language is a regional dialect (e.g. "en-GB")
		if(detectedLang.length == 5) {
			// if so, Google may still be able to translate into a non-regional equivalent (e.g. "en")
			detectedLang = detectedLang.substr(0,2);
			if (!google.language.isTranslatable(detectedLang)) {
				return; // google cannot translate into non-regional equivalent, so end function
			}
		// language is not a regional dialect, and google cannot translate into it, so end function
		} else {
			return;
		}
	}
	
	var detectedLangStr = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
	
	/*
	// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  'Translate this page into ' + detectedLangStr + '? ' +
	'<a href="javascript:changeLang(\'' + detectedLang + '\')">Yes</a> | <a href="javascript:changeLang(\'orig\')">No</a>';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='block'; // show the question on screen
	*/
	
	
		// display message asking user if they want to translate current page into detected language
	document.getElementById("mlt_translatemsg").innerHTML =  '';
	miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
	document.getElementById("mlt_translatemsg").style.display='none'; // show the question on screen
}

// create a cookie to store the current site language
function setLangCookie() {
	// expire previous cookie (if it exists)
	document.cookie = "lang=; expires=-1; path=/";

	// cookie will expire after 90 days.
	var expdate = new Date();
	expdate.setTime(expdate.getTime()+7776000000);

	// create the cookie
	document.cookie = "lang=" + GL_curLang + "; expires=" + expdate.toGMTString() + "; path=/";
}

// refresh the current page [runs if the Original Languages option was selected, or if requested by user after error(s)]
function refresh() {
	hideTransMsg();
	window.location.reload(true);
}

// run the 'initialise' function once the page has loaded.
google.setOnLoadCallback(initialise);

****************The End*****************************


*****************Save it as googlelanguage.js******************


if (!window['google']) {
window['google'] = {};
}
if (!window['google']['loader']) {
window['google']['loader'] = {};
google.loader.ServiceBase = 'http://www.google.com/uds';
google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax';
google.loader.ApiKey = 'notsupplied';
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.Secure = false;
google.loader.GoogleLocale = 'www.google.com';
google.loader.ClientLocation = {"latitude":17.385044,"longitude":78.486671,"address":{"city":"Hyderabad","region":"Andhra Pradesh","country":"India","country_code":"IN"}};
google.loader.AdditionalParams = '';
(function() {var d=true,g=null,h=false,j=encodeURIComponent,l=window,n=undefined,o=document;function p(a,b){return a.load=b}var q="push",r="replace",s="charAt",t="ServiceBase",u="name",v="getTime",w="length",x="prototype",y="setTimeout",z="loader",A="substring",B="join",C="toLowerCase";function D(a){if(a in E)return E[a];return E[a]=navigator.userAgent[C]().indexOf(a)!=-1}var E={};function F(a,b){var c=function(){};c.prototype=b[x];a.Q=b[x];a.prototype=new c}
function G(a,b){var c=Array[x].slice.call(arguments,2)||[];return function(){var e=c.concat(Array[x].slice.call(arguments));return a.apply(b,e)}}function H(a){a=Error(a);a.toString=function(){return this.message};return a}function I(a,b){for(var c=a.split(/\./),e=l,f=0;f<c[w]-1;f++){e[c[f]]||(e[c[f]]={});e=e[c[f]]}e[c[c[w]-1]]=b}function J(a,b,c){a[b]=c}if(!K)var K=I;if(!L)var L=J;google[z].t={};K("google.loader.callbacks",google[z].t);var M={},N={};google[z].eval={};K("google.loader.eval",google[z].eval);
p(google,function(a,b,c){function e(k){var m=k.split(".");if(m[w]>2)throw H("Module: '"+k+"' not found!");else if(typeof m[1]!="undefined"){f=m[0];c.packages=c.packages||[];c.packages[q](m[1])}}var f=a;c=c||{};if(a instanceof Array||a&&typeof a=="object"&&typeof a[B]=="function"&&typeof a.reverse=="function")for(var i=0;i<a[w];i++)e(a[i]);else e(a);if(a=M[":"+f]){if(c&&!c.language&&c.locale)c.language=c.locale;if(c&&typeof c.callback=="string"){i=c.callback;if(i.match(/^[[\]A-Za-z0-9._]+$/)){i=l.eval(i);
c.callback=i}}if((i=c&&c.callback!=g)&&!a.s(b))throw H("Module: '"+f+"' must be loaded before DOM onLoad!");else if(i)a.m(b,c)?l[y](c.callback,0):a.load(b,c);else a.m(b,c)||a.load(b,c)}else throw H("Module: '"+f+"' not found!");});K("google.load",google.load);
google.P=function(a,b){if(b){if(O[w]==0){P(l,"load",Q);if(!D("msie")&&!(D("safari")||D("konqueror"))&&D("mozilla")||l.opera)l.addEventListener("DOMContentLoaded",Q,h);else if(D("msie"))o.write("<script defer onreadystatechange='google.loader.domReady()' src=//:><\/script>");else(D("safari")||D("konqueror"))&&l[y](S,10)}O[q](a)}else P(l,"load",a)};K("google.setOnLoadCallback",google.P);
function P(a,b,c){if(a.addEventListener)a.addEventListener(b,c,h);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var e=a["on"+b];a["on"+b]=e!=g?aa([c,e]):c}}function aa(a){return function(){for(var b=0;b<a[w];b++)a[b]()}}var O=[];google[z].K=function(){var a=l.event.srcElement;if(a.readyState=="complete"){a.onreadystatechange=g;a.parentNode.removeChild(a);Q()}};K("google.loader.domReady",google[z].K);var ba={loaded:d,complete:d};function S(){if(ba[o.readyState])Q();else O[w]>0&&l[y](S,10)}
function Q(){for(var a=0;a<O[w];a++)O[a]();O.length=0}
google[z].d=function(a,b,c){if(c){var e;if(a=="script"){e=o.createElement("script");e.type="text/javascript";e.src=b}else if(a=="css"){e=o.createElement("link");e.type="text/css";e.href=b;e.rel="stylesheet"}(a=o.getElementsByTagName("head")[0])||(a=o.body.parentNode.appendChild(o.createElement("head")));a.appendChild(e)}else if(a=="script")o.write('<script src="'+b+'" type="text/javascript"><\/script>');else a=="css"&&o.write('<link href="'+b+'" type="text/css" rel="stylesheet"></link>')};
K("google.loader.writeLoadTag",google[z].d);google[z].M=function(a){N=a};K("google.loader.rfm",google[z].M);google[z].O=function(a){for(var b in a)if(typeof b=="string"&&b&&b[s](0)==":"&&!M[b])M[b]=new T(b[A](1),a[b])};K("google.loader.rpl",google[z].O);google[z].N=function(a){if((a=a.specs)&&a[w])for(var b=0;b<a[w];++b){var c=a[b];if(typeof c=="string")M[":"+c]=new U(c);else{c=new V(c[u],c.baseSpec,c.customSpecs);M[":"+c[u]]=c}}};K("google.loader.rm",google[z].N);
google[z].loaded=function(a){M[":"+a.module].k(a)};K("google.loader.loaded",google[z].loaded);google[z].J=function(){return"qid="+((new Date)[v]().toString(16)+Math.floor(Math.random()*1E7).toString(16))};K("google.loader.createGuidArg_",google[z].J);I("google_exportSymbol",I);I("google_exportProperty",J);google[z].b={};K("google.loader.themes",google[z].b);google[z].b.z="http://www.google.com/cse/style/look/bubblegum.css";L(google[z].b,"BUBBLEGUM",google[z].b.z);google[z].b.B="http://www.google.com/cse/style/look/greensky.css";
L(google[z].b,"GREENSKY",google[z].b.B);google[z].b.A="http://www.google.com/cse/style/look/espresso.css";L(google[z].b,"ESPRESSO",google[z].b.A);google[z].b.D="http://www.google.com/cse/style/look/shiny.css";L(google[z].b,"SHINY",google[z].b.D);google[z].b.C="http://www.google.com/cse/style/look/minimalist.css";L(google[z].b,"MINIMALIST",google[z].b.C);function U(a){this.a=a;this.q=[];this.p={};this.i={};this.e={};this.l=d;this.c=-1}
U[x].g=function(a,b){var c="";if(b!=n){if(b.language!=n)c+="&hl="+j(b.language);if(b.nocss!=n)c+="&output="+j("nocss="+b.nocss);if(b.nooldnames!=n)c+="&nooldnames="+j(b.nooldnames);if(b.packages!=n)c+="&packages="+j(b.packages);if(b.callback!=g)c+="&async=2";if(b.style!=n)c+="&style="+j(b.style);if(b.other_params!=n)c+="&"+b.other_params}if(!this.l){if(google[this.a]&&google[this.a].JSHash)c+="&sig="+j(google[this.a].JSHash);var e=[];for(var f in this.p)f[s](0)==":"&&e[q](f[A](1));for(f in this.i)f[s](0)==
":"&&this.i[f]&&e[q](f[A](1));c+="&have="+j(e[B](","))}return google[z][t]+"/?file="+this.a+"&v="+a+google[z].AdditionalParams+c};U[x].v=function(a){var b=g;if(a)b=a.packages;var c=g;if(b)if(typeof b=="string")c=[a.packages];else if(b[w]){c=[];for(a=0;a<b[w];a++)typeof b[a]=="string"&&c[q](b[a][r](/^\s*|\s*$/,"")[C]())}c||(c=["default"]);b=[];for(a=0;a<c[w];a++)this.p[":"+c[a]]||b[q](c[a]);return b};
p(U[x],function(a,b){var c=this.v(b),e=b&&b.callback!=g;if(e)var f=new W(b.callback);for(var i=[],k=c[w]-1;k>=0;k--){var m=c[k];e&&f.F(m);if(this.i[":"+m]){c.splice(k,1);e&&this.e[":"+m][q](f)}else i[q](m)}if(c[w]){if(b&&b.packages)b.packages=c.sort()[B](",");for(k=0;k<i[w];k++){m=i[k];this.e[":"+m]=[];e&&this.e[":"+m][q](f)}if(!b&&N[":"+this.a]!=g&&N[":"+this.a].versions[":"+a]!=g&&!google[z].AdditionalParams&&this.l){c=N[":"+this.a];google[this.a]=google[this.a]||{};for(var R in c.properties)if(R&&
R[s](0)==":")google[this.a][R[A](1)]=c.properties[R];google[z].d("script",google[z][t]+c.path+c.js,e);c.css&&google[z].d("css",google[z][t]+c.path+c.css,e)}else if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),e);if(this.l){this.l=h;this.c=(new Date)[v]();if(this.c%100!=1)this.c=-1}for(k=0;k<i[w];k++){m=i[k];this.i[":"+m]=d}}});
U[x].k=function(a){if(this.c!=-1){X("al_"+this.a,"jl."+((new Date)[v]()-this.c),d);this.c=-1}this.q=this.q.concat(a.components);google[z][this.a]||(google[z][this.a]={});google[z][this.a].packages=this.q.slice(0);for(var b=0;b<a.components[w];b++){this.p[":"+a.components[b]]=d;this.i[":"+a.components[b]]=h;var c=this.e[":"+a.components[b]];if(c){for(var e=0;e<c[w];e++)c[e].I(a.components[b]);delete this.e[":"+a.components[b]]}}X("hl",this.a)};U[x].m=function(a,b){return this.v(b)[w]==0};U[x].s=function(){return d};
function W(a){this.H=a;this.n={};this.r=0}W[x].F=function(a){this.r++;this.n[":"+a]=d};W[x].I=function(a){if(this.n[":"+a]){this.n[":"+a]=h;this.r--;this.r==0&&l[y](this.H,0)}};function V(a,b,c){this.name=a;this.G=b;this.o=c;this.u=this.h=h;this.j=[];google[z].t[this[u]]=G(this.k,this)}F(V,U);p(V[x],function(a,b){var c=b&&b.callback!=g;if(c){this.j[q](b.callback);b.callback="google.loader.callbacks."+this[u]}else this.h=d;if(!b||!b.autoloaded)google[z].d("script",this.g(a,b),c);X("el",this[u])});V[x].m=function(a,b){return b&&b.callback!=g?this.u:this.h};V[x].k=function(){this.u=d;for(var a=0;a<this.j[w];a++)l[y](this.j[a],0);this.j=[]};
var Y=function(a,b){return a.string?j(a.string)+"="+j(b):a.regex?b[r](/(^.*$)/,a.regex):""};V[x].g=function(a,b){return this.L(this.w(a),a,b)};
V[x].L=function(a,b,c){var e="";if(a.key)e+="&"+Y(a.key,google[z].ApiKey);if(a.version)e+="&"+Y(a.version,b);b=google[z].Secure&&a.ssl?a.ssl:a.uri;if(c!=g)for(var f in c)if(a.params[f])e+="&"+Y(a.params[f],c[f]);else if(f=="other_params")e+="&"+c[f];else if(f=="base_domain")b="http://"+c[f]+a.uri[A](a.uri.indexOf("/",7));google[this[u]]={};if(b.indexOf("?")==-1&&e)e="?"+e[A](1);return b+e};V[x].s=function(a){return this.w(a).deferred};
V[x].w=function(a){if(this.o)for(var b=0;b<this.o[w];++b){var c=this.o[b];if(RegExp(c.pattern).test(a))return c}return this.G};function T(a,b){this.a=a;this.f=b;this.h=h}F(T,U);p(T[x],function(a,b){this.h=d;google[z].d("script",this.g(a,b),h)});T[x].m=function(){return this.h};T[x].k=function(){};
T[x].g=function(a,b){if(!this.f.versions[":"+a]){if(this.f.aliases){var c=this.f.aliases[":"+a];if(c)a=c}if(!this.f.versions[":"+a])throw H("Module: '"+this.a+"' with version '"+a+"' not found!");}c=google[z].GoogleApisBase+"/libs/"+this.a+"/"+a+"/"+this.f.versions[":"+a][b&&b.uncompressed?"uncompressed":"compressed"];X("el",this.a);return c};T[x].s=function(){return h};var ca=h,Z=[],da=(new Date)[v](),X=function(a,b,c){if(!ca){P(l,"unload",ea);ca=d}if(c){if(!google[z].Secure&&(!google[z].Options||google[z].Options.csi===h)){a=a[C]()[r](/[^a-z0-9_.]+/g,"_");b=b[C]()[r](/[^a-z0-9_.]+/g,"_");l[y](G($,g,"http://csi.gstatic.com/csi?s=uds&v=2&action="+j(a)+"&it="+j(b)),1E4)}}else{Z[q]("r"+Z[w]+"="+j(a+(b?"|"+b:"")));l[y](ea,Z[w]>5?0:15E3)}},ea=function(){if(Z[w]){$(google[z][t]+"/stats?"+Z[B]("&")+"&nc="+(new Date)[v]()+"_"+((new Date)[v]()-da));Z.length=0}},$=function(a){var b=
new Image,c=fa++;ga[c]=b;b.onload=b.onerror=function(){delete ga[c]};b.src=a;b=g},ga={},fa=0;I("google.loader.recordStat",X);I("google.loader.createImageForLogging",$);

}) ();google.loader.rm({"specs":[{"name":"books","baseSpec":{"uri":"http://books.google.com/books/api.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}}}},"feeds",{"name":"friendconnect","baseSpec":{"uri":"http://www.google.com/friendconnect/script/friendconnect.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{}}},"spreadsheets","gdata","visualization",{"name":"sharing","baseSpec":{"uri":"http://www.google.com/s2/sharing/js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":false,"params":{"language":{"string":"hl"}}}},"search",{"name":"maps","baseSpec":{"uri":"http://maps.google.com/maps?file\u003dgoogleapi","ssl":"https://maps-api-ssl.google.com/maps?file\u003dgoogleapi","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"regex":"callback\u003d$1\u0026async\u003d2"},"language":{"string":"hl"}}},"customSpecs":[{"uri":"http://maps.google.com/maps/api/js","ssl":"https://maps-api-ssl.google.com/maps/api/js","key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"}},"pattern":"^(3|3..*)$"}]},"annotations_v2","wave","orkut",{"name":"annotations","baseSpec":{"uri":"http://www.google.com/reviews/scripts/annotations_bootstrap.js","ssl":null,"key":{"string":"key"},"version":{"string":"v"},"deferred":true,"params":{"callback":{"string":"callback"},"language":{"string":"hl"},"country":{"string":"gl"}}}},"language","earth","ads","elements"]});
google.loader.rfm({":search":{"versions":{":1":"1",":1.0":"1"},"path":"/api/search/1.0/2a8ff2a70ad0b091ae9dfd8b5e832141/","js":"default+en.I.js","css":"default.css","properties":{":JSHash":"2a8ff2a70ad0b091ae9dfd8b5e832141",":NoOldNames":false,":Version":"1.0"}},":language":{"versions":{":1":"1",":1.0":"1"},"path":"/api/language/1.0/62c64af2122d2da7dcb0087852fa7396/","js":"default+en.I.js","properties":{":JSHash":"62c64af2122d2da7dcb0087852fa7396",":Version":"1.0"}},":wave":{"versions":{":1":"1",":1.0":"1"},"path":"/api/wave/1.0/3b6f7573ff78da6602dda5e09c9025bf/","js":"default.I.js","properties":{":JSHash":"3b6f7573ff78da6602dda5e09c9025bf",":Version":"1.0"}},":spreadsheets":{"versions":{":0":"1",":0.3":"1"},"path":"/api/spreadsheets/0.3/8331b0bbcc74776270648505340e9200/","js":"default.I.js","properties":{":JSHash":"8331b0bbcc74776270648505340e9200",":Version":"0.3"}},":earth":{"versions":{":1":"1",":1.0":"1"},"path":"/api/earth/1.0/819ffbf1e363d238791231792a2e0a90/","js":"default.I.js","properties":{":JSHash":"819ffbf1e363d238791231792a2e0a90",":Version":"1.0"}},":annotations":{"versions":{":1":"1",":1.0":"1"},"path":"/api/annotations/1.0/11cfaf30c00ca64601d09fcac7dd8bc7/","js":"default+en.I.js","properties":{":JSHash":"11cfaf30c00ca64601d09fcac7dd8bc7",":Version":"1.0"}}});
google.loader.rpl({":scriptaculous":{"versions":{":1.8.3":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.2":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.1":{"uncompressed":"scriptaculous.js",

Initial URL


Initial Description


Initial Title
Make a web application multi lingual by using Google API......useful for PHP, Dotnet, and for other language developers to

Initial Tags


Initial Language
JavaScript