/*!
* Copyright (c) 2009 Francesco Mele jsbeans@francescomele.com
*
* This Software is licenced under the LGPL Licence (GNU Lesser General
* Public License).
* In addition to the LGPL Licence the Software is subject to the
* following conditions:
*
* i every modification must be public and comunicated to the Author
* ii every "jsbean" added to this library must be self consistent
* except for the dependence from jsbeans-x.x.x.js
* iii copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Utility Object to get and (document.)write messages in any language.
* @namespace jsbeans
* @class i18n
* @static
*/
jsbeans.i18n = {
/**
* Default language.
* @property LANG
* @type String
* @static
* */
LANG: "en",
/**
* Sets/changes the default locale to the given one.
* @method setLanguage
* @param lang {String} the language used to get all next messages
* @static
* */
setLanguage: function(lang) {
// check if it exists
if (!jsbeans.i18n["_languages"][lang]) {
lang = "en";
}
jsbeans.i18n.LANG = lang;
},
/**
* Alias for <code class="methd">setLanguage</code>
* @method setLocale
* @param lang {String} the language used to get all next messages
* @static
* */
setLocale: function(lang) {
jsbeans.i18n.setLanguage(lang);
},
/**
* Default JSON containing messages.
* @property BASE
* @type JSON
* @static
* */
BASE: undefined,
/**
* <code class="methd">get</code> uses <code>jsbeans.i18n</code> as base object for messages.<br/>
* For example <code>jsbeans.i18n.get("mama");</code> will look for the property <code>jsbeans.i18n.mama</code>.<br/>
* Use {@method} <code class="methd">setBase</code> to change message container.<br/>
* Note: <code class="methd">jsbeans.i18n.setLanguage</code> still looks for <code>jsbeans.i18n._languages</code> to check language availability.
* @method setBase
* @param obj {JSON} A JSON containing all messages. Default <code>jsbeans.i18n</code>.
* @static
* */
setBase: function(obj) {
jsbeans.i18n.BASE = obj || jsbeans.i18n;
},
/**
* Gets the message in the language set by <code class="methd">setLanguage</code> by its {@param} <code class="param">msdId</code>.<br/>
* More precisely looks for a static property jsbeans.i18n.<msgId>.<jsbeans.i18n.LANG> (e.g. jsbeans.i18n.title.en = "My title"). If not found returns the string "??<msgId>??" (e.g. ??title??) to give developer something to see and fix.<br/>
* Messages can accept numbered placeholders (e.g. "My name is {0} and my email is {1}") or in JSON format (e.g. "My name is {name} and my email is {email}") that will be replaced with optional arguments.
* @method get
* @param msgId {String} the message id
* @param [replacers] {Array | JSON | arguments} <strong>ordered</strong> values for placeholders; may be key/value pairs in case of JSON format. May be an Array (jsbeans.i18n.get('label', ['Mr', 'Jones'])) or the function arguments (jsbeans.i18n.get('label', 'Mr', 'Jones')) or JSON (jsbeans.i18n.get('label', { title: 'Mr', lastName: 'Jones'}))
* @return {String} the formatted messages in provided language or ??<msgId>?? otherwise
* @static
* */
get: function(msgId) {
var base = jsbeans.i18n.BASE[msgId];
if (typeof base == "undefined") {
// show something anyway so developer can fix it
return "??" + msgId + "??";
}
var res = base[jsbeans.i18n.LANG];
// if LANGed message is not provided (i.e. direct access to label: i18n.a_label = "a value")
if (typeof res == "undefined") {
res = base;
}
// positional, optional args for substitution
if (arguments.length > 1) {
var arg;
// replaceres are in an Array
if (arguments[1] != null && typeof(arguments[1]) === "object" && arguments[1].constructor == Array) {
for (var i = 0; i < arguments[1].length; i++) {
arg = arguments[1][i];
res = res.split("{" + (i) + "}").join(arg);
}
}
// replacers are in JSON format
else if (arguments[1] != null && typeof(arguments[1]) === "object") {
var json = arguments[1];
for (var arg in json) {
res = res.split("{" + arg + "}").join(json[arg]);
}
}
// ordered list of replacers as varargs
else {
for (var i = 1; i < arguments.length; i++) {
arg = arguments[i];
res = res.split("{" + (i-1) + "}").join(arg);
}
}
}
return res;
},
/**
* As <code class="methd">jsbeans.i18n.get</code> but writes on document using <code>document.write</code>
* @method write
* @param msgId {String}
* @param [replacers] {Array | JSON | arguments} See <code class="methd">jsbeans.i18n.get</code>.
* @return {document.write}
* @static
* */
write: function(msgId) {
if (arguments.length > 1) {
var args;
if (arguments[1] != null && typeof(arguments[1]) === "object" && arguments[1].constructor == Array) {
args = arguments[1];
}
else {
args = [];
for (var i = 1, arg; arg = arguments[i]; i++) {
args.push(arg);
}
}
document.write(jsbeans.i18n.get(msgId, args));
}
else {
document.write(jsbeans.i18n.get(msgId));
}
},
/**
* Replaces content of DOM element identified by {@param} <code class="param">selector</code> with message identified by {@param} <code class="param">msgId</code>.<br/>
* Internally it uses <code class="methd">jsbeans.i18n.get</code> to get message.
* @method put
* @param selector {String} the id of an HTML element
* @param msgId {String} the id of the message
* @param [replacers] {Array | JSON | arguments} See <code class="methd">jsbeans.i18n.get</code>.
* @static
* */
put: function(selector, msgId) {
try {
var obj = document.getElementById(selector);
if (arguments.length > 2) {
var args;
if (arguments[2] != null && typeof(arguments[2]) === "object" && arguments[2].constructor == Array) {
args = arguments[2];
}
else {
args = [];
for (var i = 2, arg; arg = arguments[i]; i++) {
args.push(arg);
}
}
obj.innerHTML = jsbeans.i18n.get(msgId, args);
}
else {
obj.innerHTML = jsbeans.i18n.get(msgId);
}
}
catch(e) {}
},
/**
* A shortcut for multiple <code class="methd">jsbeans.i18n.put</code> (<strong>without replacers</strong>).
* @method putAll
* @param json {JSON} a json in the format
* <pre>
* nameOfSelector1: msgIdForSelector1,
* nameOfSelector2: msgIdForSelector2,
* ...
* </pre>
* @static
* */
putAll: function(json) {
for (var p in json) {
jsbeans.i18n.put(p, json[p]);
}
},
/**
* Checks if a message with given {@param} <code class="param">msgId</code> has been provided
* @method has
* @param msgId {String} the id of the message to be checked
* @return {boolean} true if <code>jsbeans.i18n.BASE[msgId]</code> has been found
* @static
* */
has: function(msgId) {
return typeof jsbeans.i18n.BASE[msgId] != "undefined";
}
};
// sets default jsbeans.i18n.BASE
jsbeans.i18n.setBase();
(function() {
var scripts = document.getElementsByTagName("script");
for (var i = 0, scr; scr = scripts[i]; i++) {
var src = scr.getAttribute("src");
if (src != null && typeof(src) != "undefined" && src.indexOf("i18n.js") != -1) {
var locale = scr.getAttribute("data-locale");
// if "data-locale" attribute has been provided
if (locale != null && typeof locale != "undefined") {
jsbeans.i18n.setLocale(locale);
}
break;
}
}
})();