| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| module.exports = Catalog; |
| var formatError = require('./format'); |
| |
| function Catalog() { |
| this.formats = {}; |
| } |
| |
| function baseLang(lang) { |
| return lang.split('-')[0]; |
| } |
| |
| /** |
| * lookups the language/msgId pair in the catalog. |
| * |
| * @private |
| * @param {string} lang the language code |
| * @param {string} msgId the id of the error |
| * @returns {string|null} the format string for the lang/msgId pair or null. |
| */ |
| Catalog.prototype._lookup = function(lang, msgId) { |
| var langMap = this.formats[lang]; |
| if (!langMap) { |
| return null; |
| } |
| return langMap[msgId]; |
| }; |
| |
| /** |
| * lookups the language/msgId pair in the catalog. If there is no match |
| * on the full language the string the base language (i.e 'en' for 'en-US') is |
| * looked up instead. |
| * |
| * @private |
| * @param {string} lang the language code |
| * @param {string} msgId the id of the error |
| * @returns {string} the format string for the lang/msgId pair. |
| */ |
| Catalog.prototype.lookup = function(lang, msgId) { |
| var defaultFormat = msgId + '{:_}'; |
| return this._lookup(lang, msgId) || |
| this._lookup(baseLang(lang), msgId) || |
| defaultFormat; |
| }; |
| |
| Catalog.prototype.format = function(lang, msgId, args) { |
| return formatError(this.lookup(lang, msgId), args); |
| }; |
| |
| /** |
| * sets the format for the lang/msgId pair |
| * @private |
| * @param {string} lang the language code |
| * @param {string} msgId the id of the error |
| * @param {string} format the format of the message |
| */ |
| Catalog.prototype.set = function(lang, msgId, format) { |
| var langs = this.formats[lang]; |
| if (!langs) { |
| this.formats[lang] = {}; |
| langs = this.formats[lang]; |
| } |
| langs[msgId] = format; |
| }; |
| |
| /** |
| * sets the format for the lang/msgId pair. Also sets the format for |
| * the base of the language if no format exists for it. |
| * @private |
| * @param {string} lang the language code |
| * @param {string} msgId the id of the error |
| * @param {string} format the format of the message |
| */ |
| Catalog.prototype.setWithBase = function (lang, msgId, format) { |
| this.set(lang, msgId, format); |
| var base = baseLang(lang); |
| if (!this._lookup(base, msgId, format)) { |
| this.set(base, msgId, format); |
| } |
| }; |
| |
| var escapedStringRe = /"([^"\\]|\\.)*"/; |
| |
| /** |
| * Merges the catalog data passed in. |
| * Each valid line will have three parts. It will be: |
| * <langId> <msgId> "<format>" |
| * format will be enclosed in quotes and escaped properly. |
| * If the line begins with '#' or is malformed, it is ignored. |
| * @private |
| * @param {string} data the language code |
| */ |
| Catalog.prototype.merge = function(data) { |
| var catalog = this; |
| data.split('\n').forEach(function(line) { |
| var parts = line.split(/\s+/); |
| if (parts.length < 3) { |
| return; |
| } |
| var langId = parts[0]; |
| if (langId[0] === '#') { |
| return; |
| } |
| var msgId = parts[1]; |
| // The message is quoted, so we need to unquote it. |
| var message = parts.splice(2).join(' '); |
| var match = escapedStringRe.exec(message); |
| if (!match) { |
| return; |
| } |
| try { |
| message = JSON.parse(match[0]); |
| } catch (e) { |
| return; |
| } |
| catalog.setWithBase(langId, msgId, message); |
| }); |
| }; |