NodeJs实现脚本:将xlxs文件输出到json文件中

文章目录

    • 前期工作和依赖
    • 笔记
    • 功能
    • 代码
    • 输出

最近有一个功能,将json文件里的内容抽取到一个xlxs中,然后维护xlxs文件。当要更新json文件时,就更新xlxs的内容并把它传回json中。这个脚本主要使用NodeJS写。

以下是完成此功能时做的一些笔记。

前期工作和依赖

js文件中要使用import,因此需要在package.json中设置:"type": "module"

依赖:

import xlsx from 'xlsx';
import path, { dirname } from 'node:path';
import fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import md5 from 'blueimp-md5';

相关文档:
API 参考 | SheetJS 中文网 (nodejs.cn)
xlsx - npm (npmjs.com)

笔记

获取此文件目录名:

const __dirname = dirname(fileURLToPath(import.meta.url));

组合文件名:

const outPath = path.join(__dirname, './fileName.xlsx');

读取一个目录下的所有文件名:

const files = fs.readdirSync(dirName);

读取一个文件:

const enJson = fs.readFileSync(fileName, 'utf8');

将二维数组转换为xlxs工作表:

const sheet = xlsx.utils.aoa_to_sheet(sheetData);

将工作表添加到工作簿:

xlsx.utils.book_append_sheet(workBook, sheet, sheetName);

将工作表输出到xlsx文件中:

xlsx.writeFile(workBook, outPath, { bookType: 'xlsx' });

将数组输出到xlxs:data是数组。

const sheet = xlsx.utils.json_to_sheet(data); //将 JS 对象数组转换为工作表
const workBook= xlsx.utils.book_new();// 创建一个工作簿对象
xlsx.utils.book_append_sheet(workBook, sheet, 'sheetName'); // 将工作表添加到工作簿:
xlsx.writeFile(workBook, path, {
  bookType: 'xlsx',
}); // 输出到xlsx

功能

维护一个xlsx文档,里面包含国际化的所有翻译,如下:第一行 为 语言

enkojafr
英文翻译韩文翻译日文翻译法文翻译

有英文json翻译文件如下:src/locales/en/fileName1.json

其中key值为i18n的标记,value值为对应的翻译。

{
    "inviter": "Inviter",
    "worth": "Worth ${{value}}",
    "countDownTips": "Rewards Countdown"
}

默认语言为英语,我们需要以它为例子生成对应的其他语言文件,如生成:src/locales/fr/fileName1.json

{
    "inviter": "法文翻译1",
    "worth": "法文翻译2",
    "countDownTips": "法文翻译3"
}

所有的翻译都在xlsx中。因此我们需要读取xlsx文件,遍历src/locales/en下的对应文件(参数pageNames),将对应翻译生成到对应文件夹。若无对应翻译,则用英文兜底。

中途使用md5加密后的en翻译为key,将对应xlsx文件中的翻译(那一行)保存到set中,是因为xlsx中没有i18n标记,只有各语言翻译

将xlsx翻译文件输出到locales/[language]/[fileName]的功能封装成一个函数,参数如下:

读入的en文件夹上级为pagePath
参数:
pageNames:要维护的文件名列表,如 invite 对应locale/en/invite
filePath:xlsx文件路径
pagePath:locale文件路径
option:选项,包括
- outputKey:输出为json的某一个key值的value,没有就不填 (这个功能的代码很死板,像是硬编码,需求如此,先写着!)
- languageArray:传入一个数组,包含要求的语言,没有就不填,会默认xlsx里的所有文件

参数填错了就会报错,这个代码的健壮性并不强,只是一个加快工作效率的工具 / 练手代码。 所以建议严格按照参数要求调用函数。不要做那种:“没有outputKey应该不传,但我就传个空串”,可能会报奇怪的错误!

代码

// 入口
import xlsx from "xlsx";
import md5 from "blueimp-md5";
import fs from "node:fs";
import path from "node:path";

// 删去前后空格 特判str为undefined
const trim = (str) => (str || "").replace(/^\s+|\s+$/g, "");

// 生成一个set,key是en的翻译,value是对应row
function transSheetToMap(sheetData) {
	const map = new Map();
	for (const row of sheetData) {
		const key = md5(trim(row.en));
		map.set(key, row); // 加密后en的value为key,整个row为value
	}
	return map;
}

