I'm building a multi-language single page website with javascript and the new html template-tag and would like to use own variables like {{txt.welcome}} in html which should be replaced by the translation.
HTML:
<div class="container">
<h2>{{heading.hello}}</h2>
<p>{{txt.welcome}}<br /><img alt="{{image.description}}" src="" /></p>
</div>
Javascript:
var reg = new RegExp(/{{([a-z.]+)}}/g);
var result;
while(result = reg.exec(document.documentElement.innerHTML)) {
document.documentElement.innerHTML = document.documentElement.innerHTML.replace(result[0], translations[result[1]]);
}
It searchs for the variables in the whole document and replace them with the defined text, but with many variables the performance becomes really bad.
What would be a faster solution than looping with regex over the whole document's html?
How do it other libraries like AngularJS with {{ 'FOO' | translate }}?
The biggest issue, I think, is that you are not just running a regex, but also running a replace over the entire HTML multiple times. And you are setting the actual DOM HTML multiple times rather than manipulating a string until you get the result, and then setting the HTML once. I would strongly recommend using a library like Handlebars.js, but if you want to do it yourself, a very quick implementation would be something like:
var translations = {
heading: {
hello: "hello"
},
txt: {
welcome: "welcome"
},
image: {
description: "this is a test"
}
};
function get(obj, desc) {
var arr = desc.split(".");
while(arr.length && (obj = obj[arr.shift()]));
return obj;
}
function replaceTokens(HTML) {
return HTML.split('{{').map(function(i) {
var symbol = i.substring(0, i.indexOf('}}')).trim();
return i.replace(symbol + '}}', get(translations, symbol));
}).join('');
}
You can use your regexp (with a little modification) to split your html in an array. Then you can replace only the template chunks of your array by their translations, and finally joining it and replacing the document html with it :
var html = "a little {{foo}} in the {{bar}}"; // replace with document.documentElement.innerHTML
var translations = {foo: "boy", bar: "garden"};
var chunks = html.split(/({{[a-z.]+}})/g);
var chunksTranslated = chunks.map(function(chunk){
if(chunk.slice(0,2)==="{{" && chunk.slice(-2)==="}}") {
var id = chunk.slice(2,-2);
return translations[id];
}
return chunk;
});
var translatedHtml = chunksTranslated.join("");
//document.documentElement.innerHTML = translatedHtml;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With