Automatic jQuery Translator for Magento

created May 26, 2011, last updated June 19, 2011.

.
closeThis post was last updated 6 years 5 months 29 days ago, some of the information contained here may no longer be actual and any referenced software versions may have been updated!

GOOGLE API DEPRECATED

Google announced on the 26th of May 2011 (the day I blogged about this solution!) that the translation API used by the jQuery plugin is now deprecated and will be shut off completely in December 2011. The author of the jQuery plugin will develop it to use the Microsoft translation API. Google are shutting down the API due to “extensive abuse” and recommend using the Google Translate Element. Whether the Microsoft translation service will be as good as Google we will need to wait and see. The author of the plugin comments “… the Microsoft API provides a method for array translation (just as Google’s v2 API), which eliminates almost all bugs with this plugin, and will make it a bit faster too. The quality of the translation is not any worse I think, so there’s nothing to worry about.” If you want to implement this solution bear in mind that changes to the plugin will take place at some point and the Google API will certainly stop working in December 2011.

 

Automatic jQuery Translator for Magento

Having looked at integrating the Google element translation tool into Magento to provide a quick fix content translation service I wanted to improve this tool by automatically translating content based on visitor browser language without the visitor having to manually select a language on every page. Automatic Google jQuery Translator for Magento Despite spending a lot of time looking at ways to manipulate the Google element translator code I couldn’t come up with a good solution until I came across the jQuery dynamic google translation plugin which integrates the Google Ajax Language API to jQuery and provides a really flexible and powerful method of dynamically translating content. Using jQuery and the jQuery translation plugin we can create an automatic language translation service for Magento that detects the visitors browser language and automatically translates every Magento page to that language when it is loaded, or alternatively does the same when a new language is manually selected from the language drop down selector. This is quite an easy solution to implement but should be thoroughly tested on your development platform as it requires some changes to existing javascript libraries as well as the addition of new jQuery libraries and plugins. I have included the new jQuery libraries and plugin files required to implement this solution in a download which you can access here. Download and extract the files, copy them to your Magento installation folder and then follow the instructions below to implement automatic jQuery Google translations in your Magento store.

jQUERY & script.aculo.us
According to this Magento blog post jQuery should have no problems working with other javascript frameworks and should “work out of the box” with Magento but doesn’t due to a conflict with an older version of scriptaculous.The Magento conflict lies with the code in effects.js which we will upgrade to the latest version (1.9.0 as of December 23, 2010).

jQuery, jQuery Translator plugin and UIBlock plugin

The other libraries required are the jQuery library which provides the jQuery framework, the jQuery Translator plugin which currently integrates with the Google API to do the translations and the UIblock plugin which I’ve used to provide a neat way of updating the user interface when translations are taking place. These are included in the download package. After copying the new libraries across to the Magento /js folder we need to update the page layout XML in Magento so that the new libraries are loaded. Locate page.xml in the layout folder of your Magento stores theme and open it for editing.

Installation

First find the XML that loads the existing scriptaculous effects.js file and modify the line that loads the effects.js library and change it to load the new upgraded version as shown below. Double click the code box and use CTRL C to copy.

 <action method="addJs"><script>scriptaculous/effects-1.9.js</script></action>

Next we need to add some new XML to tell Magento to use the new jQuery library and plugins, add the following three lines before the existing line of XML that loads the prototype library in page.xml

<action method="addJs"><script>jquery/jquery-1.2.6.noConflict.min.js</script></action>
<action method="addJs"><script>jquery/jquery.translate-1.4.7.js</script></action>
<action method="addJs"><script>jquery/jquery.blockUI.js</script></action>

