Removing Chrome's “translate” DOM Property

2020-04-30 01:22发布

问题:

I'm working with some legacy code where the original developers made heavy use of generating HTML DOM nodes with a non-standard attribute named translate

<span translate="[{&quot;shown&quot;:&quot;My Account&quot;,&quot;translated&quot;:&quot;My Account&quot;,&quot;original&quot;:&quot;My Account&quot;,&quot;location&quot;:&quot;Text&quot;,&quot;scope&quot;:&quot;Mage_Customer&quot;}]">My Account</span>

and then traversing/searching for those nodes with javascript code like the following.

if (!$(target).match('*[translate]')) {
    target = target.up('*[translate]');
}

The problem I'm trying to solve is, it appears that Google Chrome automatically adds a translate attribute to every DOM node in the document, and that this DOM node's value is a boolean true. You can see this by running the following Javascript from Chrome's javascript console

> document.getElementsByTagName('p')[0].translate
true
>

Is there anyway to tell Chrome not to populate these attributes? Their presence is wrying havoc with the legacy code. PrototypeJS's match and up nodes treat these boolean object attributes as matches, while the code I'm dealing with is specifically looking for DOM nodes with an attribute named translate. I'd like to find a solution for my problem that doesn't involved rewriting the old Javascript to use methods like hasAttribute.

I tried (as a wild guess) adding the meta attributes mentioned in this article,

<meta name=”google” value=”notranslate”>
<meta name=”google” content=”notranslate”>

but the nodes in the page still has a boolean true translate attribute.

(if it matters, this is Magento's inline translation system I'm talking about here)

回答1:

The best I've been able to come up with so far is going through every DOM element in the page defining a getter that checks for the existence of an attribute. (the Object.__defineGetter__ guard clause ensures no errors in browsers that don't support modern Javascript)

if(Object.__defineGetter__)
{
    var hasTranslateAttribute = function(){
        return $(this).hasAttribute("translate");
    };
    document.observe("dom:loaded", function() {
        $$('*').each(function(theElement){
             theElement.__defineGetter__("translate", hasTranslateAttribute);
        });
    });
}

I tried defining a getting on Object.prototype and Element.prototype, but it seems like the browser's native translate is defined higher up the chain, so you need to redefine things on a per element basis.



回答2:

Replace the nonstandard attribute translate by an attribute like data-translate, which is virtually guaranteed to be and to remain undefined in HTML specifications and in browsers. The data-* attributes were invented to prevent issues like this, and they can also be used to fix them.