一个简单的I18n-json文件字段校验脚本

283 阅读2分钟

背景

小团队进行多语言项目开发时,对于前端开发人员来说,可能会存在,边开发,边把语言文件交给产品去翻译,中间基本会产生较大差距(开发个新页面,加了许多新字段,但产品翻译的还是旧文件,这中间产生的误差,每次通过git文件校验,需要花费的精力过大),故经常会写些针对项目语言校验的小脚本来本地校验

主要解决的问题

以一个文件夹为基准,对比该文件夹,找出其它相对应的json文件,比较其中的缺少字段

文件结构

image.png

  • 先将index1.json,index2.json的内容都设置为
{
  "title1": "title1",
  "title2": "title2",
  "title3": {
    "content1": "content1",
    "content2": "content2",
    "content3": "content3",
    "content4": {
      "text1": "text1",
      "text2": "text2",
      "text3": "text3"
    }
  }
}
  • copy出其它语言,例如zhko

  • 随便删点其它文件的内容

    • zh/index1.jsontitle2title3.content2删除
    • ko/index1.jsontitle3.content4.text1删除
    • ko/index2.jsontitle3.content4title3.content3删除
  • 运行代码

image.png

上代码

// 引用模块
const fs = require('fs')
var path = require('path')


// 递归获取文件夹下所有文件
var walk = function (dir, done) {
  var results = []
  fs.readdir(dir, function (err, list) {
    if (err) return done(err)
    var i = 0
    ;(function next() {
      var file = list[i++]
      if (!file) return done(null, results)
      // file = path.resolve(dir, file);
      fs.stat(file, function (err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function (err, res) {
            results = results.concat(res)
            next()
          })
        } else {
          results.push(file)
          next()
        }
      })
    })()
  })
}

// 比较json对应字段
const checkLang = (lang, lang1, url) => {
  if (!lang1) {
    console.log(url, '不存在')
    return
  }
  for (const key in lang) {
    if (Object.hasOwnProperty.call(lang, key)) {
      const value = lang[key]
      if (typeof value != 'string') {
        checkLang(lang[key], lang1[key], `${url}.${key}`)
      } else if (!lang1[key]) {
        console.log(`${url}.${key}`, '不存在')
      }
    }
  }
}


const init = () => {
  const i18nPath = './src/i18n' // i18n 路径
  let paths = []
  let defaultPath = 'en' // 默认设置校验标准
  let defaultFiles = []
  let defaultJsons = []
  try {
    paths = fs.readdirSync(i18nPath).filter((i) => !i.includes('.')) // 读取文件夹,获取对应目录文件
    paths = paths.filter((i) => defaultPath != i).map((i) => path.resolve(i18nPath, i)) // 过滤掉标准路径且返回完整路径
  } catch (err) {
    console.error(`当前路径${path.resolve(i18nPath)}不存在`)
    return
  }
  walk(`${i18nPath}/${defaultPath}`, function (err, results) {
    if (err) throw err
    defaultFiles = results
    defaultJsons = results.map((i) => {
      try {
        const data = fs.readFileSync(`${i18nPath}/${defaultPath}/${i}`, 'utf8')
        return JSON.parse(data)
      } catch (error) {
        console.error(`${i18nPath}/${defaultPath}/${i} 文件读取失败`)
        return {}
      }
    })
    while (paths.length > 0) {
      const otherPath = paths.splice(0, 1)[0]
      defaultFiles.forEach((item, ind) => {
        let lang = {}
        try {
          lang = JSON.parse(fs.readFileSync(`${otherPath}/${item}`, 'utf8'))
        } catch (error) {
          console.error(`${otherPath}/${item} 文件读取失败`, error)
          return {}
        }
        checkLang(defaultJsons[ind], lang, `${otherPath}/${item} => `)
      })
    }
  })
}

// 运行脚本
init()