Добавлена (скопипащена) команда для пулинга локалей из oneskyapp

This commit is contained in:
ErickSkrauch 2017-05-20 02:53:11 +03:00
parent ea81641ad0
commit 7609cb0e15
6 changed files with 179 additions and 6 deletions

View File

@ -18,7 +18,8 @@
"start": "rm -rf dist/ && webpack-dev-server --progress --colors",
"lint": "eslint ./src",
"i18n": "cd ./scripts && ../node_modules/.bin/babel-node i18n-collect.js",
"build": "rm -rf dist/ && NODE_ENV=production webpack --progress --colors"
"build": "rm -rf dist/ && NODE_ENV=production webpack --progress --colors",
"i18n:pull": "cd ./scripts && ../node_modules/.bin/babel-node --presets es2015,stage-0 i18n-onesky.js pull"
},
"dependencies": {
"babel-polyfill": "^6.3.14",
@ -32,6 +33,7 @@
"react-intl": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.0.0",
"babel-eslint": "^6.0.0",
"babel-loader": "^6.0.0",

View File

@ -1,3 +0,0 @@
{
"breakConfig": true
}

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

@ -0,0 +1,149 @@
/* eslint-env node */
/* eslint-disable no-console */
import onesky from 'onesky-utils';
import fs from 'fs';
import ch from 'chalk';
const LANG_DIR = `${__dirname}/../src/i18n`;
const SOURCE_LANG = 'en'; // Базовый язык, относительно которого будут формироваться все остальные переводы
const SOURCE_FILE_NAME = 'i18n.json'; // Название файла с исходными строками внутри OneSky
const INDEX_FILE_NAME = 'index.json'; // Название файла с информацией о переводах
const MIN_RELEASE_PROGRESS = 80; // Какой процент локали перевода должен быть выполнен, чтобы локаль была опубликована
/**
* Массив локалей для соответствия каноничному виду в OneSky и нашему представлению
* о том, каким должны быть имена локалей
*/
const LOCALES_MAP = {
ru: 'ru-RU',
en: 'en-GB',
sl: 'sl-SI',
fr: 'fr-FR',
el: 'el-GR',
de: 'de-DE',
sr: 'sr-RS',
};
// https://ely-translates.oneskyapp.com/admin/site/settings
const defaultOptions = {
apiKey: '5MaW9TYp0S3qdJgkZ5QLgEIDeabkFDzB',
secret: 'qd075hUNpop4DItD6KOXKQnbqWPLZilf',
projectId: 202784,
};
/**
* Переводит из кода языка в 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 || parseFloat(elem.translation_progress) > MIN_RELEASE_PROGRESS);
}
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();
const langsList = langs.map((elem) => elem.custom_locale || elem.code);
console.log(ch.green('Pulled locales: ') + langsList.map((lang) => code2locale(lang)).join(', '));
console.log('Pulling translates...');
await Promise.all(langsList.map(async (lang) => {
await pullTranslate(lang);
console.log(ch.green('Locale ') + ch.white.bold(code2locale(lang)) + ch.green(' successfully pulled'));
}));
console.log('Writing an index file...');
const mapFileContent = {};
langs.map((elem) => {
mapFileContent[elem.locale] = {
name: elem.local_name.match(/^([^\(]+)/)[0].trim(), // Обрезаем значения в скобках
progress: parseFloat(elem.translation_progress),
};
});
fs.writeFileSync(`${LANG_DIR}/${INDEX_FILE_NAME}`, formatTranslates(mapFileContent));
console.log(ch.green('The index file was successfully written'));
}
async function publish() {
console.log(`Publishing ${ch.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(ch.green('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",
"prompt": "^1.0.0"
"prompt": "^1.0.0",
"onesky-utils": "erickskrauch/nodejs-onesky-utils#locales_list"
}
}

View File

@ -1,2 +1,4 @@
export const SUPPORTED_LANGUAGES = ['be', 'en', 'ru', 'pt', 'uk'];
import LOCALES from 'i18n/index.json';
export const SUPPORTED_LANGUAGES = Object.keys(LOCALES);
export const DEFAULT_LANGUAGE = 'en';

22
src/i18n/index.json Normal file
View File

@ -0,0 +1,22 @@
{
"be": {
"name": "Беларуская",
"progress": 100
},
"en": {
"name": "English",
"progress": 100
},
"pt": {
"name": "Português",
"progress": 100
},
"ru": {
"name": "Русский",
"progress": 100
},
"uk": {
"name": "Українська",
"progress": 100
}
}