npm插件-i18n-autoinsert

1.自定义插件的初衷

最近在开发angularjs项目中使用到了国际化,例如html里有段是这样的

<h1 class="page-header" [translate]="'company.labelCompanyProfile'">Company Profile</h1>

translate会去en.json里找company.labelCompanyProfile的翻译,如果没有就直接显示Company Profile。
开发过程需要在en.json的配置文件里先定义好如下

{
  "company": {
    "labelCompanyProfile": "Company Profile"  
  }
}

每次碰到翻译的地方都要重复这个步骤,很烦人。我的想法是只需要关心html的编写,因为编写过程翻译和key都有了,是否有个命令批量将key和对应翻译给加入到en.json里,找了下没有想关的插件,于是就想自己定义一个。本篇记录开发过程,以及遇到的问题和解决方案。

2. i18n-autoinsert的开发过程记录
2.1 npm 插件开发很简单,可以参看自定义一个npm插件
2.2 安装commander插件
npm install commander
2.3 主要逻辑

index.js

#!/usr/bin/env node
var program = require('commander');
var fs = require("fs");
var path = require('path');
program
    .version('1.0.6')
    .option('-t, --translationFile [value]', 'tranFile')
    .option('-h, --htmlFile [value]', 'htmlFile')
    .option('-p, --htmlPath [value]', 'htmlPath')
    .option('-s, --showlog')
    .parse(process.argv);

var projectPath=path.join(__dirname,'../../');
if (!program.translationFile) {
    console.log('need specify -t for translationFile');
    process.exit(1);
}
if (!program.htmlFile && !program.htmlPath) {
    console.log('need specify -h for htmlFile or -p for htmlPath');
    process.exit(1);
}
//找到翻译文件
var enFile=path.join(projectPath,program.translationFile);
var htmlFiles=[];
//找出所有的html文件放到数组htmlFiles里
if(program.htmlFile) {
    var htmlFile = path.join(projectPath, program.htmlFile);
    htmlFiles.push(htmlFile);
}
if(program.htmlPath){
    var htmlPath=path.join(projectPath, program.htmlPath);
    addTargetFile(htmlPath,htmlFiles);
}
//循环htmlFiles加入翻译
htmlFiles.forEach(function(f){
    autoInsertTranslation(enFile,f);
});
console.info("done!")

function addTargetFile(htmlPath,htmlFiles){
    var files =fs.readdirSync(htmlPath);
    files.forEach( function (file){
            var f = path.join(htmlPath, file);
            if(file.indexOf(".html")!=-1||file.indexOf(".HTML")!=-1){
                htmlFiles.push(f);
            }else{
                var stats=fs.statSync(f);
                if(stats.isDirectory()){
                    addTargetFile(f,htmlFiles);
                }
            }
        });
}

function autoInsertTranslation(enFile,htmlFile) {
    if(program.showlog) {
        console.log("translation file : "+ enFile);
        console.log("html file : "+ htmlFile);
    }
    var data = fs.readFileSync(enFile);
    var tranJson = JSON.parse('{}');
    if(data.toString().trim().length!=0){
         tranJson = JSON.parse(data);
    }
    var data = fs.readFileSync(htmlFile);
   
   //正则表达式的匹配,例如
   //<input class="xxx" [translate]="'abc'">helloworld<input>
   var matches = data.toString().match(/\[translate\]=\"\'.*\'\"[\s\S]*?</gmi);
    for (var i in matches) {
        var str = matches[i];
       if((/\'(.*)\'\"[\s\S]*>([\s\S]*)</).test(str)) {
           if(RegExp.$1)
            addToJson(tranJson, RegExp.$1.trim(), RegExp.$2.trim());
       }
    }
    fs.writeFileSync(enFile, JSON.stringify(tranJson, null, '  '));
}
function addToJson(json,key,value){
    var keys=key.split("\.");
    var tmpJson=json;
    for( var j=0;j<keys.length-1;j++){
        if(!tmpJson[keys[j]]) {
            tmpJson[keys[j]] = {};
        }
        tmpJson=tmpJson[keys[j]];
    }
    //tmpJson must be a json,not a string
    if(typeof tmpJson==="object"){
        if(!tmpJson[keys[keys.length-1]])
            tmpJson[keys[keys.length-1]]=value;
    }else{
        console.error("ERROR:can't auto insert ["+key+"], because ["+key.substr(0,key.lastIndexOf("\."))+"] is not a json object in translation file," +
            "please check!!!")
    }

}
2.4 使用

插件发布好后

  1. npm install -save-dev i18n-autoinsert
  2. 在 package.json 里 script 加入
"scripts": {
...
"i18n-autoinsert": "i18n-autoinsert -t /src/assets/i18n/en.json -p /src/app/page/company/approval-groups/ --showlog"
...
}

-t 指定翻译文件,必须指定

-p 指定html的路径,程序会递归所有的子文件夹并找出html文件,-p和-h必须指定一个

-h 指定单个html路径,-p和-h必须指定一个

–showlog 可有可无,打印日志

  1. 运行
npm run i18n-autoinsert

不用头疼在en.json里一个个去写翻译

github代码

3.问题记录

npm install i i8n-autoinsert
生成出来的npm_module/.bin/i18n-autoinsert.cmd

@"%~dp0\..\i18n-autoinsert\index.js"   %*

而不是

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\..\i18n-autoinsert\index.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\..\i18n-autoinsert\index.js" %*
)

解决方式,需要在index.js加入

#!/usr/bin/env node
  1. 正则表达式匹配问题

碰到html是

<ng-template dbsTabTitle><span [translate]="'company.labelApprovalGroups'">Approval Groups</span></ng-template>

使用

var matches=data.toString().match(/\[translate\]=\"\'.*\'\">.*</gmi)

匹配到的是

[translate]="'company.labelApprovalGroups'">Approval Groups</span><

而不是想要的结果

[translate]="'company.labelApprovalGroups'">Approval Groups<

解决方式 : 使用非贪婪匹配模式,如下

/\[translate\]=\"\'.*\'\">.*?</gmi

而不是

/\[translate\]=\"\'.*\'\">.*<?/gmi
  1. 相对路径的获取
    在代码里要获取到index.js所在的路径可以使用
    __dirname

4.使用过程中发现下面的匹配不到

<h2 class="form-section-header" style="margin-top: 0px" [translate]="'company-group.create.step1.group.detail'">
        Step 1: Approval group details</h2>

原来的是

  var matches = data.toString().match(/\[translate\]=\"\'.*\'\">.*?</gmi);

解决方式

  var matches = data.toString().match(/\[translate\]=\"\'.*\'\">[\s\S]*?</gmi);

.不包含换行,[\s\S]则包含所有的字符

5.使用过程中发现下面的匹配不到,
>前多了个空格

<button (click)="createNewGroup()" [translate]="'labelCreateAnotherGroup'" >Create another Group</button>

<button  [translate]="'labelCreateAnotherGroup'" (click)="createNewGroup()" >Create another Group</button>

解决方式

 var matches = data.toString().match(/\[translate\]=\"\'.*\'\"[\s\S]*?</gmi);
    for (var i in matches) {
        var str = matches[i];
       if((/\'(.*)\'\"[\s\S]*>([\s\S]*)</).test(str)) {
           if(RegExp.$1)
            addToJson(tranJson, RegExp.$1.trim(), RegExp.$2.trim());
       }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值