mirror of
https://github.com/elyby/accounts-frontend.git
synced 2025-05-31 14:11:58 +05:30
Change prettier rules
This commit is contained in:
@ -11,59 +11,53 @@ import webpackConfig from './../../webpack.dll.config';
|
||||
// @ts-ignore
|
||||
const compiler: MultiCompiler = webpack(webpackConfig);
|
||||
|
||||
Promise.all([
|
||||
stat(`${__dirname}/../../yarn.lock`),
|
||||
stat(`${__dirname}/../../dll/vendor.json`),
|
||||
])
|
||||
.then(([lockFileStats, dllFileStats]) => {
|
||||
const lockFile = new Date(lockFileStats.mtime);
|
||||
const dll = new Date(dllFileStats.mtime);
|
||||
Promise.all([stat(`${__dirname}/../../yarn.lock`), stat(`${__dirname}/../../dll/vendor.json`)])
|
||||
.then(([lockFileStats, dllFileStats]) => {
|
||||
const lockFile = new Date(lockFileStats.mtime);
|
||||
const dll = new Date(dllFileStats.mtime);
|
||||
|
||||
if (dll < lockFile) {
|
||||
return Promise.reject({
|
||||
code: 'OUTDATED',
|
||||
});
|
||||
}
|
||||
|
||||
logResult(chalk.green('Current dlls are up to date!'));
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.code !== 'ENOENT' && err.code !== 'OUTDATED') {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
console.log('Rebuilding dlls...');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
compiler.run((err, stats) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
if (dll < lockFile) {
|
||||
return Promise.reject({
|
||||
code: 'OUTDATED',
|
||||
});
|
||||
}
|
||||
|
||||
logResult(
|
||||
chalk.green('Dll was successfully build in %s ms'),
|
||||
stats.endTime! - stats.startTime!,
|
||||
);
|
||||
logResult(chalk.green('Current dlls are up to date!'));
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.code !== 'ENOENT' && err.code !== 'OUTDATED') {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
console.log('Rebuilding dlls...');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
compiler.run((err, stats) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
logResult(chalk.green('Dll was successfully build in %s ms'), stats.endTime! - stats.startTime!);
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
logResult(chalk.red('Unexpected error checking dll state'), err);
|
||||
process.exit(1);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
logResult(chalk.red('Unexpected error checking dll state'), err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
function logResult(...args: any[]): void {
|
||||
console.log('\n');
|
||||
console.log(...args);
|
||||
console.log('\n');
|
||||
console.log('\n');
|
||||
console.log(...args);
|
||||
console.log('\n');
|
||||
}
|
||||
|
||||
function stat(path: string): Promise<Stats> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(path, (err, stats) => {
|
||||
err ? reject(err) : resolve(stats);
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(path, (err, stats) => {
|
||||
err ? reject(err) : resolve(stats);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ const DEFAULT_LOCALE = 'en';
|
||||
const SUPPORTED_LANGS = [DEFAULT_LOCALE, ...Object.keys(localesMap)];
|
||||
|
||||
interface MessageDescriptor {
|
||||
id: string | number;
|
||||
defaultMessage: string;
|
||||
id: string | number;
|
||||
defaultMessage: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -26,31 +26,26 @@ interface MessageDescriptor {
|
||||
let idToFileMap: Record<string, Array<string>> = {};
|
||||
let duplicateIds: Array<string | number> = [];
|
||||
const collectedMessages = globSync(MESSAGES_PATTERN)
|
||||
.map<[string, Array<MessageDescriptor>]>((filename) => [
|
||||
filename,
|
||||
JSON.parse(fs.readFileSync(filename, 'utf8')),
|
||||
])
|
||||
.reduce<Record<string, string>>((collection, [file, descriptors]) => {
|
||||
descriptors.forEach(({ id, defaultMessage }) => {
|
||||
if (collection[id]) {
|
||||
duplicateIds.push(id);
|
||||
}
|
||||
.map<[string, Array<MessageDescriptor>]>((filename) => [filename, JSON.parse(fs.readFileSync(filename, 'utf8'))])
|
||||
.reduce<Record<string, string>>((collection, [file, descriptors]) => {
|
||||
descriptors.forEach(({ id, defaultMessage }) => {
|
||||
if (collection[id]) {
|
||||
duplicateIds.push(id);
|
||||
}
|
||||
|
||||
collection[id] = defaultMessage;
|
||||
idToFileMap[id] = (idToFileMap[id] || []).concat(file);
|
||||
});
|
||||
collection[id] = defaultMessage;
|
||||
idToFileMap[id] = (idToFileMap[id] || []).concat(file);
|
||||
});
|
||||
|
||||
return collection;
|
||||
}, {});
|
||||
return collection;
|
||||
}, {});
|
||||
|
||||
if (duplicateIds.length) {
|
||||
console.log('\nFound duplicated ids:');
|
||||
duplicateIds.forEach((id) =>
|
||||
console.log(`${chalk.yellow(id)}:\n - ${idToFileMap[id].join('\n - ')}\n`),
|
||||
);
|
||||
console.log(chalk.red('Please correct the errors above to proceed further!'));
|
||||
console.log('\nFound duplicated ids:');
|
||||
duplicateIds.forEach((id) => console.log(`${chalk.yellow(id)}:\n - ${idToFileMap[id].join('\n - ')}\n`));
|
||||
console.log(chalk.red('Please correct the errors above to proceed further!'));
|
||||
|
||||
process.exit(1);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
duplicateIds = [];
|
||||
@ -63,178 +58,136 @@ const defaultMessagesPath = `${LANG_DIR}/${DEFAULT_LOCALE}.json`;
|
||||
const isNotMarked = (value: string) => value.slice(0, 2) !== '--';
|
||||
|
||||
const prevMessages = readJSON<Record<string, string>>(defaultMessagesPath);
|
||||
const prevMessagesMap = Object.entries(prevMessages).reduce(
|
||||
(acc, [key, value]) => {
|
||||
const prevMessagesMap = Object.entries(prevMessages).reduce((acc, [key, value]) => {
|
||||
if (acc[value]) {
|
||||
acc[value].push(key);
|
||||
acc[value].push(key);
|
||||
} else {
|
||||
acc[value] = [key];
|
||||
acc[value] = [key];
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, Array<string>>,
|
||||
);
|
||||
}, {} as Record<string, Array<string>>);
|
||||
|
||||
const keysToAdd = Object.keys(collectedMessages).filter(
|
||||
(key) => !prevMessages[key],
|
||||
);
|
||||
const keysToAdd = Object.keys(collectedMessages).filter((key) => !prevMessages[key]);
|
||||
const keysToRemove: Array<string> = Object.keys(prevMessages)
|
||||
.filter((key) => !collectedMessages[key])
|
||||
.filter(isNotMarked);
|
||||
.filter((key) => !collectedMessages[key])
|
||||
.filter(isNotMarked);
|
||||
const keysToUpdate: Array<string> = Object.entries(prevMessages).reduce(
|
||||
(acc, [key, message]) =>
|
||||
acc.concat(
|
||||
collectedMessages[key] && collectedMessages[key] !== message ? key : [],
|
||||
),
|
||||
[] as Array<string>,
|
||||
(acc, [key, message]) => acc.concat(collectedMessages[key] && collectedMessages[key] !== message ? key : []),
|
||||
[] as Array<string>,
|
||||
);
|
||||
|
||||
const keysToRename: Array<[string, string]> = [];
|
||||
// detect keys to rename, mutating keysToAdd and keysToRemove
|
||||
[...keysToAdd].forEach((toKey) => {
|
||||
const keys = prevMessagesMap[collectedMessages[toKey]] || [];
|
||||
const fromKey = keys.find((key) => keysToRemove.indexOf(key) > -1);
|
||||
const keys = prevMessagesMap[collectedMessages[toKey]] || [];
|
||||
const fromKey = keys.find((key) => keysToRemove.indexOf(key) > -1);
|
||||
|
||||
if (fromKey) {
|
||||
keysToRename.push([fromKey, toKey]);
|
||||
keysToRemove.splice(keysToRemove.indexOf(fromKey), 1);
|
||||
keysToAdd.splice(keysToAdd.indexOf(toKey), 1);
|
||||
}
|
||||
if (fromKey) {
|
||||
keysToRename.push([fromKey, toKey]);
|
||||
keysToRemove.splice(keysToRemove.indexOf(fromKey), 1);
|
||||
keysToAdd.splice(keysToAdd.indexOf(toKey), 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (
|
||||
!keysToAdd.length &&
|
||||
!keysToRemove.length &&
|
||||
!keysToUpdate.length &&
|
||||
!keysToRename.length
|
||||
) {
|
||||
console.log(chalk.green('Everything is up to date!'));
|
||||
process.exit();
|
||||
if (!keysToAdd.length && !keysToRemove.length && !keysToUpdate.length && !keysToRename.length) {
|
||||
console.log(chalk.green('Everything is up to date!'));
|
||||
process.exit();
|
||||
}
|
||||
|
||||
console.log(
|
||||
chalk.magenta(`The diff relative to default locale (${DEFAULT_LOCALE}) is:`),
|
||||
);
|
||||
console.log(chalk.magenta(`The diff relative to default locale (${DEFAULT_LOCALE}) is:`));
|
||||
|
||||
if (keysToRemove.length) {
|
||||
console.log('The following keys will be removed:');
|
||||
console.log(
|
||||
[chalk.red('\n - '), keysToRemove.join(chalk.red('\n - ')), '\n'].join(''),
|
||||
);
|
||||
console.log('The following keys will be removed:');
|
||||
console.log([chalk.red('\n - '), keysToRemove.join(chalk.red('\n - ')), '\n'].join(''));
|
||||
}
|
||||
|
||||
if (keysToAdd.length) {
|
||||
console.log('The following keys will be added:');
|
||||
console.log(
|
||||
[chalk.green('\n + '), keysToAdd.join(chalk.green('\n + ')), '\n'].join(''),
|
||||
);
|
||||
console.log('The following keys will be added:');
|
||||
console.log([chalk.green('\n + '), keysToAdd.join(chalk.green('\n + ')), '\n'].join(''));
|
||||
}
|
||||
|
||||
if (keysToUpdate.length) {
|
||||
console.log('The following keys will be updated:');
|
||||
console.log(
|
||||
[
|
||||
chalk.yellow('\n @ '),
|
||||
keysToUpdate.join(chalk.yellow('\n @ ')),
|
||||
'\n',
|
||||
].join(''),
|
||||
);
|
||||
console.log('The following keys will be updated:');
|
||||
console.log([chalk.yellow('\n @ '), keysToUpdate.join(chalk.yellow('\n @ ')), '\n'].join(''));
|
||||
}
|
||||
|
||||
if (keysToRename.length) {
|
||||
console.log('The following keys will be renamed:\n');
|
||||
console.log(
|
||||
keysToRename.reduce(
|
||||
(str, pair) =>
|
||||
[str, pair[0], chalk.yellow(' -> '), pair[1], '\n'].join(''),
|
||||
'',
|
||||
),
|
||||
);
|
||||
console.log('The following keys will be renamed:\n');
|
||||
console.log(keysToRename.reduce((str, pair) => [str, pair[0], chalk.yellow(' -> '), pair[1], '\n'].join(''), ''));
|
||||
}
|
||||
|
||||
prompt.start();
|
||||
prompt.get(
|
||||
{
|
||||
properties: {
|
||||
apply: {
|
||||
description: 'Apply changes? [Y/n]',
|
||||
pattern: /^y|n$/i,
|
||||
message: 'Please enter "y" or "n"',
|
||||
default: 'y',
|
||||
before: (value) => value.toLowerCase() === 'y',
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
apply: {
|
||||
description: 'Apply changes? [Y/n]',
|
||||
pattern: /^y|n$/i,
|
||||
message: 'Please enter "y" or "n"',
|
||||
default: 'y',
|
||||
before: (value) => value.toLowerCase() === 'y',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
(err, resp) => {
|
||||
console.log('\n');
|
||||
(err, resp) => {
|
||||
console.log('\n');
|
||||
|
||||
if (err || !resp.apply) {
|
||||
return console.log(chalk.red('Aborted'));
|
||||
}
|
||||
if (err || !resp.apply) {
|
||||
return console.log(chalk.red('Aborted'));
|
||||
}
|
||||
|
||||
buildLocales();
|
||||
buildLocales();
|
||||
|
||||
console.log(chalk.green('All locales was successfuly built'));
|
||||
},
|
||||
console.log(chalk.green('All locales was successfuly built'));
|
||||
},
|
||||
);
|
||||
|
||||
function buildLocales() {
|
||||
mkdirpSync(LANG_DIR);
|
||||
mkdirpSync(LANG_DIR);
|
||||
|
||||
SUPPORTED_LANGS.map((lang) => {
|
||||
const destPath = `${LANG_DIR}/${lang}.json`;
|
||||
const newMessages = readJSON<Record<string, string>>(destPath);
|
||||
SUPPORTED_LANGS.map((lang) => {
|
||||
const destPath = `${LANG_DIR}/${lang}.json`;
|
||||
const newMessages = readJSON<Record<string, string>>(destPath);
|
||||
|
||||
keysToRename.forEach(([fromKey, toKey]) => {
|
||||
newMessages[toKey] = newMessages[fromKey];
|
||||
delete newMessages[fromKey];
|
||||
keysToRename.forEach(([fromKey, toKey]) => {
|
||||
newMessages[toKey] = newMessages[fromKey];
|
||||
delete newMessages[fromKey];
|
||||
});
|
||||
keysToRemove.forEach((key) => {
|
||||
delete newMessages[key];
|
||||
});
|
||||
keysToUpdate.forEach((key) => {
|
||||
newMessages[`--${key}`] = newMessages[key];
|
||||
newMessages[key] = collectedMessages[key];
|
||||
});
|
||||
keysToAdd.forEach((key) => {
|
||||
newMessages[key] = collectedMessages[key];
|
||||
});
|
||||
|
||||
const sortedKeys: Array<string> = Object.keys(newMessages).sort((key1, key2) => {
|
||||
key1 = key1.replace(/^-+/, '');
|
||||
key2 = key2.replace(/^-+/, '');
|
||||
|
||||
return key1 < key2 || !isNotMarked(key1) ? -1 : 1;
|
||||
});
|
||||
|
||||
const sortedNewMessages = sortedKeys.reduce<typeof newMessages>((acc, key) => {
|
||||
acc[key] = newMessages[key];
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
fs.writeFileSync(destPath, `${JSON.stringify(sortedNewMessages, null, 4)}\n`);
|
||||
});
|
||||
keysToRemove.forEach((key) => {
|
||||
delete newMessages[key];
|
||||
});
|
||||
keysToUpdate.forEach((key) => {
|
||||
newMessages[`--${key}`] = newMessages[key];
|
||||
newMessages[key] = collectedMessages[key];
|
||||
});
|
||||
keysToAdd.forEach((key) => {
|
||||
newMessages[key] = collectedMessages[key];
|
||||
});
|
||||
|
||||
const sortedKeys: Array<string> = Object.keys(newMessages).sort(
|
||||
(key1, key2) => {
|
||||
key1 = key1.replace(/^-+/, '');
|
||||
key2 = key2.replace(/^-+/, '');
|
||||
|
||||
return key1 < key2 || !isNotMarked(key1) ? -1 : 1;
|
||||
},
|
||||
);
|
||||
|
||||
const sortedNewMessages = sortedKeys.reduce<typeof newMessages>(
|
||||
(acc, key) => {
|
||||
acc[key] = newMessages[key];
|
||||
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
destPath,
|
||||
`${JSON.stringify(sortedNewMessages, null, 4)}\n`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function readJSON<T extends {}>(destPath: string): T {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(destPath, 'utf8'));
|
||||
} catch (err) {
|
||||
console.log(
|
||||
chalk.yellow(`Can't read ${destPath}. The new file will be created.`),
|
||||
`(${err.message})`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(destPath, 'utf8'));
|
||||
} catch (err) {
|
||||
console.log(chalk.yellow(`Can't read ${destPath}. The new file will be created.`), `(${err.message})`);
|
||||
}
|
||||
|
||||
return {} as T;
|
||||
return {} as T;
|
||||
}
|
||||
|
@ -3,11 +3,7 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import CrowdinApi, {
|
||||
LanguageStatusNode,
|
||||
LanguageStatusResponse,
|
||||
ProjectInfoResponse,
|
||||
} from 'crowdin-api';
|
||||
import CrowdinApi, { LanguageStatusNode, LanguageStatusResponse, ProjectInfoResponse } from 'crowdin-api';
|
||||
import MultiProgress from 'multi-progress';
|
||||
import ch from 'chalk';
|
||||
import iso639 from 'iso-639-1';
|
||||
@ -18,8 +14,8 @@ import { ValuesType } from 'utility-types';
|
||||
import config from '../../config';
|
||||
|
||||
if (!config.crowdinApiKey) {
|
||||
console.error(ch.red`crowdinApiKey is required`);
|
||||
process.exit(126);
|
||||
console.error(ch.red`crowdinApiKey is required`);
|
||||
process.exit(126);
|
||||
}
|
||||
|
||||
const PROJECT_ID = 'elyby';
|
||||
@ -31,61 +27,52 @@ const INDEX_FILE_NAME = 'index.js';
|
||||
const MIN_RELEASE_PROGRESS = 80; // Minimal ready percent before translation can be published
|
||||
|
||||
const crowdin = new CrowdinApi({
|
||||
apiKey: PROJECT_KEY,
|
||||
projectName: PROJECT_ID,
|
||||
apiKey: PROJECT_KEY,
|
||||
projectName: PROJECT_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 RELEASED_LOCALES: Array<string> = ['be', 'fr', 'id', 'pt', 'ru', 'uk', 'vi', 'zh'];
|
||||
|
||||
/**
|
||||
* Array of Crowdin locales to our internal locales representation
|
||||
*/
|
||||
const LOCALES_MAP: Record<string, string> = {
|
||||
'pt-BR': 'pt',
|
||||
'zh-CN': 'zh',
|
||||
'pt-BR': 'pt',
|
||||
'zh-CN': 'zh',
|
||||
};
|
||||
|
||||
/**
|
||||
* This array allows us to customise native languages names, because ISO-639-1 sometimes is strange
|
||||
*/
|
||||
const NATIVE_NAMES_MAP: Record<string, string> = {
|
||||
be: 'Беларуская',
|
||||
id: 'Bahasa Indonesia',
|
||||
lt: 'Lietuvių',
|
||||
pl: 'Polski',
|
||||
pt: 'Português do Brasil',
|
||||
sr: 'Српски',
|
||||
ro: 'Română',
|
||||
zh: '简体中文',
|
||||
be: 'Беларуская',
|
||||
id: 'Bahasa Indonesia',
|
||||
lt: 'Lietuvių',
|
||||
pl: 'Polski',
|
||||
pt: 'Português do Brasil',
|
||||
sr: 'Српски',
|
||||
ro: 'Română',
|
||||
zh: '简体中文',
|
||||
};
|
||||
|
||||
/**
|
||||
* This arrays allows us to override Crowdin English languages names
|
||||
*/
|
||||
const ENGLISH_NAMES_MAP: Record<string, string> = {
|
||||
pt: 'Portuguese, Brazilian',
|
||||
sr: 'Serbian',
|
||||
zh: 'Simplified Chinese',
|
||||
pt: 'Portuguese, Brazilian',
|
||||
sr: 'Serbian',
|
||||
zh: 'Simplified Chinese',
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts Crowdin's language code to our internal value
|
||||
*/
|
||||
function toInternalLocale(code: string): string {
|
||||
return LOCALES_MAP[code] || code;
|
||||
return LOCALES_MAP[code] || code;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,247 +80,220 @@ function toInternalLocale(code: string): string {
|
||||
* хранятся в самом приложении
|
||||
*/
|
||||
function serializeToModule(translates: Record<string, any>): string {
|
||||
const src = JSON.stringify(sortByKeys(translates), null, 2);
|
||||
const src = JSON.stringify(sortByKeys(translates), null, 2);
|
||||
|
||||
return `module.exports = ${src};\n`;
|
||||
return `module.exports = ${src};\n`;
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/a/29622653/5184751
|
||||
function sortByKeys<T extends Record<string, any>>(object: T): T {
|
||||
return Object.keys(object)
|
||||
.sort()
|
||||
.reduce((result, key) => {
|
||||
// @ts-ignore
|
||||
result[key] = object[key];
|
||||
return Object.keys(object)
|
||||
.sort()
|
||||
.reduce((result, key) => {
|
||||
// @ts-ignore
|
||||
result[key] = object[key];
|
||||
|
||||
return result;
|
||||
}, {} as T);
|
||||
return result;
|
||||
}, {} as T);
|
||||
}
|
||||
|
||||
async function pullLocales(): Promise<ProjectInfoResponse['languages']> {
|
||||
const { languages } = await crowdin.projectInfo();
|
||||
const { languages } = await crowdin.projectInfo();
|
||||
|
||||
return languages;
|
||||
return languages;
|
||||
}
|
||||
|
||||
function findFile(
|
||||
root: LanguageStatusResponse['files'],
|
||||
path: string,
|
||||
): LanguageStatusNode | null {
|
||||
const [nodeToSearch, ...rest] = path.split('/');
|
||||
function findFile(root: LanguageStatusResponse['files'], path: string): LanguageStatusNode | null {
|
||||
const [nodeToSearch, ...rest] = path.split('/');
|
||||
|
||||
for (const node of root) {
|
||||
if (node.name !== nodeToSearch) {
|
||||
continue;
|
||||
for (const node of root) {
|
||||
if (node.name !== nodeToSearch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rest.length === 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return findFile(node.files, rest.join('/'));
|
||||
}
|
||||
|
||||
if (rest.length === 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return findFile(node.files, rest.join('/'));
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
interface IndexFileEntry {
|
||||
code: string;
|
||||
name: string;
|
||||
englishName: string;
|
||||
progress: number;
|
||||
isReleased: boolean;
|
||||
code: string;
|
||||
name: string;
|
||||
englishName: string;
|
||||
progress: number;
|
||||
isReleased: boolean;
|
||||
}
|
||||
|
||||
async function pull() {
|
||||
console.log('Pulling locales list...');
|
||||
const locales = await pullLocales();
|
||||
const checkingProgressBar = progressBar.newBar(
|
||||
'| Pulling locales info :bar :percent | :current/:total',
|
||||
{
|
||||
total: locales.length,
|
||||
incomplete: '\u2591',
|
||||
complete: '\u2588',
|
||||
width: locales.length,
|
||||
},
|
||||
);
|
||||
// Add prefix 'c' to current and total to prevent filling thees placeholders with real values
|
||||
const downloadingProgressBar = progressBar.newBar(
|
||||
'| Downloading translates :bar :percent | :cCurrent/:cTotal',
|
||||
{
|
||||
total: 100,
|
||||
incomplete: '\u2591',
|
||||
complete: '\u2588',
|
||||
width: locales.length,
|
||||
},
|
||||
);
|
||||
let downloadingTotal = 0;
|
||||
let downloadingReady = 0;
|
||||
console.log('Pulling locales list...');
|
||||
const locales = await pullLocales();
|
||||
const checkingProgressBar = progressBar.newBar('| Pulling locales info :bar :percent | :current/:total', {
|
||||
total: locales.length,
|
||||
incomplete: '\u2591',
|
||||
complete: '\u2588',
|
||||
width: locales.length,
|
||||
});
|
||||
// Add prefix 'c' to current and total to prevent filling thees placeholders with real values
|
||||
const downloadingProgressBar = progressBar.newBar('| Downloading translates :bar :percent | :cCurrent/:cTotal', {
|
||||
total: 100,
|
||||
incomplete: '\u2591',
|
||||
complete: '\u2588',
|
||||
width: locales.length,
|
||||
});
|
||||
let downloadingTotal = 0;
|
||||
let downloadingReady = 0;
|
||||
|
||||
interface Result {
|
||||
locale: ValuesType<typeof locales>;
|
||||
progress: number;
|
||||
translatesFilePath: string;
|
||||
}
|
||||
interface Result {
|
||||
locale: ValuesType<typeof locales>;
|
||||
progress: number;
|
||||
translatesFilePath: string;
|
||||
}
|
||||
|
||||
const results = await Promise.all(
|
||||
// TODO: there is should be some way to reimplement this
|
||||
// with reduce to avoid null values
|
||||
locales.map(
|
||||
async (locale): Promise<Result | null> => {
|
||||
const { files } = await crowdin.languageStatus(locale.code);
|
||||
checkingProgressBar.tick();
|
||||
const fileInfo = findFile(files, CROWDIN_FILE_PATH);
|
||||
const results = await Promise.all(
|
||||
// TODO: there is should be some way to reimplement this
|
||||
// with reduce to avoid null values
|
||||
locales.map(
|
||||
async (locale): Promise<Result | null> => {
|
||||
const { files } = await crowdin.languageStatus(locale.code);
|
||||
checkingProgressBar.tick();
|
||||
const fileInfo = findFile(files, CROWDIN_FILE_PATH);
|
||||
|
||||
if (fileInfo === null) {
|
||||
throw new Error(
|
||||
'Unable to find translation file. Please check the CROWDIN_FILE_PATH param.',
|
||||
);
|
||||
}
|
||||
if (fileInfo === null) {
|
||||
throw new Error('Unable to find translation file. Please check the CROWDIN_FILE_PATH param.');
|
||||
}
|
||||
|
||||
const progress = (fileInfo.words_approved / fileInfo.words) * 100;
|
||||
const progress = (fileInfo.words_approved / fileInfo.words) * 100;
|
||||
|
||||
if (
|
||||
!RELEASED_LOCALES.includes(toInternalLocale(locale.code)) &&
|
||||
progress < MIN_RELEASE_PROGRESS
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (!RELEASED_LOCALES.includes(toInternalLocale(locale.code)) && progress < MIN_RELEASE_PROGRESS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
downloadingProgressBar.update(downloadingReady / ++downloadingTotal, {
|
||||
cCurrent: downloadingReady,
|
||||
cTotal: downloadingTotal,
|
||||
});
|
||||
downloadingProgressBar.update(downloadingReady / ++downloadingTotal, {
|
||||
cCurrent: downloadingReady,
|
||||
cTotal: downloadingTotal,
|
||||
});
|
||||
|
||||
const translatesFilePath = await crowdin.exportFile(
|
||||
CROWDIN_FILE_PATH,
|
||||
locale.code,
|
||||
);
|
||||
const translatesFilePath = await crowdin.exportFile(CROWDIN_FILE_PATH, locale.code);
|
||||
|
||||
downloadingProgressBar.update(++downloadingReady / downloadingTotal, {
|
||||
cCurrent: downloadingReady,
|
||||
cTotal: downloadingTotal,
|
||||
});
|
||||
downloadingProgressBar.update(++downloadingReady / downloadingTotal, {
|
||||
cCurrent: downloadingReady,
|
||||
cTotal: downloadingTotal,
|
||||
});
|
||||
|
||||
return {
|
||||
locale,
|
||||
progress,
|
||||
translatesFilePath,
|
||||
};
|
||||
},
|
||||
),
|
||||
);
|
||||
return {
|
||||
locale,
|
||||
progress,
|
||||
translatesFilePath,
|
||||
};
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
console.log('Locales are downloaded. Writing them to file system.');
|
||||
console.log('Locales are downloaded. Writing them to file system.');
|
||||
|
||||
const indexFileEntries: { [key: string]: IndexFileEntry } = {
|
||||
en: {
|
||||
code: 'en',
|
||||
name: 'English',
|
||||
englishName: 'English',
|
||||
progress: 100,
|
||||
isReleased: true,
|
||||
},
|
||||
};
|
||||
await Promise.all(
|
||||
results
|
||||
.filter((result): result is Result => result !== null)
|
||||
.map(
|
||||
(result) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const {
|
||||
locale: { code, name },
|
||||
progress,
|
||||
translatesFilePath,
|
||||
} = result;
|
||||
const ourCode = toInternalLocale(code);
|
||||
const indexFileEntries: { [key: string]: IndexFileEntry } = {
|
||||
en: {
|
||||
code: 'en',
|
||||
name: 'English',
|
||||
englishName: 'English',
|
||||
progress: 100,
|
||||
isReleased: true,
|
||||
},
|
||||
};
|
||||
await Promise.all(
|
||||
results
|
||||
.filter((result): result is Result => result !== null)
|
||||
.map(
|
||||
(result) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const {
|
||||
locale: { code, name },
|
||||
progress,
|
||||
translatesFilePath,
|
||||
} = result;
|
||||
const ourCode = toInternalLocale(code);
|
||||
|
||||
indexFileEntries[ourCode] = {
|
||||
code: ourCode,
|
||||
name: NATIVE_NAMES_MAP[ourCode] || iso639.getNativeName(ourCode),
|
||||
englishName: ENGLISH_NAMES_MAP[ourCode] || name,
|
||||
progress: parseFloat(progress.toFixed(1)),
|
||||
isReleased: RELEASED_LOCALES.includes(ourCode),
|
||||
};
|
||||
indexFileEntries[ourCode] = {
|
||||
code: ourCode,
|
||||
name: NATIVE_NAMES_MAP[ourCode] || iso639.getNativeName(ourCode),
|
||||
englishName: ENGLISH_NAMES_MAP[ourCode] || name,
|
||||
progress: parseFloat(progress.toFixed(1)),
|
||||
isReleased: RELEASED_LOCALES.includes(ourCode),
|
||||
};
|
||||
|
||||
fs.copyFile(
|
||||
translatesFilePath,
|
||||
path.join(LANG_DIR, `${ourCode}.json`),
|
||||
0,
|
||||
(err) => {
|
||||
err ? reject(err) : resolve();
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
fs.copyFile(translatesFilePath, path.join(LANG_DIR, `${ourCode}.json`), 0, (err) => {
|
||||
err ? reject(err) : resolve();
|
||||
});
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
console.log('Writing an index file.');
|
||||
console.log('Writing an index file.');
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(LANG_DIR, INDEX_FILE_NAME),
|
||||
serializeToModule(indexFileEntries),
|
||||
);
|
||||
fs.writeFileSync(path.join(LANG_DIR, INDEX_FILE_NAME), serializeToModule(indexFileEntries));
|
||||
|
||||
console.log(ch.green('The index file was successfully written'));
|
||||
console.log(ch.green('The index file was successfully written'));
|
||||
}
|
||||
|
||||
function push() {
|
||||
return new Promise((resolve, reject) => {
|
||||
prompt.start();
|
||||
prompt.get(
|
||||
{
|
||||
properties: {
|
||||
disapprove: {
|
||||
description: 'Disapprove changed lines? [Y/n]',
|
||||
pattern: /^y|n$/i,
|
||||
message: 'Please enter "y" or "n"',
|
||||
default: 'y',
|
||||
before: (value) => value.toLowerCase() === 'y',
|
||||
},
|
||||
},
|
||||
},
|
||||
async (err, { disapprove }) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return new Promise((resolve, reject) => {
|
||||
prompt.start();
|
||||
prompt.get(
|
||||
{
|
||||
properties: {
|
||||
disapprove: {
|
||||
description: 'Disapprove changed lines? [Y/n]',
|
||||
pattern: /^y|n$/i,
|
||||
message: 'Please enter "y" or "n"',
|
||||
default: 'y',
|
||||
before: (value) => value.toLowerCase() === 'y',
|
||||
},
|
||||
},
|
||||
},
|
||||
async (err, { disapprove }) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Publishing ${ch.bold(SOURCE_LANG)} translates file...`);
|
||||
console.log(`Publishing ${ch.bold(SOURCE_LANG)} translates file...`);
|
||||
|
||||
await crowdin.updateFile(
|
||||
{
|
||||
[CROWDIN_FILE_PATH]: path.join(LANG_DIR, `${SOURCE_LANG}.json`),
|
||||
},
|
||||
{
|
||||
update_option: disapprove
|
||||
? 'update_as_unapproved'
|
||||
: 'update_without_changes',
|
||||
},
|
||||
await crowdin.updateFile(
|
||||
{
|
||||
[CROWDIN_FILE_PATH]: path.join(LANG_DIR, `${SOURCE_LANG}.json`),
|
||||
},
|
||||
{
|
||||
update_option: disapprove ? 'update_as_unapproved' : 'update_without_changes',
|
||||
},
|
||||
);
|
||||
|
||||
console.log(ch.green('Success'));
|
||||
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
|
||||
console.log(ch.green('Success'));
|
||||
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const action = process.argv[2];
|
||||
const action = process.argv[2];
|
||||
|
||||
switch (action) {
|
||||
case 'pull':
|
||||
pull();
|
||||
break;
|
||||
case 'push':
|
||||
push();
|
||||
break;
|
||||
default:
|
||||
console.error(`Unknown action ${action}`);
|
||||
}
|
||||
switch (action) {
|
||||
case 'pull':
|
||||
pull();
|
||||
break;
|
||||
case 'push':
|
||||
push();
|
||||
break;
|
||||
default:
|
||||
console.error(`Unknown action ${action}`);
|
||||
}
|
||||
} catch (exception) {
|
||||
console.error(exception);
|
||||
console.error(exception);
|
||||
}
|
||||
|
@ -1,28 +1,28 @@
|
||||
{
|
||||
"name": "scripts",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "i18n-build.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/node": "^7.8.3",
|
||||
"@types/mkdirp": "^1.0.0",
|
||||
"@types/progress": "^2.0.3",
|
||||
"chalk": "^4.0.0",
|
||||
"crowdin-api": "^4.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"iso-639-1": "^2.1.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"multi-progress": "^2.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"utility-types": "^3.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/webpack": "^4.41.13"
|
||||
}
|
||||
"name": "scripts",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "i18n-build.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/node": "^7.8.3",
|
||||
"@types/mkdirp": "^1.0.0",
|
||||
"@types/progress": "^2.0.3",
|
||||
"chalk": "^4.0.0",
|
||||
"crowdin-api": "^4.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"iso-639-1": "^2.1.3",
|
||||
"mkdirp": "^1.0.4",
|
||||
"multi-progress": "^2.0.0",
|
||||
"prompt": "^1.0.0",
|
||||
"utility-types": "^3.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/webpack": "^4.41.13"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user