Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Javascript to change website language

Tags:

I'm working on a GUI website that can use several languages. The original HTML-files I got to work with were totally static. So if translation was needed I had to parse through alle files, note where some words or terms were, collect them all hand them to the translation department and enter those translations in the new language files.

Since those files were totally static it meant having to translate whole sections several times. Not very effictient.

So now I am working on some kind of dictionary in Javascript, to just exchange the terms in those websites. Mostly it works this way:

var dicEnglish = {
term 1: "This is the English text"
Ref: "Another English text"
}
var dicFrench = {
term 1: "This is the French text"
Ref: "Another French text"   
}

Which contains all the possible content that needs to be changed. Every candidate in the HTML-code gets a class="dicRef" id="l_dicTag_#"as identifier, which I slice down to the dictionary tag and exchange with the following code:

var imgSrc = "en";
var ActiveDic;
var langSel;
if(window.name){
    langSel=window.name;
    }
else{langSel="English";
}

function LangChange(){
langClass = document.getElementsByClassName("dicRef");
var i = langClass.length;
var Start, Stop, idSrc, idDic;
var navText;

switch(langSel){
    case "French":
        langSel="French";
        imgSrc = "en";
        navText="Anglais";
        break;
    case "English":
    case "Anglais":
    default:
        langSel="English";
        imgSrc = "fr";
        navText="French";
        break;
    }
ActiveDic="dic"+langSel;
window.name=langSel;

while(i--){
    idSrc = langClass[i].id;
    Start=idSrc.indexOf("_")+1;
    Stop=idSrc.lastIndexOf("_");
    idDic=idSrc.slice(Start,Stop);
    if(window[ActiveDic][idDic]){
        document.getElementById(idSrc).innerHTML=window[ActiveDic][idDic];}
    else{
        document.getElementById(idSrc).innerHTML="N/A";
    }
}
if(document.getElementById("imgSel")){
    document.getElementById("imgSel").src="../../img/"+imgSrc+".gif";
}
if (document.getElementById("l_SelLang1_1")){
    document.getElementById("l_SelLang1_1").innerHTML=navText;
}
}

The problem lies in the uniqueness of the id-tag. Since some terms can occur more than once and some are generated the counter is needed. I'd prefer to ommit the counter, but can't find any other identifier to sort out all target terms and change their content.

Since I want to be safe for the future I'd prefer a solution that makes it possible to handle a possible third language. Working with the inner HTML would need to tag the same term several times, once for each language.

So is there any way to target all terms to be exchanged more efficently and easily, or a better way to do it? I can only work with client-side solutions, so no PHP and so on.

Thanks in advance and hopefully this wasn't too long to read.

like image 312
Blind Seer Avatar asked Aug 14 '15 10:08

Blind Seer


People also ask

How can I add language to my website in HTML?

To set the primary language of our page as English we use the 'lang' attribute along with our 'en' language code and apply this to the HTML element at the beginning of each page.


2 Answers

No offense to the other answerers but storing the text in JavaScript or in data attributes is not good for search engines or disabled site visitors and offers no benefits while added unnecessarily complicated code. The best and most simple solution in my opinion is to make use of HTML lang attribute and use JavaScript to show and hide the desired language. This solution also gracefully degrades so if a site visitor has their JavaScript disabled it will still display the content. Here is my solution:

HTML

<button id="switch-lang">Switch Language</button>

<h1><span lang="en">Hello</span> <span lang="es">Hola</span></h1>

<p lang="en">I really enjoy coding.</p>

<p lang="es">Me gusta mucho la codificación.</p>

jQuery

$('[lang="es"]').hide();

$('#switch-lang').click(function() {
  $('[lang="es"]').toggle();
  $('[lang="en"]').toggle();
});

Then I would recommend adding HTML5 Geolocation to determine which language to show initially based on the users location in the world. I would also use Fontawesome language icon to show users they can switch languages in a way that is understandable by anyone: http://fontawesome.io/icon/language/

Here is the working code example at CodePen: https://codepen.io/codepajamas/pen/ZejaQz?editors=1010

Here is an additional example on code pen using a select menu to change between 3 (or more) languages: https://codepen.io/codepajamas/pen/NjGOMV

Updated Full Example with Geolocation and Cookies

