Skip to content

Commit

Permalink
Add i18n support
Browse files Browse the repository at this point in the history
  • Loading branch information
finnp committed Dec 16, 2014
1 parent d6f9d53 commit 2372781
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 36 deletions.
53 changes: 24 additions & 29 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ var x256 = require('x256');
var through = require('through2');
var split = require('split');
var minimist = require('minimist');
var vw = require('visualwidth')

var showMenu = require('./lib/menu.js');
var showHelp = require('./lib/help.js');
var lang = require('./lib/lang.js')

module.exports = Shop;
inherits(Shop, EventEmitter);
Expand All @@ -22,6 +24,10 @@ function Shop (opts) {
this.name = opts.name;
this.options = opts;

this.usage = opts.usage;

this.i18n = lang(opts.i18n)

if (!this.name) return this._error(
'Your adventure must have a name! '
+ 'Supply an `opts.name` to adventure().'
Expand Down Expand Up @@ -79,7 +85,7 @@ Shop.prototype.execute = function (args) {
this.run(args.slice(1), this.state.current);
}
else if (cmd === 'help' || argv.help) {
showHelp({ command: this.command });
showHelp({ command: this.command, usage: this.usage });
}
else if (cmd === 'selected') {
console.log(this.state.current);
Expand All @@ -102,15 +108,12 @@ Shop.prototype.execute = function (args) {
else if (cmd === 'solution') {
var adv = this.find(this.state.current);
if (!adv) {
return console.log(
'No adventure is currently selected. '
+ 'Select an adventure from the menu.'
);
return console.log(this.i18n['no-adventure-selected']);
process.exit(1);
}
var p = adv.fn();
if (p.solution) this._show(p.solution);
else console.log('No reference solution available for this adventure.')
else console.log(this.i18n['no-solution'])
}
else if (cmd === 'reset') {
this.state.completed = [];
Expand All @@ -122,7 +125,7 @@ Shop.prototype.execute = function (args) {
this.showMenu(this.options);
}
else {
console.log('unrecognized command: ' + cmd);
console.log(this.i18n['unrecognized-command'], cmd);
}
};

Expand All @@ -141,14 +144,9 @@ Shop.prototype.find = function (name) {
Shop.prototype.verify = function (args, name) {
var self = this;
var adv = this.find(name);
if (!adv) return this._error(
'No adventure is currently selected. '
+ 'Select an adventure from the menu.'
);
if (!adv) return this._error(this.i18n["no-adventure-selected"]);
var p = adv.fn();
if (!p.verify) return this._error(
"This problem doesn't have a .verify function yet!"
);
if (!p.verify) return this._error(this.i18n["no-verify-function"]);
if (typeof p.verify !== 'function') return this._error(
'This p.verify is a ' + typeof p.verify
+ '. It should be a function instead.'
Expand All @@ -164,14 +162,9 @@ Shop.prototype.verify = function (args, name) {
Shop.prototype.run = function (args, name) {
var self = this;
var adv = this.find(name);
if (!adv) return this._error(
'No adventure is currently selected. '
+ 'Select an adventure from the menu.'
);
if (!adv) return this._error(this.i18n["no-adventure-selected"]);
var p = adv.fn();
if (!p.run) return this._error(
"This problem doesn't have a .run function."
);
if (!p.run) return this._error(this.i18n["no-run-function"]);
if (typeof p.run !== 'function') return this._error(
'This p.run is a ' + typeof p.run
+ '. It should be a function instead.'
Expand All @@ -192,14 +185,14 @@ Shop.prototype.pass = function (name, p) {
else {
console.log(
'\n' + this.colors.pass
+ '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
+ Array(vw.width(this.i18n['solution-correct']) + 13).join('@')
);
console.log(
'@@@' + this.colors.reset
+ ' YOUR SOLUTION IS CORRECT'
+ this.colors.pass + '! @@@'
+ ' ' + this.i18n['solution-correct']
+ this.colors.pass + ' @@@'
);
console.log('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');
console.log(Array(vw.width(this.i18n['solution-correct']) + 13).join('@'));
console.log(this.colors.reset + '\n');
}
if (p.solution) this._show(p.solution);
Expand All @@ -218,14 +211,14 @@ Shop.prototype.fail = function (name, p) {
else {
console.log(
this.colors.fail
+ '#########################################'
+ Array(vw.width(this.i18n['solution-incorrect']) + 13).join('#')
);
console.log(
'###' + this.colors.reset
+ ' YOUR SOLUTION IS NOT CORRECT!'
+ ' ' + this.i18n['solution-incorrect']
+ this.colors.fail + ' ###'
);
console.log('#########################################');
console.log(Array(vw.width(this.i18n['solution-incorrect']) + 13).join('#'));
console.log(this.colors.reset + '\n');
}
this.emit('fail', name);
Expand Down Expand Up @@ -259,6 +252,8 @@ Shop.prototype.showMenu = function (opts) {
fg: opts.fg,
bg: opts.bg,
command: this.command,
i18n: this.i18n,
usage: this.usage,
title: opts.title || this.name.toUpperCase(),
names: this._adventures.map(function (x) { return x.name }),
completed: this.state.completed
Expand All @@ -279,7 +274,7 @@ Shop.prototype.save = function (key) {
};

Shop.prototype._error = function (msg) {
console.error('ERROR: ' + msg);
console.error(this.i18n.error, msg);
process.exit(1);
};

Expand Down
13 changes: 13 additions & 0 deletions lib/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"help": "HELP",
"exit": "EXIT",
"error": "ERROR:",
"completed": "[COMPLETED]",
"solution-incorrect": "YOUR SOLUTION IS NOT CORRECT!",
"unrecognized-command": "unrecognized command:",
"no-adventure-selected": "No adventure is currently selected. Select an adventure from the menu.",
"solution-correct": "YOUR SOLUTION IS CORRECT!",
"no-solution": "No reference solution available for this adventure.",
"no-run-function": "This problem doesn't have a .run function.",
"no-verify-function": "This problem doesn't have a .verify function yet!"
}
4 changes: 3 additions & 1 deletion lib/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ var split = require('split');
var through = require('through2');

module.exports = function (opts) {
fs.createReadStream(__dirname + '/usage.txt')
var usage = opts.usage || fs.createReadStream(__dirname + '/usage.txt')
usage
.pipe(split())
.pipe(through(function (buf, enc, next) {
var line = buf.toString('utf8')
.replace(/\$COMMAND/g, opts.command)
Expand Down
9 changes: 9 additions & 0 deletions lib/lang.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var lang = require('./en.json');

module.exports = function (i18n) {
i18n = i18n || {}
Object.keys(lang).forEach(function (key) {
lang[key] = i18n[key] || lang[key]
})
return lang
}
15 changes: 9 additions & 6 deletions lib/menu.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var tmenu = require('terminal-menu');
var path = require('path');
var EventEmitter = require('events').EventEmitter;
var vw = require('visualwidth')
var showHelp = require('./help.js');

module.exports = function (opts) {
Expand All @@ -13,6 +14,8 @@ module.exports = function (opts) {
fg: opts.fg || 'white'
});

var i18n = opts.i18n || {}

menu.reset();

var title = opts.title || 'UNTITLED\n';
Expand All @@ -22,27 +25,27 @@ module.exports = function (opts) {
(opts.names || []).forEach(function (name) {
var isDone = (opts.completed || []).indexOf(name) >= 0;
if (isDone) {
var m = '[COMPLETED]';
var m = i18n.completed;
menu.add(
name
+ Array(65 - m.length - name.length + 1).join(' ')
+ Array(65 - vw.width(m) - vw.width(name) + 1).join(' ')
+ m
);
}
else menu.add(name);
});
menu.write('-----------------\n');
menu.add('HELP');
menu.add('EXIT');
menu.add(i18n.help);
menu.add(i18n.exit);

menu.on('select', function (label) {
var name = label.replace(/\s{2}.*/, '');

menu.close();
if (name === 'EXIT') {
if (name === i18n.exit) {
return emitter.emit('exit');
}
else if (name === 'HELP') {
else if (name === i18n.help) {
console.log();
showHelp(opts);
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"split": "~0.3.0",
"terminal-menu": "~0.2.0",
"through2": "~0.5.1",
"visualwidth": "0.0.1",
"x256": "~0.0.1"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions readme.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ completed levels. default: `'~/.config/' + opts.name`
* `opts.fg` - menu foreground color
* `opts.bg` - menu background color

* `opts.usage` - stream providing a different usage template (see below)
* `opts.i18n` - object mapping to alternative language strings (see `/lib/en.json`)

If `opts` is a string, it will be treated as the `opts.name`.

## shop.add(name, fn)
Expand Down

0 comments on commit 2372781

Please sign in to comment.