This file should be used to agregate all external scripts we need.
Multiple flags can be used in the same call.
Available flags:
--env: Generates angular environment files.
--pre: Modifies 'angular.json' to enable the build of custom locales using
angular --localize.
Languages can be defined using the environment variable LANGS,
if no value is provided all languages will be build.
Default language is always build, even if not provided.
p.e.: 'LANGS="pt" node cd --pre', will build EN and PT.
For backward compatibility we accept both long and short version of
languages, p.e.: 'pt' and 'pt-BR'
--post: Restores 'angular.json' to its original.
Signed-off-by: Tiago Melo <tmelo@suse.com>
$TEMP_DIR/bin/nodeenv -p --node=12.16.2
cd src/pybind/mgr/dashboard/frontend
- DEFAULT_LANG=`jq -r .config.locale package.json`
- if [ -z "$DASHBOARD_FRONTEND_LANGS" ]; then
- BUILD_TARGET=":${DEFAULT_LANG}"
- else
- if [ "$DASHBOARD_FRONTEND_LANGS" == "ALL" ]; then
- BUILD_TARGET=":*"
- else
- DASHBOARD_FRONTEND_LANGS_LIST=`echo "$DASHBOARD_FRONTEND_LANGS" | sed 's/ /,/g'`
- if [[ $DASHBOARD_FRONTEND_LANGS_LIST != *"${DEFAULT_LANG}"* ]]; then
- # default language must be always built
- DASHBOARD_FRONTEND_LANGS_LIST="${DASHBOARD_FRONTEND_LANGS},${DEFAULT_LANG}"
- fi
- BUILD_TARGET=":{${DASHBOARD_FRONTEND_LANGS_LIST}}"
- fi
- fi
- # number of frontend languages to build in parallel - default to 1 to work
- # around https://tracker.ceph.com/issues/43152
- [ -z "$MAX_DASHBOARD_PARALLEL_BUILDS" ] && MAX_DASHBOARD_PARALLEL_BUILDS=1
-
. $TEMP_DIR/bin/activate
timeout 1h npm ci
- echo "Building ceph-dashboard frontend with build${BUILD_TARGET} script";
- # we need to use "-- --" because so that "--prod" survives accross all
+ echo "Building ceph-dashboard frontend with build:localize script";
+ # we need to use "--" because so that "--prod" survives accross all
# scripts redirections inside package.json
- npx npm-run-all --print-label --parallel --max-parallel $MAX_DASHBOARD_PARALLEL_BUILDS "build${BUILD_TARGET} -- -- --prod"
+ npm run build:localize -- --prod
deactivate
cd $CURR_DIR
rm -rf $TEMP_DIR
OUTPUT_VARIABLE default_lang
OUTPUT_STRIP_TRAILING_WHITESPACE)
-if(DASHBOARD_FRONTEND_LANGS)
- string(STRIP "${DASHBOARD_FRONTEND_LANGS}" DASHBOARD_FRONTEND_LANGS)
- if(DASHBOARD_FRONTEND_LANGS STREQUAL "ALL")
- set(build_target ":*")
- else()
- string(FIND "${DASHBOARD_FRONTEND_LANGS}" "${default_lang}" default_idx)
- if (default_idx EQUAL -1)
- # default language must be always built
- string(CONCAT DASHBOARD_FRONTEND_LANGS "${DASHBOARD_FRONTEND_LANGS}" ",${default_lang}")
- endif()
- set(build_target ":\{${DASHBOARD_FRONTEND_LANGS}\}")
- endif()
-else(DASHBOARD_FRONTEND_LANGS)
- set(build_target ":${default_lang}")
-endif(DASHBOARD_FRONTEND_LANGS)
-
if(NOT CMAKE_BUILD_TYPE STREQUAL Debug)
- set(npm_args "-- --prod --progress=false")
+ set(npm_args "--prod --progress=false")
else()
- set(npm_args "-- --progress=false")
+ set(npm_args "--progress=false")
endif()
add_npm_command(
OUTPUT "${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend/dist"
- COMMAND npx npm-run-all --print-label --parallel --max-parallel 2 "\"build${build_target} -- ${npm_args}\""
+ COMMAND npm run build:localize -- ${npm_args}
DEPENDS ${frontend_src} frontend/node_modules
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/frontend
COMMENT "dashboard frontend is being created"
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
- "deleteOutputPath": false,
"assets": [
"src/assets",
"src/favicon.ico",
"cs": {
"localize": ["cs"]
},
- "de-DE": {
+ "de": {
"localize": ["de"]
},
- "en-US": {
+ "en": {
"localize": ["en"]
},
- "es-ES": {
+ "es": {
"localize": ["es"]
},
- "fr-FR": {
+ "fr": {
"localize": ["fr"]
},
- "id-ID": {
+ "id": {
"localize": ["id"]
},
- "it-IT": {
+ "it": {
"localize": ["it"]
},
- "ja-JP": {
+ "ja": {
"localize": ["ja"]
},
- "ko-KR": {
+ "ko": {
"localize": ["ko"]
},
- "pl-PL": {
+ "pl": {
"localize": ["pl"]
},
- "pt-BR": {
+ "pt": {
"localize": ["pt"]
},
- "zh-CN": {
+ "zh-Hans": {
"localize": ["zh-Hans"]
},
- "zh-TW": {
+ "zh-Hant": {
"localize": ["zh-Hant"]
}
}
--- /dev/null
+/**
+ * Ceph Dashboard node script
+ * This file should be used to aggregate all external scripts we need.
+ * Multiple flags can be used in the same call.
+ *
+ * Available flags:
+ * --env: Generates angular environment files.
+ *
+ * --pre: Modifies 'angular.json' to enable the build of custom locales using
+ * angular --localize.
+ * Languages can be defined using the environment variable DASHBOARD_FRONTEND_LANGS,
+ * if no value is provided all languages will be build.
+ * Default language is always build, even if not provided.
+ * p.e.: 'DASHBOARD_FRONTEND_LANGS="pt" node cd --pre', will build EN and PT.
+ * For backward compatibility we accept both long and short version of
+ * languages, p.e.: 'pt' and 'pt-BR'
+ *
+ * --res: Restores 'angular.json' to its original and removes the backup file.
+ */
+
+const fs = require('fs');
+
+const filename = './angular.json';
+const backup = './angular.backup.json';
+
+if (process.argv.includes('--env')) {
+ envBuild();
+}
+
+if (process.argv.includes('--pre')) {
+ prepareLocales();
+}
+
+if (process.argv.includes('--res')) {
+ restoreLocales();
+}
+
+function prepareLocales() {
+ try {
+ fs.accessSync(backup, fs.constants.F_OK);
+ logger(`'${backup}' alread exists, restoring it into '${filename}'}`);
+ fs.copyFileSync(backup, filename);
+ } catch (err) {
+ fs.copyFileSync(filename, backup);
+ logger(`'${filename}' was copied to '${backup}'`);
+ }
+
+ let langs = process.env.DASHBOARD_FRONTEND_LANGS || '';
+ if (langs == 'ALL') {
+ logger(`Preparing build of all languages.`);
+ return;
+ } else if (langs.length == 0) {
+ langs = [];
+ logger(`Preparing build of EN.`);
+ } else {
+ langs = langs.split(/[ ,]/);
+ logger(`Preparing build of EN and ${langs}.`);
+ }
+
+ let angular = require(filename);
+
+ let allLocales = angular['projects']['ceph-dashboard']['i18n']['locales'];
+ let locales = {};
+
+ langs.forEach((lang) => {
+ const short = lang.substring(0, 2);
+ locale = allLocales[short];
+ if (locale) {
+ locales[short] = locale;
+ } else {
+ switch (lang) {
+ case 'zh-Hans':
+ case 'zh-CN':
+ locales['zh-Hans'] = allLocales['zh-Hans'];
+ break;
+
+ case 'zh-TW':
+ case 'zh-Hant':
+ locales['zh-Hant'] = allLocales['zh-Hant'];
+ break;
+ }
+ }
+ });
+
+ angular['projects']['ceph-dashboard']['i18n']['locales'] = locales;
+ const newAngular = JSON.stringify(angular, null, 2);
+
+ fs.writeFile(filename, newAngular, (err) => {
+ if (err) throw err;
+ logger(`Writing to ${filename}`);
+ });
+}
+
+function restoreLocales() {
+ fs.access(backup, fs.constants.F_OK, (err) => {
+ logger(`'${backup}' ${err ? 'does not exist' : 'exists'}`);
+
+ if (!err) {
+ fs.copyFile(backup, filename, (err) => {
+ if (err) throw err;
+ logger(`'${backup}' was copied to '${filename}'`);
+
+ fs.unlink(backup, (err) => {
+ if (err) throw err;
+ logger(`successfully deleted '${backup}'`);
+ });
+ });
+ }
+ });
+}
+
+function envBuild() {
+ origFile = 'src/environments/environment.tpl.ts';
+ devFile = 'src/environments/environment.ts';
+ prodFile = 'src/environments/environment.prod.ts';
+
+ const replacements = [
+ { from: '{DEFAULT_LANG}', to: process.env.npm_package_config_locale },
+ { from: '{COPYRIGHT_YEAR}', to: new Date().getFullYear() }
+ ];
+ let dev = replacements.concat([{ from: `'{PRODUCTION}'`, to: false }]);
+ let prod = replacements.concat([{ from: `'{PRODUCTION}'`, to: true }]);
+
+ fs.copyFile(origFile, devFile, (err) => {
+ if (err) throw err;
+ logger(`'${origFile}' was copied to '${devFile}'`);
+
+ replace(devFile, dev);
+ });
+
+ fs.copyFile(origFile, prodFile, (err) => {
+ if (err) throw err;
+ logger(`'${origFile}' was copied to '${prodFile}'`);
+
+ replace(prodFile, prod);
+ });
+}
+
+/**
+ * Replace strings in a file.
+ *
+ * @param {*} filename Relative path to the file
+ * @param {*} replacements List of replacements, each should have from' and 'to'
+ * proprieties.
+ */
+function replace(filename, replacements) {
+ fs.readFile(filename, 'utf8', (err, data) => {
+ if (err) throw err;
+
+ replacements.forEach((rep) => {
+ data = data.replace(rep.from, rep.to);
+ });
+
+ fs.writeFile(filename, data, 'utf8', (err) => {
+ if (err) throw err;
+ logger(`Placeholders were replace in '${filename}'`);
+ });
+ });
+}
+
+/**
+ * Writes logs to the console using the [cd.js] prefix
+ */
+function logger(message) {
+ console.log(`[cd.js] ${message}`);
+}
+++ /dev/null
-var replace = require('replace-in-file');
-var buildDate = new Date();
-var copyrightYear = buildDate.getFullYear();
-const optionsNewYear = {
- files:[
- 'src/environments/environment.ts',
- 'src/environments/environment.prod.ts'
- ],
- from: /{COPYRIGHT_YEAR}/g,
- to: copyrightYear,
- allowEmptyPaths: false,
-};
-
-const optionsOldYear = {
- files:[
- 'src/environments/environment.ts',
- 'src/environments/environment.prod.ts'
- ],
- from: /year: '(.*)'/g,
- to: "year: '{COPYRIGHT_YEAR}'",
- allowEmptyPaths: false,
-};
-
-const optionsNewProd = {
- files:[
- 'src/environments/environment.prod.ts'
- ],
- from: /'{PRODUCTION}'/g,
- to: true,
- allowEmptyPaths: false,
-};
-
-const optionsNewDev = {
- files:[
- 'src/environments/environment.ts'
- ],
- from: /'{PRODUCTION}'/g,
- to: false,
- allowEmptyPaths: false,
-};
-
-const optionsOldProd = {
- files:[
- 'src/environments/environment.prod.ts',
- 'src/environments/environment.ts'
- ],
- from: /production: (.*)/g,
- to: "production: '{PRODUCTION}',",
- allowEmptyPaths: false,
-};
-
-const optionsDefaultLang = {
- files: [
- 'src/environments/environment.prod.ts',
- 'src/environments/environment.ts'
- ],
- from: /'{DEFAULT_LANG}'/g,
- to: `'${process.env.npm_package_config_locale}'`,
- allowEmptyPaths: false
-}
-
-try {
- let changeOldYearFiles = replace.sync(optionsOldYear);
- let changeNewYearFiles = replace.sync(optionsNewYear);
- let changeOldProdFiles = replace.sync(optionsOldProd);
- let changeProdFiles = replace.sync(optionsNewProd);
- let changeDevFiles = replace.sync(optionsNewDev);
- let changeDefaultLangFiles = replace.sync(optionsDefaultLang);
- console.log('Environment variables have been set');
-}
-catch (error) {
- console.error('Error occurred:', error);
- throw error
-}
}
}
},
- "load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
- "dev": true
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- }
- }
- },
"loader-runner": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
"readable-stream": "^2.0.1"
}
},
- "memorystream": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
- "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
- "dev": true
- },
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
}
}
},
- "npm-run-all": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
- "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "chalk": "^2.4.1",
- "cross-spawn": "^6.0.5",
- "memorystream": "^0.3.1",
- "minimatch": "^3.0.4",
- "pidtree": "^0.3.0",
- "read-pkg": "^3.0.0",
- "shell-quote": "^1.6.1",
- "string.prototype.padend": "^3.0.0"
- },
- "dependencies": {
- "cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "dev": true,
- "requires": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
- "read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
- "dev": true,
- "requires": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- }
- }
- }
- },
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
- "pidtree": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
- "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
- "dev": true
- },
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
"dev": true
},
- "replace-in-file": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-5.0.2.tgz",
- "integrity": "sha512-1Vc7Sbr/rTuHgU1PZuBb7tGsFx3D4NKdhV4BpEF2MuN/6+SoXcFtx+dZ1Zz+5Dq4k5x9js87Y+gXQYPTQ9ppkA==",
- "dev": true,
- "requires": {
- "chalk": "^3.0.0",
- "glob": "^7.1.6",
- "yargs": "^15.0.2"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
- "dev": true,
- "requires": {
- "@types/color-name": "^1.1.1",
- "color-convert": "^2.0.1"
- }
- },
- "chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
- },
- "supports-color": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
- "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
},
- "shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
- "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
- "dev": true
- },
"shellwords": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
"strip-ansi": "^6.0.0"
}
},
- "string.prototype.padend": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz",
- "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1"
- }
- },
"string.prototype.trimend": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"version": "0.0.0",
"license": "MIT",
"config": {
- "locale": "en-US"
+ "locale": "en"
},
"scripts": {
"ng": "ng",
"start": "npm run env_build && ng serve --host 0.0.0.0",
- "build": "export _locale=${LOCALE:-$npm_package_config_locale}; ng build --configuration=${_locale}",
- "prebuild": "npm run env_build",
- "build:cs": "LOCALE=cs npm run build",
- "build:de-DE": "LOCALE=de-DE npm run build",
- "build:en-US": "LOCALE=en-US npm run build",
- "build:es-ES": "LOCALE=es-ES npm run build",
- "build:fr-FR": "LOCALE=fr-FR npm run build",
- "build:id-ID": "LOCALE=id-ID npm run build",
- "build:it-IT": "LOCALE=it-IT npm run build",
- "build:ja-JP": "LOCALE=ja-JP npm run build",
- "build:ko-KR": "LOCALE=ko-KR npm run build",
- "build:pl-PL": "LOCALE=pl-PL npm run build",
- "build:pt-BR": "LOCALE=pt-BR npm run build",
- "build:zh-CN": "LOCALE=zh-CN npm run build",
- "build:zh-TW": "LOCALE=zh-TW npm run build",
- "env_build": "cp src/environments/environment.tpl.ts src/environments/environment.prod.ts && cp src/environments/environment.tpl.ts src/environments/environment.ts && node ./environment.build.js",
+ "build": "npm run env_build & ng build --configuration=$npm_package_config_locale",
+ "build:localize": "node cd --env --pre && ng build --localize",
+ "postbuild:localize": "node cd --res",
+ "env_build": "node cd --env",
"i18n": "npm run i18n:extract && npm run i18n:push && npm run i18n:pull && npm run i18n:merge",
"i18n:extract": "ng xi18n --output-path locale --progress=false && ngx-extractor -i 'src/**/*.ts' -f xlf -o src/locale/messages.xlf -l en-US",
"i18n:push": "npx i18ntool push -c i18n.config.json",
"ng-bullet": "1.0.3",
"ng-mocks": "9.2.0",
"npm-force-resolutions": "0.0.3",
- "npm-run-all": "4.1.5",
"prettier": "2.0.5",
"pretty-quick": "2.0.1",
- "replace-in-file": "5.0.2",
"start-server-and-test": "1.11.0",
"transifex-i18ntool": "1.1.0",
"ts-node": "8.9.1",