author linhuiw
 *  desc import * as path from 'path' ; import * as _ from 'lodash' ; import * as inquirer from 'inquirer' ; import * as fs from 'fs' ; import { PROJECT_CONFIG , KIWI_CONFIG_FILE } from './const' ; function lookForFiles ( dir , fileName ) { const files = fs . readdirSync ( dir ) ; for ( let file of files ) { const currName = path . join ( dir , file ) ; const info = fs . statSync ( currName ) ; if ( info . isDirectory ( ) ) { if ( file === '.git' || file === 'node_modules' ) { continue ; } const result = lookForFiles ( currName , fileName ) ; if ( result ) { return result ; } } else if ( info . isFile ( ) && file === fileName ) { return currName ; } } } /**
 * 获得项目配置信息
 */ function getProjectConfig ( ) { const configFile = path . resolve ( process . cwd ( ) , `./${ KIWI_CONFIG_FILE }` ) ; let obj = PROJECT_CONFIG . defaultConfig ; if ( configFile && fs . existsSync ( configFile ) ) { obj = { ... obj , ... JSON . parse ( fs . readFileSync ( configFile , 'utf8' ) ) } ; } return obj ; } /**
 * 获取语言资源的根目录
 */ function getKiwiDir ( ) { const config = getProjectConfig ( ) ; if ( config ) { return config . kiwiDir ; } } param lang function getLangDir ( lang ) { const langsDir = getKiwiDir ( ) ; return path . resolve ( langsDir , lang ) ; } /**
 * 深度优先遍历对象中的所有 string 属性，即文案
 */ function traverse ( obj , cb ) { function traverseInner ( obj , cb , path ) { _ . forEach ( obj , ( val , key ) => { if ( typeof val === 'string' ) { cb ( val , [ ... path , key ] . join ( '.' ) ) ; } else if ( typeof val === 'object' && val !== null ) { traverseInner ( val , cb , [ ... path , key ] ) ; } } ) ; } traverseInner ( obj , cb , [ ] ) ; } /**
 * 获取所有文案
 */ function getAllMessages ( lang , filter = ( message , key ) => true ) { const srcLangDir = getLangDir ( lang ) ; let files = fs . readdirSync ( srcLangDir ) ; files = files . filter ( file => file . endsWith ( '.ts' ) && file !== 'index.ts' ) . map ( file => path . resolve ( srcLangDir , file ) ) ; const allMessages = files . map ( file => { const { default : messages } = require ( file ) ; const fileNameWithoutExt = path . basename ( file ) . split ( '.' ) [ 0 ] ; const flattenedMessages = { } ; traverse ( messages , ( message , path ) => { const key = fileNameWithoutExt + '.' + path ; if ( filter ( message , key ) ) { flattenedMessages [ key ] = message ; } } ) ; return flattenedMessages ; } ) ; return Object . assign ( { } , ... allMessages ) ; } param asyncOperation param times function retry ( asyncOperation , times = 1 ) { let runTimes = 1 ; const handleReject = e => { if ( runTimes ++ < times ) { return asyncOperation ( ) . catch ( handleReject ) ; } else { throw e ; } } ; return asyncOperation ( ) . catch ( handleReject ) ; } param promise param ms function withTimeout ( promise , ms ) { const timeoutPromise = new Promise ( ( resolve , reject ) => { setTimeout ( ( ) => { reject ( `Promise timed out after ${ ms } ms.` ) ; } , ms ) ; } ) ; return Promise . race ( [ promise , timeoutPromise ] ) ; } /**
 * 使用google翻译
 */ function translateText ( text , toLang ) { const CONFIG = getProjectConfig ( ) ; const options = CONFIG . translateOptions ; const { translate : googleTranslate } = require ( 'google-translate' ) ( CONFIG . googleApiKey , options ) ; return withTimeout ( new Promise ( ( resolve , reject ) => { googleTranslate ( text , 'zh' , PROJECT_CONFIG . langMap [ toLang ] , ( err , translation ) => { if ( err ) { reject ( err ) ; } else { resolve ( translation . translatedText ) ; } } ) ; } ) , 5000 ) ; } function findMatchKey ( langObj , text ) { for ( const key in langObj ) { if ( langObj [ key ] === text ) { return key ; } } return null ; } function findMatchValue ( langObj , key ) { return langObj [ key ] ; } param obj param prefix function flatten ( obj , prefix = '' ) { var propName = prefix ? prefix + '.' : '' , ret = { } ; for ( var attr in obj ) { if ( _ . isArray ( obj [ attr ] ) ) { var len = obj [ attr ] . length ; ret [ attr ] = obj [ attr ] . join ( ',' ) ; } else if ( typeof obj [ attr ] === 'object' ) { _ . extend ( ret , flatten ( obj [ attr ] , propName + attr ) ) ; } else { ret [ propName + attr ] = obj [ attr ] ; } } return ret ; } /**
 * 获取翻译源类型
 */ async function getTranslateOriginType ( ) { const { googleApiKey , baiduApiKey } = getProjectConfig ( ) ; let translateType = [ 'Google' , 'Baidu' ] ; if ( ! googleApiKey ) { translateType = translateType . filter ( item => item !== 'Google' ) ; } if ( ! baiduApiKey || ! baiduApiKey . appId || ! baiduApiKey . appKey ) { translateType = translateType . filter ( item => item !== 'Baidu' ) ; } if ( translateType . length === 0 ) { console . log ( '请配置 googleApiKey 或 baiduApiKey ' ) ; return { pass : false , origin : '' } ; } if ( translateType . length == 1 ) { return { pass : true , origin : translateType [ 0 ] } ; } const { origin } = await inquirer . prompt ( { type : 'list' , name : 'origin' , message : '请选择使用的翻译源' , default : 'Google' , choices : [ 'Google' , 'Baidu' ] } ) ; return { pass : true , origin : origin } ; } export { getKiwiDir , getLangDir , traverse , retry , withTimeout , getAllMessages , getProjectConfig , translateText , findMatchKey , findMatchValue , flatten , lookForFiles , getTranslateOriginType } ;