/*
读入的en文件夹上级为pagePath

pageNames:要维护的文件名列表,如 invite 对应locale/en/invite 
filePath:xlsx文件路径
pagePath:locale文件路径
option:选项,包括
    - outputKey:输出为json的某一个key值的value,没有就不填
    - languageArray:传入一个数组,包含要求的语言缩写,没有就不填,会默认xlsx里的所有文件
*/
function xlsxToJson(pageNames, filePath, pagePath, option) {
	let outputKey = undefined;
	if (option.outputKey) {
		outputKey = option.outputKey;
	}

	const workBook = xlsx.readFile(filePath);
	const firstWorksheet = workBook.SheetNames[0]; // 全都放在第一个sheet中
	const sheet = workBook.Sheets[firstWorksheet];
	const sheetData = xlsx.utils.sheet_to_json(sheet); // 数组,每个项是对象,key为语言value为翻译
	const languages = option.languageArray
		? option.languageArray
		: Object.keys(sheetData[0]); // 所有语言

	const dictions = transSheetToMap(sheetData);

	for (const pageName of pageNames) {
		// 英文文件
		const pageEnJson = JSON.parse(
			fs.readFileSync(
				path.join(pagePath, "en", `${pageName}.json`),
				"utf8"
			)
		);

		// key 为 i18n标记
		const pageEnKeys = outputKey
			? Object.keys(pageEnJson[outputKey])
			: Object.keys(pageEnJson);

		for (const language of languages) {
			// 深拷贝英文样本
			const translatedJson = JSON.parse(JSON.stringify(pageEnJson));

			// translatedJson生成为对应语言,en兜底
			for (const key of pageEnKeys) {
				const translatedKey = outputKey
					? md5(trim(pageEnJson[outputKey][key]))
					: md5(trim(pageEnJson[key]));

				const translation = dictions.get(translatedKey);
				if (outputKey) {
					translatedJson[outputKey][key] =
						translation[language] || translation["en"];
				} else {
					translatedJson[key] =
						translation[language] || translation["en"];
				}
			}

			const filePath = path.join(pagePath, language, `${pageName}.json`);

			// 若文件夹不存在则创建
			if (!fs.existsSync(path.join(pagePath, language))) {
				fs.mkdirSync(path.join(pagePath, language));
			}

			fs.writeFileSync(filePath, JSON.stringify(translatedJson, null, 4));
		}
	}
}

export default xlsxToJson;
xlsxToJson(
	["invite", "player"],
	"C:/Users/somePath/i18n-all.xlsx",
	"C:/Users/somePath/locales",
	{
		outputKey: "key",
		languageArray: ["de"],
	}
);

输出

调用:要翻译的文件为invite,输出到json文件的key属性中,只翻译到de德文。

xlsxToJson(
	["invite"],
	"C:/Users/somePath/i18n-all.xlsx",
	"C:/Users/somePath/locales",
	{
		outputKey: "key",
		languageArray: ["de"],
	}
);

对应英文json如下:(有outputKey一定要填!没有的话一定不填!不然输出会很奇怪。)

// locales/en/invite.json
{
	"key": {
		"ogDesc": "Download Now!",
		"inviter": "Inviter"
	}
}

结果输出locales/de/invite.json

在这里插入图片描述

可能会封装一个npm包,可能会维护。笔记先写在这吧!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【第11章】SpringBoot实战篇之文章(下)含条件分页

文章目录 前言一、文章列表查询1. ArticleController2. ArticleService 二 、文章查询1. ArticleController2. ArticleService 三、文章更新1. ArticleController2. ArticleService 四、文章删除1. ArticleController2. ArticleService 五、文章列表查询(条件分页)1.ArticleCon…

离散数学---树

目录 1.基本概念及其相关运用 2.生成树 3.有向树 4.最优树 5.前缀码 1.基本概念及其相关运用 (1)无向树:连通而且没有回路的无向图就是无向树; 森林就是有多个连通分支,每个连通分支都是树的无连通的无向图&…

QGraphicsView实现简易地图20『鹰眼视图-全图显示』

前文链接:QGraphicsView实现简易地图19『迁徙图』 鹰眼视图-全图显示 能够显示所有已加载的瓦片地图,支持当前视口的范围显示器。鼠标在鹰眼视图上移动时,支持是否干预主视图地图加载两种模式,即移动时是否让主视图加载空白处的瓦…

揭秘800G以太网——简介

什么是800G以太网? 800G以太网是一种高带宽以太网标准,每秒可传输800 Gbps(千兆位每秒)的数据速率。它代表了以太网技术的又一进步,旨在满足不断增长的数据传输需求以及处理大量数据的能力。因此,800G以太…

翻译软件就用DT浏览器

翻译软件就用DT浏览器

【纯干货】深度学习各算法的优缺点和适用场景!建议收藏。(上篇)

