批量将本地N个英文Html文档进行中文翻译-源码篇

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总
游戏脚本-辅助自动化Android控件全解手册再战Android系列
Scratch编程案例软考全系列Unity3D学习专栏
蓝桥系列ChatGPT和AIGC

👉关于作者

专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎底部卡片私我,获取更多支持,交流让学习不再孤单

👉实践过程

const fs = require('fs')
const path = require('path')
const fanyi = require('./utils/fanyi')
const cache = require('./utils/cache')
const render = require('./render');
const tools = require('./tools')const translate =  (list, listIndex = 0) => {const listLen = list.lengthconsole.log(listIndex, '/', listLen);if (listIndex >= listLen) {console.log('完毕');return;}const suffix = tools.getFileSuffix(list[listIndex]);const jsonFile = list[listIndex].replace('.' + suffix, '.json')console.log('========正在翻译:', listIndex, '/', listLen, jsonFile);const texts = require(jsonFile)const total = texts.lengthconsole.log("总条数:", total);const writeFile = (data) => {fs.writeFileSync(jsonFile, JSON.stringify(data, null, 2));}const translation = async (index) => {if (index <= texts.length) {const current = texts[index - 1]const {origin, local} = currentif (local) {console.log(`${index}/${total} ${origin} 已翻译了-> ${local}`)translation(index + 1)return}const hasLocal = cache.get(origin)if (hasLocal) {current.local = hasLocalconsole.log(`${index}/${total} ${origin} 已缓存了-> ${hasLocal}`)writeFile(texts);translation(index + 1)} else {current.local = await fanyi(origin)cache.set(origin, current.local)writeFile(texts);setTimeout(() => {translation(index + 1)}, 1000)console.log(`${index}/${total} ${origin} API翻译-> ${current.local}`)}} else {console.log(`${index}/${total} 完成`)writeFile(texts);render(list[listIndex], jsonFile);translate(list, listIndex + 1);}}translation(1);
}const configTranslate = (filename)=>{try {const config = require(filename);for (val of config.translation){console.log("自定义译文",val.name,val.value);cache.set(val.name,val.value);}}catch (e) {console.log("自定义译文",e);}
}module.exports = {translate: translate,configTranslate,configTranslate
}

const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const getFileSuffix  = (filename)=>{const spl = filename.split(".");return spl[spl.length-1];
}//同步拷贝目录
const copyFolder = (copiedPath, resultPath) => {if (fs.existsSync(resultPath)) {fse.removeSync(resultPath)}fs.mkdirSync(resultPath);if (fs.existsSync(copiedPath)) {fse.copySync(copiedPath, resultPath)} else {console.log('这个目录不存在:', copiedPath);}
}//获取所有html或htm
const getList = (dir = '') =>{if (dir == "") {console.log('请输入目录');return;}let files = fs.readdirSync(dir);let list = [];files.forEach(async (item, index) => {let fPath = path.join(dir, item);let stat = fs.statSync(fPath);if (stat.isDirectory() === true) {let sublist = getList(fPath);sublist.forEach(file => {list.push(file);})}if (stat.isFile() === true) {if (fPath.slice(-4) == 'html' || fPath.slice(-3) == 'htm') {list.push(fPath);}}});return list;
}
module.exports = {getFileSuffix:getFileSuffix,getList:getList,copyFolder:copyFolder
}
const fs = require('fs')
const path = require('path')
const lodash = require('lodash')
const render = require('posthtml-render')
const html2texts = require('./utils/html2texts')module.exports = (htmlfile, jsonfile) => {const html = fs.readFileSync(htmlfile).toString()const texts = require(jsonfile)const { texts: originTexts, tree } = html2texts(html)originTexts.forEach((item, index) => {lodash.set(tree, item.paths, texts[index].local)})const newHtml = render(tree)try {fs.writeFileSync(htmlfile, newHtml)console.log('还原文件成功', htmlfile)}catch (e){console.log('还原文件失败', htmlfile)}
}
const fs = require('fs')
const path = require('path')
const html2texts = require('./utils/html2texts')
const tools = require('./tools')module.exports = (file) => {const filepath = file;const suffix = tools.getFileSuffix(filepath);const outpath = filepath.replace('.'+suffix, '.json')if(fs.existsSync(outpath)){return ;}const html = fs.readFileSync(filepath).toString()const { texts } = html2texts(html)const localTexts = texts.map(({ text }) => {return { origin: text, local: '' }})fs.writeFileSync(outpath, JSON.stringify(localTexts, null, 2));console.log("生成待翻译",outpath)return outpath;
}
#!/usr/bin/env node
const fs = require('fs')
const path = require('path');
const parse = require('./lib/parse');
const translate = require('./lib/translate');
const tools = require('./lib/tools');let dirname = process.argv[2]; //项目名
let fileIndex = process.argv[3] || 0; //从第几个开始
const config  = require( path.join(process.cwd(), 'config.json'));if(!config.appid || !config.secret){console.error("请配置appid and secret")return;
}
if(!dirname){console.error("请输入翻译文件夹 ");console.log('npm run [dirname]');console.log("-----------------------------------");console.log("请将项目文件放在本目录的html中");console.log("示例:");console.log("html/nodejs");console.log("html/php8");return;
}let dir = path.join(process.cwd(), 'html', dirname);//目标目录
let outDir = dir + '_zh_cn';if(!fs.existsSync(outDir)){tools.copyFolder(dir, outDir);
}
let list = tools.getList(outDir);
translate.configTranslate(dir+'/config.json')//生成json
list.forEach(file => {console.log('html',file)parse(file);
});
translate.translate(list,fileIndex);
const dayjs = require('dayjs')
const parser = require('posthtml-parser')module.exports = html => {const texts = []const tree = parser(html)const transform = (node, paths = '') => {const isStyle = node.tag === 'style'const isScript = node.tag === 'script'const isPre = node.tag === 'pre'const isCode = node.tag === 'code'if (isStyle || isScript || isCode || isPre) returnconst { placeholder } = node.attrs || {}const hasPlaceholder = !!placeholderif (hasPlaceholder) {transform(placeholder, `${paths}.attrs.placeholder`)return}const hasContent = !!node.contentif (hasContent) {node.content.forEach((item, index) => {transform(item, `${paths}.content[${index}]`)})return}const isString = typeof node === 'string'if (!isString) returnconst text = node.replace(/\s+/g, ' ').trim()const isEmpty = !textif (isEmpty) returnconst isDOCTYPE = !!text.match(/<!DOCTYPE/)const isDOCTYPE2 = !!text.match(/<!doctype/)const isComment = !!text.match(/<!--/)if (isDOCTYPE || isComment || isDOCTYPE2) returnconst isDate = dayjs(text).isValid()const isDivider = text === '|'if (isDate || isDivider) returntexts.push({ paths, text })}tree.forEach((item, index) => transform(item, `[${index}]`))return { tree, texts }
}

