前端国际化-插件模式

文章目录

  • [Webpack 插件开发](#Webpack 插件开发)
  • 解析中文
  • [调用有道翻译 API](#调用有道翻译 API)
  • [生成 JSON 语言文件](#生成 JSON 语言文件)
  • [React 国际化实现](#React 国际化实现)

Webpack 插件开发

  • 创建 i18n-webpack-plugin.js 插件:
  • 在 src 目录下扫描所有文件
  • 使用 babel-parser 解析 JavaScript/JSX 代码
  • 识别中文文本
  • 通过有道翻译 API 翻译
  • 生成 locales/en.json(英语)和 locales/zh.json(中文)
javascript 复制代码
const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const fetch = require("node-fetch");

class I18nWebpackPlugin {
  constructor(options) {
    this.options = options || {};
    this.localeDir = path.resolve(process.cwd(), "locales");
    this.zhJsonPath = path.join(this.localeDir, "zh.json");
    this.enJsonPath = path.join(this.localeDir, "en.json");
  }

  async extractChinese(content) {
    const ast = parser.parse(content, { sourceType: "module", plugins: ["jsx"] });
    const chineseTexts = new Set();

    traverse(ast, {
      StringLiteral({ node }) {
        if (/[\u4e00-\u9fa5]/.test(node.value)) {
          chineseTexts.add(node.value);
        }
      },
      JSXText({ node }) {
        if (/[\u4e00-\u9fa5]/.test(node.value.trim())) {
          chineseTexts.add(node.value.trim());
        }
      }
    });

    return Array.from(chineseTexts);
  }

  async translateText(text) {
    const apiKey = "your-app-key";
    const apiSecret = "your-app-secret";
    const url = `https://openapi.youdao.com/api?q=${encodeURIComponent(text)}&from=zh-CHS&to=en&appKey=${apiKey}`;
    
    const response = await fetch(url);
    const data = await response.json();
    return data.translation ? data.translation[0] : text;
  }

  async apply(compiler) {
    compiler.hooks.emit.tapAsync("I18nWebpackPlugin", async (compilation, callback) => {
      const srcDir = path.resolve(process.cwd(), "src");
      const files = fs.readdirSync(srcDir).filter(file => file.endsWith(".js") || file.endsWith(".jsx"));

      let translations = {};
      for (const file of files) {
        const content = fs.readFileSync(path.join(srcDir, file), "utf-8");
        const chineseTexts = await this.extractChinese(content);
        
        for (const text of chineseTexts) {
          if (!translations[text]) {
            translations[text] = await this.translateText(text);
          }
        }
      }

      if (!fs.existsSync(this.localeDir)) {
        fs.mkdirSync(this.localeDir);
      }

      fs.writeFileSync(this.zhJsonPath, JSON.stringify(translations, null, 2), "utf-8");
      fs.writeFileSync(this.enJsonPath, JSON.stringify(translations, null, 2), "utf-8");

      console.log("✅ 国际化 JSON 文件已生成!");
      callback();
    });
  }
}

module.exports = I18nWebpackPlugin;

解析中文

  • 使用 babel-parser 解析代码,提取 JSX 内的中文文本和 JavaScript 代码中的字符串中文。

调用有道翻译 API

有道 API 示例:

javascript 复制代码
const fetch = require('node-fetch');

async function translate(text, from = 'zh-CHS', to = 'en') {
  const appKey = 'your-app-key';
  const appSecret = 'your-app-secret';
  const url = `https://openapi.youdao.com/api?q=${encodeURIComponent(text)}&from=${from}&to=${to}&appKey=${appKey}`;

  const response = await fetch(url);
  const data = await response.json();
  return data.translation[0]; // 返回翻译结果
}

生成 JSON 语言文件

扫描所有 src 目录的文件后,创建 locales/en.json 和 locales/zh.json 语言包,格式如下:

javascript 复制代码
{
  "首页": "Home",
  "你好": "Hello"
}

React 国际化实现

  • 使用 react-intl 或 i18next 进行国际化支持,并在 App.js 中引入翻译文件,动态切换语言。
相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端