. .纯 干 货 . 目录 前馈神经网络 1、梯度下降(Gradient Descent) 2、随机梯度下降(Stochastic Gradient Descent, SGD) 3、小批量梯度下降(Mini-batch Gradient Descent) 4、动量(Mo…

【CSS】opacity 父元素设置透明度影响子元素显示效果解决方案

<div class"father"><div class"children"></div> </div>.father{background:#000000,opacity:0.6 } 给父元素设置透明度时&#xff0c;子元素显示效果会搜到父元素透明度的影响&#xff0c;如下图 解决方法&#xff1a; .fathe…

【纯血鸿蒙】——响应式布局如何实现?

前面介绍了自适应布局&#xff0c;但是将窗口尺寸变化较大时&#xff0c;仅仅依靠自适应布局可能出现图片异常放大或页面内容稀疏、留白过多等问题。此时就需要借助响应式布局能力调整页面结构。 响应式布局 响应式布局是指页面内的元素可以根据特定的特征&#xff08;如窗口…

展厅设计中的不同区域划分

1、公共区域 公共区域一般来说是不受限制的区域&#xff0c;这种情况下&#xff0c;会使我们想到的区域是大厅、售卖区、视频播放等&#xff0c;这些公共区域的相关设施比较完善&#xff0c;只是需要普通的安全保护设施及警报设备即可。 2、展览区域 展览区域是参观者能够触及到…

【Car Guide.2】Basic Knowledge

文章目录 【History】【投诉榜】【油 VS 电】【三元锂 vs 磷酸铁锂】【本田、丰田、大众】飞度 【杂谈】 【History】 法国&#xff0c;标志&#xff0c;雪铁龙 美国&#xff0c;通用集团&#xff0c;有别克&#xff08;GL8)&#xff0c;凯迪拉克&#xff0c;雪佛兰&#xff…

Unity3d简单对话系统的实现——使用Dialogue editor完成对话系统

目录 前言 使用方法 1.下载dialogue editor 2.新建空物体 3.对对话内容进行编辑 4.对话画布建立 5.触发对话框代码 结束语 前言 今天是坚持写博客的第21天&#xff0c;很高兴自己可以坚持&#xff0c;也希望能与大家一起进步。我们今天来看unity3d当中的一个可以轻松实…

高通CSIPHY combo mode介绍

目录 使用MIPI Switch 使用高通平台CSIPHY的Combo Mode YYYY使用Combo Mode电路图如下: 如何设置combo PHY mode CSIInfo configuration when camera works in normal mode 平台SoC一般都有多个CSIPHY以满足当前手机相机设计多摄的情况,但是一款SoC CSIPHY的个数也是一定…

使用Aspose技术将Excel/Word转换为PDF

简介&#xff1a;本文将介绍如何使用Aspose技术将Excel文件转换为PDF格式。我们将使用Aspose-Cells-8.5.2.jar包&#xff0c;并演示Java代码以及进行测试。 一、Aspose技术概述 Aspose是一款强大的文档处理库&#xff0c;支持多种编程语言&#xff0c;如Java、C#、Python等。…

C++ | Leetcode C++题解之第137题只出现一次的数字II

题目&#xff1a; 题解&#xff1a; class Solution { public:int singleNumber(vector<int>& nums) {int a 0, b 0;for (int num: nums) {b ~a & (b ^ num);a ~b & (a ^ num);}return b;} };

融云:应用出海新增长引擎,GPT-4o 后的 AI 创新与用户运营

近日&#xff0c;融云与 TikTok、维卓联合在京举办了“十年出海&#xff0c;遇上 AI”私享会。 会上&#xff0c;融云解决方案架构师于洪达带来了《应用出海新增长引擎&#xff0c;AI 创新与用户精细化运营》主题分享&#xff0c;探讨在 AI 技术大潮下应用出海通过创新运营方式…

【C++进阶】深入STL之list:模拟实现深入理解List与迭代器

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;初步了解 list &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之list &#x1f4d2;1. list…

Java | Leetcode Java题解之第132题分割回文串II

题目&#xff1a; 题解&#xff1a; class Solution {public int minCut(String s) {int n s.length();boolean[][] g new boolean[n][n];for (int i 0; i < n; i) {Arrays.fill(g[i], true);}for (int i n - 1; i > 0; --i) {for (int j i 1; j < n; j) {g[i]…

nvm,node不是内部命令,npm版本不支持问题(曾经安装过nodejs)

nvm安装后nvm -v有效&#xff0c;node指令无效 环境变量配置无问题 推荐方案 下载你需要的node版本 Index of /dist/ (nodejs.org) 下载后解压到你的nvm存储版本的位置 cmd进入切换你的使用版本&#xff08;此时你的nodejs是从网上下载的&#xff0c;npm文件是存在的&…

基于SSM+Jsp的高校信息资源共享平台

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

lua vm 五: upvalue

前言 在 lua vm 中&#xff0c;upvalue 是一个重要的数据结构。upvalue 以一种高效的方式实现了词法作用域&#xff0c;使得函数能成为 lua 中的第一类值&#xff0c;也因其高效的设计&#xff0c;导致在实现上有点复杂。 函数 (proto) upvalue 构成了闭包&#xff08;closu…