UNPKG

@singleton-i18n/angular-client

Version:

Singleton client code for Angular 10.

252 lines (213 loc) 7.6 kB
#!/usr/bin/env node /* * Copyright 2019-2021 VMware, Inc. * SPDX-License-Identifier: EPL-2.0 */ require('ts-node').register({ ignore: false, compilerOptions: {'module':'commonjs'} }); if (!process.env.DEBUG) { process.env.DEBUG = "app:log"; } let fs = require('fs'); let path = require('path'); let ArgumentParser = require('argparse').ArgumentParser; let TranslationService = require('./translation-service'); const generateToken = require('./generate-token.js'); let debug = require('debug'); let translationService; var log = debug('app:log'); log.log = console.log.bind(console); let parser = new ArgumentParser({ addHelp: true, description: 'Collect English source from LocalizedComponents' }); parser.addArgument( ['-s', '--source-dir'], { help: 'path to source directory where script will look for files ending in .l10n.ts', required: true, } ); parser.addArgument( ['-p', '--product'], { help: 'VIP product name', required: true, } ); parser.addArgument( ['-v', '--version'], { help: 'VIP product version', required: true, } ); parser.addArgument( ['-c', '--component'], { help: 'VIP product component, usually AngularJS2', required: true, } ); parser.addArgument( ['--host'], { help: 'VIP host', required: true, } ); parser.addArgument( ['-r', '--refresh-token'], { help: 'Refresh token for CSP', required: false, } ); let args = parser.parseArgs(); // When we import a TS file that imports Clarity Icons, we need to have // some shimming available to avoid a crash and a failure to collect the // English source for that TS file. require('html-element/global-shim'); global.HTMLElement = require('html-element').Element; document.cookie = ""; const walk = function (dir, done) { let results = []; fs.readdir(dir, function (err, list) { if (err) { log(err); return; } let i = 0; (function next() { let file = list[i++]; if (!file) return done(results); file = dir + '/' + file; fs.stat(file, (err, stat) => { if (stat && stat.isDirectory()) { walk(file, (res) => { results = results.concat(res); next(); }); } else if (err) { log(err); } else { results.push(file); next(); } }); })(); }); }; let OUT = {}; let KEYINFO = {}; function main() { walk(args.source_dir, (files) => { files.forEach(file => { if (file.match(/\.ts/)) { let component = fs.readFileSync(file, 'utf-8'); if (component) { // find l10n file let l10nFile = component.match(/import(?:.*)ENGLISH(?:.*)from *["'](.*)["']/); if (l10nFile) { let l10nFilePathMatched = l10nFile[1]; let l10nFilePath = path.resolve(path.dirname(file), l10nFilePathMatched + '.ts'); let ENGLISH = {}; try { ENGLISH = require(l10nFilePath.substring(0, l10nFilePath.length - 3)).ENGLISH; } catch (e) { log('failed to import ' + l10nFilePath, e); return; } // find l10n key let componentL10nKey = component.match(/L10nKey: ['"](.*)['"]/); if (componentL10nKey) { let key = componentL10nKey[1]; Object.keys(ENGLISH).forEach(k => { if (OUT[key + '.' + k]) { log(`-----------------------Detected Duplicate Keys-------------------------`); log(`KEY : '${key + '.' + k}'`); log(`PREFIX : '${key}'`); log(`SUFFIX-KEY : '${k}'`); log(`VALUE : '${ENGLISH[k]}'`); log(`PATH : '${l10nFilePath}'`); log(`---------Below Duplicate KEY:VALUE will replace above KEY:VALUE--------`); log(`DUP KEY : '${key + '.' + k}'`); log(`PREFIX : '${KEYINFO[key + '.' + k][0]}'`); log(`SUFFIX-KEY : '${KEYINFO[key + '.' + k][1]}'`); log(`VALUE : '${KEYINFO[key + '.' + k][2]}'`); log(`PATH : '${KEYINFO[key + '.' + k][3]}'`); log(`--------------------------------End-----------------------------------`); } let e = ENGLISH[k].trim(); OUT[key + '.' + k] = e; KEYINFO[key + '.' + k] = [key, k, ENGLISH[k], l10nFilePath]; }); } else { log('no key for ' + file); } } else { log('no l10n file for ' + file); } } else { log('no component for ' + file); } } }); function timer(ms) { return new Promise(res => setTimeout(res, ms)); } let todo = Object.keys(OUT); let waiting = []; let failed = []; let done = 0; let failedCount = 0; let run = true; async function collect() { while (run) { await timer(50); let k; if (todo.length) { k = todo.pop(); } else if (failed.length) { k = failed.pop(); } run = todo.length !== 0 || failed.length > 0 || waiting.length > 0; if (!k) { continue; } log(`collecting source for ${k}`); waiting.push(k); translationService.collectSource(k, OUT[k]).then(() => { log(`successfully collected source for ${k}`); waiting.pop(); done++; }, () => { log(`failed to collect source for ${k}`); failed.push(k); failedCount++; waiting.pop(); }); log(`Remaining: ${todo.length}, Failed: ${failed.length}, Pending: ${waiting.length}`); } log(`Collected ${done} strings, failed attempts: ${failedCount}`); }; collect(); }); } let tokenPromise = Promise.resolve(''); if (args.refresh_token) { tokenPromise = generateToken(args.host, args.refresh_token); } tokenPromise.then((token) => { translationService = new TranslationService( args.host, token, args.product, args.version, args.component); main(); }, (error) => { log('Failed to get token'); log(error); });