UNPKG

@enplug/scripts

Version:
213 lines (189 loc) 8.31 kB
const axios = require('axios'); const chalk = require('chalk'); const fs = require('fs'); const inquirer = require('inquirer'); const loadDevPrivateFile = require('../loadDevPrivateFile'); const rootPath = __dirname.split('node_modules')[0]; const getPackageJson = require('../getPackageJson'); const { from, throwError } = require('rxjs'); const { catchError, switchMap, tap, filter } = require('rxjs/operators'); const HTTP_UNAUTHORIZED_STATUS_CODE = 401; const HTTP_NOT_FOUND_STATUS_CODE = 404; const CROWDIN_PROJECT_ID = '401630'; const CROWDIN_PROJECT_URL = `https://api.crowdin.com/api/v2/projects/${CROWDIN_PROJECT_ID}`; const CROWDIN_STORAGE_URL = `https://api.crowdin.com/api/v2/storages`; function getCrowdinCredentials() { try { let devPrivateFile; try { devPrivateFile = loadDevPrivateFile(rootPath); } catch { try { devPrivateFile = loadDevPrivateFile('../'); } catch { devPrivateFile = loadDevPrivateFile('../../'); } } if (!devPrivateFile.crowdinCredentials) { throw new Error('Crowdin credentials missing'); } return devPrivateFile.crowdinCredentials; } catch { console.error(chalk.bold.red('Could not fetch Crowdin credentials')); console.log(`Make sure that the ${chalk.bold.yellow('dev.private.json')} file contains ${chalk.bold.yellow('{ crowdinCredentials: { login, accountKey } }')}.`); throw new Error('Could not get Crowdin credentials'); } } function getCrowdinConfig() { const pkg = getPackageJson(); if (!pkg) { console.error(chalk.bold.red('Could not find package.json file')); throw new Error('Could not find package.json file'); } if (!pkg.config || !pkg.config.crowdin || !pkg.config.crowdin.crowdinPath || !pkg.config.crowdin.localPath) { console.error(chalk.bold.red('Could not find Crowdin config')); console.log(`Make sure that the ${chalk.bold.yellow('package.json')} file contains ${chalk.bold.yellow('{ config: { crowdin: crowdinPath, localPath } }')}.`); throw new Error('Could not get Crowdin config'); } return pkg.config.crowdin; } async function findCrowdinAppDirectoryId(credentials, crowdinPath, appName) { try { if(crowdinPath.startsWith('apps') || appName !== 'en.json') { // path is apps/{app-name}/... or dashboard/{data-connector or regions-map or uploader}/en.json const url = `${CROWDIN_PROJECT_URL}/directories?filter=${appName}`; const AuthStr = 'Bearer '.concat(credentials.token); const resp = await axios.get(url, { headers: { Authorization: AuthStr } }); const directory = resp.data.data.find(d => d.data.name === appName ); return directory ? directory.data.id : undefined; } else if((crowdinPath.startsWith('dashboard') || crowdinPath.startsWith('player-web') || crowdinPath.startsWith('components')) && appName === 'en.json') { //path is dashboard/en.json or player-web/en.json or components/en.json const url = `${CROWDIN_PROJECT_URL}/directories?filter=dashboard`; const AuthStr = 'Bearer '.concat(credentials.token); const resp = await axios.get(url, { headers: { Authorization: AuthStr } }); const directory = resp.data.data.find(d => d.data.name === 'dashboard' && d.data.title === 'Dashboard' && d.data.path === '/dashboard'); return directory ? directory.data.id : undefined; } } catch (err) { if (err.response.status === HTTP_UNAUTHORIZED_STATUS_CODE) { console.error(`\n${chalk.red.bold('Provided Crowdin token is invalid')}`); console.log(`Check the ${chalk.default.yellow('dev.private.json')} file.`); return throwError(err); } } } async function findCrowdinAppSubFolderId(credentials, directoryId, subfolderName) { const url = `${CROWDIN_PROJECT_URL}/directories?directoryId=${directoryId}`; const AuthStr = 'Bearer '.concat(credentials.token); const resp = await axios.get(url, { headers: { Authorization: AuthStr } }); const subdirectory = resp.data.data.find(d => d.data.name === subfolderName); return subdirectory ? subdirectory.data.id : undefined; } async function getFileIdIfExists(credentials, directoryId, fileName) { const url = `${CROWDIN_PROJECT_URL}/files?directoryId=${directoryId}`; const AuthStr = 'Bearer '.concat(credentials.token); const resp = await axios.get(url, { headers: { Authorization: AuthStr } }); const file = resp.data.data.find(d => d.data.name === fileName); return file ? file.data.id : undefined; } function postFileToCrowdin(credentials, localPath) { const AuthStr = 'Bearer '.concat(credentials.token); const file = fs.readFileSync(localPath); const url = `${CROWDIN_STORAGE_URL}`; return from(axios.post(url, file, { headers: { "Authorization": AuthStr, "Content-Type": 'application/json', "Crowdin-API-FileName": 'en.json' } })); } async function uploadFileToCrowdinStorage(credentials, localPath) { if (!fs.existsSync(localPath)) { console.error(`${chalk.red.bold('Local file does not exists')} ${chalk.yellow.bold(`[${localPath}]`)}`); throw new Error('Local file does not exist'); } return postFileToCrowdin(credentials, localPath).pipe( catchError(error => { console('ERROR could not upload file to crowdin storage') return throwError(error); }), ).toPromise(); } async function updateCrowdinFile(credentials, crowdinPath, storageId, fileId) { const url = `${CROWDIN_PROJECT_URL}/files/${fileId}`; const AuthStr = 'Bearer '.concat(credentials.token); const body = { "storageId": storageId, "updateOption": "keep_translations_and_approvals", "importOptions": { "contentSegmentation": false, "customSegmentation": false }, "exportOptions": { "exportPattern": "%locale%.json" }, "replaceModifiedContext": false } return from(axios.put(url, body, { headers: { Authorization: AuthStr } })).pipe(tap({ next: response => { if (response.data) { console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`); } else { console.error('Unexpected result'); console.log(response); } }, error: error => { console.error('\nUnexpected error:'); console.error(error); } })).toPromise(); } async function addCrowdinFile(credentials, crowdinPath, storageId, folderId) { const url = `${CROWDIN_PROJECT_URL}/files`; const AuthStr = 'Bearer '.concat(credentials.token); const body = { "storageId": storageId, "name": "en.json", "directoryId": folderId, "context": null, "type": "json", "parserVersion": 1, "importOptions": { "contentSegmentation": false, "customSegmentation": false }, "exportOptions": { "exportPattern": "%locale%.json" }, "excludedTargetLanguages": null } return from(axios.post(url, body, { headers: { Authorization: AuthStr } })).pipe(tap({ next: response => { if (response.data) { console.log(`${chalk.green.bold('Translations uploaded to Crowdin')} ${chalk.yellow.bold(`[${crowdinPath}]`)}`); } else { console.error('Unexpected result'); console.log(response); } }, error: error => { console.error('\nUnexpected error:'); console.error(error); } })).toPromise(); } function fetchFileFromCrowdin(credentials, language, fileId) { const url = `${CROWDIN_PROJECT_URL}/translations/exports`; const AuthStr = 'Bearer '.concat(credentials.token); const body = { "targetLanguageId": language, "fileIds": [fileId] }; return axios.post(url, body, { headers: { Authorization: AuthStr } }); } function readFakeTranslationsFile(url) { return axios.get(url); } function promptAddFile(crowdinPath) { const prompt = inquirer.createPromptModule(); return from(prompt({ type: 'confirm', name: 'addFileConfirm', message: `${chalk.reset('File')} ${chalk.yellow.bold(`[${crowdinPath}]`)} ${chalk.reset('does not exist in Crowdin repository.')}\nDo you want to add this file?`, })); } module.exports = { getCrowdinCredentials, getCrowdinConfig, findCrowdinAppDirectoryId, findCrowdinAppSubFolderId, getFileIdIfExists, uploadFileToCrowdinStorage, updateCrowdinFile, addCrowdinFile, fetchFileFromCrowdin, readFakeTranslationsFile };