19
头图

Do you really think that Google Translate does not affect the functionality of the "front-end" page?

background

It was another working day where time flies. QA students suddenly raised a bug, and the "count" function of the text input box failed. After everyone searched, it was found that the test student turned on "Google Translate" and the "count" could not be "counted". It aroused my great interest. How does this seemingly "harmless human and animal" translation function affect my input box? Wei Shu and Wu Zhengba kicked off the curtain, ah~ uh (in the arrow).

This article is written according to my inquiry process, so it is not to find the right direction at a glance. Let's explore along with my thinking at the time.

image.png

1. Change of dom structure (take react code as an example)

To know why the "translation function" affects the page, start by observing the changes in the page structure each time the "translation" function takes effect. The simplest piece of code:

return ( <div>你好</div> )

Before translation:
image.png

After translation:
image.png

Check the characteristics of the font tag, it is not recommended to use it:
image.png

Try if you can get this font tag element, modify the code

  function handleShowDom() {
    console.log(document.getElementById("box").children);
  }

 return( 
   <div id="box" onClick={handleShowDom}>
    你好
   </div>
 )

image.png

It is interesting to be able to get this element. If there is logic in the code to operate by getting sub-elements in some cases, then theoretically there will be a problem.

Is it due to the change of the dom structure that the counting function text input box will disappear?

Two, compare various ui libraries of vue and react

By looking element ui the source code of 061acccfd81bc0, I didn’t find any special code logic. What's the matter? The question filled with me gave me an idea. Is it related to the principles of vue and the react framework itself? Then I will experiment with 4 kinds of ui separately. The effect of the frame:

1: react -> antd (no bug 👍🏻)

antd official website
image.png

2: react -> arco (with bugs)

arco official website

image.png

3: vue -> element (with bugs)

There is no need to demonstrate this, the start is to rely on it.

4: vue -> iview (with bugs)

iview official website

image.png

The above only 061acccfd81c81 is the perfect solution to this bug (must: respect), then we must study how it " antd

Three, delve into textarea

Since it is a problem with this input element occurring, then we started from it, take a look together element-ui with antd were produced textarea elements look like:

image.png

image.png

The difference is quite obvious. element-ui is not placed inside the label, because we cannot see the content from the perspective of the dom structure, but antd just the opposite, which may be a breakthrough.

Then we focus the "firepower" on <textarea> , and see how many assignments it has:

  return (
    <div className="App">
      <textarea rows="5" cols="40">
        内容1
      </textarea>
      <br />
      <textarea rows="5" cols="40" value="内容2"></textarea>
      <br />
      <textarea rows="5" cols="40" defaultValue="内容3"></textarea>
   </div>

image.png

It's amazing, the above three writing methods will all produce the same dom structure, so I am more curious about what writing method can hide the text in the label? I tried the way js specifies the value:

  useEffect(() => {
    document.getElementById("wrap").value = "你好世界";
  }, []);

  return (
    <div className="App">
      <textarea id="wrap" rows="5" cols="40">
        内容4
      </textarea>
   </div>
 )

image.png

Sure enough, the problem lies here. The initial value stored in the dom structure is actually the correct value. What is the difference besides these? Let's print out the relevant values:

image.png

vs🌩

image.png

I really don't know if I don't study it. The original implementation of the same component with different library implementations is so much different, and I feel that the difference in attribute values is quite a lot.

However, through experiments, we found that these attributes are not the direct cause of this bug. We still need to go deep into the source code to explore. At this time, I realized that this problem may not be the responsibility of elemnet.

4. Does Google Translate affect vue?

After many attempts, I can't believe it, but the two-way binding data such as vue's calculated properties will become invalid after translation:

<template>
  <div id="app">
    <button @click="handleClick">你好: {{n}}</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  methods:{
    handleClick(){
      this.n += 1;
      console.log(this.n)
    }
  },
  data(){
    return {
      n:1
    }
  },
}
</script>

image.png

It can be seen from the above that the variables of vue have changed, but the page cannot be updated correctly due to the change of the dom structure.