Save the modified page.xml file. The dynamic translation jQuery code can be placed in the footer.phtml template file of your Magento theme so that it runs when the page is fully loaded, this file is usually located in the template/page/html folder of your theme. Locate the file, open it for editing and append the following code at the bottom:

	<?php
	/**
	 * Automatic jquery translator for Magento
	 * blog.gaiterjones.com
	 * v0.3
	 *
	 */
	?>
	<script type="text/javascript">
	//<![CDATA[
	jQuery(function($){

			var defaultLang = '<?php echo substr(Mage::app()->getLocale()->getDefaultLocale(), 0, 2) ?>';

			$('#langSelect').change(function() {
				var pathname = window.location.pathname;
				window.location = pathname + '?translateTo=' + $('#langSelect').val();
				if ($('#langSelect').val() == defaultLang) {
					$.blockUI({
					message: '<h1>Language is being reset to default...</h1>',
					timeout: 2000
					});
				}
			});

			function doTranslateTo( destLang ){
			$('body').translate(defaultLang, destLang, {
			  not: '.doTranslate',
              start:     function(){   $.blockUI({ message: '<h1>Translating, please wait...<br />(' + defaultLang + ' > ' + destLang + ')</h1>' })   },
              complete:  function(){   $.unblockUI()  },
			  error:  	 function(){   $.growlUI('Translation Error', 'An error occured during translation...');   },
			  toggle: true
			});
	}

		<?php

		$defaultLang=substr(Mage::app()->getLocale()->getDefaultLocale(), 0, 2); // default store language

		// determine browser langugage
		if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
			// get languages from server header and assign quality rating
			foreach (explode(",", strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])) as $accept) {
				if (preg_match("!([a-z-]+)(;q=([0-9.]+))?!", trim($accept), $found)) {
					$langs[] = $found[1];
					$quality[] = (isset($found[3]) ? (float) $found[3] : 1.0);
				}
			}
			// Order the codes by quality
			array_multisort($quality, SORT_NUMERIC, SORT_DESC, $langs);
			$browserLang=substr($langs[0],0,2);

		} else {
			$browserLang=$defaultLang;
		}

		$requestedLang=Mage::app()->getRequest()->getParam('translateTo');
		//$requestedLang=$_REQUEST["translateTo"];
		$storeCode=Mage::app()->getStore()->getCode(); // store code
		$cookieName=$storeCode. "-". $defaultLang. "-jquery-translateTo"; // derive cookie name

		echo "// defaultlang - ". $defaultLang. "\n";
		echo "// requestedLang - ". $requestedLang. "\n";
		echo "// browserLang - ". $browserLang. "\n";
		echo "// storeCode - ". $storeCode. "\n";
		echo "// cookieName - ". $cookieName. "\n";
		echo "// langfromcookie - ". Mage::getModel('core/cookie')->get($cookieName). "\n"; 

		if(!empty($requestedLang)) // check for language setting in REQUEST key
		{
			if (strtolower($requestedLang) !== strtolower($defaultLang)) { // translate if requested language != to store default
				if (!empty($requestedLang))
				{
					echo "// translating to requested language from url variable.\n";
					echo "doTranslateTo('". $requestedLang. "');\n"; // Translate and write cookie data
					Mage::getModel('core/cookie')->set($cookieName, $requestedLang, time()+36000);
				} else {
					echo "// Requested Language not detected.\n";
				}
			} else {
				Mage::getModel('core/cookie')->set($cookieName, strtolower($defaultLang), time()+36000); // set cookie i.e. keep default lang when default selected
				//Mage::getModel('core/cookie')->delete($cookieName); // remove cookie i.e. revert to browser lang when default selected

			}
		} else { // check for language data in cookie

			$langFromCookie = Mage::getModel('core/cookie')->get($cookieName); // read cookie

			if (!empty($langFromCookie))
			{
				if (strtolower($langFromCookie) !== strtolower($defaultLang)) { // translate if language data in cookie != to store default
					echo "// translating to requested language from cookie data.\n";
					echo "doTranslateTo('". $langFromCookie. "')\n";
				} else {
					echo "// cookie requesed language same as store default language - no translation required.\n";
				}
			} else { // no cookie	

				if (strtolower($browserLang) !== strtolower($defaultLang)) { // translate to browser language and set cookie
					if (!empty($browserLang))
					{
						echo "// setting language to browser language.\n";
						echo "doTranslateTo('". $browserLang. "');\n";
						Mage::getModel('core/cookie')->set($cookieName, strtolower($browserLang), time()+36000); // set cookie
					} else {
						echo "// Browser language not detected.\n";
					}
				} else {
					Mage::getModel('core/cookie')->set($cookieName, strtolower($browserLang), time()+36000); // set cookie
				}
			}
		}
		?>			

	})
	//]]>
	</script>

