# fe-crowdin v1

现有web项目接入crowdin。提供“一进一出”的翻译工作流。

```
┌────────┐    ┌─────────────┐      ┌─────────┐
│ source │ => │             │      │         │
└────────┘    │             │ push │         │
     ↓        │ fe-crowdin │ <==> │ Crowdin │
┌────────┐    │             │ pull │         │
│  i18n  │ <= │             │      │         │
└────────┘    └─────────────┘      └─────────┘
```

## 3.0.0 更新说明

更新后，在crowdin.bd.js中，需要注意几个配置项：
```javascript
// 使用 Crowdin API v2 
// 1 新创建的crowdin项目，id必填，project可选；
// 2 老项目升级，增加id配置项 
module.exports = {
id: 520558,                  // 新建crowdin项目时，从Tools => API 处获取。
project: 'global-primebox',  // crowdin项目名称
key: "",                     // crowdin api v1 key
...
...
}

```

## 说明

- key是待翻译的文字，由key组成的文件是key文件
- 使用`fe-crowdin`将key(按照指定规则编写)从源文件中提取出来并生成key文件
- 使用`fe-crowdin`将key文件提交到crowdin远端，由翻译人员进行翻译
- 使用`fe-crowdin`将提交的key的翻译拉回，并准备进行下一步的处理
- 每次提交一个文件，文件间彼此互不影响，但会去重key，默认使用当前源项目分支作为唯一文件名关联
- 执行翻译只是简单的将key替换为指定语言的指定翻译，很多时候需要将`fe-crowdin`的tranaslate()编织进某种流程中

## 开始使用

### 安装

`npm install @bd/fe-crowdin`

### CLI

> CLI执行完，没提示表示成功，失败有提示，看完整提示加`-l`参数

```
Usage: cli [options] [command]

[ BD CROWDIN WORKFLOW - 3.0.0-BETA.7 ]

Options:
  -v, --version           output the version number
  -h, --help              display help for command

Commands:
  pull [options]          sync and download translates
  push [options]          gkeys and push keys to remote
  status|st [options]     show translate status
  find|fd [options]       find which file contains the key
  diff|df                 view differents between remote
  gkeys|gk [options]      generate keys from files
  filter|fl [options]     过滤本项目用到的词条到config.filterOutputPath目录
  xlsx|xl [options]       指定keys.json生成xlsx文件
    -i,--input [mypath/keys/keys_xxx.json]  要生成excel的keys.json文件路径
    -o,--output [./keys_xxx.xlsx]           execl 输出的路径
  reset                   reset local state
  sync                    sync local to remote
  init                    initalize fe-crowdin
  translate|ts [options]  [experiment] translate source
  migrate|mig [options]   [experiment] merge and migrate form current to anohter
  help [command]          display help for command
```


### API

```
let main = require('fe-crowdin');
main.getTranslates('en-us').then(a=>{
    console.log(a);
});
main.getTranslate('en-us','key').then(a=>{
    console.log(a);
});
main.getKeys().then(a=>{
    console.log(a);
});
main.getStatus().then(a=>{
    console.log(a);
});
main.translate().then(()=>{});
main.sync().then(()=>{});
```

## Option

创建配置文件`crowdin.bd.js`放到项目根目录