I kept working on this and created an updated example switching between two languages Chinese and English (if you need more than two languages you would have to hide all languages and show only the one selected instead of using toggle the way I am). This code also detects if an existing cookie is already set for the language using jQuery Cookie. It also checks their geolocation if their browser supports it automatically setting the language to Chinese if they are in either Taiwan or China and defaults to English in all other countries. The code below is commented so you can see what each step is doing and hopefully be able to modify it to suit your needs. Here it is:

HTML

<button id="switch-lang">Switch Language Icon Here</button>

<h1><span lang="en">Hello</span> <span lang="zh">你好</span></h1>

<p lang="en">I really enjoy coding.</p>

<p lang="zh">我真的很喜歡編碼。</p>

jQuery Note: this requires linking to not only jQuery but also jQuery Cookie

$(function () {
  ///// Language Switching (2 languages: English and Chinese). /////

  // Initially disable language switching button.
  $('#switch-lang').css({'pointer-events':'none',
   'cursor':'default'}).attr('disabled','disabled');

  function langButtonListen() {
    $('#switch-lang').click(function (event) {
      event.preventDefault();
      $('[lang="zh"]').toggle();
      $('[lang="en"]').toggle();
      // Switch cookie stored language.
      if ($.cookie('lang') === 'en') {
        $.cookie('lang', 'zh', { expires: 7 });
      } else {
        $.cookie('lang', 'en', { expires: 7 });
      }
    });
    // Enable lang switching button.
    $('#switch-lang').css({'pointer-events':'auto',
     'cursor':'pointer'}).removeAttr('disabled');
  }

  // Check if language cookie already exists.
  if ($.cookie('lang')) {
    var lang = $.cookie('lang');
    if (lang === 'en') {
      $('[lang="zh"]').hide();
      langButtonListen();
    } else {
      $('[lang="en"]').hide();
      langButtonListen();
    }
  } else {
    // no cookie set, so detect language based on location.
    if ("geolocation" in navigator) {
      // geolocation is available
      navigator.geolocation.getCurrentPosition(function (position) {
        // accepted geolocation so figure out which country
        var lat = position.coords.latitude,
            lng = position.coords.longitude;
        $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+lng+'&sensor=true', null, function (response) {
          var country = response.results[response.results.length-1].formatted_address;
          if (country ===  'Taiwan' || country === 'China') {
            $('[lang="en"]').hide();
            $.cookie('lang', 'zh', { expires: 7 });
            langButtonListen();
          } else {
            $('[lang="zh"]').hide();
            $.cookie('lang', 'en', { expires: 7 });
            langButtonListen();
          }
        }).fail(function (err) {
          console.log('error: '+err);
          $('[lang="zh"]').hide();
          $.cookie('lang', 'en', { expires: 7 });
          langButtonListen();
        });
      },
      function (error) {
        if (error.code == error.PERMISSION_DENIED) {
          // denied geolocation
          $('[lang="zh"]').hide();
          $.cookie('lang', 'en', { expires: 7 });
          langButtonListen();
        } else {
          console.log('Unknown error. Defaulting to English!');
          $('[lang="zh"]').hide();
          $.cookie('lang', 'en', { expires: 7 });
          langButtonListen();
        }
      });
    } else {
      // geolocation IS NOT available
      $('[lang="zh"]').hide();
      $.cookie('lang', 'en', { expires: 7 });
      langButtonListen());
    }
  }
});
like image 101
J Grover Avatar answered Sep 20 '22 12:09

J Grover


You can use data attributes: the fact that "HTML5 attributes are not supported in IE6 and IE7" means that you don't get the getAttribute() method or the dataset property for retrieving/accessing them. But you can still retrieve them as explained in this post.

<div id="geoff" data-geoff="geoff">
var geoff = document.getElementById("geoff");
alert(geoff.getAttribute("data-geoff"));

Even better, you can use jQuery .data() to support previous versions of IE.

Something along these lines should work:

<div data-translate="translation_key"></div>
$("[data-translate]").each(function(){
    var key = $(this).data('translate');
    $(this).html(dictionary[key][current_lang] || "N/A");
});

Working example: https://jsfiddle.net/x93oLad8/4/

like image 29
Andrea Casaccia Avatar answered Sep 17 '22 12:09

Andrea Casaccia