The code includes two jQuery functions, one that performs the jQuery automatic translation, and the other that monitors the language dropdown box used to manually change the page translation. The PHP code controls the automatic translation of pages based on the visitors browser language, using a cookie to store the visitors language which is subsequently used to translate every visited page to the browser language, or the language selected from the select Language dropdown box which is passed to the script via a URL request variable. Note that the code detects the default locale for the Magento store and uses this as the default language for translations.

To add the dropdown box, locate the languages.phtml file in the template/page/switch folder of your theme. Make a backup of the original file and then edit it to add the Language selector drop down box, replacing the contents of the file with the following code which includes all the languages supported by Google. This file is also included in the download package.

The language dropdown has been updated to show the current language as selected in the drop down list.

<?php
/**
 * Language switcher for jQuery Automatic Translator for Magento
 * blog.gaiterjones.com
 *
 */

$defaultLang=substr(Mage::app()->getLocale()->getDefaultLocale(), 0, 2); // default store language
$storeCode=Mage::app()->getStore()->getCode(); // store code
$cookieName=$storeCode. "-". $defaultLang. "-jquery-translateTo"; // derive cookie name
$langFromCookie = Mage::getModel('core/cookie')->get($cookieName); // read cookie
$requestedLang=Mage::app()->getRequest()->getParam('translateTo');

if (!empty($requestedLang))
{
	$languageSelected=$requestedLang;
} else {
	$languageSelected=$langFromCookie;
}

$languagesSelection =
		array(''=>'Select Language',
				substr(Mage::app()->getLocale()->getDefaultLocale(), 0, 2)=>'Default Language',
				'af'=>'Afrikaans',
				'sq'=>'Albanian',
				'ar'=>'Arabic',
				'be'=>'Belarusian',
				'bg'=>'Bulgarian',
				'ca'=>'Catalan',
				'zh-CN'=>'Chinese (Simplified)',
				'zh-TW'=>'Chinese (Traditional)',
				'hr'=>'Croatian',
				'cs'=>'Czech',
				'da'=>'Danish',
				'nl'=>'Dutch',
				'et'=>'Estonian',
				'tl'=>'Filipino',
				'fi'=>'Finnish',
				'fr'=>'French',
				'gl'=>'Galician',
				'de'=>'German',
				'el'=>'Greek',
				'ht'=>'Haitian Creole',
				'iw'=>'Hebrew',
				'hi'=>'Hindi',
				'hu'=>'Hungarian',
				'is'=>'Icelandic',
				'id'=>'Indonesian',
				'ga'=>'Irish',
				'it'=>'Italian',
				'ja'=>'Japanese',
				'ko'=>'Korean',
				'lv'=>'Latvian',
				'lt'=>'Lithuanian',
				'mk'=>'Macedonian',
				'ms'=>'Malay',
				'mt'=>'Maltese',
				'no'=>'Norwegian',
				'fa'=>'Persian',
				'pl'=>'Polish',
				'pt'=>'Portuguese',
				'ro'=>'Romanian',
				'ru'=>'Russian',
				'sr'=>'Serbian',
				'sk'=>'Slovak',
				'sl'=>'Slovenian',
				'es'=>'Spanish',
				'sw'=>'Swahili',
				'sv'=>'Swedish',
				'th'=>'Thai',
				'tr'=>'Turkish',
				'uk'=>'Ukrainian',
				'vi'=>'Vietnamese',
				'cy'=>'Welsh',
				'yi'=>'Yiddish');
?>
<div class="form-language">
	<div class="language-switcher">
		<select id="langSelect" >
<?php
	foreach($languagesSelection as $langCode=>$LangName)
	{
		if ($languageSelected === $langCode)
		{
			echo '<option selected value="'. $langCode. '">'. $LangName. '</option>';
		} else {
			echo '<option value="'. $langCode. '">'.$LangName. '</option>';
		}
	}
?>
		</select>
	</div>
</div>

Save the file and refresh the Magento cache to load the new jQuery libraries and modified template files.

Testing

Now refresh your Magento front end and you should see the new language dropdown selector in the header of your page. This is where it appears in the default theme.

Automatic Google jQuery Translator for Magento
Drop down language selector

