%PDF- %PDF-
Direktori : /home/opti/workflow/node_modules/messageformat/ |
Current File : /home/opti/workflow/node_modules/messageformat/messages.js |
/** * @classdesc Accessor for compiled MessageFormat functions * * ``` * import Messages from 'messageformat/messages' * ``` * * @class * @param {object} locales A map of locale codes to their function objects * @param {string|null} [defaultLocale] If not defined, default and initial locale is the first entry of `locales` * * @example * var fs = require('fs'); * var MessageFormat = require('messageformat'); * var mf = new MessageFormat(['en', 'fi']); * var msgSet = { * en: { * a: 'A {TYPE} example.', * b: 'This has {COUNT, plural, one{one user} other{# users}}.', * c: { * d: 'We have {P, number, percent} code coverage.' * } * }, * fi: { * b: 'Tällä on {COUNT, plural, one{yksi käyttäjä} other{# käyttäjää}}.', * e: 'Minä puhun vain suomea.' * } * }; * var cfStr = mf.compile(msgSet).toString('module.exports'); * fs.writeFileSync('messages.js', cfStr); * * ... * * var Messages = require('messageformat/messages'); * var msgData = require('./messages'); * var messages = new Messages(msgData, 'en'); * * messages.hasMessage('a') // true * messages.hasObject('c') // true * messages.get('b', { COUNT: 3 }) // 'This has 3 users.' * messages.get(['c', 'd'], { P: 0.314 }) // 'We have 31% code coverage.' * * messages.get('e') // 'e' * messages.setFallback('en', ['foo', 'fi']) * messages.get('e') // 'Minä puhun vain suomea.' * * messages.locale = 'fi' * messages.hasMessage('a') // false * messages.hasMessage('a', 'en') // true * messages.hasMessage('a', null, true) // true * messages.hasObject('c') // false * messages.get('b', { COUNT: 3 }) // 'Tällä on 3 käyttäjää.' * messages.get('c').d({ P: 0.628 }) // 'We have 63% code coverage.' */ function Messages(locales, defaultLocale) { this._data = {}; this._fallback = {}; Object.keys(locales).forEach(function(lc) { if (lc !== 'toString') { this._data[lc] = locales[lc]; if (typeof defaultLocale === 'undefined') defaultLocale = lc; } }, this); /** * List of available locales * @readonly * @memberof Messages * @member {string[]} availableLocales */ Object.defineProperty(this, 'availableLocales', { get: function() { return Object.keys(this._data); } }); /** * Current locale * * One of Messages#availableLocales or `null`. Partial matches of language tags * are supported, so e.g. with an `en` locale defined, it will be selected by * `messages.locale = 'en-US'` and vice versa. * * @memberof Messages * @member {string|null} locale */ Object.defineProperty(this, 'locale', { get: function() { return this._locale; }, set: function(lc) { this._locale = this.resolveLocale(lc); } }); this.locale = defaultLocale; /** * Default fallback locale * * One of Messages#availableLocales or `null`. Partial matches of language tags * are supported, so e.g. with an `en` locale defined, it will be selected by * `messages.defaultLocale = 'en-US'` and vice versa. * * @memberof Messages * @member {string|null} defaultLocale */ Object.defineProperty(this, 'defaultLocale', { get: function() { return this._defaultLocale; }, set: function(lc) { this._defaultLocale = this.resolveLocale(lc); } }); this._defaultLocale = this._locale; } module.exports = Messages; /** * Add new messages to the accessor; useful if loading data dynamically * * The locale code `lc` should be an exact match for the locale being updated, * or empty to default to the current locale. Use {@link #resolveLocale} for * resolving partial locale strings. * * If `keypath` is empty, adds or sets the complete message object for the * corresponding locale. If any keys in `keypath` do not exist, a new object * will be created at that key. * * @param {function|object} data Hierarchical map of keys to functions, or a * single message function * @param {string} [lc] If empty or undefined, defaults to `this.locale` * @param {string[]} [keypath] The keypath being added * @returns {Messages} The Messages instance, to allow for chaining */ Messages.prototype.addMessages = function(data, lc, keypath) { if (!lc) lc = this.locale; if (typeof data !== 'function') { data = Object.keys(data).reduce(function(map, key) { if (key !== 'toString') map[key] = data[key]; return map; }, {}); } if (Array.isArray(keypath) && keypath.length > 0) { var parent = this._data[lc]; for (var i = 0; i < keypath.length - 1; ++i) { var key = keypath[i]; if (!parent[key]) parent[key] = {}; parent = parent[key]; } parent[keypath[keypath.length - 1]] = data; } else { this._data[lc] = data; } return this; }; /** * Resolve `lc` to the key of an available locale or `null`, allowing for * partial matches. For example, with an `en` locale defined, it will be * selected by `messages.defaultLocale = 'en-US'` and vice versa. * * @param {string} lc Locale code * @returns {string|null} */ Messages.prototype.resolveLocale = function(lc) { if (this._data[lc]) return lc; if (lc) { var l = String(lc); while ((l = l.replace(/[-_]?[^-_]*$/, ''))) { if (this._data[l]) return l; } var ll = this.availableLocales; var re = new RegExp('^' + lc + '[-_]'); for (var i = 0; i < ll.length; ++i) { if (re.test(ll[i])) return ll[i]; } } return null; }; /** * Get the list of fallback locales * @param {string} [lc] If empty or undefined, defaults to `this.locale` * @returns {string[]} */ Messages.prototype.getFallback = function(lc) { if (!lc) lc = this.locale; return ( this._fallback[lc] || (lc === this.defaultLocale || !this.defaultLocale ? [] : [this.defaultLocale]) ); }; /** * Set the fallback locale or locales for `lc` * * To disable fallback for the locale, use `setFallback(lc, [])`. * To use the default fallback, use `setFallback(lc, null)`. * * @param {string} lc * @param {string[]|null} fallback * @returns {Messages} The Messages instance, to allow for chaining */ Messages.prototype.setFallback = function(lc, fallback) { this._fallback[lc] = Array.isArray(fallback) ? fallback : null; return this; }; /** * Check if `key` is a message function for the locale * * `key` may be a `string` for functions at the root level, or `string[]` for * accessing hierarchical objects. If an exact match is not found and `fallback` * is true, the fallback locales are checked for the first match. * * @param {string|string[]} key The key or keypath being sought * @param {string} [lc] If empty or undefined, defaults to `this.locale` * @param {boolean} [fallback=false] If true, also checks fallback locales * @returns {boolean} */ Messages.prototype.hasMessage = function(key, lc, fallback) { if (!lc) lc = this.locale; var fb = fallback ? this.getFallback(lc) : null; return _has(this._data, lc, key, fb, 'function'); }; /** * Check if `key` is a message object for the locale * * `key` may be a `string` for functions at the root level, or `string[]` for * accessing hierarchical objects. If an exact match is not found and `fallback` * is true, the fallback locales are checked for the first match. * * @param {string|string[]} key The key or keypath being sought * @param {string} [lc] If empty or undefined, defaults to `this.locale` * @param {boolean} [fallback=false] If true, also checks fallback locales * @returns {boolean} */ Messages.prototype.hasObject = function(key, lc, fallback) { if (!lc) lc = this.locale; var fb = fallback ? this.getFallback(lc) : null; return _has(this._data, lc, key, fb, 'object'); }; /** * Get the message or object corresponding to `key` * * `key` may be a `string` for functions at the root level, or `string[]` for * accessing hierarchical objects. If an exact match is not found, the fallback * locales are checked for the first match. * * If `key` maps to a message function, it will be called with `props`. If it * maps to an object, the object is returned directly. * * @param {string|string[]} key The key or keypath being sought * @param {object} [props] Optional properties passed to the function * @param {string} [lc] If empty or undefined, defaults to `this.locale` * @returns {string|Object<string,function|object>} */ Messages.prototype.get = function(key, props, lc) { if (!lc) lc = this.locale; var msg = _get(this._data[lc], key); if (msg) return typeof msg == 'function' ? msg(props) : msg; var fb = this.getFallback(lc); for (var i = 0; i < fb.length; ++i) { msg = _get(this._data[fb[i]], key); if (msg) return typeof msg == 'function' ? msg(props) : msg; } return key; }; /** @private */ function _get(obj, key) { if (!obj) return null; if (Array.isArray(key)) { for (var i = 0; i < key.length; ++i) { obj = obj[key[i]]; if (!obj) return null; } return obj; } return obj[key]; } /** @private */ function _has(data, lc, key, fallback, type) { var msg = _get(data[lc], key); if (msg) return typeof msg === type; if (fallback) { for (var i = 0; i < fallback.length; ++i) { msg = _get(data[fallback[i]], key); if (msg) return typeof msg === type; } } return false; }