Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-11296] Implemented the i18n synchronizer #10

Merged
merged 2 commits into from
Oct 9, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions tools/i18n-sync/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"name": "Project 1",
"privateKey": "1234",
"location": "project1"
},
{
"name": "Project 2",
"privateKey": "5678",
"location": "project2"
}
]
189 changes: 189 additions & 0 deletions tools/i18n-sync/i18n-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/env node

var fs = require('fs'),
path = require('path'),

request = require('request'),
async = require('async'),
wrench = require('wrench'),

progress = require('../../lib/progress'),

configFile = 'config.json',
config,

wtiPrefix = 'https://webtranslateit.com/api/projects/',

requestInfoTasks = [],
startTime = Date.now(),

translations = {},
transferAmount = 0;

// Create the sync tasks
try {
config = JSON.parse(fs.readFileSync(configFile));
} catch(e) {
console.error('Error reading the config file');
console.error(e.message);
}
console.log()
config.forEach(function (configEntry) {
console.log('Processing project ' + configEntry.name);
requestInfoTasks.push(function (projectNext) {
var name = configEntry.name,
privateKey = configEntry.privateKey,
location = configEntry.location;
translations[name] = {
privateKey: privateKey,
location: location,
translations: {}
};
async.parallel([

// Get the list of locales
function (next) {
request(wtiPrefix + privateKey + '.json', function (error, response, body) {
var locales = [];
body && (transferAmount += body.length);
if (error) {
next('Could not fetch the information for ' + name + ': ' + error);
} else if (response.statusCode !== 200) {
next('Could not fetch the information for ' + name + ': server returned ' + response.statusCode);
} else {
body = JSON.parse(body);
if (body.project && body.project.target_locales) {
body.project.target_locales.forEach(function(locale) {
translations[name].translations[locale.code] = {};
locales.push(locale.code);
});
translations[name].locales = locales;
next();
} else {
next('Could not fetch the information for ' + name + ': invalid server response');
}
}
});
},

// Get the list of strings
function (next) {
request(wtiPrefix + privateKey + '/strings', function (error, response, body) {
var strings = [];
body && (transferAmount += body.length);
if (error) {
next('Could not fetch the strings for ' + name + ': ' + error);
} else if (response.statusCode !== 200) {
next('Could not fetch the strings for ' + name + ': server returned ' + response.statusCode);
} else {
body = JSON.parse(body);
body.forEach(function (str) {
strings.push(str.id);
});
translations[name].strings = strings;
next();
}
});
}
], function(err, result) {
projectNext(err);
});
});
});
console.log('\nFetching project information');
async.parallel(requestInfoTasks, function(err, result) {

console.log('Fetching internationalization information');
var numRequests = 0,
p,
projectTasks = [],
pb;
Object.keys(translations).forEach(function (name) {
var translation = translations[name],
privateKey = translation.privateKey,
location = translation.location;
numRequests += translation.locales.length * translation.strings.length;
projectTasks.push(function (projectNext) {
var localeTasks = [];
translation.locales.forEach(function (locale) {
localeTasks.push(function (localeNext) {
var stringTasks = [];
translation.strings.forEach(function (str) {
stringTasks.push(function (strNext) {
request(wtiPrefix + privateKey + '/strings/' + str + '/locales/' + locale + '/translations.json', function (error, response, body) {
body && (transferAmount += body.length);
var strings = [];
if (error) {
strNext('Could not fetch the strings for ' + name + ': ' + error);
} else if (response.statusCode !== 200) {
strNext('Could not fetch the strings for ' + name + ': server returned ' + response.statusCode);
} else {
body = JSON.parse(body);
if (body.text) {
translation.translations[locale][body.string.key] = body.text;
}
strNext();
}
pb.tick(1);
});
});
});
async.parallel(stringTasks, function(err, result) {
localeNext(err, result);
});
});
});
async.parallel(localeTasks, function(err, result) {
projectNext(err);
});
});
});
pb = new progress(':paddedPercent [:bar] :etas', {
complete: '=',
incomplete: '.',
width: 65,
total: numRequests
});
pb.tick();
async.parallel(projectTasks, function(err, result) {
console.log('\n' + (transferAmount / 1000).toFixed(0) + ' kb transferred\n');
if (err) {
console.log(err);
} else {
projectTasks = [];
Object.keys(translations).forEach(function(name) {
var translation = translations[name],
location = translation.location;
projectTasks.push(function(projectNext) {
var writeTasks = [];
translation.locales.forEach(function (locale) {
writeTasks.push(function(writeNext) {
if (locale !== 'en' && Object.keys(translation.translations[locale]).length) {
var localeFile = path.join(location, 'locales');
if (!fs.existsSync(localeFile)) {
wrench.mkdirSyncRecursive(localeFile);
}
localeFile = path.join(localeFile, locale + '.js');
console.log('Writing locale file ' + localeFile);
fs.writeFile(localeFile, JSON.stringify(translation.translations[locale], false, '\t'), function(err) {
if (err) {
console.log('Error writing locale file ' + localeFile + ': ' + err);
}
writeNext(err);
});
} else {
writeNext();
}
});
});
async.parallel(writeTasks, function(err, result) {
projectNext(err);
});
});
});
async.parallel(projectTasks, function(err, result) {
console.log('\nSyncing completed ' + (err ? 'with errors' : 'successfully') + ' in ' + ((Date.now() - startTime) / 1000) + 's\n');
});
}
});
});
14 changes: 14 additions & 0 deletions tools/i18n-sync/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"author": "Bryan Hughes <bhughes@appcelerator.com>",
"name": "node-appc-i18n-sync",
"version": "0.1.0",
"main": "i18n-sync.js",
"dependencies": {
"request": "2.11.x",
"async": "0.1.x",
"wrench": "1.3.x"
},
"engines": {
"node": ">=0.6.6"
}
}