If your browser language differs from your stores default language then the page should automatically translate. If your browser language is the same as your stores, then perform a manual translation by selecting a language from the select language box. You will notice that a new request variable is appended to the site URL which triggers the dynamic translation. Navigate to other pages which should also become dynamically translated as the code reads the selected language from the cookie file. To turn off the automatic translation select the stores default language from the drop down, or select the second “default” option from the language dropdown list.

Automatic Google jQuery Translator for Magento
User interface is updated during translation using the UIBlock jQuery plugin.
Automatic jQuery Google Translation for Magento
Manual language selection is passed as a URL request variable and stored as a cookie.

To manually link to a specific language for your site, specifiy the translation request variable in the URL with the two letter language code as shown above. i.e. for a German translation use http://www.webshop.com/?translateTo=de

Automatic jQuery Google Translation for Magento
Returning to default language turns automatic translations off.

Tested with Magento community editions v1.3.x and 1.5.x Please provide feedback if you experience any problems, have successfully implemented this solution or if you have any other ideas for further development.

Resources used in creating this solution

http://www.magentocommerce.com/wiki/4_-_themes_and_template_customization/javascript_related/how_to_use_jquery_1.2.6_lastest_with_prototype

http://code.google.com/p/jquery-translate/

http://jquery.malsup.com/block/

http://jsbin.com/ozenu/1007/edit

Update Links

http://code.google.com/apis/language/translate/overview.html

http://msdn.microsoft.com/en-us/library/ff512404.aspx

 

 

Blogged in Berlin.

