背景:文档中心需要接入国际化,想节省时间做统一英文方案处理;
文档中心是基于vuepress
框架编写的;
1、利用百度翻译 API 的接口去做底层翻译处理,https://api.fanyi.baidu.com/需要在该平台上注册账号,个人高级版免费,每个月有百万字符容量;
2、利用 Node.js 模块遍历相应的目录的文件,对每一行中文进行翻译,然后替换原内容;
3、将替换好的内容写入到新的 en 目录下的文件里,如果无该目录,且自动创建该目录;
4、修改配置 config.js 添加语言切换的入口,将不同的文件内容放到语言下面;
5、查找中文并翻译的转化文件baiduFanyi.mjs
import fs, { stat } from 'fs'
import path, { resolve } from 'path'
import md5 from 'md5'
import axios from 'axios'// 百度翻译接口
const requestTranslate = q => {const apiUrl = 'http://fanyi-api.baidu.com/api/trans/vip/translate'const appid = '20230731001763594'const secret = 'R0netNArlgX8YewM9ECl'const salt = Math.random()const sign = md5(appid + q + salt + secret)const params = {q,from: 'zh',to: 'en',salt,appid,sign}return axios.get(apiUrl, {params})
}// 获取所有文件
const getListFile = dir => {let list = []let arr = fs.readdirSync(dir)arr.forEach(item => {let fullpath = path.join(dir, item)let stats = fs.statSync(fullpath)if (stats.isDirectory()) {list = list.concat(getListFile(fullpath))} else if (fullpath.lastIndexOf('.md') > -1) {// 指定的md文件后缀list.push(fullpath.slice(0))}})return list
}/*** 读取路径信息* @param {string} path 路径*/
function getStat(path) {return new Promise((resolve, reject) => {fs.stat(path, (err, stats) => {if (err) {resolve(false)} else {resolve(stats)}})})
}/*** 创建路径* @param {string} dir 路径*/
function mkdir(dir) {return new Promise((resolve, reject) => {fs.mkdir(dir, err => {if (err) {resolve(false)} else {resolve(true)}})})
}/*** 路径是否存在,不存在则创建* @param {string} dir 路径*/
async function dirExists(dir) {let isExists = await getStat(dir)// 如果该路径且不是文件,返回trueif (isExists && isExists.isDirectory()) {return true} else if (isExists) {// 如果该路径存在但是文件,返回falsereturn false}// 如果该路径不存在let tempDir = path.parse(dir).dir // 拿到上级路径// 递归判断,如果上级目录也不存在,则会代码会在此处继续循环执行,直到目录存在let status = await dirExists(tempDir)let mkdirStatusif (status) {mkdirStatus = await mkdir(dir)}return mkdirStatus
}// 要翻译的文件遍历,以中文为基础翻译
// const publicDir = ''
const publicPutDir = 'en'
// 需要遍历的文件夹
const dirPaths = [`agreement`,`FAQ`,`instructions`,`lbs`,`openapi`,`simCardRecharge`,`README.md`
]
// 获取所有的文件列表
let allFiles = []
const getAllFile = () => {for (let i = 0, len = dirPaths.length; i < len; i++) {let stats = fs.statSync(dirPaths[i])if (stats.isDirectory()) {const filePaths = getListFile(dirPaths[i])allFiles = [...allFiles, ...filePaths]} else {allFiles.push(dirPaths[i])}}
}
getAllFile()
console.log(allFiles, '\n', '翻译中...')let allContent = []
// 遍历文件内容翻译,然后写入指定的文件中
const translateAndWrite = async () => {// 遍历每个文件路径for (let i = 0, len = allFiles.length; i < len; i++) {const item = allFiles[i]// const fileName = path.basename(item, path.extname(item)) // 文件名const fullName = path.basename(item) // 文件全称加后缀const dirName = path.dirname(item) // 文件目录// let inputFullFile = publicDir + item// 读取当前文件的内容let content = fs.readFileSync(item, 'utf8')// 创建空字符串变量存放合并后的内容let mergedContent = ''let newContent = content.split('\n')let reg =/([\u4e00-\u9fa5]+\s*\S*[^|]\s*\S*[\u4e00-\u9fa5]+)|([\u4e00-\u9fa5]+)/gulet transTextArr = newContent.reduce((prev, cur, index, arr) => {cur = cur.trim()if (cur && cur.match(reg)) {return prev.concat(cur.match(reg))} else {return prev}}, [])console.log('需要翻译的文本', transTextArr)allContent = [...allContent, ...transTextArr]// 修改图片的路径content = content.replace(/..\/\.vuepress/g, '../../.vuepress')mergedContent = contentfor (let i = 0, len = transTextArr.length; i < len; i++) {let { data } = await requestTranslate(transTextArr[i])data.trans_result.forEach(d => {mergedContent = mergedContent.replace(d.src, d.dst)})}let outputDir = `${publicPutDir}/${dirName}`// 创建文件夹await dirExists(outputDir)let outputFile = `${outputDir}/${fullName}`// 写文件内容fs.writeFileSync(outputFile, mergedContent)console.log(`已成功将${item}翻译为${outputFile}\n`)}
}await translateAndWrite()
console.log('本次需要翻译的总字数', allContent.join('').length)// 像视频类的标签需要手动修改回来