michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: this.EXPORTED_SYMBOLS = ["StringBundle"]; michael@0: michael@0: const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components; michael@0: michael@0: /** michael@0: * A string bundle. michael@0: * michael@0: * This object presents two APIs: a deprecated one that is equivalent to the API michael@0: * for the stringbundle XBL binding, to make it easy to switch from that binding michael@0: * to this module, and a new one that is simpler and easier to use. michael@0: * michael@0: * The benefit of this module over the XBL binding is that it can also be used michael@0: * in JavaScript modules and components, not only in chrome JS. michael@0: * michael@0: * To use this module, import it, create a new instance of StringBundle, michael@0: * and then use the instance's |get| and |getAll| methods to retrieve strings michael@0: * (you can get both plain and formatted strings with |get|): michael@0: * michael@0: * let strings = michael@0: * new StringBundle("chrome://example/locale/strings.properties"); michael@0: * let foo = strings.get("foo"); michael@0: * let barFormatted = strings.get("bar", [arg1, arg2]); michael@0: * for each (let string in strings.getAll()) michael@0: * dump (string.key + " = " + string.value + "\n"); michael@0: * michael@0: * @param url {String} michael@0: * the URL of the string bundle michael@0: */ michael@0: this.StringBundle = function StringBundle(url) { michael@0: this.url = url; michael@0: } michael@0: michael@0: StringBundle.prototype = { michael@0: /** michael@0: * the locale associated with the application michael@0: * @type nsILocale michael@0: * @private michael@0: */ michael@0: get _appLocale() { michael@0: try { michael@0: return Cc["@mozilla.org/intl/nslocaleservice;1"]. michael@0: getService(Ci.nsILocaleService). michael@0: getApplicationLocale(); michael@0: } michael@0: catch(ex) { michael@0: return null; michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * the wrapped nsIStringBundle michael@0: * @type nsIStringBundle michael@0: * @private michael@0: */ michael@0: get _stringBundle() { michael@0: let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]. michael@0: getService(Ci.nsIStringBundleService). michael@0: createBundle(this.url, this._appLocale); michael@0: this.__defineGetter__("_stringBundle", function() stringBundle); michael@0: return this._stringBundle; michael@0: }, michael@0: michael@0: michael@0: // the new API michael@0: michael@0: /** michael@0: * the URL of the string bundle michael@0: * @type String michael@0: */ michael@0: _url: null, michael@0: get url() { michael@0: return this._url; michael@0: }, michael@0: set url(newVal) { michael@0: this._url = newVal; michael@0: delete this._stringBundle; michael@0: }, michael@0: michael@0: /** michael@0: * Get a string from the bundle. michael@0: * michael@0: * @param key {String} michael@0: * the identifier of the string to get michael@0: * @param args {array} [optional] michael@0: * an array of arguments that replace occurrences of %S in the string michael@0: * michael@0: * @returns {String} the value of the string michael@0: */ michael@0: get: function(key, args) { michael@0: if (args) michael@0: return this.stringBundle.formatStringFromName(key, args, args.length); michael@0: else michael@0: return this.stringBundle.GetStringFromName(key); michael@0: }, michael@0: michael@0: /** michael@0: * Get all the strings in the bundle. michael@0: * michael@0: * @returns {Array} michael@0: * an array of objects with key and value properties michael@0: */ michael@0: getAll: function() { michael@0: let strings = []; michael@0: michael@0: // FIXME: for performance, return an enumerable array that wraps the string michael@0: // bundle's nsISimpleEnumerator (does JavaScript already support this?). michael@0: michael@0: let enumerator = this.stringBundle.getSimpleEnumeration(); michael@0: michael@0: while (enumerator.hasMoreElements()) { michael@0: // We could simply return the nsIPropertyElement objects, but I think michael@0: // it's better to return standard JS objects that behave as consumers michael@0: // expect JS objects to behave (f.e. you can modify them dynamically). michael@0: let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); michael@0: strings.push({ key: string.key, value: string.value }); michael@0: } michael@0: michael@0: return strings; michael@0: }, michael@0: michael@0: michael@0: // the deprecated XBL binding-compatible API michael@0: michael@0: /** michael@0: * the URL of the string bundle michael@0: * @deprecated because its name doesn't make sense outside of an XBL binding michael@0: * @type String michael@0: */ michael@0: get src() { michael@0: return this.url; michael@0: }, michael@0: set src(newVal) { michael@0: this.url = newVal; michael@0: }, michael@0: michael@0: /** michael@0: * the locale associated with the application michael@0: * @deprecated because it has never been used outside the XBL binding itself, michael@0: * and consumers should obtain it directly from the locale service anyway. michael@0: * @type nsILocale michael@0: */ michael@0: get appLocale() { michael@0: return this._appLocale; michael@0: }, michael@0: michael@0: /** michael@0: * the wrapped nsIStringBundle michael@0: * @deprecated because this module should provide all necessary functionality michael@0: * @type nsIStringBundle michael@0: * michael@0: * If you do ever need to use this, let the authors of this module know why michael@0: * so they can surface functionality for your use case in the module itself michael@0: * and you don't have to access this underlying XPCOM component. michael@0: */ michael@0: get stringBundle() { michael@0: return this._stringBundle; michael@0: }, michael@0: michael@0: /** michael@0: * Get a string from the bundle. michael@0: * @deprecated use |get| instead michael@0: * michael@0: * @param key {String} michael@0: * the identifier of the string to get michael@0: * michael@0: * @returns {String} michael@0: * the value of the string michael@0: */ michael@0: getString: function(key) { michael@0: return this.get(key); michael@0: }, michael@0: michael@0: /** michael@0: * Get a formatted string from the bundle. michael@0: * @deprecated use |get| instead michael@0: * michael@0: * @param key {string} michael@0: * the identifier of the string to get michael@0: * @param args {array} michael@0: * an array of arguments that replace occurrences of %S in the string michael@0: * michael@0: * @returns {String} michael@0: * the formatted value of the string michael@0: */ michael@0: getFormattedString: function(key, args) { michael@0: return this.get(key, args); michael@0: }, michael@0: michael@0: /** michael@0: * Get an enumeration of the strings in the bundle. michael@0: * @deprecated use |getAll| instead michael@0: * michael@0: * @returns {nsISimpleEnumerator} michael@0: * a enumeration of the strings in the bundle michael@0: */ michael@0: get strings() { michael@0: return this.stringBundle.getSimpleEnumeration(); michael@0: } michael@0: }