前端国际化-插件模式

文章目录

  • [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 中引入翻译文件,动态切换语言。
相关推荐
To_OC7 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic8 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy8 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志8 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble9 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯10 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜11 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司11 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
kaiking_g12 小时前
vue项目中,静态导入 vs 动态导入 详解
前端·javascript·vue.js
江华森12 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http