126 lines
3.0 KiB
JavaScript
126 lines
3.0 KiB
JavaScript
var _ = require('lodash');
|
|
var path = require('path');
|
|
var fs = require('fs');
|
|
|
|
function I18n(opts) {
|
|
if (!(this instanceof I18n)) return new I18n(opts);
|
|
|
|
this.opts = _.defaults(opts || {}, {
|
|
defaultLocale: 'en'
|
|
});
|
|
|
|
this._locales = {};
|
|
|
|
_.bindAll(this, _.functionsIn(this));
|
|
}
|
|
|
|
// Extend locales
|
|
I18n.prototype.set = function(_locales) {
|
|
this._locales = _.extend(this._locales, _locales);
|
|
};
|
|
|
|
// Return a locales or all
|
|
I18n.prototype.get = function(lang) {
|
|
if (lang) {
|
|
lang = this.resolve(lang);
|
|
return this._locales[lang];
|
|
} else {
|
|
return this._locales;
|
|
}
|
|
};
|
|
|
|
// Return list of locales
|
|
I18n.prototype.locales = function() {
|
|
return _.keys(this._locales);
|
|
};
|
|
|
|
// Load locales from a folder
|
|
I18n.prototype.load = function(root) {
|
|
var locales = _.chain(fs.readdirSync(root))
|
|
.map(function(filename) {
|
|
var ext = path.extname(filename);
|
|
if (ext != '.json' && ext != '.js') return;
|
|
|
|
var lang = path.basename(filename, ext);
|
|
var filepath = path.resolve(root, filename);
|
|
|
|
return [
|
|
lang,
|
|
require(filepath)
|
|
];
|
|
})
|
|
.compact()
|
|
.fromPairs()
|
|
.value();
|
|
|
|
this.set(locales);
|
|
};
|
|
|
|
// Resolve a language to an existing locale
|
|
I18n.prototype.resolve = function(lang, defaultLocale) {
|
|
defaultLocale = _.isUndefined(defaultLocale)? this.opts.defaultLocale : defaultLocale;
|
|
|
|
return _.chain(this.locales())
|
|
.map(function(locale) {
|
|
return {
|
|
locale: locale,
|
|
score: compareLocales(lang, locale)
|
|
};
|
|
})
|
|
.filter(function(lang) {
|
|
return lang.score > 0;
|
|
})
|
|
.sortBy('score')
|
|
.map('locale')
|
|
.last()
|
|
.value() || defaultLocale;
|
|
};
|
|
|
|
// Translate a phrase
|
|
I18n.prototype.t = function(lang, phrase) {
|
|
var args = _.toArray(arguments).slice(2);
|
|
var kwargs = {};
|
|
var locale = this.get(lang);
|
|
|
|
if (_.isObject(_.last(args))) {
|
|
kwargs = _.last(args);
|
|
args = args.slice(0, -1);
|
|
}
|
|
|
|
var tpl = locale[phrase];
|
|
|
|
if (_.isUndefined(tpl)) {
|
|
tpl = this.get(this.opts.defaultLocale)[phrase];
|
|
}
|
|
|
|
return interpolate(tpl || phrase, args, kwargs);
|
|
};
|
|
|
|
// Compare two language to find the most adequate
|
|
function compareLocales(lang, locale) {
|
|
var langMain = _.first(lang.split('-'));
|
|
var langSecond = _.last(lang.split('-'));
|
|
|
|
var localeMain = _.first(locale.split('-'));
|
|
var localeSecond = _.last(locale.split('-'));
|
|
|
|
if (locale == lang) return 100;
|
|
if (localeMain == langMain && localeSecond == localeMain) return 51;
|
|
if (localeMain == langMain) return 50;
|
|
if (localeSecond == langSecond) return 20;
|
|
return 0;
|
|
}
|
|
|
|
// Interpolate a template
|
|
function interpolate(tpl, args, kwargs) {
|
|
var value = tpl;
|
|
kwargs = _.extend(kwargs, args);
|
|
|
|
return _.reduce(kwargs, function(value, val, key) {
|
|
var re = /{{([\s\S]*?[^\$])}}/g;
|
|
return value.replace(re, val);
|
|
}, tpl);
|
|
}
|
|
|
|
module.exports = I18n;
|