前言

单纯引入 translate.js 还需要用户手动点击切换,体验不够极致。我们可以通过浏览器原生的navigator.language接口,在页面加载之初就判断用户所在的“语言时区”,自动执行翻译指令。

核心流程

translate.js 工作逻辑不像传统的 SSR(服务端渲染),它更像是一个勤劳的粉刷匠。为了理解它的核心机制,我整理了以下伪代码,并利用高亮标记了关键步骤:

// translate.js 核心逻辑简化版
var translate = {
  execute: function() {
    // 1. 递归扫描 DOM 树,提取所有文本节点
    var nodes = this.getTextNodes(document.body); // [!code highlight]

    var textToTranslate = [];
    
    nodes.forEach(node => {
      // 2. 核心优化:优先读取本地缓存 (LocalStorage/IndexedDB)
      var cache = this.storage.get(node.text); // [!code focus]
      
      if(cache) {
        // [!code ++] 命中缓存:直接替换 DOM,0 网络请求
        node.replace(cache); 
      } else {
        // [!code --] 未命中:不做处理,加入待翻译队列
        textToTranslate.push(node.text);
      }
    });

    // 3. 队列合并打包,发送请求
    if(textToTranslate.length > 0){
      this.api.post(textToTranslate, (result) => {
        this.render(result); // 批量渲染
        this.storage.save(result); // 写入缓存
      });
    }
  }
}
  • DOM 扫描 (getTextNodes):它智能避开了 <script> 和 <style> 标签,只提取 nodeType === 3 的文本,防止翻译代码导致页面崩溃。

  • 缓存机制 (storage.get):这是它速度快的核心。通过 Hash 索引存储翻译结果,第二次访问时直接从本地读取,延迟几乎为零。

进阶玩法

光有翻译库还不够,我们不能让用户进来全是中文,还得手动找翻译按钮。最好的体验是用户无感,页面主动适应,利用浏览器原生的navigator.language API,我们可以获取用户的首选语言,并配合 translate.js 实现自动切换。

包含了大陆、港澳台、海外的三级分流逻辑:

function autoSwitchLanguage() {
  // 1. 获取浏览器语言 (兼容性处理)并转为小写
  let userLang = (navigator.language || navigator.userLanguage).toLowerCase(); // [!code highlight]
  
  // 2. 默认兜底策略:非中文地区全部设为英文
  let targetLang = 'english'; 
  let htmlLang = 'en';

  // 3. 智能判断逻辑
  // [!code focus:12] 聚焦核心判断区域
  if (userLang.startsWith('zh')) {
    // 命中中文语系
    if (userLang === 'zh-cn') {
      // 大陆地区 -> 保持简体(无需翻译)
      targetLang = 'chinese_simplified';
      htmlLang = 'zh-CN';
    } else {
      // 港澳台 (zh-hk, zh-tw, zh-mo) -> 切换繁体
      targetLang = 'chinese_traditional';
      htmlLang = 'zh-TW'; 
    }
  }

  // 4. 修改 HTML 标签属性 (对 SEO 友好)
  // [!code warning] 注意:这一步对搜索引擎识别非常重要
  document.documentElement.lang = htmlLang;

  // 5. 调用 translate.js 执行切换
  if (translate.language.getLocal() !== targetLang) {
    translate.changeLanguage(targetLang);
    console.log(`检测到环境: ${userLang}, 已切换至: ${targetLang}`);
  }
}

代码深度解析

  • startsWith('zh'):利用字符串匹配,通过这一行代码就圈定了所有华人用户,避免了列举 zh-sg, zh-my 等复杂情况。

  • document.documentElement.lang:很多翻译方案只改了文字,没改 lang 属性。加上这一行,可以让浏览器自带的翻译工具知道页面已经变了,避免重复提示翻译,同时利于 Google/Bing 的 SEO 收录。

效果对比与验证

为了验证这套逻辑的健壮性,引入前后的变化:

<!-- 原始状态 (默认) -->
<html lang="zh-CN">
  <body>你好,世界</body>
</html>

<!-- ❌ 错误示范:仅翻译文字,不改 lang -->
<html lang="zh-CN"> <!-- [!code error] 浏览器会困惑:明明写着zh-CN,内容却是英文 -->
  <body>Hello, World</body>
</html>

<!-- ✅ 正确示范 (脚本执行后) -->
<html lang="en"> <!-- [!code ++] 属性已修正,SEO 友好 -->
  <body>Hello, World</body>
</html>

实战测试

为了确保自动嗅探在全球各地都生效,我没有只用VPN简单测试,而是使用了比特浏览器进行了指纹环境模拟。

  1. 模拟美国环境 (US-IP / en-US): 页面加载瞬间,targetLang 锁定为 english,整站自动转为英文。

  2. 模拟香港环境 (HK-IP / zh-HK): 脚本精准识别非大陆中文区,自动切换为繁体中文,符合当地阅读习惯。

  3. 模拟上海环境 (CN-IP / zh-CN): 保持原生简体,不触发任何翻译 API 请求,节省资源。

结语

通过 translate.js 的轻量级翻译能力,配合navigator.language的精准分流,我们仅仅用了不到 50 行代码,就解决了一个中型项目的国际化难题。

这种方案的优势在于:

  1. 极速部署: 前端独立完成,无需后端改库。

  2. 体验极佳: 配合Hash缓存和预加载,几乎没有“闪烁感”。

  3. 成本低廉: 相比于昂贵的Google Translate API,这种方案对于个人站长简直是福音。

项目地址:https://github.com/xnx3/translate