关于前端:你真的认为Google翻译不影响前端页面功能吗

26次阅读

共计 5783 个字符,预计需要花费 15 分钟才能阅读完成。

你真的认为 Google 翻译不影响 ” 前端 ” 页面性能吗?

背景

     又是一个时光飞逝的工作日, QA 同学忽然提出 bug, 文本输入框的 ” 计数 ” 性能生效, 通过大家多方查找最初发现居然是因为测试同学开启了 ” 谷歌翻译 ” 造成的无奈 ” 计数 ”, 这就引起了我的浓厚兴趣, 到底这个看起来 ” 人畜有害 ” 的翻译性能是如何影响了我的输入框? 魏蜀吴争霸从此揭开序幕, 啊~ 额(中箭)。

     这篇文章是按我的探索过程编写的, 所以并不是一下就找到正确的方向, 跟着我过后的思路一起摸索吧。

一、dom 构造的扭转 (以 react 代码为例)

     想要晓得为什么 ” 翻译性能 ” 会影响页面, 要从察看每次 ” 翻译 ” 性能失效时页面构造的变动开始, 最为简略的一段代码:

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

翻译前:

翻译后:

     查问一下 font 标签的个性, 居然曾经不倡议应用了:

     尝试一下是否能够获取到这个 font 标签元素, 将代码改装一下

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

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

     能够获取到这个元素就有意思了, 如果某些状况下代码外面存在通过获取子元素进行操作的逻辑, 那么实践上就会出问题啊。

     难道是因为 dom 构造的扭转, 导致的 文本输入框 的计数性能会隐没吗?

二、比照 vue 与 react 各类 ui 库

     通过查看 element ui 的源码没有发现非凡的代码逻辑, 那到底是怎么回事? 满心的疑难让我萌发一种想法, 难道跟 vue 与 react 框架自身的原理无关? 那么接下来我会别离试验 4 种 ui 框架的成果:

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

antd 官网

2: react -> arco (有 bug)

arco 官网

3: vue -> element(有 bug)

     这个不必演示了, 开局就是靠它。

4: vue -> iview(有 bug)

iview 官网

     上述只有 antd是完满解决了这个 bug (必须: respect), 那必须要钻研一下它是如何 ” 力压群芳 ” 的呢?

三、深究 textarea

     既然是这个输入框元素产生的问题, 那么咱们就从它开始吧, 一起看一下 element-uiantd别离产生的 textarea 元素长什么样子:

     区别还是比拟显著的, element-ui的内容信息不是放在标签外部的, 因为咱们在 dom 构造的视角无奈查看到内容, 然而 antd 恰恰相反, 这兴许能够成为一个突破口。

     那咱们把 ” 火力 ” 集中在 <textarea> 身上, 看看它到底有多少种赋值写法:

  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>

     很微妙, 上述三种写法都会产生同样的 dom 构造, 那么就比拟好奇是什么样的写法能够暗藏标签内的文字? 我就尝试了一下 js 指定 value 的形式:

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

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

     果然问题出在这里, dom 构造内保留的竟然是初始值, 外界显示的是正确的值, 除了这些还有什么区别那? 咱们把相干的值都打印进去吧:

vs🌩

     真是不钻研不晓得, 原来同样的组件成果不同的库实现进去差这么多, 感觉属性值差的还挺多的。

     然而通过试验发现, 这些属性并不是这个 bug 的间接起因, 咱们还须要深刻源码进行探索, 此时我意识到这个问题可能不是 elemnet 的责任。

四、谷歌翻译是否影响 vue

     通过屡次尝试连本人都不敢相信, 居然 vue 的计算属性等双向绑定的数据会在翻译后生效:

<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>

     下面能够看出 vue 的变量曾经变动, 只是因为 dom 构造的扭转导致了页面无奈被正确更新。

     这是一个很危险的隐患, 因为有的用户可能会抉择 ” 总是翻译 ”, 这就导致页面性能齐全乱掉了啊!

五、谷歌翻译是否影响 react

     既然 react 的 arco 框架会出问题, 那么 react 框架也肯定会被影响, 让咱们尝试一下什么状况下会出 bug, 翻译之后点击:

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;

如果改成则不会受影响:

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