This is a very dangerous hidden danger, because some users may choose "Always translate", which leads to a complete mess of page functions!

image.png

5. Does Google Translate affect react?

Since react's arco framework will have problems, then the react framework will definitely be affected. Let's try to see under what circumstances a bug will occur. After translation, click:

import { useState } from "react";
import "./App.css";

function App() {
  const [n, setN] = useState(0);

  function handleClick() {
    setN(n + 1);
    console.log(n + 1);
  }
  return <div onClick={handleClick}>你好:{n}</div>;
}

export default App;

image.png

If it is changed, it will not be affected:

<div onClick={handleClick}>{n}</div>;

image.png

Six, the affected area (take the wording of react as an example)

By observing the difference between the implementation of antd and element-ui, I found that antd is made using the after pseudo-class. Is this related to the pseudo-class? This also proves that some situations are not affected. Let’s experiment with Google Translate Which writing methods are affected:

1: Concatenated text

The unaffected way of writing, even this way of writing every time n changes, will remove the dom structure of the font tag.

<div>{n}</div>;

The affected writing is mainly concatenated text.

<div>你好 {n}</div>;

<div>{n} {n}</div>;
2: Pseudo-element (will not be translated)

Empty dom

<div className={"box"}>.</div>

Define pseudo-elements

.box {
  height: 10px;
  width: 10px;
  border: 1px solid red;
}
.box::after {
  content: 'hello';
  display: inline-block;
}

image.png

So antd is likely to have no bugs because of pseudo-elements. If antd is not accidental, it would be too detailed.

3: Properties (very special)

The reason why it is very special is that whether the attribute is translated needs to be discussed in two cases, whether there is a text element, and the text cannot be the text inside the input.

first case: the page has only one input box

    <div>
      <span>
        <input
          type="Please enter content"
          value={value}
          onChange={change}
          placeholder={"Please enter content"}
        />
      </span>
    </div>

Obviously, this input box has not been translated:

image.png

The second case: add a string

    <div>
      <span>你好</span>
      <span>
        <input
          type="Please enter content"
          value={value}
          onChange={change}
          placeholder={"Please enter content"}
        />
      </span>
    </div>

image.png

The translation was successfully carried out and placeholder that might be shown to the user were also translated, and the other functional attributes would not be translated.

<span xxx={"xxxxxxxxx hello"}>你好</span>

image.png

7. How to block translation

In order to prevent bad experience caused by Google Translate, you only need to add the translate="no" html tag to block the translation function:

image.png

image.png

8. What is the translation of the test?

In fact, there are some users who turn on Google Translate by default. What's more, you are doing an international project. People of different languages using your website are more likely to use the default Google Translate. Then, if you don’t edit it and block it directly, We must at least monitor what language users have translated our website into? This will also facilitate us to optimize the i18n of the website in the future.

For example, our website does not have a Korean , but it is often translated into Korean. Then we can consider adding Korean?

For another example, although we have provided Korean translation, users still actively translate the website into Korean. Then we have to consider whether we can use the existing translation function to give users a clearer reminder? After all, we bring our own The translation is more accurate and the experience is better.

1: Introduction to MutationObserver

You can monitor all the changes of the dom element itself MutationObserver instantiated, a configuration item must be passed in. This configuration item can customize which changes to the dom need to be monitored. The main attributes are listed below:

  1. attributes boolean value, monitor the attribute changes of dom
  2. attributeFilter array, to monitor the change of a specific attribute of dom, filling in this parameter does not need to judge which attribute changes every time
  3. childList Boolean value, change of sub-element
  4. characterData Boolean value, monitor the change of the character data contained in the specified target node or node in the sub-node tree

It should be noted that at least one of the three attributes childList, attributes or characterData must be true, otherwise a TypeError exception will be thrown.

2: Ideas for monitoring translation

Since every time Google Translate will modify the lang <html lang="en"> tag, we will monitor the change of this attribute, and because even if the current lang="en" Google Translate to English is still lang="en" , it will be detected, so this technical solution is also feasible. of.