Comments

  1. Ruben says:

    Heyho,

    thanks for this nice tutorial! I think i have done it alright, but nothing happens at my page. Perhaps i have made a mistake. From Firebug i can see that the js are loaded, the dropdown works, too. The footer should work, too.

    Do you have any ideas what to do?

    Thank you very much 🙂

    Greets

    • PAJ says:

      HMMMMMMMM

      Make sure you have cleared your cache and refreshed your site in your browser. If the drop down is working and appending the translateTo URL variable then jQuery is working. If the translation is not working make sure the jQuery translate plugin is being loaded correctly from page.xml.

  2. Ruben says:

    Heyho PAJ,

    thx for your help 🙂

    My site is slam-shop.de.
    Test:
    http://www.slam-shop.de/?translateTo=et

    According to firebug all the js files are loaded. Drop down works, url get sappended, too. Just no translation. Also after i select a lanuage the pages refreshs but the dropdown stays at select lanuage.

    Thx for your help 🙂

    Greets

  3. Ruben says:

    Do i have to do something different on magento 1.4.1.1? I tought 1.3 and 1.5 works so 1.4 should work, too 🙂

    Once again, thx for your help!

    Greets

    • PAJ says:

      I will need to test it in 1.4, its not working because the php code is not detecting the browser language, or language URL variable properly to tell the translator to translate the page… bummer!

  4. Ruben says:

    On my site, i switched back to your old translator, because the new one suddenly started to automatically translate my shop from german to english altough my main shop language and my browser language is german.

    Greets

  5. jetsomore says:

    no idea why it isnt working on my site
    i have done exactly what you said

    check this out
    jetsomore.hk

  6. PAJ says:

    footer.phtml is cached, so you must refresh the cache after you edit it. Can take a look at this tommorow with you if you still want to have a go at getting it working. I installed under 1.4.2 and it worked ok. I did notice that I had to refresh the cache twice before translation started working properly, and there could be a problem detecting the requested language variable, which I modified with that code change.

  7. jetsomore says:

    i have turned off the site maintenance
    can you look again? thanks in advance.

    i did several cache refresh and even delete the content of cache.

  8. Ruben says:

    Hey PAJ,

    i changed back to your first translator. Of course i want to get it going, its such a nice feature 🙂

    I refreshed the cache of course after i installed it.

    Should i try it again or wait until tomorrow?

    Greets

    • PAJ says:

      Hi Ruben,

      Have updated the code for footer.phtml in the post, and added some debugging lines to show whats going on, copy the new code into footer.phtml, save, refresh the cache and let me know.

  9. Ruben says:

    Heyho PAJ,

    i updated the code, cache refresh and reload. Still does not work, but this is what the debug tells me:

    // defaultlang – de
    // requestedLang –
    // browserLang – de
    // storeCode – german
    // cookieName – german-de-jquery-translateTo
    // langfromcookie –

    This happens even when i select a language.

    Thx for your help again, this is the best support i ever got 😀

    • PAJ says:

      Footer code is updated again v0.3, see if it detects the browser lang properly. For the URL variable you can try commenting out “//” the first $requestedLang= statement, and removing the comments from the second to see if the global PHP variable will work. (this didnt work in Magento 1.5)

  10. Ruben says:

    thx for your help again 🙂

    Ok, we got a little bit further 🙂 When i update footer, nothing happens. When i comment out the first requestedLang and uncomment the second it gets translated, but always from DE to FI. I tested this un numerous browsers/computers. When i select a different language it switches to different and then translates to FI again :)))

    Greets

    • PAJ says:

      Can you post the debug comments so we can see where the FI is coming from? I would say it must be coming from the browser language detection which just doesnt seem to work for you. Perhaps we can take the conversation online to skype or something and you can tell me about your hosting etc. Otherwise I think I might just pull this post and go back to the drawing board with this!

  11. Chris says:

    Very good Tutorial. Works nearly perfect. Only the cart is not translated. I can´t translate automatically or with the Selector. Is there a Solution for that ?

    Greetings Chris

    • PAJ says:

      Glad that its working for someone! The cart translates ok with the demo shop and default theme on my dev server.

      • Chris says:

        Hmm, i see in the Sourcecode from the Cart
        // defaultlang – de
        // requestedLang –
        // browserLang – de
        // storeCode – default
        // cookieName – default-de-jquery-translateTo
        // langfromcookie – en
        // translating to requested language from cookie data.
        doTranslateTo(‘en’)
        but the Translation don´t start. I can´t see any Error in my Code because all other Pages are translated perfectly.

      • PAJ says:

        I have (almost) the same debug output and as you can see here the cart translates. Are you using a custom theme, or cart extension?

        // defaultlang – en
        // requestedLang –
        // browserLang – en
        // storeCode – default
        // cookieName – default-en-jquery-translateTo
        // langfromcookie – fr
        // translating to requested language from cookie data.
        doTranslateTo(‘fr’)

  12. Chris says:

    I am using a Custom Template (Template Master) and no Cart Extension. I am sorry but the Shop is at the time only on my Server with Xampp for testing it. But it is very strange. All Pages are correct only the Cart makes nothing. I have tested it with the Original Google HTML Code in the Header

    function googleTranslateElementInit() {
    new google.translate.TranslateElement({
    pageLanguage: ‘de’,
    includedLanguages: ‘de,en,fr’,
    layout: google.translate.TranslateElement.InlineLayout.SIMPLE
    }, ‘google_translate_element’);
    }

    and all Text is translated in the Cart but i will use your Plugin because it looks very fine with the Translation Window. Have you read this from the jquerytranslation Page : If you want to use the plugin on page load in most cases you can call it inside $(document).ready() but in some cases you have to define a callback function to be executed when the Language API is loaded. It’s not $(document).ready() but $.translate.ready():

    Sorry i am not a big Programmer. I can´t understand this complete.

  13. Chris says:

    It is working ! But ….. only with IE (I have only IE 8). I use normally Firefox 3.6.17 and K-Meleon and this Browsers can´t translate the Cart. Really crazy. Can you test this with your Installation ?

    • PAJ says:

      I have tested with Firefox 4.0, Chrome and IE 8/9 and they all translate the cart page ok. I was aware of the translate.ready function and have tested it but found it actually made things slower and caused page hangs.

      • Chris says:

        Ok, i am looking for a Solution and i think it´s the jquery 1.6.1 Libary. I must use this for my Slider and another Box that is showing random Articles. I change in the page.xml my jquery 1.6.1 to the jquery-1.2.6.noConflict.min.js and the Cart-Translation is working with all Browsers. But i can´t use the 1.2.6 because the Sliders and the Translation on the other Pages are not working with this Version. In the Cart is no Slider. So with my Sliders and 1.2.6 nothing is working on the normal Pages but the Cart is translated, with 1.6.1 all Sliders and the Translation on normal Pages are working but not in the Cart.

        Oh no, what a Problem. Can you say me where i must search for the Problem ? Is this a nonconflict Problem ?

      • PAJ says:

        Ok just tested with jQuery 1.6.1 and the cart does not translate for me either, so must be some kind of conflict there with that version. Tested with version 1.5.2 and cart translates ok. Well done for narrowing the problem down to jQuery versions. I went with the older jQuery library because I knew it had been tried and tested with Magento.

  14. Chris says:

    Now, all Pages are translated with jquery 1.5.2. Only Glider.js is not working. I am looking for another Slider/Glider to solve that Problem.

    • PAJ says:

      Chris, have you also tested the automatic translation from a browser set to a different language. This was not working at all for Ruben and I think that has something to do with server side config, apache setup etc.

  15. Chris says:

    I am going crazy. With 1.5.2 it seems all is OK but it is impossible to add a Article in the Cart on Detailpage. In the List view can i add the product in the cart. I think i am working on a neverending Story 🙁 If i change to 1.6.1 i can add the Article on all Pages. What is the difference between 1.5.2 and 1.6.1 ?

    I am testing tomorrow the Browser Language.

    • PAJ says:

      Perhaps we need to update some of the other scriptaculous files, in the original magento blog post they identified an issue with jQuery and the effects library from scriptaculous, perhaps there are other issues with other scriptaculous libraries. I will need to look into it. I dont know what the differences are in jQuery versions, I am a bit of a jQuery novice myself!

      It is frustrating that this seems to be 99.9% working, I know there are a couple of magento extensions around for languages but I’m not sure what they are like, could be worth looking into if this doesnt work. Either way let me know how you get on.

  16. PAJ says:

    Updated the code for the language drop down so that the current language either set by cookie, or from the URL variable is the selected language..

  17. Chris says:

    I don´t know, but is this 1.6.1 Problem not translating in the Cart perhaps a Problem with NoConflict ? This was the reason for another Problem with my two Boxes on Home for a while. I change in one Code the jQuery to noconflict and the two Boxes working togehter. I think we must search what is different from 1.5.2 to 1.6.1. and which function uses the Cart. I have updated the Scriptaculus Files to the actual Version but this does not solve the Problem.

    I hope you find the Problem because your Script is very usefull.

    • PAJ says:

      We need JQuery noConflict() because Magento relies heavily on the prototype javascript library which also uses the $ reference for functions, noConflict lets jQuery work with other libraries in this way without conflict. You can see on the checkout page there is some existing prototype scripts (search for $ in the source and you will see them) however these are obviously working as the cart page is working ok, so its not a conflict problem between jQuery and Prototype, and our jQuery functions are working because the drop down selector still works which uses jQuery. So that narrows it down to the translator plugin, will have a look at that to see if there are any updates.

  18. Chris says:

    Have you read this on the jquery Translater Page: Since the Google Translate API will be shut off completely on December 1, 2011 this plugin will use the Microsoft Translator service: http://msdn.microsoft.com/en-us/library/ff512404.aspx ? It seems that the Google Plugin is running out. Is the Microsoftplugin a Solution for the Carttranslationerror ? If the Google Service is down in December all searching for Bugs is for nothing or is this the right Time to change to the Microsoftplugin ?

    • PAJ says:

      Great! Google officially deprecated the API the same day that I made this blog post!

      http://code.google.com/apis/language/translate/overview.html

      Google want you to use their translator element for website translations due to too much abuse of the API. Updated the blog post with details of the planned changes to the Microsoft API, doesn’t sound as bad as I first thought…

      Will leave it up to you if you want to keep using the plugin.

      • Chris says:

        That´s really bad. All of your work is for nothing. I think i am looking for another Hack to Translate on the fly Magentopages because December is in 6 Months not in 2 Years. Are you working for a Hack with the Microsoft Plugin in the Future ?

      • PAJ says:

        Read my post update, all is not lost! I will still continue to develop this solution.

    • PAJ says:

      I didn’t write the plugin, the author says he will transfer it over to the Microsoft API, so keep an eye on the translator plugin site for updates.

    • PAJ says:

      Good question! I never did try this outside of development as it was a bit clunky. I would recommend trying the normal Google inline translator code.