node调用百度翻译api的自动翻译

185 阅读3分钟

项目需求背景介绍

公司要做把项目做成国际化的,本来要求是五种语言一同进行但是做到一半的时候给我说必须先出某个语言其他的可以后面在做所以有三种语言就搁置了。但是有的配置文件(json格式)已经有一部分这时候再用百度翻译进行中英翻译有点浪费次数(毕竟自己不是大户)。要是写的不好勿喷!!!

  1. 我想要做的结果就是:把所有old文件夹下面的文件全部翻译放入new文件夹下面
a745e75aef60da4d3e424ccf9636de8.png
  1. old文件夹下面的Button下的zh-index就代表了中文案例:
//zh-index.js
export default {
  preservation: '保存',
  see: '查看',
  edit: '编辑',
  search: '搜索',
  Button: '按钮',
  display: '显示',
  hide: '隐藏',
  empty: '清空',
  jurisdiction: '权限',
  toUpdate: '更新',
  increase: '增加',
  BatchDeletion: '批量删除',
  cache: '缓存',
  Refresh: '刷新',
  open: '展开',
  shrink: '收缩',
  SelectAll: '全选',
}
  1. 接下来废话不多说直接给兄弟们上代码有什么"注意事项"。我给兄弟们写在代码里面,当然你要是那个翻译的地方有报错,大概率是因为百度翻译api的54003请求没回来所以可以自行调节定时器时间或者在33行或者72行先配置一下把当前文件先跳过去
//index.js
//引入需要的库,有的兄弟可能会问node里面还能用import引入那是因为我在package.json里面有配置,我把package一会给兄弟们贴在下面
import fs from 'fs'
import path from 'path'
import axios from 'axios'
import CryptoJS from 'crypto-js'

/*
* 获取指定文件夹下的所有文件夹
* @params {string} path-要获取文件夹的路径
* @return {string[]} 返回一个指定包含文件的所有文件夹名称
* */
function getDir(filesPath) {
    const items = fs.readdirSync(filesPath)
    return items.filter(item => {
        const stats = fs.statSync(path.join(filesPath, item))
        return stats.isDirectory();
    }).map(item => path.join(filesPath, item))

}

/*
*处理获取到的文件夹列表
* @params {string[]} list-文件夹列表
* */
async function files(list) {
    for (const item of list) {
        //可以根据配置翻译某个文件夹下的东西
        // if (item !== 'old\Button' && item!=='old\Dialog' && item!=='old\Input') {
        //     let list = await getFile(item)
        //     await filesList(list)
        // }
        if (item === 'old\Input') {
            let list = await getFile(item)
            await filesList(list)
        }


    }
}

