UNPKG

ae-biu

Version:

Born For AE, Born To Do

230 lines (206 loc) 6.64 kB
#!/usr/bin/env node // @flow import program from 'commander' import chalk from 'chalk' import path from 'path' import fs from 'fs' import { promisify } from 'util' import sortObject from 'deep-sort-object' import flattern, { unflatten } from 'flat' import readDirRecursive from './utils/read-dir-recursive' /** * Help */ program.on('--help', () => { console.log() console.log(' Examples:') console.log() console.log(chalk.yellow(' # Get I18N data for all languages you defined in package.json')) console.log() console.log(chalk.blue(' $ ae i18n')) console.log() console.log(chalk.yellow(' # Get I18N data for specific language(s)')) console.log() console.log(chalk.blue(' $ ae i18n --lang zh-HK[,en-US]')) console.log() console.log(chalk.blue(' Tips: the first language you specific will be treated as default language')) }) /** * Usage */ program .usage('[--lang]') .option('-l, --lang [language]', 'Get I18N data for specific language') .option('-u, --no-flat', 'Unflatten I18N data') .parse(process.argv) // should flattern I18N data const flat = program.flat const handleError = (error: Error): void => { console.log() console.error(error) process.exit(1) } const handleFile = async (file: string): Promise<{[x: string]: string}> => { const temp = {} const contents = await promisify(fs.readFile)(file, 'utf8') // if you chose regexp to solve this problem // you have two problems now // find i18n expression const matched = contents.match(/__\((('|")(.(?!__\(('|")))+)\){1}/gm) if (matched) { matched.map(item => { // find i18n message key const key = item.match(/('.+?')|(".+?")/)[0].replace(/'|"/gm, '') // find i18n default message const msgMatched = item.match(/,\s?('|")(.+)('|")\)/) let defaultMsg if (msgMatched) { defaultMsg = msgMatched[2] } else { defaultMsg = key } temp[key] = defaultMsg }) } return temp } const run = async (): Promise<any> => { console.log() console.log(chalk.yellow('Let\'s start, sing L\'Internationale ~')) const start = Date.now() const pkgPath = path.resolve(process.cwd(), 'package.json') const srcDir = path.resolve(process.cwd(), 'src/modules') const staticDir = path.resolve(process.cwd(), 'src/static') try { await promisify(fs.access)(pkgPath) } catch (error) { console.error(chalk.red('Cannot find package.json, please check')) process.exit(0) } const lang = program.lang let languages = (lang && lang.split(',')) || [] languages = languages.map(lang => lang.trim()) if (!languages.length) { try { const pkgContent = await promisify(fs.readFile)(pkgPath) const pkg = JSON.parse(pkgContent) const { ae = {} } = pkg languages = ae.languages } catch (error) { handleError(error) } } console.log() console.log(chalk.yellow(`Your applied languages: ${chalk.red(languages.join(' '))}`)) try { await promisify(fs.access)(srcDir) } catch (error) { console.log() console.log(chalk.red('Cannot find source directory, do you under an AE project?')) handleError(error) } const files = await readDirRecursive(srcDir, '*.(jsx|js)') // find modules const modules = [] files.map(file => { if (/index\.jsx?$/.test(file)) { const moduleName = file.split('index')[0] modules.push(moduleName) } }) // sort by moduleName's length modules.sort((a, b) => b.length - a.length) // find i18n data const i18nData = {} await Promise.all(files.map(async (file) => { const data = await handleFile(file) i18nData[file] = data })) const handledFiles = new Set() const moduleData = {} // merge i18n data by module await Promise.all(modules.map(async module => { moduleData[module] = {} Object.keys(i18nData).map(file => { if (file.includes(module) && !handledFiles.has(file)) { moduleData[module] = { ...moduleData[module], ...i18nData[file] } handledFiles.add(file) } }) const baseLang = languages[0] let baseData = {} const i18nFile = path.resolve(module, `${baseLang}.json`) try { const fileContent = await promisify(fs.readFile)(i18nFile, 'utf8') baseData = JSON.parse(fileContent) } catch (error) { // not handled, just create a new file } // ensure current cover new baseData = { ...moduleData[module], ...baseData } // copy from base data, ensure some default data, such as error code can be added into new languages await Promise.all(languages.map(async (lang) => { let data = {} const i18nFile = path.resolve(module, `${lang}.json`) try { const fileContent = await promisify(fs.readFile)(i18nFile, 'utf8') data = JSON.parse(fileContent) } catch (error) { // not handled, just create a new file } // ensure current cover new data = { ...baseData, ...data } if (Object.keys(data).length) { const dataHandler = flat ? flattern : unflatten let content = JSON.stringify(dataHandler(sortObject(data)), null, 2) content += '\n' // add new line await promisify(fs.writeFile)(i18nFile, content) } })) })) const defaultModules = ['comp', 'fish', 'theme'] await Promise.all(defaultModules.map(async module => { const baseLang = languages[0] let baseData = {} try { const fileContent = await promisify(fs.readFile)(path.resolve(staticDir, 'locale', module, `${baseLang}.json`), 'utf8') baseData = JSON.parse(fileContent) } catch (error) { console.log() console.log(chalk.cyan('There is no default file in src/static, please check')) } await Promise.all(languages.map(async lang => { const file = path.resolve(staticDir, 'locale', module, `${lang}.json`) let data = {} try { const fileContent = await promisify(fs.readFile)(file, 'utf8') data = JSON.parse(fileContent) } catch (error) { // not handle, just create a new file } data = { ...baseData, ...data } if (Object.keys(data).length) { const dataHandler = flat ? flattern : unflatten let content = JSON.stringify(dataHandler(sortObject(data)), null, 2) content += '\n' // add new line await promisify(fs.writeFile)(file, content) } })) })) const time = (Date.now() - start) console.log() console.log(chalk.yellow(`Done in ${chalk.blue(time + 'ms')} !!!`)) } run()