Skip to content

Commit

Permalink
initial release of translations package
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensayshi committed Oct 28, 2015
0 parents commit e7bf0b4
Show file tree
Hide file tree
Showing 15 changed files with 2,077 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.csv
.~lock*
661 changes: 661 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Blocktrail Wallet Translations
This repo contains JSON files with all translations used for the Blocktrail Web and Mobile Wallet.
The scripts to convert from JSON -> CSV -> JSON are horrific right now, but they do what they're supposed to, will be cleaned up at a later stage ...

## Structure
`translations/*.json` are the main translation files, they're used in the Web Wallet.
`translations/mobile/*.json` are merged over the main translation files for the Mobile Wallet, this is mainly for button text etc. that is otherwise too big to fit.

## Install
```
npm install
```

## Create CSV to translate in Libre Calc / MS Excel
```
node export-csv.js > translations.csv
```

## Import CSV with changes back into the JSON files
```
# asumes translations.csv is in the root dir
node import-csv.js
```

## RegEx used for converting JS files to JSON
` ([A-Z].+): ?["'](.+)['"],` `"$1": "$2",`

## License
The Blocktrail Wallet source code is released under the GNU Affero General Public License.
The Blocktrail Logo and any other images / graphics are not part of this.
See [LICENSE.md](LICENSE.md).
72 changes: 72 additions & 0 deletions export-csv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
var _ = require('lodash');
var stripJsonComments = require('strip-json-comments');
var fs = require('fs');
var Q = require('q');
var csv = require('csv');

var BASE_LANGUAGE = "english";
var BLACKLIST = ['package.json'];
var DIR = __dirname + "/translations";
var MOBILE_DIR = DIR + "/mobile";

var translations = {};

fs.readdirSync(DIR).forEach(function(filename) {
if (filename.match(/\.json$/) && BLACKLIST.indexOf(filename) === -1) {
var language = filename.replace(/\.json$/, "");

var raw = fs.readFileSync(DIR + "/" + filename);
translations[language] = JSON.parse(stripJsonComments(raw.toString('utf8')));
}
});

fs.readdirSync(MOBILE_DIR).forEach(function(filename) {
if (filename.match(/\.json$/) && BLACKLIST.indexOf(filename) === -1) {
var language = filename.replace(/\.json$/, "");

var raw = fs.readFileSync(MOBILE_DIR + "/" + filename);
translations[language + "_mobile"] = JSON.parse(stripJsonComments(raw.toString('utf8')));
}
});

var languages = Object.keys(translations).sort();
// bring BASE_LANGUAGE to front
languages.splice(languages.indexOf(BASE_LANGUAGE), 1);
languages.unshift(BASE_LANGUAGE);

// put _mobile behind it's parent
_.forEach(languages, function(language, idx) {
if (language.match(/_mobile$/)) {
var _language = language.substr(0, language.length -7);

languages.splice(languages.indexOf(language), 1);
languages.splice(languages.indexOf(_language)+1, 0, language);
}
});

var keys = Object.keys(translations[BASE_LANGUAGE]).filter(function(key) { return ['NULL'].indexOf(key) === -1; });

var rows = _.map(keys, function(key) {
return [key].concat(_.map(languages, function(language) {
return translations[language][key] || "";
}));
});

rows.unshift(['KEY'].concat(languages));

rows = rows.map(function(row) {
return row.map(function(v) {
// in JSON we do multiline as ["line1", "line2"]
if (typeof v !== "string") {
v = v.join("\n");
}

return v;
});
});

csv.stringify(rows, {delimiter: ";", quoted: true}, function(err, raw) {
if (err) throw err;

console.log(raw);
});
182 changes: 182 additions & 0 deletions import-csv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
var _ = require('lodash');
var stripJsonComments = require('strip-json-comments');
var fs = require('fs');
var Q = require('q');
var csv = require('csv');
var _debug = require('debug');

var debug = function(prefix) {
var d = _debug(prefix);
return function() {
var args = Array.prototype.slice.call(arguments);
return d.apply(void 0, [args.map(function() { return '%o'; }).join(" ")].concat(args));
};
};

var BASE_LANGUAGE = "english";
var BLACKLIST = ['package.json'];
var DIR = __dirname + "/translations";
var MOBILE_DIR = DIR + "/mobile";

var translations = {};

fs.readdirSync(DIR).forEach(function(filename) {
if (filename.match(/\.json$/) && BLACKLIST.indexOf(filename) === -1) {
var language = filename.replace(/\.json$/, "");

var raw = fs.readFileSync(DIR + "/" + filename);
translations[language] = JSON.parse(stripJsonComments(raw.toString('utf8')));
}
});