👉其他

📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/183283.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习笔记 - 3D数据的常见表示方式

一、简述 从单一角度而自动合成3D数据是人类视觉和大脑的基本功能,这对计算机视觉算法来说是比较难的。但随着LiDAR、RGB-D 相机(RealSense、Kinect)和3D扫描仪等3D传感器的普及和价格的降低,3D 采集技术的最新进展取得了巨大飞跃。与广泛使用的 2D 数据不同,3D 数据具有丰…

[node] Node.js 中Stream流

[node] Node.js 中Stream流 什么是 Stream流操作从流中读取数据写入流管道流链式流 什么是 Stream Stream 是一个抽象接口&#xff0c;Node 中有很多对象实现了这个接口。例如&#xff0c;对http 服务器发起请求的request 对象就是一个 Stream&#xff0c;还有stdout&#xff…

SCI的写作前提——认识论文的本质

论文可以被视为证据和支持性解释的集合&#xff1b;也就是说&#xff0c;试图说服他人分享你的结论 1.假设 在大纲中&#xff0c;一个示例研究程序可以如下进行。 ● 研究算法的研究人员可能会推测是否有可能更好地利用CPU上的缓存来降低计算成本。 ● 初步研究可能会导致这样…

(C++)复写零--双指针法

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

【500强 Kubernetes 课程】第4章 dockerfile基础篇-基本语法

【读书笔记-首页】基于世界500强的高薪实战Kubernetes课程 第4章 dockerfile基础篇-基本语法 dockerfile&#xff1a;构建镜像的文本文件 1、FROM 作用&#xff1a;基础镜像来源 2、MAINTAINER 作用&#xff1a;作者信息 3、RUN 作用&#xff1a;构建过程中运行的命令 …

Firewalld端口富规则——删除默认开放的服务

在Redhat8.6中&#xff0c;firewalld默认开放了ssh、cockpit、dhcpv6-client三个服务的端口富规则。如果想把默认开放的服务关掉可以执行下面的命令&#xff1a; firewall-cmd --permanent --remove-servicessh firewall-cmd --permanent --remove-servicecockpit firewall-cmd…

ESP32-Web-Server 实战编程- 使用 AJAX 自动更新网页内容

ESP32-Web-Server 实战编程- 使用 AJAX 自动更新网页内容 概述 什么是 AJAX &#xff1f; AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 AJAX 是一种用于创建快速动态网页的技术。 传统的网页&#xff08;不使用 AJAX&#…

