UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

1,164 lines (1,105 loc) 44.3 kB
/*! * 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/assert", "sap/base/config", "sap/base/Eventing", "sap/base/Log", "sap/base/i18n/Localization", "sap/base/i18n/LanguageTag", "sap/base/i18n/date/CalendarType", "sap/base/i18n/date/CalendarWeekNumbering", "sap/base/util/deepEqual", "sap/base/util/extend", "sap/base/util/isEmptyObject" ], ( assert, BaseConfig, Eventing, Log, Localization, LanguageTag, CalendarType, CalendarWeekNumbering, deepEqual, extend, isEmptyObject ) => { "use strict"; const oEventing = new Eventing(); const oWritableConfig = BaseConfig.getWritableInstance(); const mSettings = {}; let mChanges; let aCustomIslamicCalendarData; let bInitialized = false; const M_ABAP_DATE_FORMAT_PATTERN = { "" : {pattern: null}, "1": {pattern: "dd.MM.yyyy"}, "2": {pattern: "MM/dd/yyyy"}, "3": {pattern: "MM-dd-yyyy"}, "4": {pattern: "yyyy.MM.dd"}, "5": {pattern: "yyyy/MM/dd"}, "6": {pattern: "yyyy-MM-dd"}, "7": {pattern: "Gyy.MM.dd"}, "8": {pattern: "Gyy/MM/dd"}, "9": {pattern: "Gyy-MM-dd"}, "A": {pattern: "yyyy/MM/dd"}, "B": {pattern: "yyyy/MM/dd"}, "C": {pattern: "yyyy/MM/dd"} }; const M_ABAP_TIME_FORMAT_PATTERN = { "" : {"short": null, medium: null, dayPeriods: null}, "0": {"short": "HH:mm", medium: "HH:mm:ss", dayPeriods: null}, "1": {"short": "hh:mm a", medium: "hh:mm:ss a", dayPeriods: ["AM", "PM"]}, "2": {"short": "hh:mm a", medium: "hh:mm:ss a", dayPeriods: ["am", "pm"]}, "3": {"short": "KK:mm a", medium: "KK:mm:ss a", dayPeriods: ["AM", "PM"]}, "4": {"short": "KK:mm a", medium: "KK:mm:ss a", dayPeriods: ["am", "pm"]} }; const M_ABAP_NUMBER_FORMAT_SYMBOLS = { "" : {groupingSeparator: null, decimalSeparator: null}, " ": {groupingSeparator: ".", decimalSeparator: ","}, "X": {groupingSeparator: ",", decimalSeparator: "."}, "Y": {groupingSeparator: " ", decimalSeparator: ","} }; function check(bCondition, sMessage) { if ( !bCondition ) { throw new TypeError(sMessage); } } function _set(sKey, oValue) { // Invalidating the BaseConfig is necessary, because Formatting.getLanguageTag // does defaulting depending on the mSettings. In case no specifc LaguageTag was // set the default would become applied and cached. If the mSettings are changed // inbetween the cache would not become invalidated because there is no direct // change to the Configuration and therefore the cached value would be wrong. BaseConfig._.invalidate(); const oOldValue = mSettings[sKey]; if (oValue != null) { mSettings[sKey] = oValue; } else { delete mSettings[sKey]; } // report a change only if old and new value differ (null/undefined are treated as the same value) if ((oOldValue != null || oValue != null) && !deepEqual(oOldValue, oValue)) { const bFireEvent = !mChanges; mChanges ??= {}; mChanges[sKey] = oValue; if (bFireEvent) { fireChange(); } } } /** * Helper that creates a LanguageTag object from the given language * or, throws an error for non BCP-47 compliant languages. * * @param {string|module:sap/base/i18n/LanguageTag} vLanguageTag A BCP-47 compliant language tag * @returns {module:sap/base/i18n/LanguageTag} The resulting LanguageTag * @private * @since 1.116.0 */ function createLanguageTag(vLanguageTag) { let oLanguageTag; if (vLanguageTag && typeof vLanguageTag === 'string') { try { oLanguageTag = new LanguageTag(vLanguageTag); } catch (e) { // ignore } } else if (vLanguageTag instanceof LanguageTag) { oLanguageTag = vLanguageTag; } return oLanguageTag; } /** * Configuration for formatting specific parameters * @public * @alias module:sap/base/i18n/Formatting * @namespace * @since 1.120 */ const Formatting = { /** * 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/Formatting$ChangeEvent * Formatting$ChangeEvent}. * * @name module:sap/base/i18n/Formatting.change * @event * @param {module:sap/base/i18n/Formatting$ChangeEvent} oEvent * @public * @since 1.120 */ /** * The formatting 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/Formatting.setLanguageTag Formatting.setLanguageTag}: * <ul> * <li><code>languageTag</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setCustomIslamicCalendarData Formatting.setCustomIslamicCalendarData}: * <ul> * <li><code>customIslamicCalendarData</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setCalendarWeekNumbering Formatting.setCalendarWeekNumbering}: * <ul> * <li><code>calendarWeekNumbering</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setCalendarType Formatting.setCalendarType}: * <ul> * <li><code>calendarType</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.addCustomCurrencies Formatting.addCustomCurrencies} / {@link module:sap/base/i18n/Formatting.setCustomCurrencies Formatting.setCustomCurrencies}: * <ul> * <li><code>currency</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setABAPDateFormat Formatting.setABAPDateFormat} (all parameters listed below): * <ul> * <li><code>ABAPDateFormat</code></li> * <li><code>"dateFormats-short"</code></li> * <li><code>"dateFormats-medium"</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setABAPTimeFormat Formatting.setABAPTimeFormat} (all parameters listed below): * <ul> * <li><code>ABAPTimeFormat</code></li> * <li><code>"timeFormats-short"</code></li> * <li><code>"timeFormats-medium"</code></li> * <li><code>"dayPeriods-format-abbreviated"</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setABAPNumberFormat Formatting.setABAPNumberFormat} (all parameters listed below): * <ul> * <li><code>ABAPNumberFormat</code></li> * <li><code>"symbols-latn-group"</code></li> * <li><code>"symbols-latn-decimal"</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setDatePattern Formatting.setDatePattern} (one of the parameters listed below): * <ul> * <li><code>"dateFormats-short"</code></li> * <li><code>"dateFormats-medium"</code></li> * <li><code>"dateFormats-long"</code></li> * <li><code>"dateFormats-full"</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setTimePattern Formatting.setTimePattern} (one of the parameters listed below): * <ul> * <li><code>"timeFormats-short"</code></li> * <li><code>"timeFormats-medium"</code></li> * <li><code>"timeFormats-long"</code></li> * <li><code>"timeFormats-full"</code></li> * </ul> * </li> * <li>{@link module:sap/base/i18n/Formatting.setNumberSymbol Formatting.setNumberSymbol} (one of the parameters listed below): * <ul> * <li><code>"symbols-latn-group"</code></li> * <li><code>"symbols-latn-decimal"</code></li> * <li><code>"symbols-latn-plusSign"</code></li> * <li><code>"symbols-latn-minusSign"</code></li> * </ul> * </li> * </ul> * * @typedef {object} module:sap/base/i18n/Formatting$ChangeEvent * @property {string} [languageTag] The formatting language tag. * @property {string} [ABAPDateFormat] The ABAP date format. * @property {string} [ABAPTimeFormat] The ABAP time format. * @property {string} [ABAPNumberFormat] The ABAP number format. * @property {object[]} [legacyDateCalendarCustomizing] The legacy date calendar customizing. * @property {object} [calendarWeekNumbering] The calendar week numbering. * @property {object} [calendarType] The calendar type. * @property {string} ["dateFormats-short"] The short date format. * @property {string} ["dateFormats-medium"] The medium date format. * @property {string} ["dateFormats-long"] The long date format. * @property {string} ["dateFormats-full"] The full date format. * @property {string} ["timeFormats-short"] The short time format. * @property {string} ["timeFormats-medium"] The medium time format. * @property {string} ["timeFormats-long"] The long time format. * @property {string} ["timeFormats-full"] The full time format. * @property {string} ["symbols-latn-group"] The latin symbols group. * @property {string} ["symbols-latn-decimal"] The latin symbols decimal. * @property {string} ["symbols-latn-plusSign"] The latin symbols plusSign. * @property {string} ["symbols-latn-minusSign"] The latin symbols minusSign. * @property {Object<string,string>} [currency] The currency. * @property {string[]} ["dayPeriods-format-abbreviated"] The abbreviated day periods format. * @public * @since 1.120 */ /** * Attaches the <code>fnFunction</code> event handler to the {@link #event:change change} event * of <code>module:sap/base/i18n/Formatting</code>. * * @param {function(module:sap/base/i18n/Formatting$ChangeEvent)} fnFunction * The function to be called when the event occurs * @public * @since 1.120 */ attachChange(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/Formatting</code>. * * @param {function(module:sap/base/i18n/Formatting$ChangeEvent)} fnFunction Function to be called when the event occurs * @public * @since 1.120 */ detachChange(fnFunction) { oEventing.detachEvent("change", fnFunction); }, /** * Returns the LanguageTag to be used for formatting. * * If no such LanguageTag has been defined, this method falls back to the language, * see {@link module:sap/base/i18n/Localization.getLanguage Localization.getLanguage()}. * * If any user preferences for date, time or number formatting have been set, * and if no format LanguageTag has been specified, then a special private use subtag * is added to the LanguageTag, indicating to the framework that these user preferences * should be applied. * * @returns {module:sap/base/i18n/LanguageTag} the format LanguageTag * @public * @since 1.120 */ getLanguageTag() { function fallback() { let oLanguageTag = new LanguageTag(Localization.getLanguage()); // if any user settings have been defined, add the private use subtag "sapufmt" if (!isEmptyObject(mSettings) || Formatting.getCalendarWeekNumbering() !== CalendarWeekNumbering.Default) { let l = oLanguageTag.toString(); if ( l.indexOf("-x-") < 0 ) { l += "-x-sapufmt"; } else if ( l.indexOf("-sapufmt") <= l.indexOf("-x-") ) { l += "-sapufmt"; } oLanguageTag = new LanguageTag(l); } return oLanguageTag; } return oWritableConfig.get({ name: "sapUiFormatLocale", type: function(sFormatLocale) {return new LanguageTag(sFormatLocale);}, defaultValue: fallback, external: true }); }, /** * Sets a new language tag to be used from now on for retrieving language * specific formatters. Modifying this setting does not have an impact on * the retrieval of translated texts! * * Can either be set to a concrete value (a BCP47 or Java locale compliant * language tag) or to <code>null</code>. When set to <code>null</code> (default * value) then locale specific formatters are retrieved for the current language. * * After changing the format locale, the framework tries to update localization * specific parts of the UI. See the documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for details and restrictions. * * <b>Note</b>: When a language tag is set, it has higher priority than a number, * date or time format defined with a call to <code>setABAPNumberFormat</code>, * <code>setABAPDateFormat</code> or <code>setABAPTimeFormat</code>. * * <b>Note</b>: See documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for restrictions. * * @param {string|module:sap/base/i18n/LanguageTag|null} vLanguageTag the new BCP47 compliant language tag; * case doesn't matter and underscores can be used instead of hyphens to separate * components (compatibility with Java Locale IDs) * @throws {TypeError} When <code>sLanguageTag</code> is given, but is not a valid BCP47 language * tag or Java locale identifier * @public * @since 1.120 */ setLanguageTag(vLanguageTag) { const oLanguageTag = createLanguageTag(vLanguageTag); check(vLanguageTag == null || oLanguageTag, "vLanguageTag must be a BCP47 language tag or Java Locale id or null"); const oOldLanguageTag = Formatting.getLanguageTag(); oWritableConfig.set("sapUiFormatLocale", oLanguageTag?.toString()); const oCurrentLanguageTag = Formatting.getLanguageTag(); if (oOldLanguageTag.toString() !== oCurrentLanguageTag.toString()) { const bFireEvent = !mChanges; mChanges ??= {}; mChanges.languageTag = oCurrentLanguageTag.toString(); if (bFireEvent) { fireChange(); } } }, /** * @deprecated As of Version 1.120 */ _set: _set, /** * Definition of a custom unit. * * @typedef {object} module:sap/base/i18n/Formatting.CustomUnit * @property {string} displayName * The unit's display name * @property {string} ["unitPattern-count-zero"] * The unit pattern for the plural form "zero"; <code>{0}</code> in the pattern is replaced by the number * @property {string} ["unitPattern-count-one"] * The unit pattern for the plural form "one"; <code>{0}</code> in the pattern is replaced by the number * @property {string} ["unitPattern-count-two"] * The unit pattern for the plural form "two"; <code>{0}</code> in the pattern is replaced by the number * @property {string} ["unitPattern-count-few"] * The unit pattern for the plural form "few"; <code>{0}</code> in the pattern is replaced by the number * @property {string} ["unitPattern-count-many"] * The unit pattern for the plural form "many"; <code>{0}</code> in the pattern is replaced by the number * @property {string} "unitPattern-count-other" * The unit pattern for all other numbers which do not match the plural forms of the other given patterns; * <code>{0}</code> in the pattern is replaced by the number * @public * @see {@link sap.ui.core.LocaleData#getPluralCategories} */ /** * Gets the custom units that have been set via {@link #.addCustomUnits Formatting.addCustomUnits} or * {@link #.setCustomUnits Formatting.setCustomUnits}. * * @returns {Object<string,module:sap/base/i18n/Formatting.CustomUnit>|undefined} * A map with the unit code as key and a custom unit definition containing a display name and different unit * patterns as value; or <code>undefined</code> if there are no custom units * * @public * @example <caption>A simple custom type "BAG" for which the value <code>1</code> is formatted as "1 bag", for * example in locale 'en', while <code>2</code> is formatted as "2 bags"</caption> * { * "BAG": { * "displayName": "Bag", * "unitPattern-count-one": "{0} bag", * "unitPattern-count-other": "{0} bags" * } * } * @since 1.123 */ getCustomUnits() { return mSettings["units"]?.["short"]; }, /** * Replaces existing custom units by the given custom units. * * <b>Note:</b> Setting custom units affects all applications running with the current UI5 core instance. * * @param {Object<string,module:sap/base/i18n/Formatting.CustomUnit>} [mUnits] * A map with the unit code as key and a custom unit definition as value; <code>mUnits</code> replaces the * current custom units; if not given, all custom units are deleted; see * {@link #.getCustomUnits Formatting.getCustomUnits} for an example * * @public * @see {@link module:sap/base/i18n/Formatting.addCustomUnits Formatting.addCustomUnits} * @since 1.123 */ setCustomUnits(mUnits) { // add custom units, or remove the existing ones if none are given let mUnitsshort = null; if (mUnits) { mUnitsshort = { "short": mUnits }; } _set("units", mUnitsshort); }, /** * Adds custom units. * * <b>Note:</b> Adding custom units affects all applications running with the current UI5 core instance. * * @param {Object<string,module:sap/base/i18n/Formatting.CustomUnit>} mUnits * A map with the unit code as key and a custom unit definition as value; already existing custom units are * replaced, new ones are added; see {@link #.getCustomUnits Formatting.getCustomUnits} for an example * * @public * @since 1.123 */ addCustomUnits(mUnits) { const mExistingUnits = Formatting.getCustomUnits(); if (mExistingUnits){ mUnits = extend({}, mExistingUnits, mUnits); } Formatting.setCustomUnits(mUnits); }, /** * Sets custom unit mappings. * Unit mappings contain key value pairs (both strings) * * {string} key: a new entry which maps to an existing unit key * * {string} value: an existing unit key * * Example: * <code> * { * "my": "my-custom-unit", * "cm": "length-centimeter" * } * </code> * Note: It is possible to create multiple entries per unit key. * Call with <code>null</code> to delete unit mappings. * @param {object} mUnitMappings unit mappings * @private * @since 1.116.0 */ setUnitMappings(mUnitMappings) { _set("unitMappings", mUnitMappings); }, /** * Adds unit mappings. * Similar to {@link .setUnitMappings} but instead of setting the unit mappings, it will add additional ones. * @param {object} mUnitMappings unit mappings * @see {@link module:sap/base/i18n/Formatting.setUnitMappings} * @private * @since 1.116.0 */ addUnitMappings(mUnitMappings) { // add custom units, or remove the existing ones if none are given const mExistingUnits = Formatting.getUnitMappings(); if (mExistingUnits){ mUnitMappings = extend({}, mExistingUnits, mUnitMappings); } Formatting.setUnitMappings(mUnitMappings); }, /** * Retrieves the unit mappings. * These unit mappings are set by {@link .setUnitMappings} and {@link .addUnitMappings} * @private * @returns {object} unit mapping object * @see {@link module:sap/base/i18n/Formatting.setUnitMappings} * @see {@link module:sap/base/i18n/Formatting.addUnitMappings} * @since 1.116.0 */ getUnitMappings() { return mSettings["unitMappings"]; }, /** * Returns the currently set date pattern or undefined if no pattern has been defined. * @param {"short"|"medium"|"long"|"full"} sStyle The date style (short, medium, long or full) * @returns {string} The resulting date pattern * @public * @since 1.120 */ getDatePattern(sStyle) { assert(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full"); return mSettings["dateFormats-" + sStyle]; }, /** * Defines the preferred format pattern for the given date format style. * * Calling this method with a null or undefined pattern removes a previously set pattern. * * If a pattern is defined, it will be preferred over patterns derived from the current locale. * * See class {@link sap.ui.core.format.DateFormat DateFormat} for details about the pattern syntax. * * After changing the date pattern, the framework tries to update localization * specific parts of the UI. See the documentation of {@link module:sap/base/i18n/Localization.setLanguage * Localization.setLanguage()} for details and restrictions. * * @param {"short"|"medium"|"long"|"full"} sStyle must be one of short, medium, long or full. * @param {string} sPattern the format pattern to be used in LDML syntax. * @public * @since 1.120 */ setDatePattern(sStyle, sPattern) { check(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full"); _set("dateFormats-" + sStyle, sPattern); }, /** * Returns the currently set time pattern or undefined if no pattern has been defined. * @param {"short"|"medium"|"long"|"full"} sStyle The time style (short, medium, long or full) * @returns {string} The resulting time pattern * @public * @since 1.120 */ getTimePattern(sStyle) { assert(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full"); return mSettings["timeFormats-" + sStyle]; }, /** * Defines the preferred format pattern for the given time format style. * * Calling this method with a null or undefined pattern removes a previously set pattern. * * If a pattern is defined, it will be preferred over patterns derived from the current locale. * * See class {@link sap.ui.core.format.DateFormat DateFormat} for details about the pattern syntax. * * After changing the time pattern, the framework tries to update localization * specific parts of the UI. See the documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for details and restrictions. * * @param {"short"|"medium"|"long"|"full"} sStyle must be one of short, medium, long or full. * @param {string} sPattern the format pattern to be used in LDML syntax. * @public * @since 1.120 */ setTimePattern(sStyle, sPattern) { check(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full"); _set("timeFormats-" + sStyle, sPattern); }, /** * Returns the currently set number symbol of the given type or undefined if no symbol has been defined. * * @param {"group"|"decimal"|"plusSign"|"minusSign"} sType the type of symbol * @returns {string} A non-numerical symbol used as part of a number for the given type, * e.g. for locale de_DE: * <ul> * <li>"group": "." (grouping separator)</li> * <li>"decimal": "," (decimal separator)</li> * <li>"plusSign": "+" (plus sign)</li> * <li>"minusSign": "-" (minus sign)</li> * </ul> * @public * @since 1.120 */ getNumberSymbol(sType) { assert(["group", "decimal", "plusSign", "minusSign"].includes(sType), "sType must be decimal, group, plusSign or minusSign"); return mSettings["symbols-latn-" + sType]; }, /** * Defines the string to be used for the given number symbol. * * Calling this method with a null or undefined symbol removes a previously set symbol string. * Note that an empty string is explicitly allowed. * * If a symbol is defined, it will be preferred over symbols derived from the current locale. * * See class {@link sap.ui.core.format.NumberFormat NumberFormat} for details about the symbols. * * After changing the number symbol, the framework tries to update localization * specific parts of the UI. See the documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for details and restrictions. * * @param {"group"|"decimal"|"plusSign"|"minusSign"} sType the type of symbol * @param {string} sSymbol will be used to represent the given symbol type * @public * @since 1.120 */ setNumberSymbol(sType, sSymbol) { check(["group", "decimal", "plusSign", "minusSign"].includes(sType), "sType must be decimal, group, plusSign or minusSign"); _set("symbols-latn-" + sType, sSymbol); }, /** * Definition of a custom currency. * * @typedef {object} module:sap/base/i18n/Formatting.CustomCurrency * @property {int} digits * The number of decimal digits to be used for the currency * @public */ /** * Gets the custom currencies that have been set via * {@link #.addCustomCurrencies Formatting.addCustomCurrencies} or * {@link #.setCustomCurrencies Formatting.setCustomCurrencies}. * There is a special currency code named "DEFAULT" that is optional. If it is set it is used for all * currencies not contained in the list, otherwise currency digits as defined by the CLDR are used as a * fallback. * * @returns {Object<string,module:sap/base/i18n/Formatting.CustomCurrency>|undefined} * A map with the currency code as key and a custom currency definition containing the number of decimals as * value; or <code>undefined</code> if there are no custom currencies * * @public * @example <caption>A simple example for custom currencies that uses CLDR data but overrides single * currencies</caption> * { * "EUR3": {"digits": 3} * "MYD": {"digits": 4} * } * * @example <caption>A simple example for custom currencies that overrides all currency information from the * CLDR</caption> * { * "DEFAULT": {"digits": 2}, * "ADP": {"digits": 0}, * ... * "EUR3": {"digits": 3} * "MYD": {"digits": 4}, * ... * "ZWD": {"digits": 0} * } * @since 1.120 */ getCustomCurrencies() { return mSettings["currency"]; }, /** * Replaces existing custom currencies by the given custom currencies. There is a special currency code named * "DEFAULT" that is optional. In case it is set, it is used for all currencies not contained in the list, * otherwise currency digits as defined by the CLDR are used as a fallback. * * <b>Note:</b> Setting custom units affects all applications running with the current UI5 core instance. * * @param {Object<string,module:sap/base/i18n/Formatting.CustomCurrency>} [mCurrencies] * A map with the currency code as key and a custom currency definition as value; the custom currency code * must contain at least one non-digit character, so that the currency part can be distinguished from the * amount part; <code>mCurrencies</code> replaces the current custom currencies; if not given, all custom * currencies are deleted; see {@link #.getCustomCurrencies Formatting.getCustomCurrencies} for an example * * @public * @see {@link module:sap/base/i18n/Formatting.addCustomCurrencies Formatting.addCustomCurrencies} * @since 1.120 */ setCustomCurrencies(mCurrencies) { check(typeof mCurrencies === "object" || mCurrencies == null, "mCurrencyDigits must be an object"); Object.keys(mCurrencies || {}).forEach(function(sCurrencyDigit) { check(typeof sCurrencyDigit === "string"); check(typeof mCurrencies[sCurrencyDigit] === "object"); }); _set("currency", mCurrencies); }, /** * Adds custom currencies. There is a special currency code named "DEFAULT" that is optional. In case it is set * it is used for all currencies not contained in the list, otherwise currency digits as defined by the CLDR are * used as a fallback. * * <b>Note:</b> Adding custom currencies affects all applications running with the current UI5 core instance. * @param {Object<string,module:sap/base/i18n/Formatting.CustomCurrency>} [mCurrencies] * A map with the currency code as key and a custom currency definition as value; already existing custom * currencies are replaced, new ones are added; the custom currency code must contain at least one non-digit * character, so that the currency part can be distinguished from the amount part; see * {@link #.getCustomCurrencies Formatting.getCustomCurrencies} for an example * * @public * @since 1.120 */ addCustomCurrencies(mCurrencies) { const mExistingCurrencies = Formatting.getCustomCurrencies(); if (mExistingCurrencies){ mCurrencies = extend({}, mExistingCurrencies, mCurrencies); } Formatting.setCustomCurrencies(mCurrencies); }, _setDayPeriods(sWidth, aTexts) { assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide", "sWidth must be narrow, abbreviated or wide"); _set("dayPeriods-format-" + sWidth, aTexts); }, /** * Returns the currently set ABAP date format (its id) or undefined if none has been set. * * @returns {"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"A"|"B"|"C"|undefined} ID of the ABAP date format, * if not set or set to <code>""</code>, <code>undefined</code> will be returned * @public * @since 1.120 */ getABAPDateFormat() { const sABAPDateFormat = oWritableConfig.get({ name: "sapUiABAPDateFormat", type: BaseConfig.Type.String, /** * @deprecated As of Version 1.120 */ defaultValue: oWritableConfig.get({ name: "sapUiLegacyDateFormat", type: BaseConfig.Type.String, external: true }), external: true }); return sABAPDateFormat ? sABAPDateFormat.toUpperCase() : undefined; }, /** * Allows to specify one of the ABAP date formats. * * This method modifies the date patterns for 'short' and 'medium' style with the corresponding ABAP * format. When called with a null or undefined format id, any previously applied format will be removed. * * After changing the date format, the framework tries to update localization * specific parts of the UI. See the documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for details and restrictions. * * @param {""|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"A"|"B"|"C"} [sFormatId=""] ID of the ABAP date format, * <code>""</code> will reset the date patterns for 'short' and 'medium' style to the * locale-specific ones. * @public * @since 1.120 */ setABAPDateFormat(sFormatId) { sFormatId = sFormatId ? String(sFormatId).toUpperCase() : ""; check(M_ABAP_DATE_FORMAT_PATTERN.hasOwnProperty(sFormatId), "sFormatId must be one of ['1','2','3','4','5','6','7','8','9','A','B','C'] or empty"); const bFireEvent = !mChanges; const sOldFormat = Formatting.getABAPDateFormat(); if (sOldFormat !== sFormatId || !bInitialized) { mChanges ??= {}; oWritableConfig.set("sapUiABAPDateFormat", sFormatId); mChanges.ABAPDateFormat = sFormatId; Formatting.setDatePattern("short", M_ABAP_DATE_FORMAT_PATTERN[sFormatId].pattern); Formatting.setDatePattern("medium", M_ABAP_DATE_FORMAT_PATTERN[sFormatId].pattern); if (bFireEvent) { fireChange(); } } }, /** * Returns the currently set ABAP time format (its id) or undefined if none has been set. * * @returns {"0"|"1"|"2"|"3"|"4"|undefined} ID of the ABAP date format, * if not set or set to <code>""</code>, <code>undefined</code> will be returned * @public * @since 1.120 */ getABAPTimeFormat() { const sABAPTimeFormat = oWritableConfig.get({ name: "sapUiABAPTimeFormat", type: BaseConfig.Type.String, /** * @deprecated As of Version 1.120 */ defaultValue: oWritableConfig.get({ name: "sapUiLegacyTimeFormat", type: BaseConfig.Type.String, external: true }), external: true }); return sABAPTimeFormat ? sABAPTimeFormat.toUpperCase() : undefined; }, /** * Allows to specify one of the ABAP time formats. * * This method sets the time patterns for 'short' and 'medium' style to the corresponding ABAP * formats and sets the day period texts to "AM"/"PM" or "am"/"pm" respectively. When called * with a null or undefined format id, any previously applied format will be removed. * * After changing the time format, the framework tries to update localization * specific parts of the UI. See the documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for details and restrictions. * * @param {""|"0"|"1"|"2"|"3"|"4"} [sFormatId=""] ID of the ABAP time format, * <code>""</code> will reset the time patterns for 'short' and 'medium' style and the day * period texts to the locale-specific ones. * @public * @since 1.120 */ setABAPTimeFormat(sFormatId) { sFormatId = sFormatId || ""; check(M_ABAP_TIME_FORMAT_PATTERN.hasOwnProperty(sFormatId), "sFormatId must be one of ['0','1','2','3','4'] or empty"); const bFireEvent = !mChanges; const sOldFormat = Formatting.getABAPTimeFormat(); if (sOldFormat !== sFormatId || !bInitialized) { mChanges ??= {}; oWritableConfig.set("sapUiABAPTimeFormat", sFormatId); mChanges.ABAPTimeFormat = sFormatId; Formatting.setTimePattern("short", M_ABAP_TIME_FORMAT_PATTERN[sFormatId]["short"]); Formatting.setTimePattern("medium", M_ABAP_TIME_FORMAT_PATTERN[sFormatId]["medium"]); Formatting._setDayPeriods("abbreviated", M_ABAP_TIME_FORMAT_PATTERN[sFormatId].dayPeriods); if (bFireEvent) { fireChange(); } } }, /** * Returns the currently set ABAP number format (its id) or undefined if none has been set. * * @returns {" "|"X"|"Y"|undefined} ID of the ABAP number format, * if not set or set to <code>""</code>, <code>undefined</code> will be returned * @public * @since 1.120 */ getABAPNumberFormat() { const sABAPNumberFormat = oWritableConfig.get({ name: "sapUiABAPNumberFormat", type: BaseConfig.Type.String, /** * @deprecated As of Version 1.120 */ defaultValue: oWritableConfig.get({ name: "sapUiLegacyNumberFormat", type: BaseConfig.Type.String, external: true }), external: true }); return sABAPNumberFormat ? sABAPNumberFormat.toUpperCase() : undefined; }, /** * Allows to specify one of the ABAP number format. * * This method will modify the 'group' and 'decimal' symbols. When called with a null * or undefined format id, any previously applied format will be removed. * * After changing the number format, the framework tries to update localization * specific parts of the UI. See the documentation of * {@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage()} * for details and restrictions. * * @param {""|" "|"X"|"Y"} [sFormatId=""] ID of the ABAP number format set, * <code>""</code> will reset the 'group' and 'decimal' symbols to the locale-specific * ones. * @public * @since 1.120 */ setABAPNumberFormat(sFormatId) { sFormatId = sFormatId ? sFormatId.toUpperCase() : ""; check(M_ABAP_NUMBER_FORMAT_SYMBOLS.hasOwnProperty(sFormatId), "sFormatId must be one of [' ','X','Y'] or empty"); const bFireEvent = !mChanges; const sOldFormat = Formatting.getABAPNumberFormat(); if (sOldFormat !== sFormatId || !bInitialized) { mChanges ??= {}; oWritableConfig.set("sapUiABAPNumberFormat", sFormatId); mChanges.ABAPNumberFormat = sFormatId; Formatting.setNumberSymbol("group", M_ABAP_NUMBER_FORMAT_SYMBOLS[sFormatId].groupingSeparator); Formatting.setNumberSymbol("decimal", M_ABAP_NUMBER_FORMAT_SYMBOLS[sFormatId].decimalSeparator); if (bFireEvent) { fireChange(); } } }, /** * * Customizing data for the support of Islamic calendar. * Represents one row of data from Table TISLCAL. * * @typedef {object} module:sap/base/i18n/Formatting.CustomIslamicCalendarData * * @property {"A"|"B"} dateFormat The date format. Column DATFM in TISLCAL. * @property {string} islamicMonthStart The Islamic date in format: 'yyyyMMdd'. Column ISLMONTHSTART in TISLCAL. * @property {string} gregDate The corresponding Gregorian date format: 'yyyyMMdd'. Column GREGDATE in TISLCAL. * * @public */ /** * Allows to specify the customizing data for Islamic calendar support * * See: {@link module:sap/base/i18n/Formatting.CustomIslamicCalendarData} * * @param {module:sap/base/i18n/Formatting.CustomIslamicCalendarData[]} aCustomCalendarData Contains the customizing data for the support of Islamic calendar. * One JSON object in the array represents one row of data from Table TISLCAL * @public * @since 1.120 */ setCustomIslamicCalendarData(aCustomCalendarData) { check(Array.isArray(aCustomCalendarData), "aCustomCalendarData must be an Array"); const bFireEvent = !mChanges; mChanges ??= {}; aCustomIslamicCalendarData = mChanges.customIslamicCalendarData = aCustomCalendarData.slice(); if (bFireEvent) { fireChange(); } }, /** * Returns the currently set customizing data for Islamic calendar support. * * See: {@link module:sap/base/i18n/Formatting.CustomIslamicCalendarData} * * @returns {module:sap/base/i18n/Formatting.CustomIslamicCalendarData[]|undefined} Returns an array that contains the customizing data. Each element in the array has properties: dateFormat, islamicMonthStart, gregDate. For details, please see {@link #.setCustomIslamicCalendarData} * @public * @since 1.120 */ getCustomIslamicCalendarData() { return aCustomIslamicCalendarData?.slice() ?? undefined; }, /** * Define whether the NumberFormatter shall always place the currency code after the numeric value, with * the only exception of right-to-left locales, where the currency code shall be placed before the numeric value. * Default configuration setting is <code>true</code>. * * When set to <code>false</code> the placement of the currency code is done dynamically, depending on the * configured locale using data provided by the Unicode Common Locale Data Repository (CLDR). * * Each currency instance ({@link sap.ui.core.format.NumberFormat.getCurrencyInstance * NumberFormat.getCurrencyInstance}) will be created with this setting unless overwritten on instance level. * * @param {boolean} bTrailingCurrencyCode Whether currency codes shall always be placed after the numeric value * @public * @since 1.120 */ setTrailingCurrencyCode(bTrailingCurrencyCode) { check(typeof bTrailingCurrencyCode === "boolean", "bTrailingCurrencyCode must be a boolean"); oWritableConfig.set("sapUiTrailingCurrencyCode", bTrailingCurrencyCode); }, /** * Returns current trailingCurrencyCode configuration for new NumberFormatter instances * * @return {boolean} Whether currency codes shall always be placed after the numeric value * @public * @since 1.120 */ getTrailingCurrencyCode() { return oWritableConfig.get({ name: "sapUiTrailingCurrencyCode", type: BaseConfig.Type.Boolean, defaultValue: true, external: true }); }, /** * Returns a live object with the current settings * TODO this method is part of the facade to be accessible from LocaleData, but it shouldn't be * * @returns {object} The custom LocaleData settings object * @private * @ui5-restricted sap.ui.core * @since 1.116.0 */ getCustomLocaleData() { return mSettings; }, /** * Returns the calendar week numbering algorithm used to determine the first day of the week * and the first calendar week of the year, see {@link module:sap/base/i18n/date/CalendarWeekNumbering * CalendarWeekNumbering}. * * @returns {module:sap/base/i18n/date/CalendarWeekNumbering} The calendar week numbering algorithm * * @public * @since 1.120 */ getCalendarWeekNumbering() { let oCalendarWeekNumbering = CalendarWeekNumbering.Default; try { oCalendarWeekNumbering = oWritableConfig.get({ name: "sapUiCalendarWeekNumbering", type: CalendarWeekNumbering, defaultValue: CalendarWeekNumbering.Default, external: true }); } catch (err) { //nothing to do, return default; } return oCalendarWeekNumbering; }, /** * Sets the calendar week numbering algorithm which is used to determine the first day of the week * and the first calendar week of the year, see {@link module:sap/base/i18n/date/CalendarWeekNumbering * CalendarWeekNumbering}. * * @param {module:sap/base/i18n/date/CalendarWeekNumbering} sCalendarWeekNumbering * The calendar week numbering algorithm * @throws {TypeError} * If <code>sCalendarWeekNumbering</code> is not a valid calendar week numbering algorithm, * defined in {@link module:sap/base/i18n/date/CalendarWeekNumbering CalendarWeekNumbering} * * @public * @since 1.120 */ setCalendarWeekNumbering(sCalendarWeekNumbering) { BaseConfig._.checkEnum(CalendarWeekNumbering, sCalendarWeekNumbering, "calendarWeekNumbering"); const sCurrentWeekNumbering = oWritableConfig.get({ name: "sapUiCalendarWeekNumbering", type: CalendarWeekNumbering, defaultValue: CalendarWeekNumbering.Default, external: true }); if (sCurrentWeekNumbering !== sCalendarWeekNumbering) { const bFireEvent = !mChanges; mChanges ??= {}; oWritableConfig.set("sapUiCalendarWeekNumbering", sCalendarWeekNumbering); mChanges.calendarWeekNumbering = sCalendarWeekNumbering; if (bFireEvent) { fireChange(); } } }, /** * Returns the calendar type which is being used in locale dependent functionality. * * When it's explicitly set by calling <code>setCalendarType</code>, the set calendar type is returned. * Otherwise, the calendar type is determined by checking the format settings and current locale. * * @returns {module:sap/base/i18n/date/CalendarType} the current calendar type, e.g. <code>Gregorian</code> * @public * @since 1.120 */ getCalendarType() { let sName, sCalendarType = oWritableConfig.get({ name: "sapUiCalendarType", type: BaseConfig.Type.String, external: true }); sCalendarType ??= null; if (sCalendarType) { for (sName in CalendarType) { if (sName.toLowerCase() === sCalendarType.toLowerCase()) { return sName; } } Log.warning("Parameter 'calendarType' is set to " + sCalendarType + " which isn't a valid value and therefore ignored. The calendar type is determined from format setting and current locale"); } const sABAPDateFormat = Formatting.getABAPDateFormat(); switch (sABAPDateFormat) { case "1": case "2": case "3": case "4": case "5": case "6": return CalendarType.Gregorian; case "7": case "8": case "9": return CalendarType.Japanese; case "A": case "B": return CalendarType.Islamic; case "C": return CalendarType.Persian; default: return Localization.getPreferredCalendarType(); } }, /** * Sets the new calendar type to be used from now on in locale dependent functionality (for example, * formatting, translation texts, etc.). * * @param {module:sap/base/i18n/date/CalendarType|null} sCalendarType the new calendar type. Set it with null to clear the calendar type * and the calendar type is calculated based on the format settings and current locale. * @public * @since 1.120 */ setCalendarType(sCalendarType) { const sOldCalendarType = Formatting.getCalendarType(); oWritableConfig.set("sapUiCalendarType", sCalendarType); const sCurrentCalendarType = Formatting.getCalendarType(); if (sOldCalendarType !== sCurrentCalendarType) { const bFireEvent = !mChanges; mChanges ??= {}; mChanges.calendarType = sCurrentCalendarType; if (bFireEvent) { fireChange(); } } } }; function fireChange() { oEventing.fireEvent("change", mChanges); mChanges = undefined; } function init() { // init ABAP formats const sABAPDateFormat = Formatting.getABAPDateFormat(); if (sABAPDateFormat !== undefined) { Formatting.setABAPDateFormat(sABAPDateFormat); } const sABAPNumberFormat = Formatting.getABAPNumberFormat(); if (sABAPNumberFormat !== undefined) { Formatting.setABAPNumberFormat(sABAPNumberFormat); } const sABAPTimeFormat = Formatting.getABAPTimeFormat(); if (sABAPTimeFormat !== undefined) { Formatting.setABAPTimeFormat(sABAPTimeFormat); } bInitialized = true; } init(); return Formatting; });