六、受影响范畴 (以 react 的写法为例)

     通过观察 antd 与 element-ui 实现的不同我发现, antd 是应用 after 伪类类做的, 难道此事与伪类无关? 这也证实了某些状况是不受影响的, 让咱们试验一下谷歌翻译都影响哪些写法:

1: 拼接文本

     不受影响的写法, 甚至这种写法每次 n 发生变化, 会移除 font 标签的 dom 构造。

<div>{n}</div>;

     受影响的写法次要是拼接的文本。

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

<div>{n} {n}</div>;
2: 伪元素(不会被翻译)

空空的 dom

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

定义伪元素

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

所以 antd 很可能是因为伪元素才没有出 bug, 如果 antd 不是无心之举那就太细节了。

3: 属性(十分非凡)

     之所以说它十分非凡, 是因为属性是否被翻译须要分两种状况探讨, 是否有文本元素, 并且这个文本不能是 input 外部的文本。

第一种状况: 页面只有一个输入框

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

不言而喻, 这个输入框没有被翻译:

第二种状况: 随便增加一个字符串

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

     胜利进行了翻译并且像 placeholder 这种可能会展现给用户的属性也被翻译了, 其余功能性的属性并不会被翻译。

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

七、如何屏蔽翻译

     为避免因谷歌翻译引起不良体验, 只须要在 html 标签上增加 translate="no" 属性即可屏蔽掉翻译性能:

八、检测被翻译成了什么

     其实存在一部分用户默认就开启谷歌翻译性能的, 更有甚者你做的是国际化我的项目, 不同语言的人应用你的网站更有可能应用默认的谷歌翻译, 那么不编间接屏蔽的状况下, 咱们要至多要监听一下用户都将咱们的网站翻译成了什么语言? 这样也不便咱们日后对网站的 i18n 进行优化。

     比方咱们网站本人没有 韩语 的翻译, 然而常常被用过翻译成 韩语 , 那么咱们能够思考减少 韩语 呢?

     再比方咱们尽管提供了 韩语 的翻译, 然而用户依然被动将网站翻译成 韩语, 那就要思考是不是咱们能够将已有的翻译性能, 更明确的提醒给用户应用? 毕竟咱们自带的翻译更精确体验也更好。

1: MutationObserver 简介

     能够监控 dom 元素自身的所有扭转, MutationObserver实例化后要传入一个配置项, 这个配置项能够自定义须要监听 dom 的哪些变动, 上面列出次要的几个属性:

  1. attributes 布尔值, 监测 dom 的属性变动
  2. attributeFilter 数组, 监测 dom 的具体某个属性的变动, 填写这个参数就不必每次判断哪个属性变动了
  3. childList布尔值, 子元素的变动
  4. characterData布尔值, 监督指定指标节点或子节点树中节点所蕴含的字符数据的变动

     须要留神的是: childList,attributes 或者 characterData 三个属性之中,至多有一个必须为 true,否则会抛出 TypeError 异样。

2: 监控翻译的思路

     因为每次谷歌翻译都会批改咱们的 <html lang="en"> 标签的 lang 属性, 所以咱们就监控这个属性的变动, 并且因为哪怕以后是 lang="en" 谷歌翻译成英语还是lang="en", 也是会被检测到的 , 所以这个技术计划也是可行的。

     新建一个 listenerI18n.js 文件, 已插件的模式引入即可:

(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"] });
})();

     比拟侥幸的是就算你设置了 <html lang="en" translate="no"> 禁止应用翻译性能, 上述办法仍能检测到用户想要用谷歌翻译翻译成什么语言。

我整顿了一份谷歌翻译的对照表, 有须要的同学请自取, 外面并不全面但列举出比拟罕用的国家:

[
  {
    "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"
  }
]

九、总结

     看似 ” 人畜有害 ” 的翻译性能, 背地居然暗藏着各种深浅不一的 ” 坑井 ”, 假如在某些 ” 金额结算页 ” 用户应用了谷歌翻译, 那么是否会造成不小的问题, 所以最好的方法还是提供欠缺的 ” 语言切换 ” 性能才是王道啊。

end

     这次就是这样, 心愿与你一起提高。

正文完
 0