PHP如何实现邮箱验证

在PHP中&#xff0c;提供了 mail() 函数用于发送邮件。使用该函数需要设置邮件头信息、收件人地址、邮件主题和邮件内容等参数。下面是一个简单的使用示例&#xff1a; $to 收件邮箱; $subject 邮件主题; $message 邮件内容; $from 发件邮箱; $headers "From: $from…

Linux 进程(一)

1 操作系统 概念&#xff1a;任何计算机系统都包含一个基本的程序集合&#xff0c;称为操作系统(OS)。笼统的理解&#xff0c;操作系统包括 内核&#xff08;进程管理&#xff0c;内存管理&#xff0c;文件管理&#xff0c;驱动管理&#xff09; 其他程序&#xff08;例…

linux安装docker(脚本一键安装配置docker)

1、创建脚本 vi initDocker.sh #安装前先更新yum&#xff0c;防止连接镜像失败 yum -y update#卸载系统之前的docker&#xff08;可选择&#xff0c;我这里直接注释了&#xff09; #yum remove docker docker-client docker-client-latest docker-common docker-latest docke…

Go 谈论了解Go语言

一、引言 Go的历史回顾 Go语言&#xff08;通常被称为Go或Golang&#xff09;由Robert Griesemer、Rob Pike和Ken Thompson在2007年开始设计&#xff0c;并于2009年正式公开发布。这三位设计者都曾在贝尔实验室工作&#xff0c;拥有丰富的编程语言和操作系统研究经验。Go的诞生…

android开发:子线程更新UI界面

多线程操作经常希望在子线程更新界面&#xff0c;这样方便调试&#xff0c;但是&#xff0c;但是经常这样做程序就不对劲了&#xff0c;为什么呢&#xff1f;因为为了保证界面流畅&#xff0c;不允许在非UI线程直接操作界面&#xff0c;只能通过一些专门途径进行。另外&#xf…

Wordpress自动定时发布怎么开通-Wordpress怎么自动发布原创文章

在当今数字化时代&#xff0c;博客已经成为许多人分享观点、经验和知识的重要平台。然而&#xff0c;对于博主们来说&#xff0c;每天按时发布一篇又一篇的文章可能是一项具有挑战性的任务。为了解决这个问题&#xff0c;一些创新的工具应运而生&#xff0c;其中包括WordPress的…

vuepress-----4、侧边栏

# 4、侧边栏 # 自动生成侧栏 如果你希望自动生成一个仅仅包含了当前页面标题&#xff08;headers&#xff09;链接的侧边栏&#xff0c;你可以通过 YAML front matter 来实现&#xff1a; --- sidebar: auto ---你也可以通过配置来在所有页面中启用它&#xff1a; // .vuep…

深入探索 Vue 响应式原理:数据驱动视图的奥秘

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Docker快速创建一个单机版的Jenkins实例

谈到 CI/CD&#xff0c;那便少不了这里面的佼佼者 Jenkins&#xff0c;正如 Jenkins 官网说的一样&#xff1a;“Build great things at any scale”&#xff0c;构建伟大&#xff0c;无所不能&#xff01; 话不多说&#xff0c;该篇文章将会带你使用 Docker 快速创建一个单机…

COGVLM论文解读(COGVLM:VISUAL EXPERT FOR LARGE LANGUAGE MODELS)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、摘要二、引言三、模型方法1、模型思路2、融合公式 四、训练方法总结 前言 2023年5月18日清华&智谱AI发布并开源VisualGLM-6B以来&#xff0c;清华KEG&…

C++多线程-传递普通变量,指针,引用给线程

注意点&#xff1a; 1、传递空间已销毁 2、多线程共享一块内存 3、传递的指针变量的生命周期小于线程 #include <iostream> #include <thread> #include <string> #include <unistd.h>using namespace std;class Para {public:Para(){cout<<…

Linux搭建FTP并安装xrdp,实现Windows系统下利用FileZilla传输文件和远程桌面连接

一、实现FTP文件传输 1、搭建FTP服务器&#xff1a; sudo apt-get install vsftpd sudo service vsftpd status 2、查看vsftpd是否正在运行&#xff0c;并监听21端口 netstat -npl | grep :21 or sudo service vsftpd status # 查看 vsftpd 服务状态 3、配置vsftpd.conf sud…

4.6-容器的端口映射

首先&#xff0c;我们来拉取Nginx的image镜像。 docker pull nginx 接下来我们创建一个Nginx的容器。 docker run --name nginx -d nginx 但是&#xff0c;这样启动nginx容器的话我们没法访问。这个时候怎么办呢&#xff1f;就需要将Nginx这个服务暴露给外面的世界。 这时可以使…