Merge branch 'onesky_integration' into develop

This commit is contained in:
ErickSkrauch 2017-02-28 01:15:45 +03:00
commit 359ac19cc0
7 changed files with 138 additions and 32 deletions

View File

@ -15,6 +15,8 @@
"lint": "eslint ./src",
"i18n:collect": "babel-node ./scripts/i18n-collect.js",
"i18n:unescape": "babel-node ./scripts/unescape-i18n.js",
"i18n:pull": "babel-node --presets es2015,stage-0 ./scripts/i18n-onesky.js pull",
"i18n:publish": "babel-node --presets es2015,stage-0 ./scripts/i18n-onesky.js publish",
"build": "npm run clean && npm run build:webpack -- --progress",
"build:webpack": "webpack --colors -p",
"build:quite": "npm run clean && npm run build:webpack -- --quite",

View File

@ -38,7 +38,7 @@ 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!'));
return;
process.exit();
}
duplicateIds = null;
@ -84,7 +84,8 @@ keysToUpdate = Object.entries(prevMessages).reduce((acc, [key, message]) =>
});
if (!keysToAdd.length && !keysToRemove.length && !keysToUpdate.length && !keysToRename.length) {
return console.log(chalk.green('Everything is up to date!'));
console.log(chalk.green('Everything is up to date!'));
process.exit();
}
console.log(chalk.magenta(`The diff relative to default locale (${DEFAULT_LOCALE}) is:`));

131
scripts/i18n-onesky.js Normal file
View File

@ -0,0 +1,131 @@
/* eslint-env node */
/* eslint-disable no-console */
import onesky from 'onesky-utils';
import fs from 'fs';
import chalk from 'chalk';
const LANG_DIR = `${__dirname}/../src/i18n`;
const SOURCE_LANG = 'en'; // Базовый язык, относительно которого будут формироваться все остальные переводы
const SOURCE_FILE_NAME = 'i18n.json'; // Название файла с исходными строками внутри OneSky
/**
* Массив локалей для соответствия каноничному виду в OneSky и нашему представлению
* о том, каким должны быть имена локалей
*/
const LOCALES_MAP = {
ru: 'ru-RU',
en: 'en-GB',
};
// https://ely-translates.oneskyapp.com/admin/site/settings
const defaultOptions = {
apiKey: '5MaW9TYp0S3qdJgkZ5QLgEIDeabkFDzB',
secret: 'qd075hUNpop4DItD6KOXKQnbqWPLZilf',
projectId: 201323,
};
/**
* Переводит из кода языка в OneSky в наше представление
*
* @param {string} code
* @return {string}
*/
function code2locale(code) {
for (const locale in LOCALES_MAP) {
if (code === LOCALES_MAP[locale]) {
return locale;
}
}
return code;
}
/**
* Переводит из нашего формата локалей в ожидаемое значение OneSky
*
* @param {string} locale
* @return {string}
*/
function locale2code(locale) {
return LOCALES_MAP[locale] || locale;
}
/**
* Форматирует входящий объект с переводами в итоговую строку в том формате, в каком они
* хранятся в самом приложении
*
* @param {object} translates
* @return {string}
*/
function formatTranslates(translates) {
return JSON.stringify(sortByKeys(translates), null, 4) + '\n'; // eslint-disable-line prefer-template
}
/**
* http://stackoverflow.com/a/29622653/5184751
*
* @param {object} object
* @return {object}
*/
function sortByKeys(object) {
return Object.keys(object).sort().reduce((result, key) => {
result[key] = object[key];
return result;
}, {});
}
async function pullReadyLanguages() {
const languages = JSON.parse(await onesky.getLanguages({...defaultOptions}));
return languages.data
.filter((elem) => elem.is_ready_to_publish)
.map((elem) => elem.custom_locale || elem.code);
}
async function pullTranslate(language) {
const rawResponse = await onesky.getFile({...defaultOptions, language, fileName: SOURCE_FILE_NAME});
const response = JSON.parse(rawResponse);
fs.writeFileSync(`${LANG_DIR}/${code2locale(language)}.json`, formatTranslates(response));
}
async function pull() {
console.log('Pulling locales list...');
const langs = await pullReadyLanguages();
console.log(chalk.green('Pulled locales: ') + langs.map((lang) => code2locale(lang)).join(', '));
console.log('Pulling translates...');
await Promise.all(langs.map(async (lang) => {
await pullTranslate(lang);
console.log(chalk.green('Locale ') + chalk.white.bold(code2locale(lang)) + chalk.green(' successfully pulled'));
}));
}
async function publish() {
console.log(`Publishing ${chalk.bold(SOURCE_LANG)} translates file...`);
await onesky.postFile({
...defaultOptions,
format: 'HIERARCHICAL_JSON',
content: fs.readFileSync(`${LANG_DIR}/${SOURCE_LANG}.json`, 'utf8'),
keepStrings: false,
language: locale2code(SOURCE_LANG),
fileName: SOURCE_FILE_NAME,
});
console.log('Success');
}
try {
const action = process.argv[2];
switch (action) {
case 'pull':
pull();
break;
case 'publish':
publish();
break;
default:
throw new Error(`Unknown action ${action}`);
}
} catch (exception) {
console.error(exception);
}

View File

@ -12,6 +12,7 @@
"dependencies": {
"chalk": "^1.1.3",
"node-babel": "^0.1.2",
"onesky-utils": "erickskrauch/nodejs-onesky-utils#locales_list",
"prompt": "^1.0.0"
}
}

View File

@ -1,13 +0,0 @@
const test = async () => {
};
const obj = {a: 1, b: 1};
const {a, b} = obj;
console.log(a, b, 'ok');
// how to:
// cd to frontend
// > ./node_modules/.bin/babel-node --presets es2015,es2017,stage-0 ./scripts/test-async-await.js

View File

@ -1,16 +0,0 @@
/* eslint-env node */
/* eslint-disable no-console */
import fs from 'fs';
import {sync as globSync} from 'glob';
const LANG_DIR = `${__dirname}/../src/i18n`;
/**
* При выгрузке из OneSky мы получаем json, в котором все не-латинские символы за-escape-ны.
* Это увеличивает вес переводов и портит дифы. Поэтому мы просто прокручиваем их json
* и на выходе получаем чистые файлы, без escape-последовательностей.
*/
globSync(`${LANG_DIR}/*.json`).forEach((filename) => {
const json = JSON.parse(fs.readFileSync(filename, 'utf8'));
fs.writeFileSync(filename, JSON.stringify(json, null, 4) + "\n");
});

View File

@ -21,7 +21,7 @@
"components.auth.chooseAccount.addAccount": "Увайсці ў другі акаўнт",
"components.auth.chooseAccount.chooseAccountTitle": "Выбар акаўнта",
"components.auth.chooseAccount.description": "Вы выканалі ўваход у некалькі акаўнтаў. Пазначце, які вы жадаеце выкарыстаць для аўтарызацыі {appName}",
"components.auth.chooseAccount.logoutAll": "Выйсці з усіх акаўтаў",
"components.auth.chooseAccount.logoutAll": "Выйсці з усіх акаўнтаў",
"components.auth.finish.authForAppFailed": "Аўтарызацыя для {appName} не атрымалася",
"components.auth.finish.authForAppSuccessful": "Аўтарызацыя для {appName} паспяхова выканана",
"components.auth.finish.copy": "Скапіяваць",