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


/ Published in: JavaScript
Save to your folder(s)



Copy this code and paste it in your HTML
  1. Read from top to Bottom see for **** especially.... /* ignore the spelling mistakes */
  2.  
  3. Make an application multi lingual by using google API....
  4. This process can even be implemented by an web service, but i have made use of google API
  5. Please follow the steps and make changes accordingly
  6.  
  7. 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......
  8.  
  9. *****************Add these 2 scripts tags into u r header and make it common for the pages so that it includes in each and everything***
  10. <!--<script type="text/javascript" src="Translate/googlelanguage.js"></script>
  11. <script type="text/javascript" src="Translate/translate.js"></script>-->
  12. ****************Better to add these 2 into head section of u r html or asp or jsp pages********************************************
  13. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  14. <html xmlns="http://www.w3.org/1999/xhtml">
  15. <head>
  16. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  17. <title>Untitled Document</title>
  18. </head>
  19.  
  20. <body>
  21. ************Add this thing into the body section where ever u wish to or u wanna Place the option for selection*******************
  22. <!-- <div><font size="+1">Select Language</font></div>
  23. <div id="mlt_languagelist"> </div>-->
  24.  
  25. -->Steps:
  26. 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.
  27.  
  28. 2) G to line number 85 there u will come to know how the langues get changed based upon u r request.
  29. 3) if(GL_curLang == "orig") {
  30. refresh();
  31. return;
  32. }
  33.  
  34. 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
  35.  
  36. Add:
  37. else if(GL_curLang == "es") { //spanish
  38. refresh();
  39. return;
  40. }
  41. else if(GL_curLang == "ja") { //japanese
  42. refresh();
  43. return;
  44. }
  45.  
  46.  
  47. 4) So add according to u r choice all this has to be followed aftr line number 888 for the 3 point.
  48.  
  49. 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.
  50. 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.
  51.  
  52. 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
  53.  
  54. 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.
  55.  
  56. 5)By this way the combo box is set with languages which you require to make the application multi lingual
  57.  
  58. 6)this particual api support 64 recognised languages , check the info in google for this particual api.
  59.  
  60.  
  61. *********************************************************************************************************************************
  62. </body>
  63. </html>
  64.  
  65.  
  66. *******************Save it as translate.js***************************
  67.  
  68. /* Multi-Language Translation Script:
  69. *
  70. * Automatically translates a webpage (containing text in more than one language) into any single language
  71. * requested by the user. Particularly useful for sites involving a lot of user-generated content (which
  72. * might have originally been written in different languages) - e.g. blogs, forums, or other community sites.
  73. * Harnesses the Google AJAX Language API to perform translation and language detection.
  74. *
  75. * Version: 0.2.5 [2010-01-22]
  76. * Author: Patrick Hathway, OdinLab, University of Reading.
  77. * For Documentation and Updates: See http://code.google.com/p/multi-language-translation/
  78. * Licence: MIT License - see http://opensource.org/licenses/mit-license.php for full terms. Also check
  79. * the script Documentation for more information, and for details of one important consideration.
  80. *
  81. * Some minor configuration is required for this script to work on your website. Follow the instructions
  82. * below, or see the Documentation for full details and examples... */
  83.  
  84. /* 1. Specify the 'Base Language' for your website: */
  85.  
  86. var GL_baseLang = "en";
  87.  
  88. /* 2. Specify the IDs for all major regions (i.e. HTML elements) in your site that should have their
  89. * contents translated. Note that an ID can only be used to identify a single element on a page (for
  90. * elements which appear multiple times, use Class Names instead - see below). The script will translate
  91. * each element separately; any elements that cannot be found on a page will be ignored: */
  92.  
  93. var GL_classIds = [
  94. ["navigation"],
  95. ["navigation", "", true],
  96. ["quick-id", "", true],
  97. ["c-quote", "", true],
  98. ["c-need-quote", "", true],
  99. ["c-index", "", true],
  100. ["c-about", "", true],
  101. ["c-exper", "", true],
  102. ["c-solution", "", true],
  103. ["c-product", "", true],
  104. ["c-contact", "", true],
  105. ["c-indian-add", "", true],
  106. ["c-work", "", true],
  107. ["c-contact", "", true],
  108. ["c-contactinf", "", true],
  109. ["c-usa-add", "", true],
  110. ["c-warning", "", true],
  111. ["right_sidebar", "fr", true],
  112. ["footer"]
  113. ];
  114.  
  115. /* 3. Specify the Class Names of all major regions (i.e. HTML elements) in your site that should have their
  116. * their contents translated. Multiple elements may appear on a page with the same class name; the script
  117. * will locate each occurrance (if present) and translate them separately: */
  118.  
  119. var GL_classNames = [
  120. ["entry_baselang"],
  121. ["entry_french", "fr"],
  122. ["index-class", "", true],
  123. ["about-class", "", true],
  124. ["association-class", "", true],
  125. ["building-class", "", true],
  126. ["career-class", "", true],
  127. ["college-class", "", true],
  128. ["construction-class", "", true],
  129. ["contact-class", "", true],
  130. ["entry_baselang", "", true],
  131. ["education-class", "", true],
  132. ["entry", "", true],
  133. ["expertise-class", "", true],
  134. ["description", "", true],
  135. ["list-custom_website", "", true],
  136. ["list-beautiful_graphic", "", true],
  137. ["list-using_nature", "", true],
  138. ["list-css_xhtml", "", true],
  139. ["description", "", true],
  140. ["list-branding_your", "", true],
  141. ["list-green_branding", "", true],
  142. ["list-who_are", "", true],
  143. ["list-long_term", "", true],
  144. ["list-the_importance", "", true],
  145. ["list-flow", "", true],
  146. ["list-click_through", "", true],
  147. ["list-scale", "", true],
  148. ["description", "", true],
  149. ["list-google_rank", "", true],
  150. ["list-ppc", "", true],
  151. ["list-custom_icon", "", true],
  152. ["list-why_use", "", true],
  153. ["list-web_standard", "", true],
  154. ["list-promoting_your", "", true],
  155. ["list-business_cards", "", true],
  156. ["fashin-class", "", true],
  157. ["right", "", true],
  158. ["web_portfolio", "", true],
  159. ["interior-class", "", true],
  160. ["manufacture-class", "", true],
  161. ["news-class", "", true],
  162. ["medical-class", "", true],
  163. ["opening-class", "", true],
  164. ["ourclass-class", "", true],
  165. ["portfolio-class", "", true],
  166. ["ecommerce-class", "", true],
  167. ["mobile-class", "", true],
  168. ["webdesign-class", "", true],
  169. ["product-class", "", true],
  170. ["professional-class", "", true],
  171. ["real-class", "", true],
  172. ["realestate-class", "", true],
  173. ["request-class", "", true],
  174. ["form_entry", "", true],
  175. ["request-id", "", true],
  176. ["requestquote-class", "", true],
  177. ["consumer-class", "", true],
  178. ["software-class", "", true],
  179. ["solutions-class", "", true],
  180. ["list-why_use", "", true],
  181. ["list-west_coast", "", true],
  182. ["list-custom_icon", "", true],
  183. ["list-crisp_graphics", "", true],
  184. ["list-scalable_across", "", true],
  185. ["testimonials-class", "", true],
  186. ["testimonials", "", true],
  187. ["tourism-class", "", true],
  188. ["trade-class", "", true],
  189. ["transport-class", "", true],
  190. ["levonsys-class", "", true],
  191. ["working-levonsys-class", "", true],
  192. ["quick", "", true],
  193. ["entry_french", "", true],
  194. ["quotes", "de", true]
  195. ];
  196.  
  197.  
  198. /* 4. Specify the default language for new visitors (leave blank to auto-detect using browser/system settings) */
  199.  
  200. var GL_curLang = "";
  201.  
  202. /* The rest of the Script should not be modified; unless you want to alter the functionality!
  203. * ------------------------------------------------------------------------------------------ */
  204.  
  205. // Global variables:
  206. var GL_srcContent; // array containing all content on the page to be translated, split up into chunks
  207. var GL_transContent = []; // array containing all chunks which have been translated
  208. var GL_chunksTotal = 0; // total number of chunks to translate
  209. var GL_curChunk; // ID of current chunk being translated
  210. var GL_errors; // array containing details of all errors that occur (if applicable)
  211. var GL_errSrcTxt; // array containing all source text that causes errors (if applicable)
  212. var GL_miniTransItems = []; // array containing element IDs/class names which contain minor items to translate
  213.  
  214. google.load("language", "1"); // load v1 of google ajax language api
  215.  
  216. // run when page loads
  217. function initialise() {
  218. addTransMsgs(); // append elements (which will display translation status messages) to page
  219. buildChunkedContent(); // create a local 'cache' of chunked content to be translated
  220. getLangCookie(); // find out the current site language (if known)
  221. getLangs(); // display listbox containing all languages the site can be translated into
  222.  
  223. // if the original languages should be shown, end function.
  224. if(GL_curLang == "orig") {
  225. return;
  226. }
  227.  
  228. // otherwise, start the translation
  229. startTranslation();
  230. }
  231.  
  232. // display listbox containing all languages the site can be translated into (so that one can be selected by user)
  233. function getLangs() {
  234. // create listbox within script so that it won't appear if JavaScript is disabled
  235. document.getElementById("mlt_languagelist").innerHTML = '<select id="mlt_language" onchange="changeLang()" style="width:150px; height:20px;"></select>';
  236. // + '<div id="mlt_langattr"></div>'
  237. var langItems = document.getElementById("mlt_language").options;
  238.  
  239. // add option to top of listbox allowing user to view the site in its original (i.e. un-translated) languages
  240. langItems.add(new Option("Original Languages", "orig", true));
  241.  
  242. // loop through list of currently available languages and add each to listbox
  243. for(var lang in google.language.Languages) {
  244. // find out the 2 character Google language code
  245.  
  246. var langCode = google.language.Languages[lang];
  247. // convert language string to title case
  248. var langString = lang.substr(0,1) + lang.substr(1).toLowerCase();
  249. // improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
  250. langString = langString.split("_").join(" - ");
  251.  
  252. // check that Google can translate content into the current language
  253. if ((google.language.isTranslatable(langCode)) && (langCode != "")) {
  254. // if so, add to listbox and translate, so native speakers of that language can find it
  255. if(langCode=="ar")
  256. {
  257. langItems.add(new Option(langString, langCode));
  258. miniTranslate(langItems[(langItems.length-1)],langCode);
  259. }
  260.  
  261. }
  262. }
  263.  
  264. document.getElementById("mlt_language").value = GL_curLang; // change listbox to display current site language
  265. google.language.getBranding("mlt_langattr"); // display Google attribution below listbox (as required by TOS)
  266. }
  267.  
  268. // start the translation
  269. function startTranslation() {
  270. // reset global variables
  271. GL_curChunk = 0; GL_errors = []; GL_errSrcTxt = [];
  272.  
  273. // check if all content has already been translated into current language since page loaded.
  274. if(chkLangTrans()) {
  275. return; // if so, don't need to translate content again
  276. }
  277.  
  278. // sanity check - can google actually translate into the current site language?
  279. if (!(google.language.isTranslatable(GL_curLang)) || (GL_curLang == "")) {
  280. return; // if not, end translation
  281. } // Otherwise, send content to google to be translated:
  282.  
  283. // show the 'Translating...' block
  284. document.getElementById("mlt_translatemsg").innerHTML = 'Translating... <span id="mlt_perc">0%</span>';
  285. miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
  286. document.getElementById("mlt_translatemsg").style.display='block';
  287.  
  288. // find out the ID of the destination language
  289. var curLangNo = document.getElementById("mlt_language").selectedIndex;
  290. var k = 0;
  291.  
  292. // create sub-array to hold all translations for current language
  293. GL_transContent[GL_transContent.length] = new Array(3);
  294. GL_transContent[(GL_transContent.length-1)][0] = []; // this array will contain all translated chunks
  295. GL_transContent[(GL_transContent.length-1)][1] = GL_curLang; // store current language
  296. GL_transContent[(GL_transContent.length-1)][2] = false; // mark translation of language as incomplete
  297.  
  298. // loop through all the chunks to be translated, send to google...
  299. for(var i = 0; i < GL_srcContent.length; i++) {
  300. // find out the source language for the current element to be translated
  301. var srcLang = GL_srcContent[i][GL_srcContent[i].length - 1];
  302.  
  303. for(var j = 0; j < (GL_srcContent[i].length - 1); j++) {
  304. /* AJAX is used to return translated chunks, so they MAY be returned in any order.
  305. To solve, include current chunk id, destination language + separators at start of each
  306. string. This is a bit of a 'hack', so try to find a better solution! */
  307. var srcText = curLangNo + "<br />" + k + "<br />" + GL_srcContent[i][j];
  308.  
  309. // send current chunk to google translate; when translated, call function translateChunk
  310. google.language.translate(srcText, srcLang, GL_curLang, translateChunk);
  311. k++;
  312. }
  313. }
  314.  
  315. setTimeout("checkTransStatus()", 1000); // run function to check translation status after 1 second
  316. }
  317.  
  318. // check if page content has already been translated into current language since page loaded.
  319. function chkLangTrans() {
  320. // loop through the list of languages the page has been translated into
  321. for(var i = 0; i < GL_transContent.length; i++) {
  322. // check if a translation for current language exists, and if so, whether it is complete.
  323. if((GL_transContent[i][1] == GL_curLang) && (GL_transContent[i][2] == true)){
  324. /* if so, don't need to send content to google again, just assemble the pre-translated content.
  325. This will *dramatically* reduce the translation time for this language! */
  326. endTranslation(i);
  327. return true;
  328. }
  329. }
  330. return false; // otherwise, all relevant page content must be submitted to google for translation.
  331. }
  332.  
  333. // This runs after each chunk has been translated...
  334. function translateChunk(result) {
  335. // handle translation errors gracefully by storing error details but allowing translation to continue
  336. if (result.error) {
  337. GL_errors[GL_errors.length] = result.error.message;
  338. }
  339. else {
  340.  
  341. /* Translated chunks may be returned in any order, so we need a method to assemble the chunks
  342. in the correct order:
  343. * Start of each chunk has a destination language id and a chunk id followed by separators.
  344. * Separator is a <br /> HTML tag, as these always appear to retain position after translation...
  345. * The destination language id is used to ensure the translated text is now in the correct language.
  346. * Each chunk is stored in the position of the 'GL_transContent' array corresponding to the current chunk id.
  347. * The ids + separators should not be shown, and are discarded from the chunk when it's stored in array.
  348. */
  349.  
  350. // split into array based on separator, so we know the id & destination language of translated chunk
  351. var transChunk = result.translation.split("<br />");
  352. // [find out length of substring to chop off from start of chunk]
  353. var chunkSubStr = 12 + transChunk[0].length + transChunk[1].length;
  354. // remove whitespace from chunk id & destination language (a problem with some translations)
  355. transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
  356. transChunk[1] = transChunk[1].replace(/^\s+|\s+$/g,"");
  357.  
  358. /* If the translated chunk has a different destination language to the current site language, discard
  359. translation & end function. This may happen if user changes language whilst translation is in progress */
  360. if(transChunk[0] != document.getElementById("mlt_language").selectedIndex) {
  361. return;
  362. }
  363.  
  364. // store translated chunk in current language array, along with detected source language (if known)
  365. GL_transContent[(GL_transContent.length-1)][0][transChunk[1]] = new Array(3);
  366. GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][0] = result.translation.substr(chunkSubStr);
  367. GL_transContent[(GL_transContent.length-1)][0][transChunk[1]][1] = result.detectedSourceLanguage;
  368. }
  369.  
  370. GL_curChunk++; // increment current chunk ID every time function is called
  371.  
  372. // calculate and display percentage of translation completed, based on number of chunks remaining
  373. var perc = (GL_curChunk / GL_chunksTotal)*100;
  374. document.getElementById("mlt_perc").innerHTML = Math.round(perc) + "%";
  375.  
  376. // when all chunks have been translated, run the 'endTranslation' function...
  377. if(GL_curChunk >= GL_chunksTotal) {
  378. endTranslation((GL_transContent.length-1)); // [final array element holds current language content!]
  379. }
  380. }
  381.  
  382. /* runs once a second whilst translation is in progress, updating contents of all elements that have already
  383.   been completely translated. Also shows 'timeout' messages if translation not completed within 30 seconds... */
  384. function checkTransStatus() {
  385. // 'static' member variables to keep track of how many times function has run, as well as current language:
  386. if((typeof checkTransStatus.chkStatusCount == 'undefined') || (checkTransStatus.curTransLang != GL_curLang)) {
  387. // reset variables if not defined yet, or if site language has changed since last function call
  388. checkTransStatus.chkStatusCount = 0;
  389. checkTransStatus.curTransLang = GL_curLang;
  390. }
  391.  
  392. // if translation is now complete, end function.
  393. if(GL_curChunk >= GL_chunksTotal) {
  394. return;
  395. }
  396.  
  397. checkTransStatus.chkStatusCount++; // increment Translation Status counter
  398.  
  399. // Store the list of languages in case they are replaced during translation
  400. var langList = document.getElementById("mlt_languagelist").innerHTML;
  401.  
  402. var curElement; var curTransChunk = 0; var curClass = 0; var curTransLang = GL_transContent.length-1;
  403.  
  404. // loop through all element IDs (as specified at script top), searching for ones with completed translations
  405. for(var i = 0; i < GL_classIds.length; i++) {
  406. curElement = document.getElementById(GL_classIds[i][0]); // find out current element
  407.  
  408. // if current element ID exists on the page, replace contents with translated chunks
  409. if(curElement != null) {
  410. // assemble and display translated chunks for current element
  411. curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,false);
  412. curClass++; // move to next element ID
  413. }
  414. }
  415.  
  416. // Get all elements on the page, so that ones with the specified class names can be located
  417. var allElements = document.getElementsByTagName("*");
  418. // loop through all element class names (as specified at script top), searching for completed translations
  419. for(var i = 0; i < GL_classNames.length; i++) {
  420. // loop through all elements, so that any with the current class name can be identified
  421. for(var j = 0; j < allElements.length; j++) {
  422. if(allElements[j].className == GL_classNames[i][0]) {
  423. // assemble and display translated chunks for current element
  424. curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],false);
  425. curClass++; // move to next element Class Name
  426. }
  427. }
  428. }
  429.  
  430. // if listbox containing all languages has been removed as a result of translation, display it again
  431. if(document.getElementById("mlt_languagelist").innerHTML == "") {
  432. document.getElementById("mlt_languagelist").innerHTML = langList;
  433. document.getElementById("mlt_language").value = GL_curLang; // change listbox to show current language
  434. }
  435.  
  436. /* if translation still isn't complete after 30 seconds, update translation message. Note: there is no
  437. need to halt the current translation completely, but we will allow user to restart it if desired! */
  438. if(checkTransStatus.chkStatusCount == 30) {
  439. // calculate and display percentage of translation completed, based on number of chunks remaining
  440. var perc = Math.round((GL_curChunk / GL_chunksTotal)*100) + "%";
  441. // update translation status message
  442. document.getElementById("mlt_translatemsg").innerHTML = 'Translating (Slowly!)... ' +
  443. '<span id="mlt_perc">' + perc + '</span> - <a href="javascript:refresh()">Retry</a>';
  444. miniTranslate(document.getElementById("mlt_translatemsg")); // translate block into site language
  445. }
  446.  
  447. setTimeout("checkTransStatus()", 1000); // check translation status again after another second
  448. }
  449.  
  450. // runs after all translations have been completed; displaying the results on screen in place of previous content
  451. function endTranslation(curTransLang) {
  452. var curElement;
  453. var curTransChunk = 0; var curClass = 0;
  454.  
  455. // loop through all element IDs (as specified at script top), replacing current contents with translations
  456. for(var i = 0; i < GL_classIds.length; i++) {
  457. curElement = document.getElementById(GL_classIds[i][0]); // find out current element
  458.  
  459. // if current element ID exists on the page, replace contents with translated chunks
  460. if(curElement != null) {
  461. // assemble and display translated chunks for current element
  462. curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,curElement,true,GL_classIds[i]);
  463. curClass++; // move to next element ID
  464. }
  465. }
  466.  
  467. // Get all elements on the page, so that ones with the specified class names can be located
  468. var allElements = document.getElementsByTagName("*");
  469. // loop through all element class names (as specified at script top), so contents can be replaced by translations
  470. for(var i = 0; i < GL_classNames.length; i++) {
  471. // loop through all elements, so that any with the current class name can be identified
  472. for(var j = 0; j < allElements.length; j++) {
  473. if(allElements[j].className == GL_classNames[i][0]) {
  474. // assemble and display translated chunks for current element
  475. curTransChunk = unpackTransChunks(curTransLang,curTransChunk,curClass,allElements[j],true,GL_classNames[i]);
  476. curClass++; // move to next element Class Name
  477. }
  478. }
  479. }
  480.  
  481. // Perform translations of all content added by the script (e.g. language strings and error messages)
  482. transAddedText();
  483.  
  484. // Re-create listbox containing all languages, in case it has been removed as a result of translation
  485. getLangs();
  486.  
  487. // translate the 'Original Languages' listbox item to equivalent in current site language
  488. miniTranslate(document.getElementById("mlt_language").options[0],GL_curLang,"Original Languages");
  489.  
  490. // if any errors occured during translation, display warning message at top of screen and end function
  491. if(GL_errors.length != 0) {
  492. document.getElementById("mlt_translatemsg").innerHTML = GL_errors.length + ' Problems(s) Occurred During Translation: ' +
  493. '<a href="javascript:refresh()">Retry</a> - <a href="javascript:showErrDetails()">Details</a> - ' +
  494. '<a href="javascript:hideTransMsg()">Hide</a>';
  495. miniTranslate(document.getElementById("mlt_translatemsg")); // translate warning message into current site language
  496. return;
  497. }
  498.  
  499. // mark translation of page into current language as complete, so that translation can be quicker next time.
  500. GL_transContent[curTransLang][2] = true;
  501.  
  502. hideTransMsg(); // otherwise, hide 'Translating...' message
  503. }
  504.  
  505. // assemble and display translated chunks for current element on page
  506. function unpackTransChunks(curTransLang,curTransChunk,curClassNum,curElement,transComplete,curClass) {
  507. // 'static' member variable to keep track of how many times function has run
  508. if(typeof unpackTransChunks.curLinkId == 'undefined') {
  509. // reset curLinkId variable if not defined yet - it's used to identify the correct 'show source text' link
  510. unpackTransChunks.curLinkId = 0;
  511. } unpackTransChunks.curLinkId++; var j = unpackTransChunks.curLinkId; // increment current link id, j is an alias
  512.  
  513. var curContent = ""; // reset translated contents of current element
  514. var initTransChunk = curTransChunk; // store initial chunk id of current element
  515.  
  516. // loop through all translated chunks, assembling all translated content for current element
  517. for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
  518. // if current chunk does not exist, translation is not complete or errors occurred
  519. if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == false)) {
  520. break; // stop looping through chunks if full translation has not yet been completed
  521. } else if((GL_transContent[curTransLang][0][curTransChunk] == null) && (transComplete == true)) {
  522. // if full translation IS complete, show warning message and a link to show source text (in red)
  523. curContent += '<div style="color: red;" id="mlt_srctxt' + j + '">[<span class="mlt_transerrtxt">' +
  524. '<em style="text-transform: uppercase;">THIS SECTION COULD NOT BE TRANSLATED</em> - '+
  525. '<a id="mlt_srctxtlnk' + j + '" href="javascript:showSrcTxt(' + j + ',' + curClassNum + ',' + (i+1) +
  526. ')">View Source Text [+]</a></span><span id="mlt_srctxtbracket' + j + '">]</span></div>';
  527. GL_errSrcTxt[GL_errSrcTxt.length] = GL_srcContent[curClassNum][i]; // store affected source text
  528. unpackTransChunks.curLinkId++; j = unpackTransChunks.curLinkId; // increment current link id
  529. } else {
  530. // otherwise append current translated chunk to translated content string
  531. curContent += GL_transContent[curTransLang][0][curTransChunk][0];
  532. }
  533. curTransChunk++; // move to next chunk
  534. }
  535.  
  536. // if translation is complete, replace contents of current element with translated text
  537. if(transComplete == true) {
  538. curElement.innerHTML = curContent;
  539. // append a language string to bottom of current element if desired
  540. getLangString(curTransLang,curElement,curClass,initTransChunk,(GL_srcContent[curClassNum].length - 1),j,curClassNum);
  541. // otherwise, check if all translated chunks for current element were assembled
  542. } else if((i == (GL_srcContent[curClassNum].length - 1)) && (GL_transContent[curTransLang][0][initTransChunk][2] != true)) {
  543. // if so (and current element translation is not yet marked as complete), replace contents with translation
  544. curElement.innerHTML = curContent;
  545. GL_transContent[curTransLang][0][initTransChunk][2] = true; // mark current element translation as complete
  546. }
  547.  
  548. return curTransChunk; // return current chunk id to calling function
  549. }
  550.  
  551. // If required, find and append a string containing the Source Language to the bottom of the specified element
  552. function getLangString(curTransLang,curElement,curClass,curTransChunk,transChunksLen,j,curClassNum) {
  553.  
  554. var detectedLang = "";
  555.  
  556. // if the current element does not need a language string appended, end function
  557. if(curClass[2] != true) {
  558. return;
  559. }
  560.  
  561. // if source language for current element has already been manually specified, set this as detected language
  562. if(curClass[1] != "") {
  563. detectedLang = curClass[1];
  564. }
  565. // otherwise find out language based on the detected source languages for translated chunks in current element
  566. else {
  567. detectedLang = findDetectedLang(curTransLang,curTransChunk,transChunksLen);
  568. }
  569.  
  570. // if detected language is same as site language, there is no need to display language string, so end function
  571. if(detectedLang == GL_curLang){
  572. return;
  573. }
  574.  
  575. var srcLangString = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
  576.  
  577. // append language string to current element...
  578. // curElement.innerHTML += '<div style="color: green;" id="mlt_srctxt' + j + '"></div>';
  579. }
  580.  
  581. // convert a google language code into a formatted string containing the language name
  582. function getFmtLangStr(lang) {
  583. // loop through list of supported languages and retrieve names
  584. for(var l in google.language.Languages) {
  585. if(google.language.Languages[l] == lang) {
  586. // convert language string into title case
  587. var lang = l.substr(0,1) + l.substr(1).toLowerCase();
  588. // improve formatting of 'chinese_simplified' and 'chinese_traditional' language strings
  589. lang = lang.split("_").join(" - ");
  590. break; // stop loop (don't need to continue searching for languages)
  591. }
  592. }
  593. // if language cannot be found in list of supported languages, set language to 'unknown'
  594. if(typeof lang == "undefined") {
  595. lang = "An Unknown Language";
  596. }
  597. return lang; // return formatted language string
  598. }
  599.  
  600. // find out the most common detected language for all translated chunks in current element, to appear in language string
  601. function findDetectedLang(curTransLang,curTransChunk,transChunksLen) {
  602. var chunkLangs = []; langCounter = 0;
  603.  
  604. // loop through all translated chunks in current element
  605. for(var i = 0; i < transChunksLen; i++) {
  606. // bugfix: set detected language to 'undefined' if an error occurred during translation...
  607. if(GL_transContent[curTransLang][0][curTransChunk] == null) {
  608. GL_transContent[curTransLang][0][curTransChunk] = new Array(3);
  609. GL_transContent[curTransLang][0][curTransChunk][1] = "undefined";
  610. }
  611. // loop through array of detected languages to see if current chunk has an existing detected language
  612. for(var j = 0; j < chunkLangs.length; j++) {
  613. if(chunkLangs[j][0] == GL_transContent[curTransLang][0][curTransChunk][1]) {
  614. // if so, increment counter containing the total number of chunks with that language
  615. chunkLangs[j][1]++;
  616. break; // halt loop
  617. }
  618. }
  619. // if current chunk has a language not yet detected, add it to end of detected languages array
  620. if(j == chunkLangs.length) {
  621. chunkLangs[j] = new Array(2);
  622. chunkLangs[j][0] = GL_transContent[curTransLang][0][curTransChunk][1]; // name of detected language
  623. chunkLangs[j][1] = 1; // total number of chunks with that language
  624. }
  625. curTransChunk++; // move to next chunk
  626. }
  627.  
  628. /* once array has been created containing all detected languages in current element, loop through it
  629. to find the most common detected language - language string should contain this */
  630. for(i = 0; i < chunkLangs.length; i++) {
  631. if(chunkLangs[i][1] > langCounter) {
  632. /* if current language was detected more times than all previous languages, store language
  633. and number of times detected - so that next language can be compared against this total */
  634. var detectedLang = chunkLangs[i][0];
  635. langCounter = chunkLangs[i][1];
  636. }
  637. }
  638.  
  639. return detectedLang; // return the most common detected language
  640. }
  641.  
  642. // Auto-translate all text added previously by the script (including language strings and error messages)
  643. function transAddedText() {
  644. var allElements = document.getElementsByTagName("*"); // get all elements on page, so relevant ones can be translated
  645. var foundElements = [];
  646.  
  647. // loop through all elements to find any of class 'mlt_langstring' or 'mlt_transerrtxt'
  648. for(var i=0; i<allElements.length; i++) {
  649. if((allElements[i].className == "mlt_langstring") || (allElements[i].className == "mlt_transerrtxt")) {
  650. foundElements[foundElements.length] = allElements[i];
  651. }
  652. }
  653.  
  654. // translate all located elements (runs separately from above code to prevent infinite loop as items are translated)
  655. for(i = 0; i < foundElements.length; i++) {
  656. miniTranslate(foundElements[i]); // translate current element
  657. }
  658. }
  659.  
  660. /* this function runs before any translation takes place, and creates a local 'cache' of all content to be translated (in chunks)
  661.   - meaning the content can be submitted to Google more rapidly, and the resulting translations can then be sorted reliably */
  662. function buildChunkedContent() {
  663. var curElement; GL_srcContent = []; var j = 0;
  664.  
  665. /* loop through all applicable element IDs (as specified at script top), converting the contents of each into chunks,
  666. and storing each chunk in an array */
  667. for(var i = 0; i < GL_classIds.length; i++) {
  668. curElement = document.getElementById(GL_classIds[i][0]); // find out current element
  669. // check that element actually exists on the page - if not, ignore it
  670. if(curElement != null) {
  671. GL_srcContent[j] = createChunks(curElement); // separate the content of current element into chunks
  672. GL_chunksTotal += GL_srcContent[j].length; // store a running total of the number of chunks created
  673.  
  674. // if a Source Language is not specified for current element, store Base Language in array instead
  675. if(GL_classIds[i].length == 1) {
  676. GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
  677. } else {
  678. // otherwise store the specified language (or a blank string if this is to be auto-detected)
  679. GL_srcContent[j][GL_srcContent[j].length] = GL_classIds[i][1];
  680. }
  681. j++;
  682. }
  683. }
  684.  
  685. // get all elements on page, so that the ones specified can be located
  686. var allElements = document.getElementsByTagName("*");
  687. // loop through all applicable element IDs (as specified at script top), converting into chunks and storing in array
  688. for(var i = 0; i < GL_classNames.length; i++) {
  689. // find all elements which have the current class name
  690. for(var k = 0; k < allElements.length; k++) {
  691. if(allElements[k].className == GL_classNames[i][0]) {
  692. // separate the content of current element into chunks
  693. GL_srcContent[j] = createChunks(allElements[k]);
  694. // store a running total of the number of chunks created
  695. GL_chunksTotal += GL_srcContent[j].length;
  696.  
  697. // if a Source Language is not specified for current element, store Base Language in array
  698. if(GL_classNames[i].length == 1) {
  699. GL_srcContent[j][GL_srcContent[j].length] = GL_baseLang;
  700. } else {
  701. // otherwise store specified language (or a blank string if auto-detected)
  702. GL_srcContent[j][GL_srcContent[j].length] = GL_classNames[i][1];
  703. }
  704. j++;
  705. }
  706. }
  707. }
  708. }
  709.  
  710. /* Web browsers (and Google) limit the amount of text translated per request, so split contents of current element into chunks.
  711.   The aim is to achieve this whilst maintaining the translation integrity */
  712. function createChunks(srcContent) {
  713. var chars = 1000; // number of characters to allow per chunk.
  714.  
  715. /* We do NOT want the content inside any HTML tag to be split between chunks (as this could cause
  716. rendering problems), so create 2 arrays storing tags and textual content of current div separately */
  717. var tags = srcContent.innerHTML.match(/<.*?>/g);
  718. var text = srcContent.innerHTML.split(/<.*?>/g);
  719. if(tags == null) {
  720. tags = new Array();} // handle content containing no tags
  721.  
  722. var curchar = 0; var tagnum = 0; var textnum = 0; var contTotal = tags.length + text.length;
  723. // create an array containing content to be chunked, with tags + text separately re-assembled (in order)
  724. var content = new Array(contTotal);
  725. // loop through content of current div
  726. for(var i=0; i < contTotal; i++) {
  727. // if current position in content is the start of a tag char, add appropriate tag to content array
  728. if(srcContent.innerHTML.substr(curchar,1) == "<") {
  729. content[i] = tags[tagnum];
  730. curchar += tags[tagnum].length;
  731. tagnum++;
  732. // if it is a text string, add the corresponding text to the curent element in content array
  733. } else {
  734. content[i] = text[textnum];
  735. curchar += text[textnum].length;
  736. textnum++;
  737. }
  738. }
  739.  
  740. // Create the chunks - don't split either tags or words (to ensure as high translation quality as possible)
  741. var chunks = []; var curChunk = 0;
  742. chunks[0]="";
  743. for (i = 0; i < contTotal; i++) {
  744. // if next content item (tag or textual) won't exceed length of current chunk, add it to chunk
  745. if((chunks[curChunk].length + content[i].length) < chars) {
  746. chunks[curChunk] += content[i];
  747. } else {
  748. // otherwise, proceed to next chunk.
  749. curChunk++;
  750. // add the entire content item to this chunk if possible (to ensure better translation)
  751. if(content[i].length < chars) {
  752. chunks[curChunk] = content[i];
  753. }
  754. else {
  755. // only split further in rare cases where text length exceeds maximum chunk size
  756. var curPos = 0;
  757. do {
  758. // retrieve the maximum amount of text that can fit in this chunk
  759. var subContent = content[i].substr(curPos,chars);
  760. // find out how many words are in this substring
  761. var words = subContent.split(" ");
  762. // chop off final word, so words aren't split up between chunks
  763. var lastWordPos = subContent.length - words[(words.length-1)].length;
  764. if(subContent.length < chars) { // [bugfix: prevent word cut-off on final iteration]
  765. lastWordPos = subContent.length}
  766. chunks[curChunk] = subContent.substr(0,lastWordPos); // store in chunk
  767. curChunk++; // remainder of text will go in next chunk
  768. curPos+=lastWordPos; // store current position in text, for further processing
  769. } while(subContent.length >= chars); // repeat until all this text has been chunked
  770. curChunk--; // because there may still be space in the current chunk!
  771. }
  772. }
  773. }
  774.  
  775. return chunks; // return chunked content to calling function...
  776. }
  777.  
  778. // Append elements to page (will be used to display translation messages), and specify their css styles.
  779. function addTransMsgs() {
  780. // add element to page which will contain translation messages
  781. var transCont = document.createElement("div");
  782. document.body.appendChild(transCont);
  783.  
  784. // add element to container created above - this will display the translation messages
  785. var translateMsg = document.createElement("div");
  786. translateMsg.id = "mlt_translatemsg";
  787. transCont.appendChild(translateMsg);
  788.  
  789. // define visual styles for translation messages displayed on screen
  790. translateMsg.style.backgroundColor = "silver";
  791. translateMsg.style.border = "3px green solid";
  792. translateMsg.style.padding = "5px";
  793. translateMsg.style.fontSize = "large";
  794. translateMsg.style.fontWeight = "bold";
  795. translateMsg.style.textAlign = "left";
  796. translateMsg.style.color = "black";
  797.  
  798. // more translation message styles (these should not need editing!)
  799. translateMsg.style.left = "-50%";
  800. translateMsg.style.position = "relative";
  801. translateMsg.style.display = "none";
  802.  
  803. // define the styles for the container element
  804. transCont.style.left = "50%";
  805. transCont.style.zIndex = "1000";
  806. if(!(/MSIE 6/i.test(navigator.userAgent))) {
  807. // styles for all browsers except IE6
  808. transCont.style.position = "fixed";
  809. transCont.style.top = "0px";
  810. }
  811. else {
  812. // styles for IE6
  813. transCont.style.position = "absolute";
  814. transCont.style.setExpression("top", "(i = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + 'px'");
  815. }
  816. }
  817.  
  818. // Hide 'Translating...' message (or translation error message) - runs at end of translation, or if user dismisses error message
  819. function hideTransMsg() {
  820. document.getElementById("mlt_translatemsg").innerHTML = "";
  821. document.getElementById("mlt_translatemsg").style.display='none';
  822. }
  823.  
  824. // if the user clicks on the 'Details' link [after error(s) occurred], show details of all errors on screen
  825. function showErrDetails() {
  826. // continue to show original error message (but remove 'Details' link)
  827. document.getElementById("mlt_translatemsg").innerHTML = '<span id="mlt_transerrmsg1">' + GL_errors.length +
  828. ' Problems(s) Occurred During Translation: ' + '<a href="javascript:refresh()">Retry</a> - ' +
  829. '<a href="javascript:hideTransMsg()">Hide</a>... <br /><em>Error(s) Reported:</em></span>' +
  830. '<ul style="margin: 0px; padding: 0px;" id="mlt_transerrlist"></ul>';
  831.  
  832. // Loop through array containing details of all errors, and show them as a list on screen
  833. for(var i = 0; i < GL_errors.length; i++) {
  834. document.getElementById("mlt_transerrlist").innerHTML += '<li style="margin-left: 15px;">' + GL_errors[i] + '.</li> ';
  835. }
  836.  
  837. /* create a textarea - this will show the original source text of all affected sections (as HTML) to aid debugging
  838. Note: because translations are returned using AJAX, the affected sections are not NECESSARILY in the same order as
  839. the errors reported (though in many cases, they will be!) */
  840. document.getElementById("mlt_translatemsg").innerHTML += '<em id="mlt_transerrmsg2">Section(s) Affected:</em><br />' +
  841. '<textarea id="mlt_errsrctxt" rows="8" readonly="readonly" style="width: 99%; background-color: silver; border: 1px gray solid;">' +
  842. '</textarea>';
  843.  
  844. // Loop through Source Text array, appending to textarea.
  845. for(var i = 0; i < GL_errSrcTxt.length; i++) {
  846. document.getElementById("mlt_errsrctxt").value += "Affected Section " + (i+1) + ":\n" + GL_errSrcTxt[i] + "\n\n";
  847. }
  848.  
  849. // Translate the entire contents of the Translation Errors box (with the exception of the text inside the textarea)
  850. miniTranslate(document.getElementById("mlt_transerrmsg1")); miniTranslate(document.getElementById("mlt_transerrlist"));
  851. miniTranslate(document.getElementById("mlt_transerrmsg2"));
  852. }
  853.  
  854. // function runs when the user clicks on a link to view the original source text for a translated element / chunk
  855. function showSrcTxt(curLinkId,curClassNum,curChunkId) {
  856. // if the current chunk should be shown only, display chunk on screen
  857. if((curChunkId-1) != -1) {
  858. document.getElementById("mlt_srctxt"+curLinkId).innerHTML +=
  859. '<div id="mlt_srctxtcontent' + curLinkId + '">'+GL_srcContent[curClassNum][(curChunkId-1)]+']</div>';
  860. } else {
  861. // otherwise assemble all chunks for current element, and display on screen
  862. var srcTxt = "";
  863. for(var i = 0; i < (GL_srcContent[curClassNum].length - 1); i++) {
  864. srcTxt += GL_srcContent[curClassNum][i];
  865. }
  866. document.getElementById("mlt_srctxt"+curLinkId).innerHTML +=
  867. '<div id="mlt_srctxtcontent' + curLinkId + '">'+srcTxt+']</div>';
  868. }
  869.  
  870. // update Source Text link so that when clicked in future, the source text will be hidden instead...
  871. srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
  872. srcTxtLnk.innerHTML = "Hide Source Text [-]";
  873. srcTxtLnk.href = 'javascript:hideSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
  874. miniTranslate(srcTxtLnk); // translate link text
  875. document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = ""; // hide bracket after link
  876. }
  877.  
  878. // function runs when the user clicks on a link to hide the original source text for a translated element / chunk
  879. function hideSrcTxt(curLinkId,curClassNum,curChunkId) {
  880. // remove the element containing the original source text
  881. srcTxtContent = document.getElementById("mlt_srctxtcontent"+curLinkId);
  882. document.getElementById("mlt_srctxt"+curLinkId).removeChild(srcTxtContent);
  883.  
  884. // update Source Text link so that when clicked in future, the source text will be shown instead...
  885. srcTxtLnk = document.getElementById("mlt_srctxtlnk"+curLinkId);
  886. srcTxtLnk.innerHTML = "View Source Text [+]";
  887. srcTxtLnk.href = 'javascript:showSrcTxt(' + curLinkId + ',' + curClassNum + ',' + curChunkId + ')';
  888. miniTranslate(srcTxtLnk); // translate link text
  889. document.getElementById("mlt_srctxtbracket"+curLinkId).innerHTML = "]"; // show bracket after link
  890. }
  891.  
  892. // translate small non crucial items of text into current site language
  893. function miniTranslate(item,destLang,srcTxt) {
  894. if(typeof destLang == "undefined") {
  895. var destLang = GL_curLang; // if the destLang argument was not specified, use the current site language
  896. }
  897. if(typeof srcTxt == "undefined") {
  898. var srcTxt = item.innerHTML; // if the srcText argument was not specified, use the current item contents
  899. }
  900.  
  901. // loop through translated items array to see if a translation for current text already exists since page loaded
  902. for(var i = 0; i < GL_miniTransItems.length; i++) {
  903. // check if source text and destination language match a translated item (and a completed translation exists for it)
  904. if((GL_miniTransItems[i][1] == srcTxt) && (GL_miniTransItems[i][2] == destLang) && (GL_miniTransItems[i][3] != "")) {
  905. item.innerHTML = GL_miniTransItems[i][3]; // if so, display existing translation in item
  906. item.title = srcTxt.split(/<.*?>/g).join(""); // display English source text as a tooltip (strip HTML first)
  907. return; // Don't need to send a translation request to Google, so end function.
  908. }
  909. }
  910.  
  911. // store item to be translated in global array for access by callback function
  912. GL_miniTransItems[GL_miniTransItems.length] = new Array(4);
  913. GL_miniTransItems[(GL_miniTransItems.length-1)][0] = item;
  914. GL_miniTransItems[(GL_miniTransItems.length-1)][1] = srcTxt;
  915. GL_miniTransItems[(GL_miniTransItems.length-1)][2] = destLang;
  916. GL_miniTransItems[(GL_miniTransItems.length-1)][3] = "";
  917.  
  918. // create source text by adding current item ID to start of item text (ID will ensure correct item is translated)
  919. srcTxt = (GL_miniTransItems.length-1) + "<br />" + srcTxt;
  920.  
  921. google.language.translate(srcTxt, "en", destLang, function(result) {
  922. if (!result.error) {
  923. // split into array based on separator, so we know the id of translated item
  924. var transChunk = result.translation.split("<br />");
  925. // [find out length of substring to chop off from start of item]
  926. var chunkSubStr = 6 + transChunk[0].length;
  927. // remove whitespace from item id (a problem with some translations)
  928. transChunk[0] = transChunk[0].replace(/^\s+|\s+$/g,"");
  929.  
  930. // display english source text of translated item (with HTML stripped) if user hovers mouse over it
  931. var strippedSrcTxt = GL_miniTransItems[transChunk[0]][1].split(/<.*?>/g).join("");
  932. GL_miniTransItems[transChunk[0]][0].title = "[" + strippedSrcTxt + "]";
  933.  
  934. // store and display translation of specified item (stripping item ID from start of text)
  935. GL_miniTransItems[transChunk[0]][3] = result.translation.substr(chunkSubStr);
  936. GL_miniTransItems[transChunk[0]][0].innerHTML = GL_miniTransItems[transChunk[0]][3];
  937. }
  938. });
  939. }
  940.  
  941. // runs when the user changes the site language
  942. function changeLang(destLang) {
  943. if(typeof destLang != "undefined") {
  944. GL_curLang = destLang; // if the destLang argument was specified, set new site language to this
  945. document.getElementById("mlt_language").value = GL_curLang; // change listbox to display new site language
  946. } else {
  947. // otherwise get the new language requested by user
  948. GL_curLang = document.getElementById("mlt_language").value;
  949. }
  950.  
  951. // store the requested language in a cookie
  952. setLangCookie();
  953.  
  954. // if the original site languages should be shown, refresh the page.
  955. if(GL_curLang == "orig") {
  956. refresh();
  957. return;
  958. }
  959.  
  960. // otherwise, start the translation
  961. startTranslation();
  962. }
  963.  
  964. // find out the value of the language cookie (if it exists)
  965. function getLangCookie() {
  966. var curStoredLang;
  967. // retrieve a list of cookies for this page, split into array elements (separated by ; if multiple cookies)
  968. var getCurLang=document.cookie.split(";");
  969. // loop through all array elements (i.e. cookies) until one with name 'lang' is found.
  970. for(var i=0; i < getCurLang.length; i++) {
  971.  
  972. // remove whitespace from cookies (a problem if there are multiple cookies)
  973. var lngCookie = getCurLang[i].replace(/^\s+|\s+$/g,"");
  974.  
  975. if(lngCookie.indexOf("lang=") == 0) {
  976. // find out value of lang
  977. curStoredLang = lngCookie.substring(5);
  978. }
  979. }
  980.  
  981. // if language cookie exists, set current site language to stored value
  982. if(typeof curStoredLang != "undefined") {
  983. GL_curLang = curStoredLang;
  984. // otherwise, check if an initial language has been specified
  985. } else if((GL_curLang == "") || (typeof GL_curLang == "undefined")) {
  986. detectUserLang(); // if not, find out user's language based on their settings, and offer to translate into that language
  987. GL_curLang = "orig"; // show site using original languages for now
  988. return; // don't want to store language in cookie until one has been specified, so end function
  989. }
  990.  
  991. setLangCookie(); // if valid cookie exists or initial language was specified, set/renew cookie (to store new expiry date)
  992. }
  993.  
  994. // If a new user has not specified a language yet, offer to translate page into their current browser / system language
  995. function detectUserLang(){
  996. /* detect user's current language (if they are using IE this will be based on the regional settings on their system;
  997. otherwise it will be based on the default language of their current browser) */
  998. var detectedLang = (navigator.language) ? navigator.language : navigator.userLanguage;
  999.  
  1000. // if language cannot be detected for some reason, end function.
  1001. if((typeof detectedLang == "undefined") || (detectedLang == "")) {
  1002. return;
  1003. }
  1004.  
  1005. // if language is regional dialect (e.g. "en-gb"), check last 2 letters are upper case - for google compatibility.
  1006. if(detectedLang.length == 5) {
  1007. detectedLang = detectedLang.substr(0,3) + detectedLang.substr(3).toUpperCase();
  1008. }
  1009.  
  1010. // check that Google can translate content into detected language
  1011. if (!google.language.isTranslatable(detectedLang)) {
  1012. // if not, check if language is a regional dialect (e.g. "en-GB")
  1013. if(detectedLang.length == 5) {
  1014. // if so, Google may still be able to translate into a non-regional equivalent (e.g. "en")
  1015. detectedLang = detectedLang.substr(0,2);
  1016. if (!google.language.isTranslatable(detectedLang)) {
  1017. return; // google cannot translate into non-regional equivalent, so end function
  1018. }
  1019. // language is not a regional dialect, and google cannot translate into it, so end function
  1020. } else {
  1021. return;
  1022. }
  1023. }
  1024.  
  1025. var detectedLangStr = getFmtLangStr(detectedLang); // retrieve name of detected language as a formatted string
  1026.  
  1027. /*
  1028. // display message asking user if they want to translate current page into detected language
  1029. document.getElementById("mlt_translatemsg").innerHTML = 'Translate this page into ' + detectedLangStr + '? ' +
  1030. '<a href="javascript:changeLang(\'' + detectedLang + '\')">Yes</a> | <a href="javascript:changeLang(\'orig\')">No</a>';
  1031. miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
  1032. document.getElementById("mlt_translatemsg").style.display='block'; // show the question on screen
  1033. */
  1034.  
  1035.  
  1036. // display message asking user if they want to translate current page into detected language
  1037. document.getElementById("mlt_translatemsg").innerHTML = '';
  1038. miniTranslate(document.getElementById("mlt_translatemsg"),detectedLang); // translate question into detected language
  1039. document.getElementById("mlt_translatemsg").style.display='none'; // show the question on screen
  1040. }
  1041.  
  1042. // create a cookie to store the current site language
  1043. function setLangCookie() {
  1044. // expire previous cookie (if it exists)
  1045. document.cookie = "lang=; expires=-1; path=/";
  1046.  
  1047. // cookie will expire after 90 days.
  1048. var expdate = new Date();
  1049. expdate.setTime(expdate.getTime()+7776000000);
  1050.  
  1051. // create the cookie
  1052. document.cookie = "lang=" + GL_curLang + "; expires=" + expdate.toGMTString() + "; path=/";
  1053. }
  1054.  
  1055. // refresh the current page [runs if the Original Languages option was selected, or if requested by user after error(s)]
  1056. function refresh() {
  1057. hideTransMsg();
  1058. window.location.reload(true);
  1059. }
  1060.  
  1061. // run the 'initialise' function once the page has loaded.
  1062. google.setOnLoadCallback(initialise);
  1063.  
  1064. ****************The End*****************************
  1065.  
  1066.  
  1067. *****************Save it as googlelanguage.js******************
  1068.  
  1069.  
  1070. if (!window['google']) {
  1071. window['google'] = {};
  1072. }
  1073. if (!window['google']['loader']) {
  1074. window['google']['loader'] = {};
  1075. google.loader.ServiceBase = 'http://www.google.com/uds';
  1076. google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax';
  1077. google.loader.ApiKey = 'notsupplied';
  1078. google.loader.KeyVerified = true;
  1079. google.loader.LoadFailure = false;
  1080. google.loader.Secure = false;
  1081. google.loader.GoogleLocale = 'www.google.com';
  1082. google.loader.ClientLocation = {"latitude":17.385044,"longitude":78.486671,"address":{"city":"Hyderabad","region":"Andhra Pradesh","country":"India","country_code":"IN"}};
  1083. google.loader.AdditionalParams = '';
  1084. (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}
  1085. 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);
  1086. 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);
  1087. 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);
  1088. 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);
  1089. 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)}
  1090. function Q(){for(var a=0;a<O[w];a++)O[a]();O.length=0}
  1091. 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>')};
  1092. 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);
  1093. 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";
  1094. 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}
  1095. 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)==
  1096. ":"&&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};
  1097. 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&&
  1098. 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}}});
  1099. 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};
  1100. 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=[]};
  1101. 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)};
  1102. 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};
  1103. 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(){};
  1104. 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=
  1105. 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",$);
  1106.  
  1107. }) ();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"]});
  1108. 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"}}});
  1109. google.loader.rpl({":scriptaculous":{"versions":{":1.8.3":{"uncompressed":"scriptaculous.js","compressed":"scriptaculous.js"},":1.8.2":{"uncompre

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.