cp-stack
cp-stack

Reputation: 866

Trying to Change Language with jQuery

I am following this tutorial which outlines a simple way to make a site multilingual using jQuery. First off I am very proficient in HTML/CSS and PHP/MySQL, however I am just getting started with JavaScript.

I have spent some time searching the web and I am unable to find a problem with my code. Here is what I have.

My HTML code looks like this:

<h5 class="info-text">Be notified when we launch.</h5>

My XML according to the tutorial looks like this:

<?xml version="1.0" encoding="UTF-8"?>
    <translations>
   <translation id="info-text">
    <english>Be notified when we launch</english>
    <spanish>notificar cuando tu lanza</spanish>
   </translation>
    </translations>

(Sorry my Spanish is not very good. But this is for testing purposes only).

My jQuery script looks like this:

<script type="text/javascript" language="javascript">
$(function() {
    var language = 'english';
    $.ajax({
        url: 'includes/languages.xml',
        success: function(xml) {
            $(xml).find('translation').each(function(){
                var id = $(this).attr('id');
                var text = $(this).find(language).text();
                $("." + id).html(text);
            });
        }
    });
});
</script>

I did include the jQuery file in my header like so:

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.2.3.min.js"></script>

Not sure what I am doing wrong. Any help would be much appreciated. Thanks.

Upvotes: 0

Views: 7699

Answers (1)

Mark Schultheiss
Mark Schultheiss

Reputation: 34158

Your selector is wrong $("." + id).html(text); change to $("#" + id).html(text);

WELL I must have been tired when I wrote that. You obviously are targeting a class not an ID there. Sorry for that and wasting time.

Now to address the issue at hand.

Let us assume your markup is (derived from yours)

<h5 class="info-text">put stuff here.</h5>
<h5 class="charlie">charlie.</h5>
<h5 id="walt">walt.</h5>

And our XML is (also in your form but with more):

  <?xml version="1.0" encoding="UTF-8"?>
  <translations>
    <translation id="info-text">
      <english>Be notified when we launch</english>
      <spanish>notificar cuando tu lanza</spanish>
    </translation>
    <translation id="walt">
      <english>Be notified when we launch for walt</english>
      <spanish>notificar cuando tu lanza for walt</spanish>
    </translation>
    <translation id="charlie">
      <english>Be notified when we launch for charlie</english>
      <spanish>notificar cuando tu lanza for charlie</spanish>
    </translation>
  </translations>

Then we must address the issue of the XML and retrieving that via ajax.

To declare the task at hand, we wish to replace based upon a language, the text of the elements on the page (see our markup above) that match the elements pointed to by our incoming XML (from ajax) via an attribute pointing to the page element.

With this it appears your code is very close but likely the XML in the ajax is at issue. It HAS to be XML and not text (string) in type in order to select it using jQuery like you have done. Simple enough, let't tell our ajax to pull as XML. Early versions of jQuery had XML as the default for ajax, but let's not trust that and force it to be XML by adding: dataType: "xml",

$(function() {
    var language = 'english';
    $.ajax({
        url: 'includes/languages.xml',
        dataType: "xml"
    }).done(function(xml) {
        $(xml).find('translation').each(function(){
            var id = $(this).attr('id');
            var text = $(this).find(language).text();
            $("." + id).html(text);
        });
    });
});

Now that should resolve your issue specifically.


Custom just because I was intrigued, but a useful exercise

This is possibly overkill for your use but fun still

NOTE Assume "xmlDoc" contains the xml document from ajax or whatever.

With a slight set of changes however, we can target differing types of elements (by class, id etc).

HTML for custom:

<div id="container">
  <h5 id="info-text">put stuff here.</h5>
  <h5 class="charlie">charlie.</h5>
  <h5 mycustom="bill">bill.</h5>
  <h5 class="bill">bill.</h5>
  <h5 id="walt">walt.</h5>
  <h5 id="walter">walter custom.</h5>
</div>

Custom xml:

<?xml version="1.0" encoding="UTF-8"?>
<translations>
  <translation id="info-text">
    <english>Be notified when we launch</english>
    <spanish>notificar cuando tu lanza</spanish>
  </translation>
  <translation id="walt" custom="[id=walter]">
    <english>Be notified when we launch for walt</english>
    <spanish>notificar cuando tu lanza for walt</spanish>
  </translation>
  <translation id="charlieidthing" class="charlie">
    <english>Be notified when we launch for charlie</english>
    <spanish>notificar cuando tu lanza for charlie</spanish>
  </translation>
  <translation customAttribute="mycustom,bill" targetclass="bill">
    <english>Be notified when we launch for bill</english>
    <spanish>notificar cuando tu lanza for bill</spanish>
  </translation>
</translations>

Here is the custom code to process all that:

var language = "spanish";
function decodeSelector(encoded) {
  var elem = document.createElement('textarea');
  elem.innerHTML = encoded;
  var decoded = elem.value;
  return decoded;
}

function getSelector(attr) {
  var xType = attr.localName;
  var xSelect = attr.nodeValue;
  // here we match the custom attributes in the markup/enhance as needed
  switch (xType) {
    // class either in class or targetclass attributes
    case "class":
    case "targetclass":
      xSelect = "." + xSelect;
      break;
    // id in id or targetid attributes
    case "id":
    case "targetid":
      xSelect = "#" + xSelect;
      break;
    // some custom attribute with a name,value content pair
    // example in XML: customAttribute="mycustom,bill"
    case "customAttribute":
      var s = xSelect.split(",");
      xSelect = "[" + s[0] + "='" + decodeSelector(s[1]) + "']";
      break;
    // some encoded selector (any jQuery selector)
    case "custom":
      xSelect = decodeSelector(xSelect);
      break;
    // used to ignore other attributes
    default:
      xSelect = "";
      break;
  }
  return xSelect;
}

function setTarget(targetPick, languageText) {
  var attrs = targetPick.attributes;
  for (var j = 0; j < attrs.length; j++) {
    var xSelect = getSelector(attrs[j]);
    if (xSelect) {
      var target = $(xSelect);
      //  target.css('background-color', 'pink'); you can do this also
      target.text(languageText);
    }
  }
}

Now process it (this is in document ready but should be in your ajax done):

$(function() {
  $(xmlDoc).find('translation').each(function() {
    var targetTranslation = $(this).find(language);
    var text = targetTranslation.text();
    setTarget(this, text);
  });
});

Here is a fiddle for the custom (note I used an XML string and parsed it) https://jsfiddle.net/MarkSchultheiss/z8qbsku4/

Upvotes: 2

Related Questions