使用 Node.js 处理 Excel 格式的多语言文件为 JS 版语言包

1,509 阅读3分钟

背景介绍

在做国际化时,运营或者产品往往会给到 Excel 版的多语言包,少则几个,多则十几个,而且经常会频繁的修改语言包的内容。而前端要根据 Excel 文件转成对应的 JSON 或者 JS 文件,手动处理显然是不现实的,一来费时费力,效率低下,二来容易出错,最重要的是不符合程序员的做事风格,机械的事情当然要交给机器去做了。

基础准备

  • Node.js 环境
  • node-xlsx 依赖包,一个强大的 Excel 文件处理库
  • Node.js API
    • fs.writeFile
    • fs.stat
    • fs.mkdir
    • util.inspect

测试数据

下面以一个示例文件开始代码编写

这是模拟的多语言 Excel 文件,注意第一列是根据最终语言包的格式自己添加上去的,第一行的表格头中 % 也是自己添加的,主要是用来生成对应的 JS 文件名

这是最终生成的 JS 文件

开始

初始化环境

创建一个文件夹并初始化 Node.js 项目,我这里创建了一个名为excel-to-js的文件夹。

npm init -y

安装 node-xlsx 依赖包

npm install node-xlsx --save

主代码逻辑

新建一个 JS 文件如 app.js,并添加如下代码

const fs = require('fs');
const path = require('path');
const util = require('util');
const xlsx = require('node-xlsx');

const sheets = xlsx.parse('./file/langes.xlsx');
/**
 * sheets是一个数组,数组中的每一项对应 langes.xlsx 这个文件里的多个表格
 * 如sheets[0]对应 Sheet1 这个表格
 * sheets[1]对应 Sheet2 这个表格
 */
const sheet = sheets[0]; // 我们这里只取第一个表
const filePath = './lang' // 多语言生成后会存放在此目录下

let obj = {}
const col = sheet['data'][0] // 表格中的第一行,用来获取多语言名称以生成对应的 js 文件

for (let j = 3; j < col.length; j++) {
    // sheet 是一个 json 对象,格式为{name:"Sheet1",data:[]},我们想要的数据就存储在data里
    let key = ''

    // i 对应 excel 文件里的行,根据自己的表格修改
    for (let i = 1; i < sheet["data"].length; i++) {
        let row = sheet['data'][i];

        if (row && row.length > 0) {
            let title = row[0].split('.')
            // 获取表格中的一级模块和二级模块
            if (title.length > 1) {
                key = title[0]
                key2 = title[1]
            } else {
                key2 = title[0]
            }

            !obj[key] && (obj[key] = {})

            obj[key][key2] = row[j]
        }
    }
    const fileName = col[j].split('%')[1]

    creatFile(obj, fileName)
}

/**
* 将数据写入文件
* @param {string} 要写入的内容
* @param {string} 要保存的文件名
*/
async function creatFile(con, name) {
    const str = 'export default '
    // con 中的内容如果不处理的话写入文件后会显示成 [object Object]
    const data = util.inspect(con, { showHidden: false, depth: null })
    const isExists = await getStat(filePath) // 判断路径是否存在
    if (!isExists) {
        await mkdir(filePath) // 创建文件目录
    }
    const file = path.join(filePath, name + '.js')
    fs.writeFile(file, str + data, (err) => {
        if (err) throw err;
        console.log(name + ' 保存成功!');
    });
}

/**
 * 判断目录是否存在
 *  @param {string} dir 目录
 */
function getStat(dir) {
    return new Promise((resolve, reject) => {
        fs.stat(dir, (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)
            }
        })
    })
}

在命令行中执行如下命令

node app.js

查看 lang 文件夹下是否生成对应的文件。

如果手动创建了多语言文件夹的话,上面代码中两个函数 getStatmkdir可以省略,然后修改 creatFile 函数为如下代码即可:

function creatFile(con, name) {
    const str = 'export default '
    // con 中的内容如果不处理的话写入文件后会显示成 [object Object]
    const data = util.inspect(con, { showHidden: false, depth: null })
    // 以下代码删除
    // const isExists = await getStat(filePath) // 判断路径是否存在
    // if (!isExists) {
    //     await mkdir(filePath) // 创建文件目录
    // }
    const file = path.join(filePath, name + '.js')
    fs.writeFile(file, str + data, (err) => {
        if (err) throw err;
        console.log(name + ' 保存成功!');
    });
}

代码仓库

github.com/hawuji/exce…

参考