Haven’t on the nuggets for a long time, have been busy with new business, don’t have the time (actually they know these are just excuses, is lazy), brought a small plugin again today, used to extract all i18n language text in the project and generate all languages translation file, if it can manually modify the translation interface turns bad, Plugin will not overwrite existing translation language, perfectly compatible with old project code, hope to improve some work efficiency, leave work early, hahaha.
background
Because all the new projects need to be bilingual in Chinese and English, my former colleagues wrote the language configuration in the Chinese and English language configuration files by writing them by themselves, such as this.$t(” project “). When the new requirements came down, my hands were almost broken. So I made a plug-in to automatically generate language configuration files, so it’s nice to leave work early.
Those who want to see the code go directly to the Pikaz-Translate repository
Train of thought
$t(“”),i18n.t(“”)), and then generate JSON files. And through the translation interface will be Chinese JSON file, translated into English JSON file, not much to say, on the code.
Recurse all files in the directory and extract the text
const path = require('path')
const fs = require('fs')
// node execution path
const dirPath = process.cwd()
// Json file key
const langKey = []
/ * * *@description: folder traversal *@param {content} Content/Folder path *@return {type}* /
const fileTra = (content) = > {
// Read the file according to the file path, return the file list
return new Promise((resolve, reject) = > {
fs.readdir(content, async function (err, files) {
if (err) {
console.warn(err)
reject(err)
} else {
// Iterate over the list of files read
for (let i = 0; i < files.length; i++) {
// Get the absolute path to the current file
const filedir = path.join(content, files[i])
// Obtain file information based on the file path
const isFile = await fileRead(filedir)
// If it is a folder, recursively traverse the files under that folder
if(! isFile) {await fileTra(filedir)
} else {
// Read the file
const fileContent = fs.readFileSync(filedir, 'utf-8')
// Extract i18N language text
const lang = getTranslateKey(fileContent)
lang.forEach((item) = > {
if (langKey.indexOf(item) === -1 || item === ' ') {
langKey.push(item)
}
})
}
}
resolve(files)
}
})
})
}
/ * * *@description: matches the contents of t(") or t("") *@param {type}
* @return {type}* /
const getTranslateKey = (source) = > {
let result = []
const reg = / ($| \ \.) t\((\'|\")([^\)\'\"]+)(\'|\")(,([^\)\'\"]+))? \)/gm
let matchKey
while ((matchKey = reg.exec(source))) {
result.push(matchKey[3])}return result
}
/ * * *@description: Determine whether it is a file or folder *@param {String} Filedir/File path *@return {type}* /
const fileRead = (filedir) = > {
return new Promise((resolve, reject) = > {
fs.stat(filedir, function (err, stats) {
if (err) {
console.warn('Obtaining file stats failed')
reject(err)
} else {
/ / file
const isFile = stats.isFile()
/ / folder
const isDir = stats.isDirectory()
if (isFile) {
resolve(true)}if (isDir) {
resolve(false}}})})}/ * * *@description: Translate Chinese JSON file into English JSON file *@param {String} En/Chinese language file path *@param {String} En/English language file path *@param {String} Lang/language type, default English *@return {type}* /
const pikazI18nTranslate = async (zh, en, lang = 'en') = > {const zhPath = path.join(dirPath, zh)
let zhJson = fs.readFileSync(zhPath, 'utf-8')
zhJson = zhJson ? JSON.parse(zhJson) : {}
const enPath = path.join(dirPath, en)
let enJson = fs.readFileSync(enPath, 'utf-8')
enJson = enJson ? JSON.parse(enJson) : {}
const key = []
Object.keys(zhJson).forEach((k) = > {
if (Object.keys(enJson).indexOf(k) === -1) {
key.push(k)
}
})
for (let i = 0; i < key.length; i++) {
const e = await translate(key[i], lang)
enJson[key[i]] = e
}
return new Promise((resolve, reject) = > {
const err = fs.writeFileSync(enPath, JSON.stringify(enJson), 'utf8')
if (err) {
reject(err)
}
resolve()
})
}
Copy the code
Translate the Chinese JSON file into English
const axios = require('axios')
/ * * *@description: Translation interface *@param {String} En/Translated text *@param {String} Lang/Translated language *@param {String} I/Number of requests, no more requests after three times *@return {type}* /
const translate = (zh, lang) = > {
return new Promise((resolve, reject) = > {
axios
.get('http://fanyi.youdao.com/translate', {
params: {
doctype: 'json'.type: lang,
i: zh,
},
})
.then(async (res) => {
resolve(res.data.translateResult[0] [0].tgt)
})
.catch((err) = > {
reject(err)
})
})
}
/ * * *@description: Translate Chinese JSON file into English JSON file *@param {String} En/Chinese language file path *@param {String} En/English language file path *@param {String} Lang/language type, default English *@return {type}* /
const pikazI18nTranslate = async (zh, en, lang = 'en') = > {const zhPath = path.join(dirPath, zh)
let zhJson = fs.readFileSync(zhPath, 'utf-8')
zhJson = zhJson ? JSON.parse(zhJson) : {}
const enPath = path.join(dirPath, en)
let enJson = fs.readFileSync(enPath, 'utf-8')
enJson = enJson ? JSON.parse(enJson) : {}
const key = []
Object.keys(zhJson).forEach((k) = > {
if (Object.keys(enJson).indexOf(k) === -1) {
key.push(k)
}
})
for (let i = 0; i < key.length; i++) {
const e = await translate(key[i], lang)
enJson[key[i]] = e
}
return new Promise((resolve, reject) = > {
const err = fs.writeFileSync(enPath, JSON.stringify(enJson), 'utf8')
if (err) {
reject(err)
}
resolve()
})
}
Copy the code
complete
The main logic looks like this, and there are a few points to note:
The first: The i18N language text in the project is better used in Chinese, such as this.$t(” use Chinese “), which is better semantic, but also more convenient to view the project and generate language configuration file, if the old project is used in English, don’t worry, just call the function pikazI18nLang to extract the text, Then write the corresponding Chinese and English, of course, will be more troublesome, but the old project, can only endure…
The second: Translation interface using the public interface, for the same IP request frequency limit, if a translation is not successful, can try to perform a second, or open proxy change their IP, of course, want to pursue a better translation quality, pay for the translation of the API is better, of course, this simple change on its own can fork translation function.
Quick tips
In the vscode editor, open the user fragment
Select New global snippet file with a filename such as i18N
Write to the fragment file
{
"Print to $t": {
"prefix": "t"."body": [
"$$t('$1')",]."description": "Log output to $t"}}Copy the code
$t(“) : $t(“) : $t(“) :
The effect
I18n text in the file in the target directory to be extracted
Call the plug-in function in a JS file
Execute the script file
Final effect:
Generated Chinese JSON file content
The content of the generated English JSON file
Complete project code
pikaz-translate
The plugin has been uploaded to NPM, and it’s easy to use with pikaz-Translate, complete documentation as always, and sample code.
The last
Tanabata, I wish you a happy Tanabata, single dog can only continue to coding, pleasure in pain, ha ha.