Create a new listenerI18n.js file and import it in the form of a plug-in:

(function () {
  const oHtml = document.getElementsByTagName("html")[0];
  const observer = new window.MutationObserver((mutations) => {
    console.log(`上报: 翻译为  ${oHtml.getAttribute("lang")}`);
  });
  observer.observe(oHtml, { attributes: true, attributeFilter: ["lang"] });
})();

Fortunately, even if you set <html lang="en" translate="no"> prohibit the use of the translation function, the above method can still detect which language the user wants to translate into with Google Translate.

image.png

I have compiled a comparison table of Google Translate. Students who need it, please pick it up. It is not comprehensive but lists the more commonly used countries:

[
  {
    "name": "简体中文",
    "lang": "zh-CN"
  },
  {
    "name": "英语",
    "lang": "en"
  },
  {
    "name": "阿拉伯语",
    "lang": "ar"
  },
  {
    "name": "爱尔兰语",
    "lang": "ga"
  },
  {
    "name": "白俄罗斯语",
    "lang": "be"
  },
  {
    "name": "保加利亚语",
    "lang": "bg"
  },

  {
    "name": "繁体中文",
    "lang": "zh-TW"
  },
  {
    "name": "波兰语",
    "lang": "pl"
  },
  {
    "name": "波斯语",
    "lang": "fa"
  },
  {
    "name": "丹麦语",
    "lang": "da"
  },
  {
    "name": "德语",
    "lang": "de"
  },
  {
    "name": "俄语",
    "lang": "ru"
  },

  {
    "name": "法语",
    "lang": "fr"
  },
  {
    "name": "菲律宾语",
    "lang": "tl"
  },
  {
    "name": "芬兰语",
    "lang": "fi"
  },
  {
    "name": "高棉语",
    "lang": "km"
  },
  {
    "name": "格鲁吉亚语",
    "lang": "ka"
  },
  {
    "name": "哈萨克语",
    "lang": "kk"
  },
  {
    "name": "韩语",
    "lang": "ko"
  },
  {
    "name": "荷兰语",
    "lang": "nl"
  },
  {
    "name": "老挝语",
    "lang": "lo"
  },
  {
    "name": "罗马尼亚语",
    "lang": "ro"
  },
  {
    "name": "马来语",
    "lang": "ms"
  },
  {
    "name": "蒙古语",
    "lang": "mn"
  },
  {
    "name": "孟加拉语",
    "lang": "bn"
  },
  {
    "name": "缅甸语",
    "lang": "my"
  },
  {
    "name": "尼泊尔语",
    "lang": "ne"
  },
  {
    "name": "挪威语",
    "lang": "no"
  },
  {
    "name": "葡头牙语",
    "lang": "pt"
  },
  {
    "name": "日语",
    "lang": "ja"
  },
  {
    "name": "瑞典语",
    "lang": "sv"
  },
  {
    "name": "世界语",
    "lang": "eo"
  },
  {
    "name": "泰语",
    "lang": "th"
  },
  {
    "name": "土耳其语",
    "lang": "tr"
  },
  {
    "name": "乌克兰语",
    "lang": "uk"
  },
  {
    "name": "西班牙语",
    "lang": "es"
  },
  {
    "name": "希腊语",
    "lang": "el"
  },
  {
    "name": "匈牙利语",
    "lang": "hu"
  },
  {
    "name": "意大利语",
    "lang": "it"
  },
  {
    "name": "印度尼西亚语",
    "lang": "id"
  },
  {
    "name": "越南语",
    "lang": "vi"
  },
  {
    "name": "爪哇语",
    "lang": "jw"
  }
]

Nine, summary

It seems that the translation function of "human and animal harmless" hides various shades of "pits" behind it. Assuming that users use Google Translate on certain "amount settlement pages", will it cause serious problems? So the best way is to provide a complete "language switching" function is the kingly way.

end

This is the case this time, I hope to make progress with you.


lulu_up
5.7k 声望6.9k 粉丝

自信自律, 终身学习, 创业者