前端國際化優(yōu)化方案

國際化一般都是使用 i18n 這個(gè)庫,在開發(fā)過程中需要對(duì)中英文兩個(gè)文件內(nèi)容中添加對(duì)應(yīng)中英文文本,業(yè)務(wù)代碼中使用可讀性差。通過下面的腳本可以實(shí)現(xiàn)1.業(yè)務(wù)代碼可以直接寫$t(中文)。2.不需要?jiǎng)?chuàng)建中英文件。最后只需要將最后生成的內(nèi)容放在自己項(xiàng)目對(duì)應(yīng)的國際化文件夾下并正確引入就可以了,每次提測(cè)前跑一邊腳本既可??梢允∪ズ芏囿w力工作,解放雙手

使用到的node內(nèi)置庫和方法

內(nèi)置庫:fs(操作文件) path(獲取路徑) crypto(加密解密)
fs.readdir 讀取目錄
fs.readFile 讀取指定文件的內(nèi)容
fs.stat 檢測(cè)是文件還是目錄
fs.writeFile 寫入文件
fs.rmdir:刪除目錄
fs.mkdir:創(chuàng)建目錄
fs.unlink:刪除文件

新增tool/readFlie.js(目的是掃描所有業(yè)務(wù)層代碼中的$t()包含的內(nèi)容,輸出成文件)

// fs.readdir 讀取目錄
// fs.readFile 讀取指定文件的內(nèi)容
// fs.stat 檢測(cè)是文件還是目錄
// fs.writeFile 寫入文件
// fs.rmdir:刪除目錄
// fs.mkdir:創(chuàng)建目錄
// fs.unlink:刪除文件
// xxx.isDirectory();//檢查目錄是否存在的方法
const fs = require('fs');
// 加載 path 模塊
const path = require('path');

// 給導(dǎo)出的對(duì)象key做轉(zhuǎn)化
const { encrypt } = require('./cryptolalia');

// 默認(rèn)讀取整個(gè)業(yè)務(wù)層文件的位置
const filename = path.resolve(__dirname, '../src');
// 默認(rèn)需要編譯的文件類型
const fileType = ["vue", "js"];
// 存放查找到的所有文件路徑
const fileList = [];
// 存放所有文案的集合
const texts = [];




/**
 * 
 * 執(zhí)行腳本
 * 
 */
createCatalogue();
/**
 * 
 * 創(chuàng)建i18n目錄
 * 
 */
function createCatalogue() {
    const i18nPath = path.resolve(__dirname, '../src/i18n');
    try {
        //檢查某個(gè)文件是否存在-不能拿到外面  因?yàn)殚_始沒有這層目錄statSync方法會(huì)拋異常
        const stat = fs.statSync(i18nPath);
        if (stat.isDirectory()) {
            const filePath = path.resolve(__dirname, '../src/i18n/zh.js');
            //如果可以執(zhí)行到這里那么就表示存在了
            // 存在此文件夾就刪除
            fs.unlink(filePath, (error) => {
                if (error) {
                    console.log('刪除文件失敗');
                }
                console.log('刪除文件成功');
                // 寫入的位置
                const outputFilePath = path.resolve(__dirname, '../src/i18n/zh.js');
                createFile(outputFilePath);
            });
        }
    } catch (e) {
        //捕獲異常
        console.log('檢查i18n文件夾不存在,創(chuàng)建新的文件夾');
        fs.mkdir(i18nPath, (err) => {
            if (err) {
                console.log('創(chuàng)建文件夾時(shí)出錯(cuò)')
            } else {
                console.log('創(chuàng)建文件成功')
                // 寫入的位置
                const outputFilePath = path.resolve(__dirname, '../src/i18n/zh.js');
                createFile(outputFilePath);
            }
        });
    }
}
/**
 * 
 * @param {輸出位置} outputPath 
 * 執(zhí)行生成文件
 * 
 */

function createFile(outputPath) {
    readDirRecur(filename, function () {
        const LENGTH = fileList.length;
        fileList.forEach(file => {
            // //讀取指定文件夾下的VUE和JS文件
            fs.readFile(file, "utf-8", function (err, data) {
                if (err) {
                    throw err;
                }
                // 匹配$t() 包裹的內(nèi)容
                const rge = /\$t\(.*?\)/g
                const array = data.match(rge);
                // 需要把每個(gè)文件內(nèi)掃描出符合規(guī)則的數(shù)組在合并到一個(gè)新數(shù)組中
                getText(LENGTH, array, function () {
                    const obj = {};
                    texts.forEach(item => {
                        const firstIndex = item.indexOf("(");
                        const lastIndex = item.lastIndexOf(")");
                        let text = item.substring(firstIndex + 2, lastIndex - 1);
                        // 這里需要使用加密算法包裹,這里沒有使用的時(shí)候自己加
                        const h = encrypt(text);
                        obj[h] = text;
                    })
                    // 寫入文件
                    fs.writeFile(outputPath, JSON.stringify(obj), function (err) {
                        if (err) {
                            return console.log('文件寫入失敗!' + err.message);
                        }
                        console.log("生成文件成功!");
                    });
                })
            })
        })
    })
}
/**
 * 
 * @param {*} fileList 
 * @param {*} array 
 * @param {*} callback 
 * 獲取所有文案
 */
