(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);