UNPKG

translator

Version:

[ABANDONED] Translator for node and also for browser

481 lines (438 loc) 15.4 kB
// Generated by CoffeeScript 1.6.3 (function() { var Args, Cache, JsonLoader, Loader, Storage, Translator, callsite, isBrowser, path, pluralForms; Cache = require('cache-storage'); Storage = require('cache-storage/lib/Storage/Storage'); Args = require('normalize-arguments'); path = require('./node/path'); pluralForms = require('./pluralForms'); Loader = require('./Loaders/Loader'); JsonLoader = require('./Loaders/Json'); isBrowser = typeof window !== 'undefined'; if (!isBrowser) { callsite = require('callsite'); } Translator = (function() { Translator.prototype.loader = null; Translator.prototype.language = null; Translator.prototype.plurals = null; Translator.prototype.replacements = null; Translator.prototype.filters = null; Translator.prototype.data = null; Translator.prototype.cache = null; function Translator(pathOrLoader) { var config, data, language, stack, _config; this.plurals = {}; this.replacements = {}; this.filters = []; this.data = {}; if (!pathOrLoader) { throw new Error('You have to set path to base directory or to config file or loader.'); } if (typeof pathOrLoader === 'string') { if (pathOrLoader.charAt(0) === '.' && isBrowser) { throw new Error('Relative paths to dictionaries is not supported in browser.'); } if (pathOrLoader.charAt(0) === '.') { stack = callsite(); pathOrLoader = path.join(path.dirname(stack[1].getFileName()), pathOrLoader); } pathOrLoader = path.normalize(pathOrLoader); config = { path: pathOrLoader, loader: 'Json' }; if (pathOrLoader.match(/\.json$/) !== null) { _config = require(pathOrLoader); if (typeof _config.path !== 'undefined') { config.path = _config.path; } if (typeof _config.loader !== 'undefined') { config.loader = _config.loader; } if (config.path.charAt(0) === '.') { config.path = path.join(path.dirname(pathOrLoader), config.path); } } pathOrLoader = new (require('./Loaders/' + config.loader))(config.path); } this.setLoader(pathOrLoader); for (language in pluralForms) { data = pluralForms[language]; this.addPluralForm(language, data.count, data.form); } } Translator.prototype.expand = function(main) { var _this = this; if (main == null) { main = null; } if (main === null) { main = isBrowser ? window : global; } main._ = function() { return _this.translate.apply(_this, arguments); }; main._m = function() { return _this.translateMap.apply(_this, arguments); }; main._p = function() { return _this.translatePairs.apply(_this, arguments); }; return main; }; Translator.prototype.setLoader = function(loader) { if (!(loader instanceof Loader)) { throw new Error('Loader must be an instance of translator/Loaders/Loader.'); } return this.loader = loader; }; Translator.prototype.invalidate = function() { return this.data = {}; }; Translator.prototype.setCacheStorage = function(cacheStorage) { if (!cacheStorage instanceof Storage) { throw new Error('Cache storage must be an instance of cache-storage/Storage/Storage.'); } return this.cache = new Cache(cacheStorage, 'translator'); }; Translator.prototype.addPluralForm = function(language, count, form) { this.plurals[language] = { count: count, form: form }; return this; }; Translator.prototype.addReplacement = function(search, replacement) { this.replacements[search] = replacement; return this; }; Translator.prototype.removeReplacement = function(search) { if (typeof this.replacements[search] === 'undefined') { throw new Error('Replacement ' + search + ' was not found.'); } delete this.replacements[search]; return this; }; Translator.prototype.addFilter = function(fn) { this.filters.push(fn); return this; }; Translator.prototype.applyFilters = function(translation) { var filter, i, t, _i, _j, _len, _len1, _ref; if (Object.prototype.toString.call(translation) === '[object Array]') { for (i = _i = 0, _len = translation.length; _i < _len; i = ++_i) { t = translation[i]; translation[i] = this.applyFilters(t); } return translation; } _ref = this.filters; for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { filter = _ref[_j]; translation = filter(translation); } return translation; }; Translator.prototype.loadCategory = function(_path, name, language) { var categoryName, conds, data, file; if (language == null) { language = this.language; } categoryName = _path + '/' + name; if (typeof this.data[categoryName] === 'undefined') { if (this.cache === null) { data = this.loader.load(_path, name, language); data = this.normalizeTranslations(data); } else { data = this.cache.load(language + ':' + categoryName); if (data === null) { data = this.loader.load(_path, name, language); data = this.normalizeTranslations(data); conds = {}; if (typeof window === 'undefined' || (typeof window !== 'undefined' && window.require.simq === true && typeof window.require.version !== 'undefined' && parseInt(window.require.version.replace(/\./g, '')) >= 510)) { _path = this.loader.getFileSystemPath(_path, name, language); if (_path !== null) { conds.files = [_path]; } } this.cache.save(language + ':' + categoryName, data, conds); } else { file = this.loader.load(_path, name, language); data = this.normalizeTranslations(file); } } this.data[categoryName] = data; } return this.data[categoryName]; }; Translator.prototype.normalizeTranslations = function(translations) { var buf, list, match, name, result, sub, t, translation, _i, _j, _len, _len1; result = {}; for (name in translations) { translation = translations[name]; list = false; if ((match = name.match(/^--\s(.*)/)) !== null) { name = match[1]; list = true; } if (typeof translation === 'string') { result[name] = [translation]; } else if (Object.prototype.toString.call(translation) === '[object Array]') { result[name] = []; for (_i = 0, _len = translation.length; _i < _len; _i++) { t = translation[_i]; if (typeof t === 'object') { buf = []; for (_j = 0, _len1 = t.length; _j < _len1; _j++) { sub = t[_j]; if (/^\#.*\#$/.test(sub) === false) { buf.push(sub); } } result[name].push(buf); } else { if (/^\#.*\#$/.test(t) === false) { if (list === true && typeof t !== 'object') { t = [t]; } result[name].push(t); } } } } } return result; }; Translator.prototype.hasTranslation = function(message, language) { if (language == null) { language = this.language; } return this.findTranslation(message, language) !== null; }; Translator.prototype.findTranslation = function(message, language) { var data, info; if (language == null) { language = this.language; } info = this.getMessageInfo(message); data = this.loadCategory(info.path, info.category, language); if (typeof data[info.name] === 'undefined') { return null; } else { return data[info.name]; } }; Translator.prototype.translate = function(message, count, args) { var found, language, match, num, params, translation; if (count == null) { count = null; } if (args == null) { args = {}; } params = Args(arguments, [Args.any, Args.number(null), Args.object({})]); message = params[0]; count = params[1]; args = params[2]; language = this.language; found = false; if (typeof message !== 'string') { return message; } if (count !== null) { args.count = count; } if ((match = message.match(/^\:(.*)\:$/)) !== null) { message = match[1]; if ((match = message.match(/^[a-z]+\|(.*)$/)) !== null) { message = match[1]; } } else { if ((match = message.match(/^([a-z]+)\|(.*)$/)) !== null) { language = match[1]; message = match[2]; } if (language === null) { throw new Error('You have to set language.'); } num = null; if ((match = message.match(/(.+)\[(\d+)\]$/)) !== null) { message = match[1]; num = parseInt(match[2]); } message = this.applyReplacements(message, args); translation = this.findTranslation(message, language); found = this.hasTranslation(message, language); if (num !== null) { if (!this.isList(translation)) { throw new Error('Translation ' + message + ' is not a list.'); } if (typeof translation[num] === 'undefined') { throw new Error('Item ' + num + ' was not found in ' + message + ' translation.'); } translation = translation[num]; } if (translation !== null) { message = this.pluralize(message, translation, count, language); } } message = this.prepareTranslation(message, args); if (found) { message = this.applyFilters(message); } return message; }; Translator.prototype.translatePairs = function(message, key, value, count, args) { var i, k, result, _i, _len; if (count == null) { count = null; } if (args == null) { args = {}; } key = "" + message + "." + key; value = "" + message + "." + value; key = this.translate(key, count, args); value = this.translate(value, count, args); if (Object.prototype.toString.call(key) !== '[object Array]' || Object.prototype.toString.call(value) !== '[object Array]') { throw new Error('Translations are not arrays.'); } if (key.length !== value.length) { throw new Error('Keys and values translations have not got the same length.'); } result = {}; for (i = _i = 0, _len = key.length; _i < _len; i = ++_i) { k = key[i]; result[k] = value[i]; } return result; }; Translator.prototype.translateMap = function(list, count, args, base) { var i, k, m, params, type, _i, _len; if (count == null) { count = null; } if (args == null) { args = {}; } if (base == null) { base = null; } type = Object.prototype.toString.call(list); if (type !== '[object Array]' && type !== '[object Object]') { throw new Error('Translate map is only for arrays and objects.'); } params = Args(arguments, [Args.oneOf([Args.array, Args.object]), Args.number(null), Args.object({}), Args.string(null)]); list = params[0]; count = params[1]; args = params[2]; base = params[3]; base = base !== null ? base + '.' : ''; if (type === '[object Array]') { for (i = _i = 0, _len = list.length; _i < _len; i = ++_i) { m = list[i]; list[i] = this.translate(base + m, count, args); } } else { for (k in list) { m = list[k]; list[k] = this.translate(base + m, count, args); } } return list; }; Translator.prototype.isList = function(translation) { return Object.prototype.toString.call(translation[0]) === '[object Array]'; }; Translator.prototype.pluralize = function(message, translation, count, language) { var n, plural, pluralForm, result, t, _i, _j, _len, _len1; if (count == null) { count = null; } if (language == null) { language = this.language; } if (count !== null) { if (typeof translation[0] === 'string') { pluralForm = 'n=' + count + ';plural=+(' + this.plurals[language].form + ');'; n = null; plural = null; eval(pluralForm); message = plural !== null && typeof translation[plural] !== 'undefined' ? translation[plural] : translation[0]; } else { result = []; for (_i = 0, _len = translation.length; _i < _len; _i++) { t = translation[_i]; result.push(this.pluralize(message, t, count, language)); } message = result; } } else { if (typeof translation[0] === 'string') { message = translation[0]; } else { message = []; for (_j = 0, _len1 = translation.length; _j < _len1; _j++) { t = translation[_j]; message.push(t[0]); } } } return message; }; Translator.prototype.prepareTranslation = function(message, args) { var m, result, _i, _len; if (args == null) { args = {}; } if (typeof message === 'string') { message = this.applyReplacements(message, args); } else { result = []; for (_i = 0, _len = message.length; _i < _len; _i++) { m = message[_i]; result.push(this.prepareTranslation(m, args)); } message = result; } return message; }; Translator.prototype.applyReplacements = function(message, args) { var name, pattern, replacements, value; if (args == null) { args = {}; } replacements = this.replacements; for (name in args) { value = args[name]; replacements[name] = value; } for (name in replacements) { value = replacements[name]; if (value !== false) { pattern = new RegExp('%' + name + '%', 'g'); message = message.replace(pattern, value); } } return message; }; Translator.prototype.getMessageInfo = function(message) { var category, name, num, result, _path; num = message.lastIndexOf('.'); _path = message.substr(0, num); name = message.substr(num + 1); num = _path.lastIndexOf('.'); category = _path.substr(num + 1); _path = _path.substr(0, num).replace(/\./g, '/'); result = { path: _path, category: category, name: name }; return result; }; return Translator; })(); module.exports = Translator; }).call(this);