let count = 0;
function getText(LENGTH, array, callback) {
    count++;
    if (array) {
        array.forEach(txt => {
            texts.push(txt)
        })
    }
    if (LENGTH === count) {
        callback();
    }
}
/**
 * 
 * @param {目錄位置} folder 
 * @param {所有文件查找成功的回調(diào)} callback 
 * 讀取指定文件 路徑,回調(diào)函數(shù)
 * 
 */
function readDirRecur(folder, callback) {
    // 讀取目錄
    fs.readdir(folder, function (err, files) {
        let count = 0;
        // 為了最后能執(zhí)行回調(diào)函數(shù)成功獲取到所有.*結(jié)尾的文件
        let checkEnd = function () {
            ++count == files.length && callback()
        }
        files.forEach(function (file) {
            const fullPath = path.resolve(__dirname, folder + '/' + file);
            // 檢測(cè)是文件還是目錄
            fs.stat(fullPath, function (err, stats) {
                if (stats.isDirectory()) {
                    return readDirRecur(fullPath, checkEnd);
                } else {
                    const suffix = file.split(".")[1];
                    if (fileType.includes(suffix)) {
                        fileList.push(fullPath)
                    }
                    checkEnd()
                }
            })
        })
        //為空時(shí)直接回調(diào)
        files.length === 0 && callback()
    })
}
新增tool/restore.js(目的是把生成好的中英文文件給轉(zhuǎn)換成正常的中文key)

// fs.readdir 讀取目錄
// fs.readFile 讀取指定文件的內(nèi)容
// fs.stat 檢測(cè)是文件還是目錄
// fs.writeFile 寫入文件
// fs.rmdir:刪除目錄
// fs.mkdir:創(chuàng)建目錄
// fs.unlink:刪除文件
// xxx.isDirectory();//檢查目錄是否存在的方法
const fs = require('fs');
// 加載 path 模塊
const path = require('path');

// 給導(dǎo)出的對(duì)象key做轉(zhuǎn)化
const { decrypt } = require('./cryptolalia');

/**
 * 
 * 執(zhí)行讀取腳本
 * 
 */
restoreFile();
/**
 * 
 * 讀取文件內(nèi)容并轉(zhuǎn)化
 * 
 */
function restoreFile() {
    const filePath = path.resolve(__dirname, '../src/i18n');
    // 讀取目錄
    fs.readdir(filePath, (err, files) => {
        if (err) {
            console.log('讀取目錄出現(xiàn)錯(cuò)誤,請(qǐng)先執(zhí)行npm run translate');
        } else {
            console.log('讀取目錄成功');
            files.forEach(file => {
                const fullPath = path.resolve(__dirname, filePath + '/' + file);
                fs.readFile(fullPath, "utf-8", (err, data) => {
                    if (err) {
                        console.log('讀取內(nèi)容出現(xiàn)錯(cuò)誤');
                    }
                    console.log('讀取內(nèi)容成功');
                    const object = JSON.parse(data);
                    const newObject = {};
                    for (const key in object) {
                        if (Object.hasOwnProperty.call(object, key)) {
                            const element = object[key];
                            const newKey = decrypt(key);
                            newObject[newKey] = element;
                        }
                    }
                    // 寫入文件
                    fs.writeFile(fullPath, JSON.stringify(newObject), function (err) {
                        if (err) {
                            return console.log('文件寫入失敗!' + err.message);
                        }
                        console.log("更新文件成功!");
                    });
                })
            })
        }
    })
}
新增tool/cryptolalia.js(加密文件沒什么好介紹的)
const CryptoJS = require("crypto");
// 加密
const encrypt = (content) => {
    const nameBuffer = Buffer.from(content); // 等同于 Buffer.from(name, "utf-8")
    const enecodedName = nameBuffer.toString("base64");
    return enecodedName
}
// 解密
const decrypt = (content) => {
    const decodeBuffer = Buffer.from(content, "base64"); // 第二個(gè)參數(shù)就不能省略了
    const decodedName = decodeBuffer.toString("utf-8");
    return decodedName
}

//暴露出去
module.exports = {
    encrypt,
    decrypt
};
腳本有了,使用方式如下

1.打開根目錄下package.json,增加兩行命令

"scripts": {
    "translate": "node ./tool/readFlie.js",
    "restore": "node ./tool/restore.js"
  },

2.執(zhí)行npm run translate 生成文件
3.找到src/i18n/zh.js,復(fù)制里面的內(nèi)容
4.將復(fù)制的內(nèi)容在谷歌翻譯中進(jìn)行機(jī)翻
5.在src/i18n文件夾中新建en.js
6.將機(jī)翻內(nèi)容粘貼進(jìn)去并保存
7.執(zhí)行npm run restore 還原內(nèi)容

此案例中使用的是VUE框架別的框架暫時(shí)還沒有嘗試,有興趣的同學(xué)可以嘗試一些別的框架。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容