UNPKG

loc

Version:

lightweight simple translation module with dynamic json storage

246 lines (229 loc) 7.99 kB
/** * Checks if 'html' is part of the request header. * @param {Object} req Express / Connect Request Object * @return {Boolean} true, if the term 'html' was found in the request header. */ exports.acceptsHtmlExplicit = function(req) { var accept = req.headers["accept"]; if (!accept) return false; return (~accept.indexOf("html")); } /** * Checks whether the term 'str' contains a term that is in the 'excludeList'. * @param {String} str Term to search in. * @param {Array} excludeList The exclude list array. * @return {Boolean} true if at least one of the 'excludeList' terms was found inside 'str'. */ exports.isExcluded = function(str, excludeList) { var excluded = false; if (!str) return true; excludeList.forEach(function(exclude) { if (~str.indexOf(exclude)) { excluded = true; } }); return excluded; } /** * Load the dependency scripts from the file system. * @param {Object} dependencies [optional: Dependency object] * @param {String} type dependency type * @return {Object} dependencies lookup Object. */ exports.loadDependencies = function(dependencies, type) { if (!type) type = dependencies, dependencies = {}; var fs = require('fs'); fs.readdirSync(__dirname + '/' + type).forEach(function(filename) { if (!/\.js$/.test(filename)) return; var name = filename.replace('.js', ''); dependencies[name] = require('./' + type + '/' + name); }); return dependencies; } /** * Gets the dependency. * First looks it up in the `dependencies` Object. * Then tries to require the `dependency` String. * Then check if the `dependency` is a valid dependency Object. * If all of the checks fail, throws an error. * * @param {Object} dependencies dependencies lookup Object * @param {String|Object} dependency String:path to the dependency | or Object:the external dependency * @return {Object} the dependency Object, or throws an error. */ exports.getDependency = function(dependencies, dependency) { var loaded; if (typeof dependency == 'string') { // try load built in dependency loaded = dependencies[dependency]; if (loaded) return loaded; // try require the dependency try { loaded = require(dependency); dependencies[loaded.name] = loaded; return loaded; } catch (err) { throw new('dependency could not be loaded' + err); } } else if (dependency.name) { dependencies[dependency.name] = dependency; return dependency; } throw new('dependency could not be loaded' + err); }; exports.languagePattern = '([a-zA-Z]{1,3}(?:-(?:[a-zA-Z0-9]{2,8}))*)'; /** * Extracts the context out of the translation key 'str'. * E.g.: url/sitewide -> returns: url/ * @param {String} str The translation key * @return {String} The extracted context. */ exports.extractContext = function(str) { var index = str.lastIndexOf('/'); str = str.substr(0, index + 1); if (str == '') str = '/'; return str; } /** * Extracts the key out of the translation key 'str'. * E.g.: url/sitewide -> returns: sitewide * @param {String} str The translation key * @return {String} The extracted key. */ exports.extractKey = function(str) { var index = str.lastIndexOf('/'); return str.substr(index + 1); } /** * Returns the key path to lookup in the 'localeCache'. * It converts e.g. * locale=de-ch * context=url/client/title * -> to: * de-ch.url.client./.title * * @param {String} locale The locale string: e.g. en or en-GB * @param {String} context The context e.g. url/client/ or context combined with the key. e.g. url/client/title * @param {String} key Optional: key. e.g. title * @return {String} The converted string for the localeCache lookup. E.g.: de-ch.url.client./.title */ exports.getKeyPath = function(locale, context, key) { var keyString = key ? '.' + Key : ''; return locale + exports.ctxToQueryString(context) + keyString; } exports.ctxToQueryString = function(ctx) { var index = ctx.lastIndexOf('/'); ctx = ctx.replace('/', '.'); ctx = ctx.substr(0, index) + './.' + ctx.substr(index + 1); if (ctx.charAt(0) != '.') ctx = '.' + ctx; // add dot in the beginning if (ctx.charAt(ctx.length - 1) == '.') ctx = ctx.substr(0, ctx.length - 1); // remove dot in the end return ctx; } /** * @see: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key. * @param {Object} o The Object to query * @param {String} s The String query like: 'part3[0].name' * @return {Object} The search result according to the query(s) on the object(o). */ exports.queryObj = function(o, s) { s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties s = s.replace(/^\./, ''); // strip a leading dot var a = s.split('.'); while (a.length) { var n = a.shift(); if (n in o) { o = o[n]; } else { return; } } return o; } /** * @see: http://stackoverflow.com/questions/5484673/javascript-how-to-dynamically-create-nested-objects-using-object-names-given-by * @param {Object} o Object to query. * @param {Object|String} keyPath The Key path on the object(o) to set the value on. e.g. 'a.b.c' or ['a', 'b', 'c'] * @return {Boolean} true, if the object exists, else false. */ exports.existsObj = function(o, keyPath) { if ('string' == typeof keyPath) keyPath = keyPath.split('.'); for (var i = 0; i < keyPath.length; i++) { key = keyPath[i]; if (!(key in o)) return false; o = o[key]; } return true; } /** * @see: http://stackoverflow.com/questions/5484673/javascript-how-to-dynamically-create-nested-objects-using-object-names-given-by * @param {Object} o Object to query. * @param {Object|String} keyPath The Key path on the object(o) to set the value on. e.g. 'a.b.c' or ['a', 'b', 'c'] * @return {Boolean} true, if the object exists, else false. */ exports.getObj = function(o, keyPath) { if ('string' == typeof keyPath) keyPath = keyPath.split('.'); for (var i = 0; i < keyPath.length; i++) { key = keyPath[i]; if (!(key in o)) return false; o = o[key]; } return o; } /** * @see: http://stackoverflow.com/questions/5484673/javascript-how-to-dynamically-create-nested-objects-using-object-names-given-by * @param {Object} o Object to assign something. * @param {Object|String} keyPath The Key path on the object(o) to set the value on. e.g. 'a.b.c' or ['a', 'b', 'c'] * @param {Object} value Any value to set on the Object(o) with the given path(keyPath) * @return {Object} Returns the value. */ exports.setObj = function(o, keyPath, value) { if ('string' == typeof keyPath) keyPath = keyPath.split('.'); lastKeyIndex = keyPath.length - 1; for (var i = 0; i < lastKeyIndex; i++) { key = keyPath[i]; if (!(key in o)) o[key] = {} o = o[key]; } o[keyPath[lastKeyIndex]] = value; return value; } exports.contextExists = function(localeCache, locale, context) { var query = exports.getKeyPath(locale, context); return exports.existsObj(localeCache, query); } /** * debug function for development log outputs. * usage e.g. NODE_DEBUG='i18n http' node app.js * @param {String} x Message */ if (process.env.NODE_DEBUG && /i18n/.test(process.env.NODE_DEBUG)) { exports.debug = function() { var args = Array.prototype.slice.call(arguments, 0); args.unshift('i18n: %s') console.error.apply(this, args); }; } else { exports.debug = function() {}; } /** * Merge object b with object a. * * var a = { foo: 'bar' } * , b = { bar: 'baz' }; * * utils.merge(a, b); * // => { foo: 'bar', bar: 'baz' } * * @param {Object} a * @param {Object} b * @return {Object} * @api private */ exports.merge = function(a, b) { if (a && b) { for (var key in b) { a[key] = b[key]; } } return a; };