I'm writing a Google Chrome extension for a popular e-merce SAAS which will replace English text strings to Spanish inside its admin panel.
I've e with a solution which replaces EVERYTHING, so when finding an a href, it also replaces it which is not desired:
var els = document.getElementsByTagName("*");
for(var i = 0, l = els.length; i < l; i++) {
var el = els[i];
// ==Menu_left_dropdown==
el.innerHTML = el.innerHTML.replace(/View your user account/gi, 'Tu cuenta');
el.innerHTML = el.innerHTML.replace(/Terms of service/gi, 'Términos y condiciones');
el.innerHTML = el.innerHTML.replace(/Privacy policy/gi, 'Privacidad');
el.innerHTML = el.innerHTML.replace(/Log out/gi, 'Salir');
// ==Menu_left=
el.innerHTML = el.innerHTML.replace(/Search/gi, 'Buscar');
el.innerHTML = el.innerHTML.replace(/Dashboard/gi, 'Panel');
el.innerHTML = el.innerHTML.replace(/Orders/gi, 'Pedidos');
el.innerHTML = el.innerHTML.replace(/Customers/gi, 'Clientes');
el.innerHTML = el.innerHTML.replace(/Products/gi, 'Productos');
}
Getting elements by class or id, wouldn't be easy to maintain as they might change without the platform informing us. I also plan to add more locales so any suggestion on how to approach a cleaner way to organize the strings would be great.
I'm writing a Google Chrome extension for a popular e-merce SAAS which will replace English text strings to Spanish inside its admin panel.
I've e with a solution which replaces EVERYTHING, so when finding an a href, it also replaces it which is not desired:
var els = document.getElementsByTagName("*");
for(var i = 0, l = els.length; i < l; i++) {
var el = els[i];
// ==Menu_left_dropdown==
el.innerHTML = el.innerHTML.replace(/View your user account/gi, 'Tu cuenta');
el.innerHTML = el.innerHTML.replace(/Terms of service/gi, 'Términos y condiciones');
el.innerHTML = el.innerHTML.replace(/Privacy policy/gi, 'Privacidad');
el.innerHTML = el.innerHTML.replace(/Log out/gi, 'Salir');
// ==Menu_left=
el.innerHTML = el.innerHTML.replace(/Search/gi, 'Buscar');
el.innerHTML = el.innerHTML.replace(/Dashboard/gi, 'Panel');
el.innerHTML = el.innerHTML.replace(/Orders/gi, 'Pedidos');
el.innerHTML = el.innerHTML.replace(/Customers/gi, 'Clientes');
el.innerHTML = el.innerHTML.replace(/Products/gi, 'Productos');
}
Getting elements by class or id, wouldn't be easy to maintain as they might change without the platform informing us. I also plan to add more locales so any suggestion on how to approach a cleaner way to organize the strings would be great.
Share Improve this question edited Jun 25, 2014 at 22:48 Brock Adams 93.5k23 gold badges240 silver badges304 bronze badges asked Jun 25, 2014 at 20:18 alexandresaizalexandresaiz 2,7669 gold badges30 silver badges40 bronze badges 1- you can check for el.children, and if present, skip the text replacement on that non-child node. that should keep your href attribs intact. – dandavis Commented Jun 25, 2014 at 20:36
1 Answer
Reset to default 15To avoid trashing URL's, id's, event handler's, etc.; you need to act only on the TEXT_NODE
s of a web page. Never use innerHTML
.
An efficient way to act on text nodes is to use a Tree Walker.
For the replacement terms, use an array.
Putting it all together, the code looks like this:
var replaceArry = [
[/View your user account/gi, 'Tu cuenta'],
[/Terms of service/gi, 'Términos y condiciones'],
[/Privacy policy/gi, 'Privacidad'],
// etc.
];
var numTerms = replaceArry.length;
var txtWalker = document.createTreeWalker (
document.body,
NodeFilter.SHOW_TEXT,
{ acceptNode: function (node) {
//-- Skip whitespace-only nodes
if (node.nodeValue.trim() )
return NodeFilter.FILTER_ACCEPT;
return NodeFilter.FILTER_SKIP;
}
},
false
);
var txtNode = null;
while (txtNode = txtWalker.nextNode () ) {
var oldTxt = txtNode.nodeValue;
for (var J = 0; J < numTerms; J++) {
oldTxt = oldTxt.replace (replaceArry[J][0], replaceArry[J][1]);
}
txtNode.nodeValue = oldTxt;
}