```
{
    id: 520558,                                 //新建crowdin项目时，从Tools => API 处获取。
    project: 'global-primebox',                 //crowdin项目名称
    key: "",                                    //crowdin key 
	sourcePath: "",                             //源文件路径
	outputPath: "",                             //输入翻译路径，不填不输出，可以忽略
	filterOutputPath: '',                       //执行翻译后输入的目录(过滤本项目内的词条)
	longKeyPath: "",                            //长文本（大篇文章）所在目录，这个不能够提交到的crowdin，只能自己维护，但可以搭载fed-crowdin流程之中，减轻一点负担
	buildSourcePath: './src',                   //执行翻译读取的源目录
	buildOutputPath: './dist',                  //执行翻译后输入的目录
	gkeysPathIgnore: ['node_modules', '.git'],  //忽略源文件中的目录
	dingdingRobot: true,
	dingdingRobotScret: '',
	defaultLang: { lang: "en-us", exclude: ["zh-cn", "zh-hk", "ja-jp", "zh-tw"] },
	gkeysSuffix: [".ejs", ".html", '.vue'],
	departKeys: ["", "ENV", "unsafety_link", "tiny_amount_link", "---"],
	languageMap: {
		'en-us': {
			'crowdin': 'en-US',
			'LANG': 'en-us',
			'LANG_CODE': 'en',
			'LANG_AREA': 'us',
			'ROOT': '/',
			'ZENDESK_LANG': 'en-us'
		}
	},
	watch(hooker) {
		// hooker.hook('pull-end', ({ remote, util }) => {
		// 	return remote.getTranslateStatus('en-us').then(a => {
		// 		util.formatStatus(a.files);
		// 	});
		// });
	}
    =>
}
```

## 定制

`fe-crowdin`在流程中织入hook，可以在不同环节中参与功能定制

```
Hooker
    .hook('sync-start', () => {})
    .hook('sync-diff', ({ info: { add, remove, edit } }) => {})
    .hook('sync-remove-start', ({ file }) => {})
    .hook('sync-remove-end', ({ file, error }) => {})
    .hook('sync-add-start', ({ file }) => {})
    .hook('sync-add-end', ({ file, error }) => {})
    .hook('sync-edit-start', ({ file }) => {})
    .hook('sync-edit-end', ({ file, error }) => {})
    .hook('sync-end', ({ error }) => {});
    .hook('pull-start', () => {})
    .hook('translate-get-start', () => {})
    .hook('download-start', () => {})
    .hook('download-progress', ({ transferred, percent, total }) => {})
    .hook('download-end', ({ error }) => {})
    .hook('download-ignore', () => {})
    .hook('translate-get-end', ({ error }) => {})
    .hook('output-start', () => {})
    .hook('output-variable', ({ variable }) => { })
    .hook('output-translate', ({ fileName, lang, translate }) => { })
    .hook('output-end', ({ error }) => {})
    .hook('pull-end', ({ error }) => {});
    .hook('gkeys-start', () => {})
    .hook('gkeys-keys', ({ keys }) => {})
    .hook('gkeys-end', ({ error }) => {})
    .hook('push-start', () => {})
    .hook('push-keys', ({ add, remove }) => { })
    .hook('push-end', ({ add, remove, error }) => {});
    .hook('build-start', () => {})
    .hook('build-end', ({ error }) => {});
    .hook('uploadkey-start', ({ fileName }) => {})
    .hook('uploadkey-end', ({ fileName, error }) => {})
    .hook('uploadtranslate-start', ({ fileName, language }) => {})
    .hook('uploadtranslate-end', ({ fileName, language, error }) => {});
    .hook('getkey-start', ({ fileId, fileName }) => {})
    .hook('getkey-end', ({ fileId, error }) => {});
    .hook('dingding-start', () => {})
    .hook('dingding-message', ({ info: { branchName, taskName, project, userName, removeInfo, addInfo, comment, dingdingURL, message, tokit, config } }) => {})
    .hook('dingding-end', ({ error }) => {});
    .hook('status-start', () => {})
    .hook('status-end', () => {})
    .hook('status-error', e => {});
    .hook('translate-source-start', () => { })
    .hook('translate-source-progress', ({ progress, total, current }) => {})
    .hook('translate-source-end', ({ error }) => {})
    .hook('get-keys-from',({ content, path, suffix, keys }) => {}) 
    .hook('translate-source-file',({lang,translates,content,path,regex,defaultLang,sourcePath,outputs,config,util})=>{})
    .hook('transport-source-transport',({lang,path,defaultLang,sourcePath,outputPaths,config,util})=>{})
```

