自定义通过翻译API进行时的监听事件

当 translate.execute() 触发执行翻译时,它会先从 浏览器缓存 中取,如果有则会直接从缓存中将翻译结果拿出来渲染到页面上,以做到瞬间翻译。
但是如果有的在本地没有缓存时,这部分没有缓存的文字将会通过API的方式进行请求翻译接口进行翻译。而这种方式毕竟是网络请求,考虑到网络延迟以及翻译API的执行耗时,这个可能要消耗0.5~2秒的时间才会完成翻译。 这样在用户(使用者)看来,就是页面先显示了原本的语种1秒,然后才会翻译成用户需要的语种。 而本文章则是针对这个过程,来进行自定义监听做一些你想做的事情。

两个触发事件

1. 请求翻译API之前触发

已经扫描完整个DOM,并且经过了一系列处理,拿到最终要通过翻译API接口进行翻译的文本,进行向API接口发送网络请求之前,触发,触发这个后会立即向翻译API发送网络请求。

  1. translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
  2. console.log('这里你可以做一些自己的自定义操作');
  3. });

2. 请求翻译API完成并在DOM渲染完毕后触发

也就是在也面上被翻译的元素的内容,已经完全被翻译过来(眼睛已经能看到文字被翻译过来)之后,才会触发。

  1. translate.listener.execute.renderFinishByApi.push(function(uuid, from, to){
  2. console.log('这里你可以做一些自己的自定义操作');
  3. });

使用说明

1. 参数说明

上面两个事件都是传入了一个自定义方法

  1. function(uuid, from, to){
  2. ...
  3. }

其中有个uuid的参数,可以用这个来取得当前传入到翻译API的文本以及所设计到的DOM节点。
可以这样来取 uuid 对应的相关数据:

  1. translate.nodeQueue[uuid]

打印出来可以看到:

需要注意的是,当前我执行的是将当前页面翻译为英文的操作。 上图可以看到 list 下有 简体中文、也有英文。
因为我们是要翻译为英文,也就是 上图中 english 的数组部分它只是被扫描出来了,但它并不会实际参与进翻译中去的,也就是在通过翻译API进行翻译的文本中,是不包含 list[english] 这个的。
也就是当前触发我们function 这个方法的翻译元素,实际是:

  1. translate.nodeQueue[uuid].list[from]

也就是展开其中某个语种,可以看到:

也就是
如果你想获得参与当前翻译的实际的文本,可以从 translate.nodeQueue[uuid].list[from][遍历集合].translateText 取得;
如果你想获得参与当前翻译的原本DOM中的文本,可以从 translate.nodeQueue[uuid].list[from][遍历集合].original 取得;
如果你想获得参与当前翻译的node节点,可以从 translate.nodeQueue[uuid].list[from][遍历集合].nodes 取得;

另外有关uuid的解释: 页面可能会触发多次翻译,每执行一次翻译,就会生成一个uuid,来存储跟当前执行的翻译相关的数据,不至于翻译执行多了使数据产生错乱。

注意,请不要直接对 translate.nodeQueue 的数据进行操作,你只可以读,不可以写。避免造成数据错乱。你想对数据处理,可以读出数据来后自行创建一个变量进行赋予,处理你自己定义的变量。

2. 可触发多次

触发可以触发多次,并不是只能触发一次,比如你可以这样写:

  1. translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
  2. console.log('111');
  3. });
  4. translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
  5. console.log('222');
  6. });
  7. translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
  8. console.log('333');
  9. });

这个 111、222、333 都会被打印出来。至于它的执行顺序,则是跟代码的顺序一样,先打印 111、在打印 222、在打印 333 ,因为你代码的顺序就是这样的,它跟你代码的顺序是保持一致的。

3. 根据源语言不通进行多次触发

正常情况下,是根据本地语言不同,进行分别请求翻译的,比如本地中包含中文、英文、俄语三种语种,要翻译为韩语,那么

也就会触发三次

使用示例 - 控制按钮显示文字

这个示例的实际场景是,网页中有个按钮 <button id="translateButton" ...> 当点击按钮后,进行语言切换,翻译为英语,按钮文字发生改变,翻译完后,按钮文字还原。
当用户点击按钮进行翻译时,翻译会触发一个网络请求,进行翻译操作,网络请求可能是0.5秒,也可能是1.5秒,另外翻译时,会将网页中的文本进行按语种进行分类,也就是点击了一个翻译按钮,有可能发起的是这三个网络请求:

  1. 简体中文翻译为英文
  2. 繁体中文翻译为英文
  3. 俄语翻译为英文

这里的需求是,当点击翻译按钮后,发起翻译的网络请求的过程中,并且这三个任何一个还没得到相应结果时,也就是任何一个网络请求的状态还在请求中时, 翻译按钮的文本变为正在翻译中... ,当三个翻译的网络请求都完成时(不管成功还是失败还是接口报错等任何情况), 翻译按钮的文本变为翻译
代码为:

  1. window.currentTranslateIsProgress = 0; //0是未进行翻译,或已经翻译完成,大于0则是有正在进行的翻译网络请求,数字便是正在进行网络请求的数量。
  2. translate.listener.execute.renderStartByApi.push(function(uuid, from, to){
  3. currentTranslateIsProgress++;
  4. console.log('发起翻译的网络请求,将 '+from+' 翻译为 '+to+', 当前是正在进行中的第'+currentTranslateIsProgress+"个翻译网络请求");
  5. document.getElementById('translateButton').innerHTML='正在翻译中...';
  6. });
  7. translate.listener.execute.renderFinishByApi.push(function(uuid, from, to){
  8. currentTranslateIsProgress--;
  9. console.log('完成翻译的网络请求,将 '+from+' 翻译为 '+to);
  10. if(currentTranslateIsProgress == 0){
  11. document.getElementById('translateButton').innerHTML='翻译';
  12. }
  13. });

注意

  1. 需要 translate.js v3.13.8.20250220 及更高版本才支持此能力
  2. 如果翻译时,浏览器本地已经有全部缓存了,不需要在通过翻译API来进行翻译文本了,那么这两个事件是不会触发的。因为他们单纯只是为了监听 翻译API的网络请求及完成的。