分享一个React、或者Vue项目中实现i18n翻译的小工具

前言

目前有很多项目都会涉及国际化,来支持多语言环境。
例如:在React和Vue这两个最流行的框架中,最常使用的两套UI库:Ant Design、Element中都实现了国际化需求。而且,实现的方式相差不大,都是通过缓存对象的语言环境,然后读取对应的语言文件。eg:zh-cn.js,en.js...(当然也有zh-cn.json,en.json)。使用方式可以参考官网。

使用国际化的不方便

虽然国际化实现起来看似比较简单(当然确实也比较简单)。但是,在实际项目中,还是有比较麻烦的地方。

  • 突然感觉增加了好多需求啊,增加一句话,可能需要改动好几个文件。
  • 产品大大突然反悔了,运营大大觉得翻译不顺畅了,怎了吧,改翻译文件吧...

等等类似这样的情况

怎么解决呢?

推荐一套简单的翻译系统,在代码阶段只需要实现一到两套语言环境。剩下的,产品大大、运营大大你们说了算,你们说怎么翻译就怎么翻译吧(在合理的上线流程内)

使用方法

1.首先,按照惯例,贴两个文档,根据介绍(文档都是英文的),搭建需要环境:

一张很好的实现思路图(当然是盗图了)

2.在项目中使用统一引用方式,如:

  • {{$t('Turnover-Total')}}
  • 3.项目package.json中加入
    "scripts": {"i18n": "node --experimental-modules --loader ./build/custom-loader.mjs build/build-i18n.js"},

    4.build-i18n.js

    简易版(生成一份翻译文件)
    
    import i18n from '../src/assets/i18n/index-build.js
    import fs from 'fs'
    
    console.log('开始过滤翻译')
    
    for (let locale in i18n) {
      let data = i18n[locale]
    
      // 删除多余的 key
      for (let key in data) {
        if (data[key] !== '') {
          console.info(`删除已经翻译完成的: ${key}`)
          delete data[key]
        }
      } 
      
      // 输出翻译文件
      fs.writeFile(\`./src/assets/i18n/untranslate/${locale}.txt\`, JSON.stringify(data, Object.keys(data).sort(), 2) + '\n', err => {
        err && console.error(err)
      })
    }
    
    console.log('过滤完成')
    多文件版(生成对应文件目录下的翻译文件,并提取公共文件)
    // 翻译文件路径
    const jsPath = ['./webapp/pages/**/*/i18n/index.js']
    
    // 写入公共index.js
    jsPath.forEach(p => {
      glob.sync(p).forEach(p => {
        fs.writeFile(p, `${data}`, err => {
          err && console.error(err)
        })
      })
    })
    
    // 获取所有目录
    paths.forEach(p => {
      glob.sync(p).forEach(file => {
        let writepath = file.replace(/[^<>/\\\|:""\*\?]+\.\w+$/, '')
        if (directory.indexOf(writepath) === -1) {
          directory.push(writepath)
        }
      })
    })
    
    // 写入翻译文件
    function onParse(writepath) {
      for (let locale in i18n) {
        glob.sync(`${writepath}i18n/${locale}.json`).forEach(file => {
          ++allFile
          fs.readFile(file, { encoding: 'utf8' }, (err, data) => {
            if (err) {
              console.error(err)
              return
            }
            data = JSON.parse(data)
            for (let key in currentKeys) {
              if (!(key in data)) {
                locale === "en_US" || "zh_CN" ? data[key] = key : data[key] = ''
              }
            }
            
    // 删除多余的 key
    for (let key in data) {
      if (!(key in currentKeys)) {
        delete data[key]
      }
    }
    // 输出翻译文件
        fs.writeFileSync(`${writepath}i18n/${locale}.json`, JSON.stringify(data, Object.keys(data).sort(), 2) + '\n', err => {
          err && console.error(err)
        })
      })
    })
    }
    }
        
    // 统计所有key及个数
    function countCommonKeys() {
      jsonPath.forEach(p => {
        glob.sync(p).forEach(file => {
          ++jsonNumber
          fs.readFile(file, { encoding: 'utf8' }, (err, data) => {
            if (err) {
              console.error(err)
              return
            }
            data = JSON.parse(data)
            for (let key in data) {
              if (!(key in countKeys)) {
                countKeys[key] = 0
                // console.log(key)
              } else {
                // console.log(`---${key}---`)
                countKeys[key]++
              }
            }
    
    
            if (--jsonNumber === 0) {
              // console.log(countKeys)
              // getCommonKey()
            }
          })
        })
      })
    }
        
    // 提取公共翻译文件
    function getCommonKey() {
      for (let locale in i18n) {
        let common = {}
        [`./webapp/pages/**/*/i18n/${locale}.json`].forEach(p => {
          glob.sync(p).forEach(file => {
            fs.readFile(file, { encoding: 'utf8' }, (err, data) => {
              data = JSON.parse(data)
              for (let key in data) {
                if (countKeys[key] > 3) {
                  common[key] = data[key]
                  delete data[key]
                }
              }
            })
            fs.writeFile(file, JSON.stringify(data, Object.keys(data).sort(), 2) + '\n', { encoding: 'utf8' }, err => {
              err && console.error(err)
            })
          })
          fs.writeFile(`./webapp/assets/i18n/${locale}.json`, JSON.stringify(common, Object.keys(common).sort(), 2) + '\n', { encoding: 'utf8' }, err => {
            err && console.error(err)
          })
        })
      }
    }
    

    5.在服务器加入定时任务(执行间隔根据服务器性能)。

    怎么操作呢

    翻译系统长这样:
    分享一个React、或者Vue项目中实现i18n翻译的小工具_第1张图片

    然后就给各位产品、运营分配账号(谁的是谁的)
    让他们尽情翻译吧(当然是在开发流程当中了)
    自行选择对应的语言,查找主键key(可以使用中文或者英文作为主键key,不过还是建议中文作为key,因为翻译跟习惯的问题,减少因为重复带来的问题)

    你可能感兴趣的:(javascript,前端,node.js,i18n)