Skip to content
Browse files

refactor and tests almost done

  • Loading branch information...
1 parent f4df90b commit cadeaecc65264b1421165eafa3868947ec823df3 @masylum committed Mar 15, 2011
View
2 Readme.md
@@ -25,7 +25,7 @@ Dialect is the painless nodejs module that deals with i18n.
var dialect = require('dialect').dialect({current_locale: 'es', store: 'mongodb'});
- d.sync('all', 3600, function (err, foo) {
+ dialect.sync({interval:3600}, function (err, foo) {
d.get('Hello World!'); // => Hola mundo
});
View
0 examples/contexts.js
No changes.
View
17 examples/hello_world.js
@@ -0,0 +1,17 @@
+var dialect = require('..').dialect({
+ locales: ['es', 'en'],
+ current_locale: 'es',
+ store: {mongodb: {}}
+ }),
+ _ = dialect.get,
+ original = 'Hello World!',
+ translation = 'Hola Mundo!';
+
+console.log(_(original));
+dialect.set({original: original, locale: 'es'}, translation);
+
+dialect.sync({interval: 3600}, function (err, foo) {
+ console.log(_(original));
+ console.log(_('Inexistant'));
+ process.exit();
+});
View
22 examples/plurals.js
@@ -0,0 +1,22 @@
+var dialect = require('..').dialect({
+ locales: ['es', 'en'],
+ current_locale: 'es',
+ store: {mongodb: {}}
+ }),
+ _ = dialect.get;
+
+[1, 2, 3].forEach(function (i) {
+ console.log(_(['{count} Beer', '{count} Beers', {count: i}]));
+});
+
+dialect.set({original: '{count} Beer', locale: 'es', plural: 1}, '{count} pivo');
+dialect.set({original: '{count} Beer', locale: 'es', plural: 2}, '{count} pivi');
+dialect.set({original: '{count} Beer', locale: 'es', plural: 3}, '{count} piva');
+
+dialect.sync({interval: 3600}, function (err, foo) {
+ [1, 2, 3].forEach(function (i) {
+ console.log(_(['{count} Beer', '{count} Beers', {count: i}]));
+ });
+ process.exit();
+});
+
View
74 lib/dialect.js
@@ -15,10 +15,18 @@ module.exports = function (options) {
return str.replace(/\{([^}]+)\}/g, function (_, key) {
return params[key];
});
+ },
+
+ _connect = function (cb) {
+ if (DIALECT.store.is_connected()) {
+ cb();
+ } else {
+ DIALECT.store.connect(cb);
+ }
};
- // memory cache dictionaries
+ Object.defineProperty(DIALECT, 'store', {value : null, writable: true});
Object.defineProperty(DIALECT, 'dictionaries', {value : {}, writable: true});
/**
@@ -66,7 +74,7 @@ module.exports = function (options) {
}
if (!current_dictionary || _options.base_locale === _options.current_locale) {
- return original;
+ return _parse(Array.isArray(original) ? original[pluralize(params.count)] : original, params);
} else {
key = _io.getKeyFromQuery({
@@ -80,10 +88,12 @@ module.exports = function (options) {
}
if (typeof translation !== 'string') {
- _options.store.add(
- {original: index, locale: _options.current_locale},
- translation
- );
+ _connect(function () {
+ DIALECT.store.add(
+ {original: index, locale: _options.current_locale},
+ translation
+ );
+ });
return _parse(Array.isArray(original) ? original[pluralize(params.count)] : original, params);
} else {
return _parse(translation, params);
@@ -111,32 +121,70 @@ module.exports = function (options) {
}
// Database
- _options.store.set(query, {translation: translation}, cb);
+ _connect(function () {
+ DIALECT.store.set(query, {translation: translation}, cb);
+ });
return DIALECT;
};
/**
* Loads the dictionaries from the store
- * and re-caches them to memory
+ * and caches them to memory
*
* @param {String} locale
* @param {Function} cb
* @return dialect
*/
- DIALECT.reCache = function (locale, cb) {
- if (locale === null) {
- _options.locales.forEach(function (locale) {
- _io.cacheDictionary(locale, cb);
+ DIALECT.sync = function (options, cb) {
+ var executed = false,
+ funk = require('funk')(),
+
+ run_once = function (cb) {
+ return function () {
+ if (!executed) {
+ executed = true;
+ cb();
+ }
+ };
+ },
+
+ fn = function (cb) {
+ _connect(function () {
+ if (options.locale === undefined) {
+ _options.locales.forEach(function (locale) {
+ _io.cacheDictionary(locale, funk.nothing());
+ });
+ funk.parallel(run_once(cb));
+ } else {
+ _io.cacheDictionary(options.locale, run_once(cb));
+ }
+ });
+ };
+
+ if (options.interval) {
+ fn(function () {
+ cb();
+ DIALECT.interval = setInterval(fn, options.interval, function () { });
});
} else {
- _io.cacheDictionary(locale, cb);
+ fn(cb);
}
+
return DIALECT;
};
if (!_options || !_options.store) {
throw Error("You need to provide a store");
+ } else {
+ try {
+ (function () {
+ var lib = typeof _options.store === 'string' ? _options.store : Object.keys(_options.store)[0];
+ DIALECT.store = require('./stores/' + lib)(_options.store[lib]);
+ }());
+ } catch (exc) {
+ throw exc;
+ }
}
// defaults
View
2 lib/helpers/io.js
@@ -56,7 +56,7 @@ module.exports.IO = function (DIALECT) {
throw Error("You must provide a locale");
}
- DIALECT.config('store').get({locale: locale}, function (err, data) {
+ DIALECT.store.get({locale: locale}, function (err, data) {
var dictionary = {},
key = null,
i = null;
View
5 lib/store.js
@@ -1,5 +0,0 @@
-var path = './stores/';
-
-['mongodb', 'sqlite'/*, 'json', 'redis'*/].forEach(function (store) {
- module.exports[store] = require(path + store);
-});
View
30 lib/stores/mongodb.js
@@ -12,9 +12,11 @@ module.exports = function (options) {
var STORE = {},
- _default = function (callback) {
- callback = callback || function () { };
- };
+ _default = function (thing) {
+ return thing || function () { };
+ },
+
+ _is_connected = false;
options = options || {};
@@ -29,20 +31,30 @@ module.exports = function (options) {
)});
/**
+ * Exposes is_connected
+ *
+ * @return is_connected
+ */
+ STORE.is_connected = function () {
+ return _is_connected;
+ };
+
+ /**
* Connects to the Store
*
* @param {Function} callback
* @return store
*/
STORE.connect = function (callback) {
- _default(callback);
+ callback = _default(callback);
STORE.db.open(function (err, db) {
if (err) {
callback(err, null);
} else {
db.collection(options.collection || 'translations', function (err, collection) {
+ _is_connected = true;
STORE.collection = collection;
callback(err, collection);
});
@@ -61,7 +73,7 @@ module.exports = function (options) {
*/
STORE.get = function (query, callback) {
- _default(callback);
+ callback = _default(callback);
query = query || {};
STORE.collection.find(query, function (err, cursor) {
@@ -85,7 +97,7 @@ module.exports = function (options) {
*/
STORE.add = function (doc, translation, callback) {
- _default(callback);
+ callback = _default(callback);
STORE.collection.findOne(doc, function (err, data) {
if (err) {
@@ -116,7 +128,7 @@ module.exports = function (options) {
*/
STORE.set = function (query, translation, callback) {
- _default(callback);
+ callback = _default(callback);
query = query || {};
STORE.collection.update(query, {'$set': translation}, callback);
@@ -134,7 +146,7 @@ module.exports = function (options) {
STORE.destroy = function (query, callback) {
- _default(callback);
+ callback = _default(callback);
query = query || {};
STORE.collection.remove(query, callback);
@@ -152,7 +164,7 @@ module.exports = function (options) {
STORE.count = function (query, callback) {
- _default(callback);
+ callback = _default(callback);
query = query || {};
STORE.collection.count(query, callback);
View
30 lib/stores/sqlite.js
@@ -16,20 +16,31 @@ module.exports = function (options) {
_table = options.table || 'dialect',
_default = function (callback) {
- callback = callback || function () { };
- };
+ return callback || function () { };
+ },
+
+ _is_connected = false;
Object.defineProperty(STORE, 'db', {value : new sqlite.Database()});
/**
+ * Exposes is_connected
+ *
+ * @return is_connected
+ */
+ STORE.is_connected = function () {
+ return _is_connected;
+ };
+
+ /**
* Connects to the Store
*
* @param {Function} callback
* @return store
*/
STORE.connect = function (callback) {
- _default(callback);
+ callback = _default(callback);
STORE.db.open(options.database || 'dialect.db', function (err) {
if (err) {
@@ -40,6 +51,9 @@ module.exports = function (options) {
' (original TEXT, locale TEXT, translation TEXT,' +
' plural NUMBER, context TEXT, PRIMARY KEY(original, locale, plural, context))',
function (err, data) {
+ if (!err) {
+ _is_connected = true;
+ }
callback(err, data);
}
);
@@ -58,7 +72,7 @@ module.exports = function (options) {
*/
STORE.get = function (query, callback) {
- _default(callback);
+ callback = _default(callback);
STORE.db.execute(
sqlizer({table: _table}).find(query).sql,
@@ -80,7 +94,7 @@ module.exports = function (options) {
*/
STORE.add = function (doc, translation, callback) {
- _default(callback);
+ callback = _default(callback);
STORE.get(doc, function (err, data) {
if (err) {
@@ -111,7 +125,7 @@ module.exports = function (options) {
*/
STORE.set = function (query, translation, callback) {
- _default(callback);
+ callback = _default(callback);
STORE.db.execute(sqlizer({table: _table}).update(query, {'$set': {translation: translation}}).sql, callback);
@@ -128,7 +142,7 @@ module.exports = function (options) {
STORE.destroy = function (query, callback) {
- _default(callback);
+ callback = _default(callback);
STORE.db.execute(sqlizer({table: _table}).remove(query).sql, callback);
@@ -144,7 +158,7 @@ module.exports = function (options) {
*/
STORE.count = function (query, callback) {
- _default(callback);
+ callback = _default(callback);
STORE.db.execute(sqlizer({table: _table}).find(query).count().sql, function (err, data) {
callback(err, !err && data && data.length ? data[0].count : 0);
View
95 test/dialect.js
@@ -10,6 +10,12 @@ var testosterone = require('testosterone')({title: 'Dialect core'}),
return io;
});
return io;
+ },
+
+ _stubConnect = function (dialect) {
+ gently.expect(dialect.store, 'connect', function (cb) {
+ cb();
+ });
};
testosterone
@@ -29,7 +35,7 @@ testosterone
.add(' WHEN no `base_locale` or `current_locale` given \n' +
' THEN it should use `en` as default', function (spec) {
- var options = {store: {}},
+ var options = {store: {mongodb: {}}},
d = dialect(options);
spec(function () {
@@ -40,7 +46,7 @@ testosterone
.add(' WHEN no `locales` given \n' +
' THEN it should use `[en]` as default', function (spec) {
- var options = {store: {}},
+ var options = {store: {mongodb: {}}},
d = dialect(options);
spec(function () {
@@ -55,7 +61,7 @@ testosterone
.add(' GIVEN a call to config \n' +
' WHEN just param `key` is given \n' +
' THEN it should return `_option[key]`', function (spec) {
- var options = {store: {}, base_locale: 'en'},
+ var options = {store: {mongodb: {}}, base_locale: 'en'},
d = dialect(options);
spec(function () {
@@ -65,17 +71,17 @@ testosterone
.add(' WHEN no params given \n' +
' THEN it should return the whole `_option`', function (spec) {
- var options = {store: {}, base_locale: 'en'},
+ var options = {store: {mongodb: {}}, base_locale: 'en'},
d = dialect(options);
spec(function () {
- assert.deepEqual(d.config(), {store: {}, base_locale: 'en', current_locale: 'en', locales: ['en']});
+ assert.deepEqual(d.config(), {store: {mongodb: {}}, base_locale: 'en', current_locale: 'en', locales: ['en']});
})();
})
.add(' WHEN `key` and `value` params given \n' +
' THEN it should set the `_option[key]` to `value`', function (spec) {
- var options = {store: {}, base_locale: 'en'},
+ var options = {store: {mongodb: {}}, base_locale: 'en'},
d = dialect(options);
d.config('base_locale', 'es');
@@ -86,26 +92,75 @@ testosterone
})
////////////////////////////////////////////
- // reCache
+ // sync
////////////////////////////////////////////
- .add('GIVEN a call to `reCache` \n' +
+ .add('GIVEN a call to `sync` \n' +
' WHEN asking for a `locale` \n' +
' THEN should call `cacheDicionary` of `IO`', function (spec) {
- var store = {},
+ var store = {mongodb: {}},
options = {locales: ['en', 'es'], store: store},
io = _stubIO(),
d = dialect(options),
cb = function () { };
spec();
+ _stubConnect(d);
gently.expect(io, 'cacheDictionary', function (locale, cb) {
assert.equal(locale, 'en');
assert.ok(cb);
});
- d.reCache('en', cb);
+
+ d.sync({locale: 'en'}, cb);
+ })
+
+ .add(' WHEN not asking for a `locale` \n' +
+ ' THEN should call `cacheDicionary` for each locale', function (spec) {
+
+ var store = {mongodb: {}},
+ options = {locales: ['en', 'es'], store: store},
+ io = _stubIO(),
+ d = dialect(options),
+ cb = function () { };
+
+ spec();
+
+ _stubConnect(d);
+ options.locales.forEach(function (l) {
+ gently.expect(io, 'cacheDictionary', function (locale, cb) {
+ assert.equal(locale, l);
+ assert.ok(cb);
+ });
+ });
+ d.sync({}, cb);
+ })
+
+ .add(' WHEN passing a `interval` \n' +
+ ' THEN should call `cacheDicionary` every `interval` seconds', function (spec) {
+
+ var store = {mongodb: {}},
+ options = {locales: ['en', 'es'], store: store},
+ io = _stubIO(),
+ d = dialect(options),
+ cb = function () { };
+
+ spec();
+
+ _stubConnect(d);
+ gently.expect(io, 'cacheDictionary', function (locale, cb) {
+ assert.equal(locale, 'es');
+ assert.ok(cb);
+ cb();
+ });
+
+ gently.expect(require('timers'), 'setInterval', function (fn, delay) {
+ assert.ok(fn);
+ assert.equal(delay, 3000);
+ });
+
+ d.sync({locale: 'es', interval: 3000}, cb);
})
////////////////////////////////////////////
@@ -116,7 +171,7 @@ testosterone
' WHEN `query.original` or `query.locale` or `translation` is missing \n' +
' THEN an error should be thrown', function (spec) {
- var options = {locales: ['en', 'es'], store: {}},
+ var options = {locales: ['en', 'es'], store: {mongodb: {}}},
d = dialect(options);
spec();
@@ -141,7 +196,7 @@ testosterone
.add(' WHEN `query.original` and `query.locale` and `translation` are valid \n' +
' THEN should set the translation to the `store`', function (spec) {
- var store = {},
+ var store = {mongodb: {}},
query = {original: 'hello', locale: 'foo'},
translation = 'foola',
options = {locales: ['en', 'es'], store: store},
@@ -153,7 +208,8 @@ testosterone
spec();
- gently.expect(store, 'set', function (q, u, cb) {
+ _stubConnect(d);
+ gently.expect(d.store, 'set', function (q, u, cb) {
assert.deepEqual(q, query);
assert.deepEqual(u, {translation: translation});
assert.deepEqual(cb, callback);
@@ -171,7 +227,7 @@ testosterone
' WHEN `original` is not provided or invalid (String|Array) \n' +
' THEN an error should be thrown', function (spec) {
- var options = {locales: ['en', 'es'], store: {}},
+ var options = {locales: ['en', 'es'], store: {mongodb: {}}},
d = dialect(options);
spec();
@@ -190,7 +246,7 @@ testosterone
.add(' WHEN `original` is valid and cached on memory \n' +
' THEN should return the parsed translation from memory', function (spec) {
- var options = {locales: ['en', 'es', 'sl'], store: {}, current_locale: 'es'},
+ var options = {locales: ['en', 'es', 'sl'], store: {mongodb: {}}, current_locale: 'es'},
d = dialect(options);
d.dicionaries = {};
@@ -245,11 +301,11 @@ testosterone
' THEN should try to store the new word on the `store` \n' +
' AND should return original in singular or plural form', function (spec) {
- var store = {},
+ var store = {mongodb: {}},
options = {locales: ['en', 'es'], current_locale: 'es', store: store},
d = dialect(options),
stub_add = function (original) {
- gently.expect(store, 'add', function (q, u, cb) {
+ gently.expect(d.store, 'add', function (q, u, cb) {
assert.deepEqual(q, {original: original, locale: 'es'});
assert.deepEqual(u, undefined);
});
@@ -259,17 +315,22 @@ testosterone
spec();
+ _stubConnect(d);
// no params
stub_add('One cat');
assert.equal(d.get('One cat'), 'One cat');
+ _stubConnect(d);
// singular
stub_add('cat');
assert.equal(d.get(['cat', 'cats', {count: 1}]), 'cat');
+ _stubConnect(d);
// plural
stub_add('cat');
assert.equal(d.get(['cat', 'cats', {count: 2}]), 'cats');
+
+ _stubConnect(d);
stub_add('cat');
assert.equal(d.get(['cat', 'cats', {count: 3}]), 'cats');
})
View
9 test/io.js
@@ -1,10 +1,11 @@
var testosterone = require('testosterone')({title: 'IO helper lib'}),
assert = testosterone.assert,
gently = global.GENTLY = new (require('gently')),
- store = {},
- dialect = require('./..').dialect({locales: ['en', 'es'], current_locale: 'es', store: store}),
+ dialect = require('./..').dialect({locales: ['en', 'es'], current_locale: 'es', store: {mongodb: {}}}),
io = require('./../lib/helpers/io').IO(dialect);
+dialect.store = {};
+
testosterone
////////////////////////////////////////////
@@ -56,7 +57,7 @@ testosterone
' THEN it should get the dictionary from the store \n' +
' AND cache it on memory', function (spec) {
spec(function () {
- gently.expect(store, 'get', function (query, cb) {
+ gently.expect(dialect.store, 'get', function (query, cb) {
assert.deepEqual(query, {locale: 'es'});
assert.ok(query, cb);
cb(null, [{original: 'hello', translation: 'hola'}]);
@@ -70,7 +71,7 @@ testosterone
assert.deepEqual(dialect.dictionaries.es, {hello: 'hola'});
// with plural and contexts
- gently.expect(store, 'get', function (query, cb) {
+ gently.expect(dialect.store, 'get', function (query, cb) {
assert.deepEqual(query, {locale: 'es'});
assert.ok(query, cb);
cb(null, [{original: 'hello', translation: 'hola', context: 'salute', plural: 1}]);
View
13 test/stores/mongodb.js
@@ -1,5 +1,6 @@
var testosterone = require('testosterone')({title: 'Mongodb store'}),
assert = testosterone.assert,
+ STORE = require('../../lib/stores/mongodb'),
gently = global.GENTLY = new (require('gently'));
testosterone
@@ -15,7 +16,7 @@ testosterone
spec(function () {
var db = {},
- store = require('../../lib/store').mongodb();
+ store = STORE();
// error
gently.expect(store.db, 'open', function (cb) {
@@ -56,7 +57,7 @@ testosterone
' AND return the translation according to `query`', function (spec) {
spec(function () {
- var store = require('../../lib/store').mongodb();
+ var store = STORE();
store.collection = {};
@@ -102,7 +103,7 @@ testosterone
' AND add the `translation` if is not on the store', function (spec) {
spec(function () {
- var store = require('../../lib/store').mongodb(),
+ var store = STORE(),
original = {original: 'hello'},
new_doc = {original: 'hello', translation: 'hola'};
@@ -162,7 +163,7 @@ testosterone
' AND update the translations according to `query` and `update`', function (spec) {
spec(function () {
- var store = require('../../lib/store').mongodb(),
+ var store = STORE(),
original = {original: 'hello'},
translation = {translation: 'hola'},
new_doc = {original: 'hello', translation: 'hola'};
@@ -194,7 +195,7 @@ testosterone
' AND remove the translation according to `query`', function (spec) {
spec(function () {
- var store = require('../../lib/store').mongodb(),
+ var store = STORE(),
original = {original: 'hello'};
store.collection = {};
@@ -223,7 +224,7 @@ testosterone
' AND count the translations according to `query`', function (spec) {
spec(function () {
- var store = require('../../lib/store').mongodb(),
+ var store = STORE(),
original = {original: 'hello'};
store.collection = {};
View
13 test/stores/sqlite.js
@@ -1,5 +1,6 @@
var testosterone = require('testosterone')({title: 'SQLite store'}),
assert = testosterone.assert,
+ SQLITE = require('../../lib/stores/sqlite'),
gently = global.GENTLY = new (require('gently'));
testosterone
@@ -15,7 +16,7 @@ testosterone
spec(function () {
var db = {},
- store = require('../../lib/store').sqlite({table: 'test'});
+ store = SQLITE({table: 'test'});
// error
gently.expect(store.db, 'open', function (database, cb) {
@@ -63,7 +64,7 @@ testosterone
' AND return the translation according to `query`', function (spec) {
spec(function () {
- var store = require('../../lib/store').sqlite();
+ var store = SQLITE();
store.collection = {};
@@ -104,7 +105,7 @@ testosterone
' AND add the `translation` if is not on the store', function (spec) {
spec(function () {
- var store = require('../../lib/store').sqlite(),
+ var store = SQLITE(),
original = {original: 'hello'},
new_doc = {original: 'hello', translation: 'hola'};
@@ -164,7 +165,7 @@ testosterone
' AND update the translations according to `query` and `update`', function (spec) {
spec(function () {
- var store = require('../../lib/store').sqlite();
+ var store = SQLITE();
store.collection = {};
@@ -192,7 +193,7 @@ testosterone
' AND remove the translation according to `query`', function (spec) {
spec(function () {
- var store = require('../../lib/store').sqlite(),
+ var store = SQLITE(),
original = {original: 'hello'};
store.collection = {};
@@ -221,7 +222,7 @@ testosterone
' AND count the translations according to `query`', function (spec) {
spec(function () {
- var store = require('../../lib/store').sqlite(),
+ var store = SQLITE(),
original = {original: 'hello'};
store.collection = {};

0 comments on commit cadeaec

Please sign in to comment.
Something went wrong with that request. Please try again.