@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
633 lines (594 loc) • 27.3 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
/*eslint-disable max-len */
/**
* ResourceBundle-based DataBinding
*
* @namespace
* @name sap.ui.model.resource
* @public
*/
// Provides the resource bundle based model implementation
sap.ui.define([
"sap/base/Log",
"sap/base/i18n/ResourceBundle",
"sap/ui/base/SyncPromise",
"sap/ui/core/Supportability",
"sap/ui/model/BindingMode",
"sap/ui/model/Model",
"./ResourcePropertyBinding"
], function (Log, ResourceBundle, SyncPromise, Supportability, BindingMode, Model, ResourcePropertyBinding) {
"use strict";
var sClassname = "sap.ui.model.resource.ResourceModel",
rLeadingDotsOrSlashes = /^(?:\/|\.)*/; // matches leading dots or slashes
/**
* Constructor for a new ResourceModel.
*
* <h3>Declarative Usage</h3>
* The ResourceModel can be created using configuration objects instead of
* <code>ResourceBundle</code> instances.
* This is the recommended way and enables:
* <ul>
* <li>use of terminologies in the bundle and in the enhancements</li>
* <li>a guaranteed order of resolution</li>
* </ul>
*
* <h3>Programmatic Usage</h3>
* The ResourceModel can be created in a programmatic manner which means that
* <code>ResourceBundle</code> instances are used instead of configurations.
* Existing ResourceBundles can either be used in the <code>bundle</code> parameter or in the
* <code>enhanceWith</code> array.
* Runtime errors are thrown when <code>ResourceBundle</code> instances are used with
* <code>terminologies</code>.
* Also when using <code>ResourceModel#enhance</code> with <code>terminologies</code>.
*
* @example <caption>Use ResourceModel with configurations (declarative) and terminologies</caption>
*
* sap.ui.require(["sap/ui/model/resource/ResourceModel"], function(ResourceModel){
* // ...
* var oResourceModel = new ResourceModel({
* // specify url of the base .properties file
* bundleUrl : "i18n/messagebundle.properties",
* async : true,
* enhanceWith: [
* {
* bundleUrl: "appvar1/i18n/i18n.properties",
* terminologies: {
* oil: {
* bundleUrl: "appvar1/i18n/terminologies.oil.i18n.properties",
* supportedLocales: ["de", "fr"]
* }
* }
* },
* {
* bundleUrl: "appvar2/i18n/i18n.properties",
* terminologies: {
* retail: {
* bundleUrl: "appvar2/i18n/terminologies.retail.i18n.properties",
* supportedLocales: ["de", "fr"]
* }
* }
* }
* ],
* supportedLocales: ["de", "fr"],
* fallbackLocale: "de",
* terminologies: {
* oil: {
* bundleUrl: "i18n/terminologies.oil.i18n.properties",
* supportedLocales: ["de", "fr"]
* },
* retail: {
* bundleUrl: "i18n/terminologies.retail.i18n.properties",
* supportedLocales: ["de", "fr"]
* }
* },
* activeTerminologies: ["retail"]
* });
* // ...
* });
*
*
*
* @example <caption>Use ResourceModel with existing ResourceBundles, terminologies not supported</caption>
*
* sap.ui.require(["sap/ui/model/resource/ResourceModel", "sap/base/i18n/ResourceBundle"], function(ResourceModel, ResourceBundle){
* // ...
* var oResourceModel = new ResourceModel({
* // specify url of the base .properties file
* bundle : ResourceBundle.create({
* bundleUrl: "i18n/messagebundle.properties",
* supportedLocales: ["de", "fr"]
* }),
* async : true,
* enhanceWith: [
* ResourceBundle.create({
* bundleUrl: "appvar1/i18n/i18n.properties",
* supportedLocales: ["de", "fr"]
* }),
* ResourceBundle.create({
* bundleUrl: "appvar2/i18n/i18n.properties",
* supportedLocales: ["de", "fr"]
* })
* ],
* supportedLocales: ["de", "fr"],
* fallbackLocale: "de"
* });
* // ...
* });
*
* @param {object} oData
* Parameters used to initialize the <code>ResourceModel</code>; at least one of
* <code>bundle</code>, <code>bundleName</code> or <code>bundleUrl</code> must be set; if more
* than one property is set, they are evaluated in the mentioned order
* @param {string[]} [oData.activeTerminologies]
* The list of active terminologies, e.g. <code>["oil", "retail"]</code>.
* This parameter is passed to the underlying ResourceBundle (see
* {@link module:sap/base/i18n/ResourceBundle.create}). This parameter is ignored when
* <code>bundle</code> is set. Will cause an error if <code>enhanceWith</code> contains
* instances of <code>ResourceBundle</code>. Supported since 1.77.0.
* @param {boolean} [oData.async=false]
* <b>Deprecated as of Version 1.125</b>; always use asynchronous loading for performance reasons
* @param {module:sap/base/i18n/ResourceBundle} [oData.bundle]
* A resource bundle instance; when given, this bundle is used instead of creating a bundle
* from the provided <code>bundleUrl</code>, <code>bundleName</code> and
* <code>bundleLocale</code> properties. However, to support reloading the bundle when the
* current session locale changes, the corresponding <code>bundleName</code> or
* <code>bundleUrl</code> should be specified if known. Otherwise, the bundle is not updated
* on locale changes.
* Note: This parameter should not be used when using enhancements.
* Terminologies require enhancements with <code>bundleUrl</code>, <code>bundleName</code> and
* <code>bundleLocale</code> in combination with <code>enhanceWith</code> which contains a
* list of <code>ResourceBundle.Configurations</code>.
* Terminologies must be defined in a declarative way, with configurations and not with
* instances of <code>ResourceBundle</code>.
* @param {string} [oData.bundleLocale]
* A locale in "BCP-47 language tag" notation specifying the locale in which to load the
* bundle; when not given, the current session locale of UI5 is used (recommended)
* @param {string} [oData.bundleName]
* UI5 module name in dot notation referring to the base ".properties" file; this name is
* resolved to a path just as for normal UI5 modules, to which ".properties" is then
* appended (e.g. a name like "myapp.i18n.myBundle" can be given); relative module names are
* not supported
* @param {string} [oData.bundleUrl]
* URL pointing to the base ".properties" file of a bundle (".properties" file without any
* locale information, e.g. "../../i18n/mybundle.properties"); relative URLs are evaluated
* relative to the document.baseURI
* @param {sap.ui.model.BindingMode} [oData.defaultBindingMode=OneWay]
* The default binding mode to use; it can be <code>OneWay</code> or <code>OneTime</code>
* (only when synchronous loading is used); the <code>TwoWay</code> mode is not supported
* @param {module:sap/base/i18n/ResourceBundle[]|module:sap/base/i18n/ResourceBundle.Configuration[]} [oData.enhanceWith]
* A list of resource bundles or resource bundle configurations that enhance the texts from
* the main bundle; intended for extensibility scenarios; see also the class documentation.
* ResourceBundles use the ResourceModel's enhance mechanism and <code>ResourceBundle.Configurations</code>
* get passed to the underlying ResourceBundle (see
* {@link module:sap/base/i18n/ResourceBundle.create}). Supported since 1.77.0.
* @param {string} [oData.fallbackLocale="en"]
* A fallback locale to be used after all locales derived from <code>bundleLocale</code> have
* been tried, but before the 'raw' bundle is used. Can either be a BCP47 language tag or a
* JDK compatible locale string (e.g. "en-GB", "en_GB" or "en").
*
* To prevent a generic fallback, use the empty string (<code>""</code>). E.g. by providing
* <code>fallbackLocale: ""</code> and <code>supportedLocales: ["en"]</code>, only the bundle
* "en" is requested without any fallback. This parameter is passed to the underlying
* ResourceBundle (see {@link module:sap/base/i18n/ResourceBundle.create}). Supported since
* 1.77.0.
* @param {string[]} [oData.supportedLocales]
* List of supported locales (aka 'language tags') to restrict the fallback chain. Each entry
* in the array can either be a BCP47 language tag or a JDK compatible locale string (e.g.
* "en-GB", "en_GB" or "en"). An empty string (<code>""</code>) represents the 'raw' bundle.
*
* <b>Note:</b> The given language tags can use modern or legacy ISO639 language codes.
* Whatever language code is used in the list of supported locales will also be used when
* requesting a file from the server. If the <code>bundleLocale</code> contains a legacy
* language code like "sh" and the <code>supportedLocales</code> contains [...,"sr",...], "sr"
* will be used in the URL. This mapping works in both directions. This parameter is passed to
* the underlying ResourceBundle (see {@link module:sap/base/i18n/ResourceBundle.create}).
* Supported since 1.77.0.
* @param {Object<string,module:sap/base/i18n/ResourceBundle.TerminologyConfiguration>} [oData.terminologies]
* An object, mapping a terminology identifier (e.g. "oil") to a
* <code>ResourceBundle.TerminologyConfiguration</code>. A terminology is a resource bundle
* configuration for a specific use case (e.g. "oil"). It does neither have a
* <code>fallbackLocale</code> nor can it be enhanced with <code>enhanceWith</code>. This
* parameter is passed to the underlying ResourceBundle (see
* {@link module:sap/base/i18n/ResourceBundle.create}). This parameter is ignored when
* <code>bundle</code> is set. Will cause an error if <code>enhanceWith</code> contains
* instances of <code>ResourceBundle</code>.
* Supported since 1.77.0.
*
* @alias sap.ui.model.resource.ResourceModel
* @author SAP SE
* @class
* Model implementation for resource bundles.
*
* This model is not prepared to be inherited from.
*
* This model allows to bind control properties against translatable texts. Its data is taken
* from a {@link module:sap/base/i18n/ResourceBundle} and it only supports property bindings.
*
* In contrast to most other models, binding paths for a <code>ResourceModel</code> must not
* start with a slash; they are absolute by default, and there's no further structure. Each key
* in the underlying resource bundle is a valid binding path.
*
* In extensibility scenarios, the texts of the resource bundle can be {@link #enhance enhanced}
* with additional resource bundles. These additional bundles can define new texts for existing
* keys, texts for new keys, or both. When texts for existing keys are replaced, the latest
* enhancement wins.
*
* This model supports the binding modes <code>OneWay</code> and <code>OneTime</code>, but not
* <code>TwoWay</code>. When the recommended asynchronous loading of the bundle is used, binding
* mode <code>OneTime</code> can't be used.
*
* @extends sap.ui.model.Model
* @public
* @version 1.147.0
*/
var ResourceModel = Model.extend("sap.ui.model.resource.ResourceModel", /** @lends sap.ui.model.resource.ResourceModel.prototype */ {
constructor : function (oData) {
var bUseResourceModelEnhanceMechanism;
Model.apply(this, arguments);
this.aCustomBundles = [];
this.bReenhance = false;
this.bAsync = !!(oData && oData.async);
if (!this.bAsync) {
Log.warning("Usage of synchronous loading is deprecated. For performance reasons, asynchronous loading"
+ " is strongly recommended.", undefined, sClassname);
}
this.sDefaultBindingMode = oData.defaultBindingMode || BindingMode.OneWay;
this.mSupportedBindingModes = {
"OneWay" : true,
"TwoWay" : false,
"OneTime" : !this.bAsync
};
if (this.bAsync && this.sDefaultBindingMode == BindingMode.OneTime) {
Log.warning("Using binding mode OneTime for asynchronous ResourceModel is not supported!");
}
this.oData = Object.assign({}, oData);
// the new ResourceBundle's enhance mechanism works only with
// ResourceBundle.Configurations; if there is a ResourceBundle in the enhanceWith
// parameter, use the ResourceModel's enhance mechanism to be backward compatible.
bUseResourceModelEnhanceMechanism = Array.isArray(this.oData.enhanceWith)
&& this.oData.enhanceWith.some(function (oEnhanceWith) {
return oEnhanceWith instanceof ResourceBundle;
});
if (oData && oData.bundle) {
this._oResourceBundle = oData.bundle;
bUseResourceModelEnhanceMechanism = true;
} else if (oData && (oData.bundleUrl || oData.bundleName)) {
if (bUseResourceModelEnhanceMechanism) {
delete this.oData.enhanceWith;
// terminologies and activeTerminologies are only supported when there are
// no ResourceBundles in the enhanceWith array
if (oData.terminologies || oData.activeTerminologies) {
throw new Error("'terminologies' parameter and 'activeTerminologies' parameter are not"
+ " supported in configuration when enhanceWith contains ResourceBundles");
}
}
_load(this);
} else {
throw new Error("At least bundle, bundleName or bundleUrl must be provided!");
}
// ResourceModel's enhance mechanism
if (bUseResourceModelEnhanceMechanism && Array.isArray(oData.enhanceWith)) {
if (this.bAsync) {
this._pEnhanced = oData.enhanceWith.reduce(function (chain, bundle) {
return chain.then(this.enhance.bind(this, bundle));
}.bind(this), Promise.resolve());
} else {
oData.enhanceWith.forEach(this.enhance.bind(this));
}
}
}
});
/**
* This method ensures that the bundleName does not contain leading slashes or dots by removing them.
* @param {string} sBundleName the bundle's name, e.g. ".i18n.i18n"
* @returns {string} sanitized bundleName without leading slashes or dots
* @private
*/
ResourceModel._sanitizeBundleName = function(sBundleName) {
// Starting slashes or dots are removed to prevent a leading-slash error thrown through
// the sap.ui.require.toUrl function call
if (sBundleName && (sBundleName[0] === "/" || sBundleName[0] === ".")) {
Log.error('Incorrect resource bundle name "' + sBundleName + '"',
'Leading slashes or dots in resource bundle names are ignored, since such names are'
+ ' invalid UI5 module names. Please check whether the resource bundle "'
+ sBundleName + '" is actually needed by your application.',
sClassname);
sBundleName = sBundleName.replace(rLeadingDotsOrSlashes, "");
}
return sBundleName;
};
/**
* Returns the resource bundle or a promise resolving with the resource bundle.
*
* @param {object} oData
* Parameters used to load the resource bundle; see constructor of the
* {@link sap.ui.model.resource.ResourceModel}
* @param {string[]} [oData.activeTerminologies]
* The list of active terminologies, e.g. <code>["oil", "retail"]</code>.
* This parameter is passed to the underlying ResourceBundle (see
* {@link module:sap/base/i18n/ResourceBundle.create}). Supported since 1.77.0.
* @param {string} [oData.bundleLocale]
* A locale in "BCP-47 language tag" notation specifying the locale in which to load the
* bundle; when not given, the current session locale of UI5 is used (recommended)
* @param {string} [oData.bundleName]
* UI5 module name in dot notation referring to the base ".properties" file
* @param {string} [oData.bundleUrl]
* URL pointing to the base ".properties" file of a bundle
* @param {module:sap/base/i18n/ResourceBundle[]|module:sap/base/i18n/ResourceBundle.Configuration[]} [oData.enhanceWith]
* A list of resource bundles or resource bundle configurations that enhance the texts from
* the main bundle; intended for extensibility scenarios; see also the class documentation.
* ResourceBundles use the ResourceModel's enhance mechanism and ResourceBundle.Configurations
* get passed to the underlying ResourceBundle (see
* {@link module:sap/base/i18n/ResourceBundle.create}). Supported since 1.77.0.
* @param {string} [oData.fallbackLocale="en"]
* A fallback locale to be used after all locales derived from <code>bundleLocale</code> have
* been tried, but before the 'raw' bundle is used. Can either be a BCP47 language tag or a
* JDK compatible locale string (e.g. "en-GB", "en_GB" or "en").
*
* To prevent a generic fallback, use the empty string (<code>""</code>). E.g. by providing
* <code>fallbackLocale: ""</code> and <code>supportedLocales: ["en"]</code>, only the bundle
* "en" is requested without any fallback. This parameter is passed to the underlying
* ResourceBundle (see {@link module:sap/base/i18n/ResourceBundle.create}).
* @param {string[]} [oData.supportedLocales]
* List of supported locales (aka 'language tags') to restrict the fallback chain. Each entry
* in the array can either be a BCP47 language tag or a JDK compatible locale string (e.g.
* "en-GB", "en_GB" or "en"). An empty string (<code>""</code>) represents the 'raw' bundle.
* <b>Note:</b> The given language tags can use modern or legacy ISO639 language codes.
* Whatever language code is used in the list of supported locales will also be used when
* requesting a file from the server. If the <code>bundleLocale</code> contains a legacy
* language code like "sh" and the <code>supportedLocales</code> contains [...,"sr",...], "sr"
* will be used in the URL. This mapping works in both directions. This parameter is passed
* to the underlying ResourceBundle (see {@link module:sap/base/i18n/ResourceBundle.create}).
* @param {Object<string,module:sap/base/i18n/ResourceBundle.TerminologyConfiguration>} [oData.terminologies]
* An object mapping a terminology identifier (e.g. "oil") to a
* <code>ResourceBundle.TerminologyConfiguration</code>. A terminology is a resource bundle
* configuration for a specific use case (e.g. "oil"). It does neither have a
* <code>fallbackLocale</code> nor can it be enhanced with <code>enhanceWith</code>. This
* parameter is passed to the underlying ResourceBundle (see
* {@link module:sap/base/i18n/ResourceBundle.create}). Supported since 1.77.0.
* @param {boolean} bAsync
* Whether the resource bundle should be loaded asynchronously
* @returns {module:sap/base/i18n/ResourceBundle|Promise<module:sap/base/i18n/ResourceBundle>}
* Loaded resource bundle or <code>Promise</code> resolving with the resource bundle in async
* case
*
* @private
* @ui5-restricted sap.ui.core.Component
*/
ResourceModel.loadResourceBundle = function (oData, bAsync) {
var sLocale = oData.bundleLocale,
mParams;
// sanitize bundleName for backward compatibility
oData.bundleName = ResourceModel._sanitizeBundleName(oData.bundleName);
mParams = Object.assign({
async: bAsync,
includeInfo: Supportability.collectOriginInfo(),
locale: sLocale
}, oData);
return ResourceBundle.create(mParams);
};
/**
* Enhances the resource model with a custom resource bundle.
*
* The custom bundle can define new texts for keys existing in the main bundle, texts for new
* keys, or both. A resource model can be enhanced with multiple resource bundles by calling
* this method multiple times. Each call appends to the list of enhancements, but no bundle can
* be removed from the list.
*
* When looking up a text for a key, the enhancements are processed in reverse order. Texts from
* the last added resource bundle are preferred over texts from previously added bundles or
* texts from the main bundle.
*
* @param {module:sap/base/i18n/ResourceBundle|object} oData
* Either an already loaded bundle instance, or a configuration object with parameters to load
* a new resource bundle. When a configuration object is given, at least one of
* <code>bundleUrl</code> or <code>bundleName</code> must be set; if both are set,
* <code>bundleName</code> wins
* @param {string} [oData.bundleLocale]
* A locale in "BCP-47 language tag" notation specifying the locale in which to load the
* bundle; when not given, the current session locale of UI5 is used (recommended)
* @param {string} [oData.bundleName]
* UI5 module name in dot notation, referring to the base ".properties" file; this name is
* resolved to a path like the paths of normal UI5 modules, and ".properties" is then
* appended (e.g. a name like "myapp.i18n.myBundle" can be given); relative module names are
* not supported
* @param {string} [oData.bundleUrl]
* URL pointing to the base ".properties" file of a bundle (".properties" file without any
* locale information, e.g. "../../i18n/mybundle.properties"); relative URLs are evaluated
* relative to the document.baseURI
* @returns {Promise|null} A Promise resolving when the enhancement is finished or
* <code>null</code> if the <code>ResourceModel</code> is configured to act synchronously
* @since 1.16.1
* @public
*/
ResourceModel.prototype.enhance = function (oData) {
var that = this,
fResolve,
oPromise = this.bAsync ? new Promise(function (resolve) {
fResolve = resolve;
}) : null;
function doEnhance() {
if (oData instanceof ResourceBundle) {
that._oResourceBundle._enhance(oData);
that.checkUpdate(true);
if (oPromise) {
fResolve(true);
}
} else {
if (oData.terminologies) {
throw new Error("'terminologies' parameter is not"
+ " supported for enhancement");
}
var bundle = ResourceModel.loadResourceBundle(oData, that.bAsync);
if (bundle instanceof Promise) {
bundle.then(function (customBundle) {
that._oResourceBundle._enhance(customBundle);
that.checkUpdate(true);
fResolve(true);
}, function () {
fResolve(true);
});
} else if (bundle) {
that._oResourceBundle._enhance(bundle);
that.checkUpdate(true);
}
}
}
if (this._oPromise) {
Promise.resolve(this._oPromise).then(doEnhance);
} else {
doEnhance();
}
if (!this.bReenhance) {
this.aCustomBundles.push(oData);
}
return oPromise;
};
/**
* Gets a property binding for the given path in the resource model. Only <code>sPath</code>
* from {@link sap.ui.model.Model#bindProperty} is supported; other parameters are ignored.
*
* @param {string} sPath
* The path pointing to the property that should be bound; in contrast to most other models,
* the binding path for a <code>ResourceModel</code> must not start with a slash, it is
* absolute by default and there's no further structure. Each key in the underlying resource
* bundle is a valid binding path.
* @return {sap.ui.model.PropertyBinding}
* The property binding for the given path
*
* @public
*/
ResourceModel.prototype.bindProperty = function (sPath) {
return new ResourcePropertyBinding(this, sPath);
};
/**
* Returns the value for the property with the given path.
*
* @param {string} sPath
* The path to the property
* @returns {string|null}
* The value of the property in the resource bundle or <code>null</code> if resource bundle is
* not available
*
* @public
*/
ResourceModel.prototype.getProperty = function (sPath) {
return this._oResourceBundle ? this._oResourceBundle.getText(sPath) : null;
};
/**
* Gets the resource bundle of this model.
*
* @returns {(module:sap/base/i18n/ResourceBundle|Promise<module:sap/base/i18n/ResourceBundle>)}
* The loaded resource bundle or a Promise resolving with it in asynchronous case
*
* @public
*/
ResourceModel.prototype.getResourceBundle = function () {
if (!this.bAsync) {
return this._oResourceBundle;
} else {
var p = this._oPromise;
if (p) {
return new Promise(function (resolve, reject) {
function _resolve(oBundle) {
resolve(oBundle);
}
p.then(_resolve, _resolve);
});
} else {
return Promise.resolve(this._oResourceBundle);
}
}
};
/**
* Reload resource bundle if current session locale changes. In that case
* <code>bundleName</code> or <code>bundleUrl</code> have to be specified.
*
* @private
* @see sap.ui.base.ManagedObject#_handleLocalizationChange
*/
ResourceModel.prototype._handleLocalizationChange = function () {
var that = this;
SyncPromise.resolve(this.getResourceBundle()).then(function (oBundle) {
var oEventParameters;
if (that.bAsync) {
oEventParameters = {
url: ResourceBundle._getUrl(that.oData.bundleUrl,
// sanitize bundleName for backward compatibility
ResourceModel._sanitizeBundleName(that.oData.bundleName)),
async: true
};
that.fireRequestSent(oEventParameters);
}
var oRecreateResult = oBundle._recreate();
if (oRecreateResult instanceof Promise) {
that._oPromise = oRecreateResult;
}
return SyncPromise.resolve(oRecreateResult).then(function (oNewResourceBundle) {
that._oResourceBundle = oNewResourceBundle;
that._reenhance();
delete that._oPromise;
that.checkUpdate(true);
}).finally(function () {
if (that.bAsync) {
that.fireRequestCompleted(oEventParameters);
}
});
}).catch(function (oError) {
Log.error("Failed to reload bundles after localization change", oError, sClassname);
});
};
/**
* Re-applies all enhancements after localization changed; <code>bundleName</code> or
* <code>bundleUrl</code> have to be specified.
*
* @private
* @see sap.ui.model.resource.ResourceModel#enhance
*/
ResourceModel.prototype._reenhance = function () {
this.bReenhance = true;
this.aCustomBundles.forEach(function (oData) {
this.enhance(oData);
}.bind(this));
this.bReenhance = false;
};
/**
* Loads the resource bundle of the given resource model.
*
* @param {sap.ui.model.resource.ResourceModel} oModel The resource model instance
*
* @private
*/
function _load(oModel) {
var oData = oModel.oData;
if (oData && (oData.bundleUrl || oData.bundleName)) {
var res = ResourceModel.loadResourceBundle(oData, oData.async);
if (res instanceof Promise) {
// sanitize bundleName for backward compatibility
var oEventParam = {
url: ResourceBundle._getUrl(oData.bundleUrl,
ResourceModel._sanitizeBundleName(oData.bundleName)),
async: true
};
oModel.fireRequestSent(oEventParam);
oModel._oPromise = res;
oModel._oPromise.then(function (oBundle) {
oModel._oResourceBundle = oBundle;
oModel._reenhance();
delete oModel._oPromise;
oModel.checkUpdate(true);
oModel.fireRequestCompleted(oEventParam);
});
} else {
oModel._oResourceBundle = res;
oModel._reenhance();
oModel.checkUpdate(true);
}
}
}
return ResourceModel;
});