fs.readdirSync(MOBILE_DIR).forEach(function(filename) {
if (filename.match(/\.json$/) && BLACKLIST.indexOf(filename) === -1) {
var language = filename.replace(/\.json$/, "");

var raw = fs.readFileSync(MOBILE_DIR + "/" + filename);
translations[language + "_mobile"] = JSON.parse(stripJsonComments(raw.toString('utf8')));
}
});

var languages = Object.keys(translations).sort();
// bring BASE_LANGUAGE to front
languages.splice(languages.indexOf(BASE_LANGUAGE), 1);
languages.unshift(BASE_LANGUAGE);

// put _mobile behind it's parent
_.forEach(languages, function(language, idx) {
if (language.match(/_mobile$/)) {
var _language = language.substr(0, language.length -7);

languages.splice(languages.indexOf(language), 1);
languages.splice(languages.indexOf(_language)+1, 0, language);
}
});

var keys = Object.keys(translations[BASE_LANGUAGE]).filter(function(key) { return ['NULL'].indexOf(key) === -1; });

var raw = fs.readFileSync(__dirname + "/translations.csv").toString('utf8');

csv.parse(raw, {delimiter: ";", columns: true}, function(err, data) {
if (err) throw err;

data.forEach(function(row) {
languages.forEach(function(language) {
if (row[language]) {
if (row[language].match(/\n/)) {
row[language] = row[language].split(/\n/);
}

if (keys.indexOf(row.KEY) !== -1) {
translations[language][row.KEY] = row[language];
}
}
});
});

languages.forEach(function(language) {
var isMobile = language.match(/_mobile$/);
var filename = isMobile ? language.substr(0, language.length -7) : language;

var rawOriginal = fs.readFileSync((isMobile ? MOBILE_DIR : DIR) + "/" + filename + ".json").toString('utf8');
var rowsOriginal = rawOriginal.split("\n");
var commentLines = {};
var blankLines = {}; // @TODO
var comments = {};
var skip = 0;

_.forEach(rowsOriginal, function(row, idx) {
if (skip > 0) {
skip--;
return;
}

var blankLine = row.match(/^\s*$/);
var commentLine = row.match(/^( *?)\/\/(.+)/);
var comment = row.match(/".+?[^\\]",(( *?)\/\/(.+))$/);

debug('import-csv:parse-original')("-----------");
debug('import-csv:parse-original')(row, !!blankLine, !!commentLine, !!comment);

if (blankLine) {
var beforeKey = null;

_.any(rowsOriginal.slice(idx+1), function(nextRow, nextIdx) {
var key = nextRow.match(/^( +?)"(.+?)"( *?):/);

debug('import-csv:parse-original')(nextRow, !!commentLine, !!key);

if (key) {
beforeKey = key[2];

return true;
}
});

if (beforeKey) {
blankLines[beforeKey] = true;
}

} else if (commentLine) {
var _commentLine = [commentLine[0]];
var beforeKey = null;

_.any(rowsOriginal.slice(idx+1), function(nextRow, nextIdx) {
var commentLine = nextRow.match(/^( *)\/\/(.+)/);
var key = nextRow.match(/^( +?)"(.+?)"( *?):/);

debug('import-csv:parse-original')(nextRow, !!commentLine, !!key);

if (key) {
beforeKey = key[2];

return true;
} else if (commentLine) {
_commentLine.push(commentLine[0]);
skip++;
} else {
debug('import-csv:parse-original')('WHAT IS THIS?', nextRow);
}
});

debug('import-csv:parse-original')(_commentLine);
if (beforeKey) {
commentLines[beforeKey] = _commentLine;
}
} else if (comment) {
var key = row.match(/^( +?)"(.+?)"( *?):/);

debug('import-csv:parse-original')(!!comment && comment[1], !!key && key[2]);

if (key) {
comments[key[2]] = comment[1];
}

}
});

var json = JSON.stringify(translations[language], null, 4).split("\n");

json.slice().forEach(function(line) {
var key = line.match(/^( +?)"(.+?)"( *?):/);

debug('import-csv:output')(line, !!key && key[2], !!key && typeof commentLines[key[2]] !== "undefined");

if (!!key && blankLines[key[2]]) {
json.splice(json.indexOf(line), 0, "");
}

if (!!key && commentLines[key[2]]) {
commentLines[key[2]].reverse().forEach(function(comment) {
json.splice(json.indexOf(line), 0, comment);
});
}

if (!!key && comments[key[2]]) {
json.splice(json.indexOf(line), 1, line + comments[key[2]]);
}
});

fs.writeFileSync((isMobile ? MOBILE_DIR : DIR) + "/" + filename + ".json", json.join("\n") + "\n");
});
});
Loading

0 comments on commit e7bf0b4

Please sign in to comment.