Skip to content

Commit

Permalink
First version finished! All tests up and running.
Browse files Browse the repository at this point in the history
  • Loading branch information
masylum committed Oct 28, 2010
1 parent 3f65992 commit 6ce7d1d
Show file tree
Hide file tree
Showing 18 changed files with 128 additions and 202 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -7,3 +7,6 @@
[submodule "support/vows"]
path = support/vows
url = http://github.com/cloudhead/vows.git
[submodule "support/lingo"]
path = support/lingo
url = git@github.com:masylum/lingo.git
12 changes: 11 additions & 1 deletion Readme.md
@@ -1,4 +1,12 @@
# Dialect
,, ,, ,,
`7MM db `7MM mm
MM MM MM
,M""bMM `7MM ,6"Yb. MM .gP"Ya ,p6"bo mmMMmm
,AP MM MM 8) MM MM ,M' Yb 6M' OO MM
8MI MM MM ,pm9MM MM 8M"""""" 8M MM
`Mb MM MM 8M MM MM YM. , YM. , MM
`Wbmd"MML..JMML.`Moo9^Yo..JMML.`Mbmmd' YMbmd' `Mbmo


Dialect is a painless nodejs library to deal with i18n, and L10n.

Expand Down Expand Up @@ -85,4 +93,6 @@ This module is currently *under construction*

Dialect is heavily tested using a mix of Vows and node asserts module.

npm install eyes

make test
82 changes: 65 additions & 17 deletions lib/dialect.js
Expand Up @@ -3,7 +3,19 @@ var fs = require('fs');
module.exports = function (options) {
var dialect = {},
funk = require('./../support/funk/lib/funk'),
lingo = require('./../support/lingo'),
Language = lingo.Language,
dictionaries = {},
current_language = null,

parse = function (str, params) {
var matches = /(\{(.*?)\})+/g.exec(str);

// shameless copy/inspiration from lingo (TJ)
return str.replace(/\{([^}]+)\}/g, function (_, key) {
return params[key];
});
},

