This commit is contained in:
wxzhang 2022-02-22 17:38:45 +08:00
commit 1e4f95ad01
13 changed files with 2386 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/.vscode
/node_modules

20
demodata/a/a1.js Normal file
View File

@ -0,0 +1,20 @@
t("a1:aaaaa")
t('no aaaaa')
t("no aaaaa")
t('no aaaaa')
t('a1:bbbbb',a,b,c)
t("cccc Arrow Function",()=>{},c)
t("dddd中国",c)
t("eeeeee", )
t("x:from a")

20
demodata/a/a2.js Normal file
View File

@ -0,0 +1,20 @@
t("a2:aaaaa")
t('no erer')
t("no aaareraa")
t('no fdfd')
t('fdgfdgfdg',a,b,c)
t("cccc Arrow Function",()=>{},c)
t("ddddd中国",c)
t("eeeeee", )
t("x:from a")

16
demodata/b/b1.js Normal file
View File

@ -0,0 +1,16 @@
t("aaaaa")
t('bbbbb',a,b,c)
t("cccc",()=>{},c)
t("ddddd中国",()=>{},c)
t("eeeeee")
t("ddddd中国",()=>{},c)
t("x:from b")

9
demodata/c/c1.js Normal file
View File

@ -0,0 +1,9 @@
t("ccccc")
t('cccccdc')
t("x:from c",ddd)

20
demodata/c/c2.js Normal file
View File

@ -0,0 +1,20 @@
t("a2:aaaaa")
t('no erer')
t("no aaareraa")
t('no fdfd')
t('fdgfdgfdg',a,b,c)
t("cccc Arrow Function",()=>{},c)
t("ddddd中国",c)
t("eeeeee", )
t("x:from a")

14
demodata/index.js Normal file
View File

@ -0,0 +1,14 @@
t("aaaaa")
t('aaaaa1') t("aaaaa2") t('aaaaa 3')
t('bbbbb',a,b,c)
t("cccc",()=>{},c)
t("ddddd中国",()=>{},c)
t("eeeeee", )

View File

@ -0,0 +1,3 @@
export default {
"确定":"OK" // a/b/b1.js
}

17
package.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "voerka-i18n",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"extract": ""
},
"author": "",
"license": "ISC",
"dependencies": {
"deepmerge": "^4.2.2",
"gulp": "^4.0.2",
"through2": "^4.0.2"
}
}

2138
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

109
src/extract.plugin.js Normal file
View File

@ -0,0 +1,109 @@
/**
* 从源文件中提取要翻译的文本
*/
const through2 = require('through2')
const deepmerge = require("deepmerge")
// 捕获翻译函数的表达式
const DefaultTranslateMatcher = /\bt\(\s*("|'){1}(?:((?<namespace>\w+):))?(?<text>.*?)(((\1\s*\)){1})|((\1){1}\s*(,(\w|\d|(?:\{.*\})|(?:\[.*\])|([\"\'\(].*[\"\'\)]))*)*\s*\)))/gm
/**
* 找出要翻译的文本列表 {namespace:[text,text],...}
* {namespace:{text:[],...}
* @param {*} content
* @param {*} matcher
* @returns
*/
function getTranslateTexts(content,matcher,namespace,file){
if(!matcher) return
let texts = {default:{}}
while ((result = matcher.exec(content)) !== null) {
// 这对于避免零宽度匹配的无限循环是必要的
if (result.index === matcher.lastIndex) {
matcher.lastIndex++;
}
const text = result.groups.text
if(text){
const ns = result.groups.namespace || namespace
if(!(ns in texts)){
texts[ns] = {}
}
texts[ns][text] = [file.relative]
}
}
return texts
}
// 将texts合并到results中
function mergeTranslateTexts(results,texts){
}
// 获取指定文件的名称空间
/**
*
* @param {*} file
* @param {*} namespaces 名称空间配置 {<name>:[path,...,path],<name>:path,<name>:(file)=>{}}
*/
function getFileNamespace(file,options){
const {output, namespaces } = options
const refPath = file.relative.toLowerCase()
for(let [name,paths] of Object.entries(options.namespaces)){
if(typeof paths === "string"){
paths = [paths]
}
for(let path of paths){
if(refPath.startsWith(path.toLowerCase())){
return name
}
}
}
return "default"
}
module.exports = function(options={}){
options = Object.assign({
debug : true, // 输出调试信息
format : "js", // 目标文件格式取值JSON,JS
languages : ["en","zh"], // 目标语言列表
defaultLanguage: "zh", // 默认语言
matcher : DefaultTranslateMatcher, // 匹配翻译函数并提取内容的正则表达式
namespaces : {}, // 命名空间, {[name]: [path,...,path]}
output : null // 输出目录,如果没有指定,则转让
},options)
let {debug,output:outputPath,languages} = options
// 输出语言文件 {cn:{default:<文件>,namespace:<文件>},en:{default:{}}}
let outputFiles = languages.map(language=>{})
// 保存提交提取的文本 = {}
let results = {}
// file == vinyl实例
return through2.obj(function(file, encoding, callback){
if(!outputPath){
outputPath = path.join(file.base,"languages")
}
// 跳过空文件
if(file.isNull()){
return callback()
}
// 跳过流文件
if(file.isStream()){
return callback()
}
// 获取该文件的
const namespace = getFileNamespace(file,options)
if(debug) console.log(namespace," : ",file.path)
// 提出出翻译文件
const texts = getTranslateTexts(file.contents.toString(),options.matcher,namespace,file)
results = deepmerge(results,texts)
callback()
},function(callback){
console.log("输出路径:",outputPath)
console.log(JSON.stringify(results,null,2))
});
}

18
src/extract.test.js Normal file
View File

@ -0,0 +1,18 @@
const gulp = require('gulp');
const extract = require('./extract.plugin');
const path = require('path');
const soucePath = path.join(__dirname,'../demodata')
gulp.src([
soucePath+ '/**',
"!"+ soucePath+ '/languages/**'
]).pipe(extract({
// output: path.join(soucePath , 'languages'),
namespaces:{
"a":"a",
"b":"b",
}
}))
.pipe(gulp.dest(path.join(__dirname,'../demodata/languages')));

0
src/index.js Normal file
View File