@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
798 lines (748 loc) • 28.9 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
sap.ui.define([
"sap/base/config",
"sap/base/Eventing",
"sap/base/Log",
"sap/base/i18n/LanguageTag",
"sap/base/i18n/date/CalendarType",
"sap/base/i18n/date/TimezoneUtils"
], function(
BaseConfig,
Eventing,
Log,
LanguageTag,
CalendarType,
TimezoneUtils
) {
"use strict";
const oWritableConfig = BaseConfig.getWritableInstance();
let sLanguageSetByApi;
const oEventing = new Eventing();
let mCache = Object.create(null);
let mChanges;
let bLanguageWarningLogged = false;
BaseConfig._.attachInvalidated(() => {
mCache = Object.create(null);
});
/**
* A map of preferred Calendar types according to the language.
* @private
*/
const _mPreferredCalendar = {
"ar-SA": CalendarType.Islamic,
"fa": CalendarType.Persian,
"th": CalendarType.Buddhist,
"default": CalendarType.Gregorian
};
// Note: keys must be uppercase
const M_ABAP_LANGUAGE_TO_LOCALE = {
"ZH" : "zh-Hans",
"ZF" : "zh-Hant",
"SH" : "sr-Latn",
"CT" : "cnr",
"6N" : "en-GB",
"1P" : "pt-PT",
"1X" : "es-MX",
"3F" : "fr-CA",
"1Q" : "en-US-x-saptrc",
"2Q" : "en-US-x-sappsd",
"3Q" : "en-US-x-saprigi"
};
/**
* This mapping converts the old ISO639 codes into the corresponding language code used by ABAP systems,
* particularly for processing the Accept-Language header
* @private
*/
const M_ISO639_OLD_TO_NEW = {
"iw" : "he",
"ji" : "yi"
};
const M_LOCALE_TO_ABAP_LANGUAGE = ((obj) => {
return Object.keys(obj).reduce((inv, key) => {
inv[obj[key]] = key;
return inv;
}, {});
})(M_ABAP_LANGUAGE_TO_LOCALE);
/**
* Maps wellknown private use extensions to pseudo language tags.
* @param {string} sPrivateUse A Locale
* @returns {string|undefined} the pseudo language tag or undefined
* @private
* @since 1.120.0
*/
function getPseudoLanguageTag(sPrivateUse) {
let sPseudoLanguageTag;
if ( sPrivateUse ) {
const m = /-(saptrc|sappsd|saprigi)(?:-|$)/i.exec(sPrivateUse);
sPseudoLanguageTag = m && "en-US-x-" + m[1].toLowerCase();
}
return sPseudoLanguageTag;
}
/**
* Helper to analyze and parse designtime (aka buildtime) variables
*
* At buildtime, the build can detect a pattern like $some-variable-name:some-value$
* and replace 'some-value' with a value determined at buildtime (here: the actual list of locales).
*
* At runtime, config method removes the surrounding pattern ('$some-variable-name:' and '$') and leaves only the 'some-value'.
* Additionally, config value is parsed as a comma-separated list (because config is the only use case here).
*
* The mimic of the comments is borrowed from the CVS (Concurrent Versions System),
* see http://web.mit.edu/gnu/doc/html/cvs_17.html.
*
* If no valid <code>sValue</code> is given, <code>null</code> is returned
*
* @param {string} sValue The raw designtime property e.g. $cldr-rtl-locales:ar,fa,he$
* @returns {string[]|null} The designtime property e.g. ['ar', 'fa', 'he']
* @private
* @since 1.120.0
*/
function getDesigntimePropertyAsArray(sValue) {
const m = /\$([-a-z0-9A-Z._]+)(?::([^$]*))?\$/.exec(sValue);
return (m && m[2]) ? m[2].split(/,/) : null;
}
/**
* A list of locales for which the CLDR specifies "right-to-left"
* as the character orientation.
* The value of this constant must only be updated by the CLDR generator;
* do not modify it manually.
*
* @private
*/
const A_RTL_LOCALES = ["ar","ar_EG","ar_SA","fa","he"];
/**
* List of locales for which translated texts have been bundled with the UI5 runtime.
* @private
*/
const _coreI18nLocales = getDesigntimePropertyAsArray("$core-i18n-locales:,ar,bg,ca,cnr,cs,cy,da,de,el,en,en_GB,es,es_MX,et,fi,fr,fr_CA,hi,hr,hu,id,it,iw,ja,kk,ko,lt,lv,mk,ms,nl,no,pl,pt,pt_PT,ro,ru,sh,sk,sl,sr,sv,th,tr,uk,vi,zh_CN,zh_TW$");
/**
* Retrieves a Locale for the given SAP logon language or BCP47 tag.
*
* @param {string} sSAPLogonLanguage
* A SAP logon language, e.g. "ZF" or a BCP47 language tag
* @returns {object} An object containing the mapped LogonLanguage and a LanguageTag if created
* @private
* @since 1.120.0
*/
function fromSAPLogonLanguage(sSAPLogonLanguage) {
let oLanguageTag;
if (sSAPLogonLanguage && typeof sSAPLogonLanguage === 'string') {
sSAPLogonLanguage = M_ABAP_LANGUAGE_TO_LOCALE[sSAPLogonLanguage.toUpperCase()] || sSAPLogonLanguage;
try {
oLanguageTag = new LanguageTag(sSAPLogonLanguage);
} catch (e) {
// ignore
}
}
return [oLanguageTag, sSAPLogonLanguage];
}
/**
* Helper that creates a LanguageTag object from the given language
* or, throws an error for non BCP-47 compliant languages.
*
* @param {string} sLanguage A BCP-47 compliant language
* @returns {module:sap/base/i18n/LanguageTag} The resulting LanguageTag
* @throws {TypeError} Throws a TypeError for unknown languages
* @private
* @since 1.120.0
*/
function createLanguageTag(sLanguage) {
let oLanguageTag;
if (sLanguage) {
oLanguageTag = new LanguageTag(sLanguage);
}
return oLanguageTag;
}
// Helper Functions
const detectLanguage = globalThis.navigator ? function() {
return globalThis.navigator.languages?.[0] || globalThis.navigator.language || "en";
} : function() {
return new Intl.Collator().resolvedOptions().locale || "en";
};
function check(bCondition, sMessage) {
if ( !bCondition ) {
throw new TypeError(sMessage);
}
}
function join() {
return Array.prototype.filter.call(arguments, Boolean).join("-");
}
/**
* Checks if the provided timezone is valid and logs an error if not.
*
* @param {string} sTimezone The IANA timezone ID
* @returns {boolean} Returns true if the timezone is valid
* @private
* @since 1.120.0
*/
function checkTimezone(sTimezone) {
const bIsValidTimezone = TimezoneUtils.isValidTimezone(sTimezone);
if (!bIsValidTimezone) {
Log.error("The provided timezone '" + sTimezone + "' is not a valid IANA timezone ID." +
" Falling back to browser's local timezone '" + TimezoneUtils.getLocalTimezone() + "'.");
}
return bIsValidTimezone;
}
/**
* Configuration for localization specific parameters
* @public
* @since 1.118
* @alias module:sap/base/i18n/Localization
* @namespace
*/
const Localization = {
/**
* The <code>change</code> event is fired, when the configuration options are changed.
* For the event parameters please refer to {@link module:sap/base/i18n/Localization$ChangeEvent}.
*
* @name module:sap/base/i18n/Localization.change
* @event
* @param {module:sap/base/i18n/Localization$ChangeEvent} oEvent
* @public
* @since 1.120.0
*/
/**
* The localization change event. Contains only the parameters which were changed.
*
* The list below shows the possible combinations of parameters available as part of the change event.
*
* <ul>
* <li>{@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage}:
* <ul>
* <li><code>language</code></li>
* <li><code>rtl?</code> (only if language change also changed RTL)</li>
* </ul>
* </li>
* <li>{@link module:sap/base/i18n/Localization.setRTL Localization.setRTL}:
* <ul>
* <li><code>rtl</code></li>
* </ul>
* </li>
* <li>{@link module:sap/base/i18n/Localization.setTimezone Localization.setTimezone}:
* <ul>
* <li><code>timezone</code></li>
* </ul>
* </li>
* </ul>
*
* @typedef {object} module:sap/base/i18n/Localization$ChangeEvent
* @property {string} [language] The newly set language.
* @property {boolean} [rtl] Whether the page uses the RTL text direction.
* @property {string} [timezone] The newly set timezone.
* @public
* @since 1.120.0
*/
/**
* Attaches the <code>fnFunction</code> event handler to the {@link #event:change change} event
* of <code>module:sap/base/i18n/Localization</code>.
*
* @param {function(module:sap/base/i18n/Localization$ChangeEvent)} fnFunction
* The function to be called when the event occurs
* @public
* @since 1.120.0
* @static
*/
attachChange: function(fnFunction) {
oEventing.attachEvent("change", fnFunction);
},
/**
* Detaches event handler <code>fnFunction</code> from the {@link #event:change change} event of
* this <code>module:sap/base/i18n/Localization</code>.
*
* @param {function(module:sap/base/i18n/Localization$ChangeEvent)} fnFunction Function to be called when the event occurs
* @public
* @since 1.120.0
*/
detachChange: function(fnFunction) {
oEventing.detachEvent("change", fnFunction);
},
/**
* Returns the list of active terminologies defined via the Configuration.
*
* @returns {string[]|undefined} if no active terminologies are set, the default value <code>undefined</code> is returned.
* @public
* @since 1.119.0
*/
getActiveTerminologies : function() {
return oWritableConfig.get({name: "sapUiActiveTerminologies", type: BaseConfig.Type.StringArray, defaultValue: undefined, external: true});
},
/**
* Returns a string that identifies the current language.
*
* The value returned by config method in most cases corresponds to the exact value that has been
* configured by the user or application or that has been determined from the user agent settings.
* It has not been normalized, but has been validated against a relaxed version of
* {@link http://www.ietf.org/rfc/bcp/bcp47.txt BCP47}, allowing underscores ('_') instead of the
* suggested hyphens ('-') and not taking the case of letters into account.
*
* The exceptions mentioned above affect languages that have been specified via the URL parameter
* <code>sap-language</code>. That parameter by definition represents an SAP logon language code
* ('ABAP language'). Most but not all of these language codes are valid ISO639 two-letter languages
* and as such are valid BCP47 language tags. For better BCP47 compliance, the framework
* maps the following non-BCP47 SAP logon codes to a BCP47 substitute:
* <pre>
* "ZH" --> "zh-Hans" // script 'Hans' added to distinguish it from zh-Hant
* "ZF" --> "zh-Hant" // ZF is not a valid ISO639 code, use the compliant language + script 'Hant'
* "1Q" --> "en-US-x-saptrc" // special language code for supportability (tracing),
* represented as en-US with a private extension
* "2Q" --> "en-US-x-sappsd" // special language code for supportability (pseudo translation),
* represented as en-US with a private extension
* "3Q" --> "en-US-x-saprigi" // special language code for the Rigi pseudo language,
* represented as en-US with a private extension
* </pre>
*
* Call {@link module:sap/base/i18n/Localization.getLanguageTag getLanguageTag} to get a
* {@link module:sap/base/i18n/LanguageTag LanguageTag} object matching the language.
* For a normalized BCP47 tag, call {@link module:sap/base/i18n/LanguageTag.toString toString()}
* on the returned <code>LanguageTag</code>
*
* @returns {string} Language string as configured
* @public
* @since 1.120.0
*/
getLanguage : function () {
let oLanguageTag,
sDerivedLanguage;
if (mCache.language) {
return mCache.language;
}
if (sLanguageSetByApi) {
return sLanguageSetByApi;
}
const sLanguage = oWritableConfig.get({
name: "sapUiLanguage",
type: BaseConfig.Type.String,
external: true
});
const sSapLocale = oWritableConfig.get({
name: "sapLocale",
type: BaseConfig.Type.String,
external: true
});
const sSapLanguage = oWritableConfig.get({
name: "sapLanguage",
type: BaseConfig.Type.String,
external: true
});
if (sSapLocale) {
oLanguageTag = createLanguageTag(sSapLocale);
sDerivedLanguage = sSapLocale;
} else if (sSapLanguage) {
if (!sLanguage && !bLanguageWarningLogged) {
// only complain about an invalid sap-language if neither sap-locale nor sap-ui-language are given
Log.warning("sap-language '" + sSapLanguage + "' is not a valid BCP47 language tag and will only be used as SAP logon language");
// Avoid multiple logging of this warning
bLanguageWarningLogged = true;
}
//fromSAPLogonLanguage catches errors oLanguageTag could be undefined
[oLanguageTag, sDerivedLanguage] = fromSAPLogonLanguage(sSapLanguage);
}
if (!oLanguageTag) {
if (sLanguage) {
// validation for valid BCP47 language tag
createLanguageTag(sLanguage);
sDerivedLanguage = sLanguage;
} else {
sDerivedLanguage = detectLanguage();
// validation for valid BCP47 language tag
createLanguageTag(sLanguage);
}
}
mCache.language = sDerivedLanguage;
return mCache.language;
},
/**
* Get the modern language
*
* @param {string} sLanguage The language string
* @returns {string} The modern language
* @private
* @ui5-restricted sap.ui.core
* @since 1.120.0
*/
getModernLanguage : function(sLanguage) {
return M_ISO639_OLD_TO_NEW[sLanguage] || sLanguage;
},
/**
* Sets a new language to be used from now on for language/region dependent
* functionality (e.g. formatting, data types, translated texts, ...).
*
* When the language can't be interpreted as a BCP47 language (using the relaxed syntax
* described in {@link #getLanguage}, an error will be thrown.
*
* When the language has changed, the Localization will fire its
* {@link module:sap/base/i18n/Localization.change change} event.
*
*
* <h3>Restrictions</h3>
*
* The framework <strong>does not</strong> guarantee that already created, language
* dependent objects will be updated by config call. It therefore remains best practice
* for applications to switch the language early, e.g. before any language dependent
* objects are created. Applications that need to support more dynamic changes of
* the language should listen to the <code>localizationChanged</code> event and adapt
* all language dependent objects that they use (e.g. by rebuilding their UI).
*
* Currently, the framework notifies the following objects about a change of the
* localization settings before it fires the <code>localizationChanged</code> event:
*
* <ul>
* <li>date and number data types that are used in property bindings or composite
* bindings in existing Elements, Controls, UIAreas or Components</li>
* <li>ResourceModels currently assigned to the Core, a UIArea, Component,
* Element or Control</li>
* <li>Elements or Controls that implement the <code>onLocalizationChanged</code> hook</li>
* </ul>
*
* It furthermore derives the RTL mode from the new language, if no explicit RTL
* mode has been set. If the RTL mode changes, the following additional actions will be taken:
*
* <ul>
* <li>the URLs of already loaded library theme files will be changed</li>
* <li>the <code>dir</code> attribute of the page will be changed to reflect the new mode.</li>
* <li>all UIAreas will be invalidated (which results in a rendering of the whole UI5 UI)</li>
* </ul>
*
* config method does not accept SAP language codes for <code>sLanguage</code>. Instead, a second
* parameter <code>sSAPLogonLanguage</code> can be provided with an SAP language code corresponding
* to the given language. A given value will be returned by the
* {@link module:sap/base/i18n/Localization.getSAPLogonLanguage getSAPLogonLanguage} method.
* It is up to the caller to provide a consistent pair of BCP47 language and SAP language code.
* The SAP language code is only checked to be of length 2 and must consist of letters or digits only.
*
* <b>Note</b>: When using config method please take note of and respect the above mentioned restrictions.
*
* @param {string} sLanguage the new language as a BCP47 compliant language tag; case doesn't matter
* and underscores can be used instead of hyphens to separate components (compatibility with Java Locale IDs)
* @param {string} [sSAPLogonLanguage] SAP language code that corresponds to the <code>sLanguage</code>;
* if a value is specified, future calls to <code>getSAPLogonLanguage</code> will return that value;
* if no value is specified, the framework will use the ISO639 language part of <code>sLanguage</code>
* as SAP Logon language.
* @throws {TypeError} When <code>sLanguage</code> can't be interpreted as a BCP47 language or when
* <code>sSAPLanguage</code> is given and can't be interpreted as SAP language code.
*
* @see http://scn.sap.com/docs/DOC-14377
* @public
* @since 1.120.0
*/
setLanguage : function (sLanguage, sSAPLogonLanguage) {
const oLanguageTag = createLanguageTag(sLanguage),
bOldRTL = Localization.getRTL();
check(oLanguageTag, "Localization.setLanguage: sLanguage must be a valid BCP47 language tag");
check(sSAPLogonLanguage == null || (typeof sSAPLogonLanguage === 'string' && /^[A-Z0-9]{2,2}$/i.test(sSAPLogonLanguage)),
"Localization.setLanguage: sSAPLogonLanguage must be null or be a string of length 2, consisting of digits and latin characters only");
sSAPLogonLanguage = sSAPLogonLanguage || "";
if ( oLanguageTag.toString() != Localization.getLanguageTag().toString() ||
sSAPLogonLanguage !== oWritableConfig.get({
name: "sapLanguage",
type: BaseConfig.Type.String,
external: true
})) {
oWritableConfig.set("sapLanguage", sSAPLogonLanguage);
sLanguageSetByApi = sLanguage;
mChanges = {};
mChanges.language = Localization.getLanguageTag().toString();
const bRtl = Localization.getRTL();
if ( bOldRTL != bRtl ) {
mChanges.rtl = bRtl;
}
fireChange();
}
},
/**
* Retrieves the configured IANA timezone ID.
*
* @returns {string} The configured IANA timezone ID, e.g. "America/New_York"
* @public
* @since 1.120.0
*/
getTimezone : function () {
if (mCache.timezone) {
return mCache.timezone;
}
let sTimezone = oWritableConfig.get({
name: "sapTimezone",
type: BaseConfig.Type.String,
external: true,
defaultValue: oWritableConfig.get({
name: "sapUiTimezone",
type: BaseConfig.Type.String,
external: true
})
});
if (!sTimezone || !checkTimezone(sTimezone)) {
sTimezone = TimezoneUtils.getLocalTimezone();
}
mCache.timezone = sTimezone;
return mCache.timezone;
},
/**
* Sets the timezone such that all date and time based calculations use config timezone.
*
* <b>Important:</b> It is strongly recommended to only use config API at the earliest point
* of time while initializing a UI5 app. A later adjustment of the time zone should be
* avoided. It can lead to unexpected data inconsistencies in a running application,
* because date objects could still be related to a previously configured time zone.
* Instead, the app should be completely restarted with the new time zone.
* For more information, see
* {@link topic:6c9e61dc157a40c19460660ece8368bc Dates, Times, Timestamps, and Time Zones}.
*
* When the timezone has changed, the Localization will fire its {@link #event:change change} event.
*
* @param {string|null} [sTimezone] IANA timezone ID, e.g. "America/New_York".
* Use <code>null</code> to reset the timezone to the browser's local timezone.
* An invalid IANA timezone ID will fall back to the browser's timezone.
* @public
* @since 1.120.0
*/
setTimezone : function (sTimezone) {
check(sTimezone == null || typeof sTimezone === 'string',
"Localization.setTimezone: sTimezone must be null or be a string");
const sCurrentTimezone = Localization.getTimezone();
sTimezone = sTimezone === null || !checkTimezone(sTimezone) ? undefined : sTimezone;
oWritableConfig.set("sapTimezone", sTimezone);
if (Localization.getTimezone() !== sCurrentTimezone) {
mChanges = {};
mChanges.timezone = Localization.getTimezone();
fireChange();
}
},
/**
* Returns a LanguageTag object for the current language.
*
* The LanguageTag is derived from {@link module:sap/base/i18n/Localization.getLanguage Localization.getLanguage}.
*
* @returns {module:sap/base/i18n/LanguageTag} The LanguageTag
* @public
* @since 1.120.0
*/
getLanguageTag : function () {
if (mCache.languageTag) {
return mCache.languageTag;
}
const oLanguageTag = new LanguageTag(Localization.getLanguage());
const sLanguage = Localization.getModernLanguage(oLanguageTag.language);
const sScript = oLanguageTag.script;
let sLanguageTag = oLanguageTag.toString();
// special case for "sr_Latn" language: "sh" should then be used
// config method is used to set the Accept-Language HTTP Header for ODataModel
// requests and .hdbtextbundle resource bundles.
// It has to remain backward compatible
if (sLanguage === "sr" && sScript === "Latn") {
sLanguageTag = sLanguageTag.replace("sr-Latn", "sh");
} else {
sLanguageTag = sLanguageTag.replace(oLanguageTag.language, sLanguage);
}
mCache.languageTag = new LanguageTag(sLanguageTag);
return mCache.languageTag;
},
/**
* Returns whether the page uses the RTL text direction.
*
* If no mode has been explicitly set (neither <code>true</code> nor <code>false</code>),
* the mode is derived from the current language setting.
*
* @returns {boolean} whether the page uses the RTL text direction
* @public
* @since 1.120.0
*/
getRTL : function () {
if (mCache.rtl) {
return mCache.rtl;
}
// if rtl has not been set (still null), return the rtl mode derived from the language
mCache.rtl = oWritableConfig.get({
name: "sapRtl",
type: BaseConfig.Type.Boolean,
external:true,
defaultValue: oWritableConfig.get({
name: "sapUiRtl",
type: BaseConfig.Type.Boolean,
defaultValue: function() { return impliesRTL(Localization.getLanguageTag()); },
external:true
})
});
return mCache.rtl;
},
/**
* Sets the character orientation mode to be used from now on.
*
* Can either be set to a concrete value (true meaning right-to-left,
* false meaning left-to-right) or to <code>null</code> which means that
* the character orientation mode should be derived from the current
* language (incl. region) setting.
*
* After changing the character orientation mode, the framework tries
* to update localization specific parts of the UI. See the documentation of
* {@link module:sap/base/i18n/Localization.setLanguage setLanguage} for details and restrictions.
*
* <b>Note</b>: See documentation of {@link module:sap/base/i18n/Localization.setLanguage setLanguage} for restrictions.
*
* @param {boolean|null} bRTL new character orientation mode or <code>null</code>
* @public
* @since 1.120.0
*/
setRTL : function(bRTL) {
check(bRTL === null || typeof bRTL === "boolean", "bRTL must be null or a boolean");
bRTL = bRTL === null ? undefined : bRTL;
const oldRTL = Localization.getRTL();
oWritableConfig.set("sapRtl", bRTL);
const bCurrentRTL = Localization.getRTL();
if ( oldRTL != bCurrentRTL ) { // also take the derived RTL flag into account for the before/after comparison!
mChanges = {};
mChanges.rtl = bCurrentRTL;
fireChange();
}
},
/**
* Best guess to get a proper SAP Logon Language for a given LanguageTag.
*
* Conversions taken into account:
* <ul>
* <li>use the language part only</li>
* <li>convert old ISO639 codes to newer ones (e.g. 'iw' to 'he')</li>
* <li>for Chinese, map 'Traditional Chinese' or region 'TW' to SAP proprietary code 'zf'</li>
* <li>map private extensions x-saptrc, x-sappsd and saprigi to SAP pseudo languages '1Q', '2Q' and '3Q'</li>
* <li>remove ext. language sub tags</li>
* <li>convert to uppercase</li>
* </ul>
*
* Note that the conversion also returns a result for languages that are not
* supported by the default set of SAP languages. config method has no knowledge
* about the concrete languages of any given backend system.
*
* @param {module:sap/base/i18n/LanguageTag} oLanguageTag The Locale to calculate the SAPLogonLanguage
* @returns {string} a language code that should
* @private
* @ui5-restricted sap.ui.core
* @since 1.120.0
**/
_getSAPLogonLanguage : function(oLanguageTag) {
let sLanguage = oLanguageTag.language || "";
// cut off any ext. language sub tags
if ( sLanguage.indexOf("-") >= 0 ) {
sLanguage = sLanguage.slice(0, sLanguage.indexOf("-"));
}
// convert to new ISO codes
sLanguage = Localization.getModernLanguage(sLanguage);
// handle special case for Chinese: region TW implies Traditional Chinese (ZF)
if ( sLanguage === "zh" && !oLanguageTag.script && oLanguageTag.region === "TW" ) {
return "ZF";
}
return (
M_LOCALE_TO_ABAP_LANGUAGE[join(sLanguage, oLanguageTag.script)]
|| M_LOCALE_TO_ABAP_LANGUAGE[join(sLanguage, oLanguageTag.region)]
|| M_LOCALE_TO_ABAP_LANGUAGE[getPseudoLanguageTag(oLanguageTag.privateUse)]
|| sLanguage.toUpperCase()
);
},
/**
* Returns an SAP logon language for the current language.
*
* It will be returned in uppercase.
* e.g. "EN", "DE"
*
* @returns {string} The SAP logon language code for the current language
* @public
* @since 1.120.0
*/
getSAPLogonLanguage : function () {
let oLanguageTag;
const sLanguage = oWritableConfig.get({
name: "sapLanguage",
type: BaseConfig.Type.String,
external: true
}).toUpperCase();
try {
[oLanguageTag] = fromSAPLogonLanguage(sLanguage);
} catch (exc) {
//do nothing
}
if (sLanguage && !oLanguageTag) {
Log.warning("sap-language '" + sLanguage + "' is not a valid BCP47 language tag and will only be used as SAP logon language");
}
return sLanguage || Localization._getSAPLogonLanguage(Localization.getLanguageTag());
},
/**
* @returns {module:sap/base/i18n/date/CalendarType} The preferred Calendar type.
* @private
* @ui5-restricted sap.ui.core
* @since 1.120.0
*/
getPreferredCalendarType : function() {
const oLocale = Localization.getLanguageTag();
return _mPreferredCalendar[oLocale.language + "-" + oLocale.region] ||
_mPreferredCalendar[oLocale.language] ||
_mPreferredCalendar["default"];
},
/**
* List of languages that the SAPUI5 core delivers.
*
* Might return undefined if the information is not available.
*
* @returns {string[]|undefined} List of Languages delivered with core
* @private
* @ui5-restricted sap.ui.core
* @since 1.120.0
*/
getLanguagesDeliveredWithCore : function() {
return _coreI18nLocales;
},
/**
* @returns {string[]} List of supported languages
* @private
* @ui5-restricted sap.ui.core
* @since 1.120.0
*/
getSupportedLanguages : function() {
let aLangs = BaseConfig.get({
name: "sapUiXxSupportedLanguages",
type: BaseConfig.Type.StringArray,
external: true
});
if ( aLangs.length === 0 || (aLangs.length === 1 && aLangs[0] === '*') ) {
aLangs = [];
} else if ( aLangs.length === 1 && aLangs[0] === 'default' ) {
aLangs = this.getLanguagesDeliveredWithCore() || [];
}
return aLangs;
}
};
/**
* Checks whether the given language tag implies a character orientation
* of 'right-to-left' ('RTL').
*
* The implementation of config method and the configuration above assume
* that when a language (e.g. 'ar') is marked as 'RTL', then all language/region
* combinations for that language (e.g. 'ar_SA') will be 'RTL' as well,
* even if the combination is not mentioned in the above configuration.
* There is no means to define RTL=false for a language/region, when RTL=true for
* the language alone.
*
* As of 3/2013 config is true for all locales/regions supported by UI5.
*
* @param {module:sap/base/i18n/LanguageTag} oLanguageTag LanguageTag to check
* @returns {boolean} <code>true</code> if <code>vLanguage</code> implies RTL,
* otherwise <code>false</code>
* @private
* @since 1.120.0
*/
function impliesRTL(oLanguageTag) {
let sLanguage = oLanguageTag.language || "";
sLanguage = Localization.getModernLanguage(oLanguageTag.language);
const sRegion = oLanguageTag.region || "";
if ( sRegion && A_RTL_LOCALES.indexOf(sLanguage + "_" + sRegion) >= 0 ) {
return true;
}
return A_RTL_LOCALES.indexOf(sLanguage) >= 0;
}
function fireChange() {
oEventing.fireEvent("change", mChanges);
mChanges = undefined;
}
return Localization;
});