(function(Web, global) {
	// Rx zum Ersetzen der Argumente-Platzhalter: {0}, {1} etc.
var _replacementRx = /(\{+)(\d+)(\}+)/g,
	// Rx zum Ersetzen einfacher geschweifter Klammern durch doppelte in den Argumenten
	// bei Match von doubleBracesRx
	_bracesRx = /\{|\}/g,
	// Rx zum Ersetzen doppelter geschweifter Klammern durch eine
	_doubleBracesRx = /\{{2,}|\}{2,}/g,
	// wiederverwendbare Funktion für die Ersetzung der Klammern
	_replaceBraces = function(braces) {
		return braces.substr(Math.floor(braces.length / 2));
	},
	// Fügt die Übersetzungen an ein Translation-Objekt an
	_applyTranslations = function(o, translations) {
		if (translations)
			for (var i in translations)
				if (translations.hasOwnProperty(i) && i !== '__type' && i !== 'translate' && i !== 't')
					o[i] = new MultiLangText(translations[i]);
	},
	Translation,

/**
 * @class IDU.Core.Web.MultiLang.MultiLangText
 * Objekt für die Herausgabe eines konkreten übersetzten Textes für JS-Komponenten.
 * Diese Klasse kann nicht direkt erstellt werden, sondern wird nur intern von
 * {@link IDU.Core.Web.MultiLang.Translation} verwendet.
 * @author Robin
 * @date 2013-05-27
 * @private
 */
/**
 * @class MultiLangText
 * @ignore
 */
/**
 * @constructor
 * @member IDU.Core.Web.MultiLang.MultiLangText
 * Erstellt eine neue Text-Instanz
 * @param {String} text Der Text, so wie er serverseitig in JsTranslationBase definiert wurde
 * @private
 */
MultiLangText = function(text)
{
	this.text = text || '';
	// Checken und merken, ob das jedes Mal notwendig ist
	this.hasArgs = _replacementRx.test(this.text);
	_replacementRx.lastIndex = 0; // test auf die gleiche RegExp setzt den nach hinten, da /g
	this.hasDoubleBraces = _doubleBracesRx.test(this.text);
	// Hier war noch Überlegung, direkt die toString zurückzugeben, um das in der Form
	// MyClass.MyText(args) aufzurufen
	// Aber dann gehen die oben gesetzten Eigenschaften verlustig.
	// Und hier für jeden Text eine Inline-Funktion zu erstellen, ist zu viel.
};
/**
 * @member IDU.Core.Web.MultiLang.MultiLangText
 * Gibt den Text zurück und ersetzt vorhandene Platzhalter durch die angegebenen Werte.
 * @param {Object[]/Object...} [args] Werte, die in die Platzhalter eingesetzt werden sollen.
 * @return {String}
 */
MultiLangText.prototype.translate = function(args)
{
	var text = this.text;

	if (this.hasArgs)
	{
		args = args || [];
		if (arguments.length > 0 && typeof args.pop !== 'function')
			args = Array.prototype.slice.call(arguments);
	
		// Argumente ersetzen
		if (this.hasDoubleBraces)
			text = text.replace(_replacementRx, function(wholeMatch, bracesBefore, index, bracesAfter) {
				// Doppelte Klammern berücksichtigen.
				// Da unten die restlichen doppelten Klammern ersetzt werden, müssen hier alle Klammern
				// in den Argumenten verdoppelt werden. Noch keine Möglichkeit gefunden, das in einem Rutsch
				// zu machen. JS-RegExp unterstützt leider keine Lookbehinds.
				if (bracesBefore.length % 2 !== 0 && bracesAfter.length % 2 !== 0)
					return bracesBefore.substr(1)
						+ (typeof args[index] !== 'undefined'
							? (typeof args[index] === 'string'
								? args[index].replace(_bracesRx, '$&$&')
								: args[index])
							: '')
						+ bracesAfter.substr(1);
				else
					return wholeMatch;
			});
		else
			text = text.replace(_replacementRx, function(wholeMatch, bracesBefore, index, bracesAfter) {
				// Hier können keine doppelten Klammern mehr drin sein, dann wäre es schon oben durchgelaufen
				return typeof args[index] != 'undefined' ? args[index] : '';
			});
	}
	// Doppelte Klammern ersetzen, z.B.
	// {{0}} wird zu {0}
	if (this.hasDoubleBraces)
		text = text.replace(_doubleBracesRx, _replaceBraces);

	return text;
};
/**
 * @method t
 * @member IDU.Core.Web.MultiLang.MultiLangText
 * @inheritdoc IDU.Core.Web.MultiLang.MultiLangText#method-translate
 */
MultiLangText.prototype.t = MultiLangText.prototype.translate; // Shortcut
/**
 * @member IDU.Core.Web.MultiLang.MultiLangText
 * Gibt den Text zurück.
 * @return {String}
 */
MultiLangText.prototype.toString = function()
{
	return this.text;
};
/**
 * @class IDU.Core.Web.MultiLang.Translation
 * Objekt für die Herausgabe von übersetzten Texten in JS-Komponenten.
 * Jede serverseitig Serialisierte Klasse vom Typ JsTranslationBase
 * ist eine Instanz hiervon. Für ein Shortcut auf die Übersetzungen
 * empfiehlt sich ein Closure der Form
 * 
 *     (function(ml) {
 *         var translatedText = ml.t('Key', 'Standard-Text', 'Arg1');
 *     })(MyTranslation);
 * 
 * oder die Generierung des Objekts für das Closure über die {@link #lazy}-Methode.
 * @extensionpack IDU.Core.Web.Sencha.Common.ExtensionPacks.Multilang
 * @registrator IDU.Core.Web.MultiLang.MultiLangHelper.RegisterScriptsInPage()
 * @author Robin
 * @date 2013-05-27
 */
/**
 * @class Translation
 * @ignore
 */
/**
 * @constructor
 * @member IDU.Core.Web.MultiLang.Translation
 * Erstellt ein neues Translation-Objekt
 * @param {Object} translations Texte
 * @private
 */
Translation = function(translations)
{
	_applyTranslations(this, translations);
};
/**
 * @member IDU.Core.Web.MultiLang.Translation
 * Gibt den Text der angegebenen Property in der aktuellen Übersetzung
 * zurück und ersetzt vorhandene Platzhalter durch die angegebenen Werte.
 * @param {String} key Property des JsTranslationBase-Objekts
 * @param {String} defaultText Standard-Text, der ausgegeben wird, wenn
 * die Property nicht vorhanden ist.
 * @param {Object[]/Object...} [args] Werte, die in die Platzhalter eingesetzt werden sollen.
 * @return {String}
 */
Translation.prototype.translate = function(key, defaultText)
{
	var trans = this[key];
	if (!trans)
	{
		if (Web.isDebugBuild && typeof global.console !== 'undefined')
			console.warn('Zur Property "' + key + '" existiert kein Text. Es wird der Default-Wert zurückgegeben.');
		// Das merken. Führt zwar dazu, dass o.g. Meldung nicht mehr kommt, aber 1x reicht das ja auch aus.
		trans = this[key] = new MultiLangText(defaultText);
	}
	return trans.translate(Array.prototype.slice.call(arguments, 2));
};
/**
 * @method t
 * @member IDU.Core.Web.MultiLang.Translation
 * @inheritdoc IDU.Core.Web.MultiLang.Translation#method-translate
 */
Translation.prototype.t = Translation.prototype.translate; // Shortcut
/**
 * @member IDU.Core.Web.MultiLang.Translation
 * Gibt den Texts der angegebenen Property eines Translation-Objekt in der aktuellen Übersetzung
 * zurück und ersetzt vorhandene Platzhalter durch die angegebenen Werte.
 * @param {String/IDU.Core.Web.MultiLang.Translation} translation Translation-Objekt oder Name des Objekts
 * @param {String} key Property des JsTranslationBase-Objekts
 * @param {String} defaultText Standard-Text, der ausgegeben wird, wenn
 * die Property nicht vorhanden ist.
 * @param {Object[]/Object...} [args] Werte, die in die Platzhalter eingesetzt werden sollen.
 * @return {String}
 * @static
 */
Translation.translate = function(translation, key, defaultText)
{
	if (typeof translation === 'string')
		translation = Web.tryResolve(translation);
	if (!(translation instanceof Translation))
		throw new Error('Translation.translate: Das angegebene Objekt ist keine Instanz von IDU.Core.Web.MultiLang.Translation.');
	return translation.translate(key, defaultText, Array.prototype.slice.call(arguments, 3));
};
/**
 * @member IDU.Core.Web.MultiLang.Translation
 * Generiert ein {@link IDU.Core.Web.MultiLang.Translation Translation}-Objekt für die
 * Verwendung in einem Closure. Es ist dabei egal, ob die Übersetzungen bereits
 * in der Seite registriert sind oder erst später registriert werden.
 * Es ist jedoch zu beachten, dass der Zugriff auf die Übersetzungen erst erfolgen kann,
 * wenn der komplette DOM (onReady) geladen ist. Diese Funktion ist sozusagen ein reines
 * Komfort-Feature.
 * 
 *     (function (ml) {
 *         // var text = ml.t('text'); // das würde noch nicht gehen
 *         
 *         Ext.onReady(function() {
 *             var text = ml.t('text'); // das würde gehen
 *         });
 *     })(IDU.Core.Web.MultiLang.Translation.lazy('My.Namespace.To.Translations'));
 * 
 * @param {String} translation Namespace der Übersetzung
 * @return {IDU.Core.Web.MultiLang.Translation}
 * @static
 */
Translation.lazy = function(translation)
{
	return Web.tryResolve(translation) || Web.namespace(translation, new Translation());
};
/**
 * @member IDU.Core.Web.MultiLang.Translation
 * Registriert ein JsTranslationBase-Objekt in der Seite.
 * Aufruf der Funktion wird serverseitig generiert.
 * @param {String} className Name der Klasse inkl. Namespace
 * @param {Object} translations Texte
 * @return {IDU.Core.Web.MultiLang.Translation}
 * @static
 */
Translation.register = function(className, translations)
{
	var trans = Web.tryResolve(className);
	if (trans)
		_applyTranslations(trans, translations);
	else
		trans = Web.namespace(className, new Translation(translations));
	return trans;
};
// Klasse öffentlich machen
Web.namespace('IDU.Core.Web.MultiLang.Translation', Translation);
})(IDU.Core.Web, window);