/*
获取指定文件夹下面的所有文件
@params {string} path-要获取文件夹的路径
@return {string[]} 返回一个指定包含文件的所有文件夹名称;code是文件的名称;filePath是文件的路径;mkdirName是文件夹的名称准备用来在new文件夹下面生成对应的文件夹名称
* */
function getFile(filesPath) {
    const items = fs.readdirSync(filesPath);
    //item.endsWith('.js')获取所有后缀为.js的文件列表名称,兄弟们可以自行更换
    return items.filter(item => item.endsWith('.js')).map(item => {
        return {
            code: item.split('-')[0],//这个code是把文件名称切割了取得前面的文件用来做文件编码。例如:中文:zh-index.js结果就变成了zh,这个zh代表的是百度翻译api的编码列表可以去自行参考百度翻译api
            //百度翻译阿皮地址:https://fanyi-api.baidu.com/product/113
            filePath: `./${path.join(filesPath, item)}`,
            mkdirName: filesPath.split('\')[1],
            file: item
        }
    })
}

/*
*处理获取到的文件列表
@params {string[]} list-文件列表
* */
async function filesList(list) {
    let zh = list.filter(item => item.code === 'zh')
    let zhJson = await i18nJson(zh[0])
    let i18nList = list.filter(item => item.code !== 'zh' && item.code !== 'vn')
    for (const item of i18nList) {
        let json = await i18nJson(item)
        //可以根据配置翻译某个文件夹下的某个文件
        if (json.code === 'th') {
            let obj = await zhToI18n(zhJson, json)
            obj.newMkdir = 'new'
            await writeFile(obj)
        }
    }
}

/*
传入文件对象
@params {object} 传入文件对象;code:文件的code,filePath:文件路径,mkdirName:文件名称
@returns {object} 返回一个对象,code:文件的code,filePath:文件路径,mkdirName:文件名称,json:文件内容,codeKeys:文件内容的key,codeValues:文件内容的value,codeEntries:文件内容的key和value
* */
async function i18nJson(json) {
    let {default: res} = await getImport(json.filePath)
    let {code, mkdirName, file} = json
    return {
        code, mkdirName, json: res, codeKeys: Object.keys(res), fileName: file,// codeValues:Object.values(res),
        // codeEntries:Object.entries(res)
    }
}

/*
* @params {string} 传入文件路径
* @returns {object} 返回一个获取到路径文件的对象
* */
async function getImport(url) {
    return await import(url)
}

// 国际化语言编码映射
let map = new Map([['zh', 'zh'], ['en', 'en'], ['vn', 'vie'], ['th', 'th'], ['mx', 'spa']])

/*
@params{object} zh:传入的中文文件对象
@params{object} i18n:传入的其他语言文件对象
@returns {object} 返回一个翻译后的对象code:语言编码;json:翻译后的对象;mkdirName:文件夹名称;
* */
async function zhToI18n(zh, i18n) {
    let {code = 'zh', codeKeys, json: zhJson} = zh
    let {code: i18nCode, json: i18nJson, mkdirName, fileName} = i18n
    if (!i18nCode) {
        new Error('请传入要翻译的语言编码')
        return false
    }
    let json = {}
    for (const item of codeKeys) {
        if (i18nJson[item]) {
            json[item] = i18nJson[item]
        } else {
            json[item] = await BaiduApi({
                val: zhJson[item], from: map.get(code), to: map.get(i18nCode)
            });
        }
    }
    return {
        code: i18nCode, json, mkdirName, fileName
    }
}

function BaiduApi(options) {
    return new Promise(async (resolve) => {
        let {val, from, to} = options
        let appid = '你的appid'//appid可以自行去百度翻译api申请在百度翻译开发者中心会看到你的appid和密钥
        let token = '你的百度翻译密钥'//百度翻译的密钥
        let salt = Math.random()
        let sign = MD5(`${appid}${val}${salt}4QVyfspNcCiuAz8Lo7Ut`)
        let url = `https://fanyi-api.baidu.com/api/trans/vip/translate?q=${encodeURIComponent(val)}&from=${from}&to=${to}&appid=${appid}&salt=${salt}&sign=${sign}`
        let res = await axios.get(url)
        //在这做了一秒的定时原因是如果不做会报错54003,请降低您的调用频率,或在控制台进行身份认证后切换为高级版/尊享版。如果您是尊贵的vip玩家就当我没说
        setTimeout(() => {
            console.log(res.data, `${val}==============请求结果`)
            resolve(res?.data?.trans_result[0]?.dst || '')
        }, 1000)
    }).catch(err => {
        new Error(err)
        console.log(err, '请求错误')
    })


}

// md5加密
function MD5(val) {
    return CryptoJS.MD5(val).toString()
}

/*
* @params {object} obj:传入要写入文件的对象
* */
function writeFile(json) {
    let {newMkdir, mkdirName, fileName, json: val} = json
    if (!fs.existsSync(newMkdir)) {
        fs.mkdirSync(newMkdir)
    }
    if (!fs.existsSync(`${newMkdir}/${mkdirName}`)) {
        fs.mkdirSync(`${newMkdir}/${mkdirName}`)
    }
    fs.writeFileSync(`${newMkdir}/${mkdirName}/${fileName}`, `export default ${JSON.stringify(val)}`)
}

//使用方法
try {
    //‘./old’的文件夹可自行更改为别的文件夹名称
    let list = await getDir('./old')
    await files(list)
} catch (err) {
    new Error(err)
}
  • package.json
{
  "name": "yes",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index.js"//这个是我在开发的时候用的一个热更新,兄弟们直接使用node index.js就ok了
  },
  "author": "",
  "license": "ISC",
  "type": "module",
  "devDependencies": {
    "axios": "^1.7.8",
    "crypto-js": "^4.2.0",
    "nodemon": "^3.1.7"
  }
}