mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-05-31 14:11:58 +05:30
Reimplement the pull command of the crowdin script
This commit is contained in:
@ -3,7 +3,10 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import axios from 'axios';
|
||||
import JSON5 from 'json5';
|
||||
import CrowdinApi, { LanguageStatusNode, LanguageStatusResponse, ProjectInfoResponse } from 'crowdin-api';
|
||||
import { TranslationStatus, Translations, Credentials } from '@crowdin/crowdin-api-client';
|
||||
import MultiProgress from 'multi-progress';
|
||||
import ch from 'chalk';
|
||||
import iso639 from 'iso-639-1';
|
||||
@ -18,7 +21,9 @@ if (!config.crowdinApiKey) {
|
||||
process.exit(126);
|
||||
}
|
||||
|
||||
const PROJECT_ID = 'elyby';
|
||||
const ORGANIZATION_ID = 'elyby';
|
||||
const PROJECT_ID = 350687;
|
||||
const FILE_ID = 6;
|
||||
const PROJECT_KEY = config.crowdinApiKey;
|
||||
const CROWDIN_FILE_PATH = 'accounts/site.json';
|
||||
const SOURCE_LANG = 'en';
|
||||
@ -26,16 +31,22 @@ const LANG_DIR = path.resolve(`${__dirname}/../app/i18n`);
|
||||
const INDEX_FILE_NAME = 'index.js';
|
||||
const MIN_RELEASE_PROGRESS = 80; // Minimal ready percent before translation can be published
|
||||
|
||||
const credentials: Credentials = {
|
||||
token: config.crowdinApiKey,
|
||||
};
|
||||
const translationStatusApi = new TranslationStatus(credentials);
|
||||
const translationsApi = new Translations(credentials);
|
||||
|
||||
const crowdin = new CrowdinApi({
|
||||
apiKey: PROJECT_KEY,
|
||||
projectName: PROJECT_ID,
|
||||
projectName: ORGANIZATION_ID,
|
||||
});
|
||||
const progressBar = new MultiProgress();
|
||||
|
||||
/**
|
||||
* Locales that has been verified by core team members
|
||||
*/
|
||||
const RELEASED_LOCALES: Array<string> = ['be', 'fr', 'id', 'pt', 'ru', 'uk', 'vi', 'zh'];
|
||||
const releasedLocales: Array<string> = ['be', 'fr', 'id', 'pt', 'ru', 'uk', 'vi', 'zh'];
|
||||
|
||||
/**
|
||||
* Array of Crowdin locales to our internal locales representation
|
||||
@ -80,7 +91,7 @@ function toInternalLocale(code: string): string {
|
||||
* хранятся в самом приложении
|
||||
*/
|
||||
function serializeToModule(translates: Record<string, any>): string {
|
||||
const src = JSON.stringify(sortByKeys(translates), null, 2);
|
||||
const src = JSON5.stringify(sortByKeys(translates), null, 4);
|
||||
|
||||
return `module.exports = ${src};\n`;
|
||||
}
|
||||
@ -129,6 +140,70 @@ interface IndexFileEntry {
|
||||
isReleased: boolean;
|
||||
}
|
||||
|
||||
async function pullNew(): Promise<void> {
|
||||
console.log('Pulling translation progress...');
|
||||
const { data: translationProgress } = await translationStatusApi.getFileProgress(PROJECT_ID, FILE_ID, 100);
|
||||
|
||||
const localesToPull: Array<string> = [];
|
||||
const indexFileEntries: Record<string, IndexFileEntry> = {
|
||||
en: {
|
||||
code: 'en',
|
||||
name: 'English',
|
||||
englishName: 'English',
|
||||
progress: 100,
|
||||
isReleased: true,
|
||||
},
|
||||
};
|
||||
|
||||
translationProgress.forEach(({ data: { languageId, approvalProgress } }) => {
|
||||
const locale = toInternalLocale(languageId);
|
||||
if (releasedLocales.includes(locale) || approvalProgress >= MIN_RELEASE_PROGRESS) {
|
||||
localesToPull.push(languageId);
|
||||
indexFileEntries[locale] = {
|
||||
code: locale,
|
||||
name: NATIVE_NAMES_MAP[locale] || iso639.getNativeName(locale),
|
||||
englishName: ENGLISH_NAMES_MAP[locale] || iso639.getName(locale),
|
||||
progress: approvalProgress,
|
||||
isReleased: releasedLocales.includes(locale),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Add prefix 'c' to current and total to prevent filling thees placeholders with real values
|
||||
const downloadingProgressBar = progressBar.newBar('Downloading translates :bar :percent | :cCurrent/:total', {
|
||||
total: localesToPull.length,
|
||||
incomplete: '\u2591',
|
||||
complete: '\u2588',
|
||||
width: Object.keys(indexFileEntries).length - 1,
|
||||
});
|
||||
let downloadingReady = 0;
|
||||
|
||||
const promises = localesToPull.map(async (languageId): Promise<void> => {
|
||||
const { data: { url } } = await translationsApi.buildProjectFileTranslation(PROJECT_ID, FILE_ID, {
|
||||
targetLanguageId: languageId,
|
||||
exportApprovedOnly: true,
|
||||
});
|
||||
|
||||
const fileResponse = await axios.get(url, {
|
||||
// Disable response parsing
|
||||
transformResponse: [],
|
||||
});
|
||||
fs.writeFileSync(path.join(LANG_DIR, `${toInternalLocale(languageId)}.json`), fileResponse.data);
|
||||
|
||||
downloadingProgressBar.update(++downloadingReady / localesToPull, {
|
||||
cCurrent: downloadingReady,
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
console.log('Writing an index file');
|
||||
|
||||
fs.writeFileSync(path.join(LANG_DIR, INDEX_FILE_NAME), serializeToModule(indexFileEntries));
|
||||
|
||||
console.log(ch.green('The index file was successfully written'));
|
||||
}
|
||||
|
||||
async function pull() {
|
||||
console.log('Pulling locales list...');
|
||||
const locales = await pullLocales();
|
||||
@ -169,7 +244,7 @@ async function pull() {
|
||||
|
||||
const progress = (fileInfo.words_approved / fileInfo.words) * 100;
|
||||
|
||||
if (!RELEASED_LOCALES.includes(toInternalLocale(locale.code)) && progress < MIN_RELEASE_PROGRESS) {
|
||||
if (!releasedLocales.includes(toInternalLocale(locale.code)) && progress < MIN_RELEASE_PROGRESS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -196,7 +271,7 @@ async function pull() {
|
||||
|
||||
console.log('Locales are downloaded. Writing them to file system.');
|
||||
|
||||
const indexFileEntries: { [key: string]: IndexFileEntry } = {
|
||||
const indexFileEntries: Record<string, IndexFileEntry> = {
|
||||
en: {
|
||||
code: 'en',
|
||||
name: 'English',
|
||||
@ -223,7 +298,7 @@ async function pull() {
|
||||
name: NATIVE_NAMES_MAP[ourCode] || iso639.getNativeName(ourCode),
|
||||
englishName: ENGLISH_NAMES_MAP[ourCode] || name,
|
||||
progress: parseFloat(progress.toFixed(1)),
|
||||
isReleased: RELEASED_LOCALES.includes(ourCode),
|
||||
isReleased: releasedLocales.includes(ourCode),
|
||||
};
|
||||
|
||||
fs.copyFile(translatesFilePath, path.join(LANG_DIR, `${ourCode}.json`), 0, (err) => {
|
||||
@ -286,7 +361,7 @@ try {
|
||||
|
||||
switch (action) {
|
||||
case 'pull':
|
||||
pull();
|
||||
pullNew();
|
||||
break;
|
||||
case 'push':
|
||||
push();
|
||||
|
@ -11,15 +11,18 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/node": "^7.8.3",
|
||||
"@crowdin/crowdin-api-client": "^1.8.0",
|
||||
"@types/mkdirp": "^1.0.0",
|
||||
"@types/progress": "^2.0.3",
|
||||
"axios": "^0.19.2",
|
||||
"chalk": "^4.0.0",
|
||||
"crowdin-api": "^4.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"iso-639-1": "^2.1.3",
|
||||
"json5": "^2.1.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"multi-progress": "^2.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"prompt": "https://github.com/flatiron/prompt.git#master",
|
||||
"utility-types": "^3.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
Reference in New Issue
Block a user