loadDictionariesToMemory = function (reload) {
options.locales.forEach(function (locale) {
Expand All @@ -23,15 +35,11 @@ module.exports = function (options) {
options.store.get({locale: locale}, fk.add(function (err, data) {
var json = {}, i = null;
for (i in data) {
if (Object.keys(data[i]).length === 4) {
json[data[i].original] = data[i].translation;
} else {
json[data[i].original] = {
translation: data[i].translation,
count: data[i].count,
context: data[i].context
};
}
json[data[i].original] = {
translation: data[i].translation,
count: data[i].count,
context: data[i].context
};
}
fs.writeFileSync(
options.path + locale + '.js',
Expand Down Expand Up @@ -106,9 +114,20 @@ module.exports = function (options) {
};

dialect.config = function (key, value) {

if (value !== undefined) {
options[key] = value;

switch (key) {
case 'current_locale':
current_language = new Language(value);
break;
case 'path':
options.path = value.replace(/(.*)\/?/, '$1/');
break;
}
}

return options[key];
};

Expand All @@ -124,6 +143,9 @@ module.exports = function (options) {
*/
dialect.getTranslation = function (original, callback) {
var translation = '',
params = Array.isArray(original) ? original.slice(-1)[0] : {},
index = 0,
str_original = original,
i = 0;

if ((typeof original !== 'string' && !Array.isArray(original)) || original.length === 0) {
Expand All @@ -138,12 +160,25 @@ module.exports = function (options) {
if (Object.keys(dictionaries).length === 0) {
loadDictionariesToMemory();
}
translation = dictionaries[options.current_locale][original];

if (params.count) {
index = current_language.isPlural(params.count) ? 0 : 1;
str_original = Array.isArray(original) ? original[index] : original;
}

if (Object.keys(dictionaries[options.current_locale]).length > 0) {
translation = dictionaries[options.current_locale][str_original];
if (typeof translation === 'object') {
translation = translation.translation; // lol
}
} else {
translation = undefined;
}

if (translation === undefined) {
storeNewTranslation(original, callback);
}
return translation || original;
return parse(translation || str_original, params);
}
};

Expand All @@ -163,18 +198,29 @@ module.exports = function (options) {
* @api public
*/
dialect.setTranslation = function (query, translation, callback) {
var fk = funk();
var fk = funk(),
update = {translation: translation};

// COUNT
if (query.count) {
query = {original: query.original, locale: query.locale, count: query.count};
}

// CONTEXT
if (query.context) {
update.context = query.context;
}

// DB
if (options.store) {
options.store.set(query, translation, fk.nothing()); // fire and forget
options.store.set(query, update, fk.nothing()); // fire and forget
}

// JSON store
addTranslationToJSON(query, translation, fk.nothing());
addTranslationToJSON(query, update, fk.nothing());

// Memory
dictionaries[query.locale][query.original] = translation;
dictionaries[query.locale][query.original] = update;

fk.parallel(function () {
if (callback) {
Expand All @@ -187,11 +233,13 @@ module.exports = function (options) {
// INIT
if (!options || !options.path) {
throw new Error("You need to provide the path where you want to store the JSON dictionaries");
} else {
options.path = options.path.replace(/(.*)\/?/, '$1/');
}

options.base_locale = options.base_locale || 'en';

['path', 'current_locale'].forEach(function (conf) {
dialect.config(conf, options[conf]);
});

return dialect;
};
5 changes: 3 additions & 2 deletions lib/stores/mongodb.js
Expand Up @@ -79,6 +79,7 @@ module.exports = function (options, callback) {
} else {
doc = {original: query.original, locale: query.locale, translation: translation};
}

this.collection.findOne({original: query.original, locale: query.locale}, function (err, data) {
if (!data) {
self.collection.insert(
Expand Down Expand Up @@ -111,11 +112,11 @@ module.exports = function (options, callback) {
* @param {Function} callback
* @api public
*/
mongoStore.set = function (query, translation, callback) {
mongoStore.set = function (query, update, callback) {
try {
this.collection.update(
query,
{'$set': {translation: translation}},
{'$set': update},
function (err, data) {
if (callback) {
callback(err, mongoStore);
Expand Down
1 change: 1 addition & 0 deletions support/lingo
Submodule lingo added at 262e01
1 change: 0 additions & 1 deletion test/data/integration/ca.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/en.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/en_en.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/es.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/es_es.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/fr.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/it.js

This file was deleted.

1 change: 0 additions & 1 deletion test/data/integration/pt.js

This file was deleted.

28 changes: 0 additions & 28 deletions test/helpers/stores.js

This file was deleted.

67 changes: 45 additions & 22 deletions test/integration_test.js
Expand Up @@ -101,9 +101,15 @@ var fs = require('fs'),

// JSON
if (locale === dialect.config('base_locale')) {
test(assert.equal, [original, JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original]]);
test(assert.equal, [
original,
JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original].translation
]);
} else {
test(assert.equal, [JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original], null]);
test(assert.equal, [
JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original].translation,
null
]);
}

// Memory (Missing translations always get same str)
Expand All @@ -129,7 +135,10 @@ var fs = require('fs'),
test(assert.equal, [data[0].translation, translation]);

// JSON available on this local machine, but on other they need to sync
test(assert.equal, [JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original], translation]);
test(assert.equal, [
JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original].translation,
translation
]);

// Memory available on this local machine
test(assert.equal, [dialect.getTranslation(original), translation]);
Expand Down Expand Up @@ -161,7 +170,6 @@ var fs = require('fs'),
// get Store and empty the DB
require('./..').store({store: 'mongodb', database: 'test_2'}, function (error, store) {
store.collection.remove({}, function (err, data) {

// GIVEN a store
// =============
var original = 'E muito bom', translation = 'Esta molt be';
Expand Down Expand Up @@ -224,8 +232,14 @@ var fs = require('fs'),
// THEN it should get it from DB files and populate JSON and memory again
// ======================================================================
translated_string = dialect.getTranslation(original, function (err, data) {
test(assert.equal, [JSON.parse(fs.readFileSync(dialect.config('path') + 'it.js').toString())[original], original]);
test(assert.equal, [JSON.parse(fs.readFileSync(dialect.config('path') + 'fr.js').toString())[original], translation]);
test(assert.equal, [JSON.parse(fs.readFileSync(
dialect.config('path') + 'it.js').toString())[original].translation,
original
]);
test(assert.equal, [JSON.parse(fs.readFileSync(
dialect.config('path') + 'fr.js').toString())[original].translation,
translation
]);
exit();
});

Expand Down Expand Up @@ -258,13 +272,14 @@ var fs = require('fs'),
require('./..').store({store: 'mongodb', database: 'test_4'}, function (error, store) {
store.collection.remove({}, function (err, data) {

var options = {count: 1, context: 'females', what: 'good'},
var options = {count: 1, context: 'females', name: 'Anna'},
original = [
'You have {count} {what} friend',
'You have {count} {what} friends',
'You have {count} friend called {name}',
'You have {count} friends called {name}',
options
],
translation = 'Tienes 1 buena amiga'; // If this works, I'm a genius
translation = 'Tienes {count} amiga llamada {name}',
parsed_translation = 'Tienes 1 amiga llamada Anna'; // If this works, I'm a genius

dialect.config('store', store);

Expand Down Expand Up @@ -324,38 +339,46 @@ var fs = require('fs'),
}
}());

// Memory (Missing translations always get same str)
test(assert.equal, [dialect.getTranslation(original), original]);
// Memory (Missing translations get same str but parsed)
test(assert.equal, [dialect.getTranslation(original), 'You have 1 friend called Anna']);
});

fk.parallel(function () {
exit();
/*

// WHEN a translator introduces a translation to a target locale
// =============================================================
translation = 'Me encanta el gazpacho';
locale = 'es';

dialect.setTranslation({original: original, locale: locale}, translation, function () {
dialect.setTranslation({
original: original[0],
locale: dialect.config('current_locale'),
context: 'female',
count: 'singular'
}, translation, function () {

// THEN it should save it to the Store, JSON and Memory for each locale
// ====================================================================
dialect.config('store').get({original: original, locale: locale}, function (err, data) {
dialect.config('store').get(
{original: original[0], locale: dialect.config('current_locale')}, function (err, data) {
var locale = dialect.config('current_locale');

// DB
test(assert.equal, [data[0].locale, locale]);
test(assert.equal, [data[0].original, original]);
test(assert.equal, [data[0].original, original[0]]);
test(assert.equal, [data[0].translation, translation]);

// JSON available on this local machine, but on other they need to sync
test(assert.equal, [JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original], translation]);
test(assert.equal, [
JSON.parse(fs.readFileSync(dialect.config('path') + locale + '.js').toString())[original[0]].translation,
'Tienes {count} amiga llamada {name}'
]);

// Memory available on this local machine
test(assert.equal, [dialect.getTranslation(original), translation]);
test(assert.equal, [dialect.getTranslation(original), parsed_translation]);

exit(); // OMG, I'm a genius!

});
});
*/
});

});
Expand Down

0 comments on commit 6ce7d1d

Please sign in to comment.