function gettext(str) {
	if (typeof(i18n) != 'undefined' && i18n[str]) return i18n[str];
	return str;
}
function ngettext(s, p, n) {
	if (n > 1) return gettext(p);
	return gettext(s);
}
function _(str) {
	return gettext(str)
}
function sprintf(str) {
	var bits = str.split('%');
	var out = bits[0];
	var re = /^([ds])(.*)$/;
	for (var i=1; i<bits.length; i++) {
		p = re.exec(bits[i]);
		if (!p || arguments[i]==null) continue;
		if (p[1] == 'd') out += parseInt(arguments[i], 10);
		else if (p[1] == 's') out += arguments[i];
		out += p[2];
	}
	return out;
}

(function(){
	var events;
	var check = function(e){
		var target = $(e.target);
		var parents = target.getParents();
		events.each(function(item){
			var element = item.element;
			if (element != target && !parents.contains(element)) item.fn.call(element, e);
		});
	}
	Element.Events.outerClick = {
		onAdd: function(fn){
			if(!events) {
				document.addEvent('click', check);
				events = [];
			}
			events.push({element: this, fn: fn});
		},
		onRemove: function(fn){
			events = events.filter(function(item){
				return item.element != this || item.fn != fn;
			}, this);
			if (!events.length) {
				document.removeEvent('click', check);
				events = null;
			}
		}
	}
});

function trace(message){
	if(console) console.log(message);
	else alert(message);
}

Element.implement({
				  
	highlight: function(start, end, property){
		if (!property) property = 'background-color';
		if (!end){
			end = this.retrieve('highlight:original', this.getStyle(property));
			end = (end == 'transparent') ? '#fff' : end;
		}
		var tween = this.get('tween');
		tween.start(property, start || '#ffff88', end).chain(function(){
			this.setStyle(property, null);
			tween.callChain();
		}.bind(this));
		return this;
	}

});