@ui5/webcomponents-localization 0.0.0-0f0e49a22 → 0.0.0-10f3c0dc7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/.eslintignore +2 -1
  2. package/CHANGELOG.md +1935 -0
  3. package/LICENSE.txt +201 -0
  4. package/README.md +7 -9
  5. package/dist/.tsbuildinfo +1 -0
  6. package/dist/Assets-fetch.d.ts +1 -0
  7. package/dist/Assets-fetch.js +3 -0
  8. package/dist/Assets-fetch.js.map +1 -0
  9. package/dist/Assets-node.d.ts +11 -0
  10. package/dist/Assets-node.js +12 -0
  11. package/dist/Assets-node.js.map +1 -0
  12. package/dist/CalendarUtils.d.ts +3 -0
  13. package/dist/CalendarUtils.js +6 -0
  14. package/dist/CalendarUtils.js.map +1 -0
  15. package/dist/DateFormat.d.ts +23 -1
  16. package/dist/DateFormat.js +16 -0
  17. package/dist/DateFormat.js.map +1 -1
  18. package/dist/Locale.d.ts +5 -0
  19. package/dist/Locale.js +7 -0
  20. package/dist/Locale.js.map +1 -0
  21. package/dist/LocaleData.d.ts +0 -1
  22. package/dist/NumberFormat.d.ts +5 -0
  23. package/dist/NumberFormat.js +7 -0
  24. package/dist/NumberFormat.js.map +1 -0
  25. package/dist/dates/CalendarDate.d.ts +0 -1
  26. package/dist/dates/CalendarDate.js.map +1 -1
  27. package/dist/dates/ExtremeDates.d.ts +1 -1
  28. package/dist/dates/ExtremeDates.js.map +1 -1
  29. package/dist/dates/UI5Date.d.ts +0 -1
  30. package/dist/dates/convertMonthNumbersToMonthNames.d.ts +2 -2
  31. package/dist/dates/convertMonthNumbersToMonthNames.js.map +1 -1
  32. package/dist/dates/getRoundedTimestamp.js.map +1 -1
  33. package/dist/dates/modifyDateBy.d.ts +2 -1
  34. package/dist/dates/modifyDateBy.js +34 -19
  35. package/dist/dates/modifyDateBy.js.map +1 -1
  36. package/dist/dates/transformDateToSecondaryType.js.map +1 -1
  37. package/dist/generated/assets/cldr/Unicode-Data-Files-LICENSE.txt +39 -0
  38. package/dist/generated/assets/cldr/ar.json +7355 -5531
  39. package/dist/generated/assets/cldr/ar_EG.json +7355 -5531
  40. package/dist/generated/assets/cldr/ar_SA.json +7354 -5530
  41. package/dist/generated/assets/cldr/bg.json +6103 -4452
  42. package/dist/generated/assets/cldr/ca.json +6205 -4440
  43. package/dist/generated/assets/cldr/cnr.json +6476 -0
  44. package/dist/generated/assets/cldr/cs.json +6519 -4960
  45. package/dist/generated/assets/cldr/cy.json +6564 -5211
  46. package/dist/generated/assets/cldr/da.json +6048 -4308
  47. package/dist/generated/assets/cldr/de.json +6174 -4313
  48. package/dist/generated/assets/cldr/de_AT.json +6175 -4314
  49. package/dist/generated/assets/cldr/de_CH.json +6181 -4312
  50. package/dist/generated/assets/cldr/el.json +5995 -4281
  51. package/dist/generated/assets/cldr/el_CY.json +5995 -4281
  52. package/dist/generated/assets/cldr/en.json +6395 -4316
  53. package/dist/generated/assets/cldr/en_AU.json +6536 -4319
  54. package/dist/generated/assets/cldr/en_GB.json +6518 -4329
  55. package/dist/generated/assets/cldr/en_HK.json +6423 -4337
  56. package/dist/generated/assets/cldr/en_IE.json +6414 -4328
  57. package/dist/generated/assets/cldr/en_IN.json +6602 -4333
  58. package/dist/generated/assets/cldr/en_NZ.json +6414 -4328
  59. package/dist/generated/assets/cldr/en_PG.json +6415 -4329
  60. package/dist/generated/assets/cldr/en_SG.json +6419 -4333
  61. package/dist/generated/assets/cldr/en_ZA.json +6417 -4329
  62. package/dist/generated/assets/cldr/es.json +6226 -4331
  63. package/dist/generated/assets/cldr/es_AR.json +6260 -4334
  64. package/dist/generated/assets/cldr/es_BO.json +6258 -4333
  65. package/dist/generated/assets/cldr/es_CL.json +6151 -4334
  66. package/dist/generated/assets/cldr/es_CO.json +6151 -4333
  67. package/dist/generated/assets/cldr/es_MX.json +6268 -4335
  68. package/dist/generated/assets/cldr/es_PE.json +6050 -4333
  69. package/dist/generated/assets/cldr/es_UY.json +6044 -4335
  70. package/dist/generated/assets/cldr/es_VE.json +6043 -4334
  71. package/dist/generated/assets/cldr/et.json +6182 -4340
  72. package/dist/generated/assets/cldr/fa.json +6187 -4367
  73. package/dist/generated/assets/cldr/fi.json +6439 -4463
  74. package/dist/generated/assets/cldr/fr.json +6228 -4357
  75. package/dist/generated/assets/cldr/fr_BE.json +6228 -4357
  76. package/dist/generated/assets/cldr/fr_CA.json +6244 -4351
  77. package/dist/generated/assets/cldr/fr_CH.json +6246 -4375
  78. package/dist/generated/assets/cldr/fr_LU.json +6228 -4357
  79. package/dist/generated/assets/cldr/he.json +6361 -4869
  80. package/dist/generated/assets/cldr/hi.json +6098 -4295
  81. package/dist/generated/assets/cldr/hr.json +6203 -4583
  82. package/dist/generated/assets/cldr/hu.json +6067 -4364
  83. package/dist/generated/assets/cldr/id.json +5979 -4060
  84. package/dist/generated/assets/cldr/it.json +6103 -4299
  85. package/dist/generated/assets/cldr/it_CH.json +6103 -4299
  86. package/dist/generated/assets/cldr/ja.json +6145 -4211
  87. package/dist/generated/assets/cldr/kk.json +6237 -4339
  88. package/dist/generated/assets/cldr/ko.json +6024 -4189
  89. package/dist/generated/assets/cldr/lt.json +6459 -4850
  90. package/dist/generated/assets/cldr/lv.json +6114 -4587
  91. package/dist/generated/assets/cldr/mk.json +6177 -0
  92. package/dist/generated/assets/cldr/ms.json +5821 -4021
  93. package/dist/generated/assets/cldr/nb.json +6154 -4335
  94. package/dist/generated/assets/cldr/nl.json +6306 -4294
  95. package/dist/generated/assets/cldr/nl_BE.json +6306 -4294
  96. package/dist/generated/assets/cldr/pl.json +6461 -4667
  97. package/dist/generated/assets/cldr/pt.json +6234 -4235
  98. package/dist/generated/assets/cldr/pt_PT.json +6309 -4372
  99. package/dist/generated/assets/cldr/ro.json +6170 -4563
  100. package/dist/generated/assets/cldr/ru.json +6732 -4909
  101. package/dist/generated/assets/cldr/ru_UA.json +6732 -4909
  102. package/dist/generated/assets/cldr/sk.json +6256 -4939
  103. package/dist/generated/assets/cldr/sl.json +6279 -4910
  104. package/dist/generated/assets/cldr/sr.json +6186 -4585
  105. package/dist/generated/assets/cldr/sr_Latn.json +6171 -4574
  106. package/dist/generated/assets/cldr/sv.json +6211 -4362
  107. package/dist/generated/assets/cldr/th.json +6126 -4214
  108. package/dist/generated/assets/cldr/tr.json +6245 -4400
  109. package/dist/generated/assets/cldr/uk.json +6806 -4858
  110. package/dist/generated/assets/cldr/vi.json +6016 -4070
  111. package/dist/generated/assets/cldr/zh_CN.json +5969 -4100
  112. package/dist/generated/assets/cldr/zh_HK.json +5977 -4108
  113. package/dist/generated/assets/cldr/zh_SG.json +5977 -4108
  114. package/dist/generated/assets/cldr/zh_TW.json +6033 -4131
  115. package/dist/generated/json-imports/LocaleData-fetch.d.ts +1 -0
  116. package/dist/generated/json-imports/LocaleData-fetch.js +93 -0
  117. package/dist/generated/json-imports/LocaleData-fetch.js.map +1 -0
  118. package/dist/generated/json-imports/LocaleData-node.d.ts +1 -0
  119. package/dist/generated/json-imports/LocaleData-node.js +93 -0
  120. package/dist/generated/json-imports/LocaleData-node.js.map +1 -0
  121. package/dist/generated/json-imports/LocaleData.d.ts +1 -0
  122. package/dist/generated/json-imports/LocaleData.js +89 -89
  123. package/dist/generated/json-imports/LocaleData.js.map +1 -0
  124. package/dist/getCachedLocaleDataInstance.js +2 -0
  125. package/dist/getCachedLocaleDataInstance.js.map +1 -1
  126. package/dist/locale/getLocaleData.js +2 -0
  127. package/dist/locale/getLocaleData.js.map +1 -1
  128. package/dist/sap/base/Event.js +59 -0
  129. package/dist/sap/base/Eventing.js +147 -0
  130. package/dist/sap/base/Log.js +2 -239
  131. package/dist/sap/base/assert.js +28 -1
  132. package/dist/sap/base/config/MemoryConfigurationProvider.js +20 -0
  133. package/dist/sap/base/config.js +17 -0
  134. package/dist/sap/base/future.js +12 -0
  135. package/dist/sap/base/i18n/Formatting.d.ts +13 -0
  136. package/dist/sap/base/i18n/Formatting.js +18 -0
  137. package/dist/sap/base/i18n/Formatting.js.map +1 -0
  138. package/dist/sap/base/i18n/LanguageTag.js +179 -0
  139. package/dist/sap/base/i18n/Localization.d.ts +7 -0
  140. package/dist/sap/base/i18n/Localization.js +17 -0
  141. package/dist/sap/base/i18n/Localization.js.map +1 -0
  142. package/dist/sap/base/i18n/ResourceBundle.js +20 -0
  143. package/dist/sap/base/i18n/date/CalendarType.js +44 -0
  144. package/dist/sap/base/i18n/date/CalendarWeekNumbering.js +106 -0
  145. package/dist/sap/base/i18n/date/TimezoneUtils.js +471 -0
  146. package/dist/sap/base/i18n/date/_EnumHelper.js +37 -0
  147. package/dist/sap/base/strings/camelize.js +30 -0
  148. package/dist/sap/base/strings/formatMessage.js +93 -15
  149. package/dist/sap/base/util/LoaderExtensions.js.map +1 -1
  150. package/dist/sap/base/util/ObjectPath.d.ts +4 -0
  151. package/dist/sap/base/util/ObjectPath.js +4 -33
  152. package/dist/sap/base/util/ObjectPath.js.map +1 -0
  153. package/dist/sap/base/util/Properties.js +12 -0
  154. package/dist/sap/base/util/Version.js +163 -0
  155. package/dist/sap/base/util/_merge.js +83 -26
  156. package/dist/sap/base/util/array/uniqueSort.js +37 -15
  157. package/dist/sap/base/util/deepClone.js +102 -0
  158. package/dist/sap/base/util/deepEqual.js +75 -51
  159. package/dist/sap/base/util/deepExtend.js +60 -0
  160. package/dist/sap/base/util/extend.js +58 -7
  161. package/dist/sap/base/util/fetch.js +8 -0
  162. package/dist/sap/base/util/isEmptyObject.js +34 -0
  163. package/dist/sap/base/util/isPlainObject.js +35 -1
  164. package/dist/sap/base/util/merge.js +57 -0
  165. package/dist/sap/base/util/mixedFetch.js +3 -0
  166. package/dist/sap/base/util/now.js +22 -7
  167. package/dist/sap/base/util/resolveReference.js +3 -0
  168. package/dist/sap/base/util/uid.js +27 -0
  169. package/dist/sap/ui/Device.js +25 -3
  170. package/dist/sap/ui/Global.js +1 -0
  171. package/dist/sap/ui/VersionInfo.js +14 -0
  172. package/dist/sap/ui/base/DataType.js +708 -0
  173. package/dist/sap/ui/base/DesignTime.js +11 -0
  174. package/dist/sap/ui/base/EventProvider.js +21 -0
  175. package/dist/sap/ui/base/Interface.js +47 -1
  176. package/dist/sap/ui/base/Metadata.js +470 -171
  177. package/dist/sap/ui/base/Object.js +284 -48
  178. package/dist/sap/ui/base/OwnStatics.js +6 -0
  179. package/dist/sap/ui/base/SyncPromise.js +98 -0
  180. package/dist/sap/ui/core/AnimationMode.js +42 -0
  181. package/dist/sap/ui/core/CalendarType.js +24 -8
  182. package/dist/sap/ui/core/Configuration.d.ts +2 -2
  183. package/dist/sap/ui/core/Configuration.js +2 -0
  184. package/dist/sap/ui/core/Configuration.js.map +1 -1
  185. package/dist/sap/ui/core/ControlBehavior.js +11 -0
  186. package/dist/sap/ui/core/Core.d.ts +3 -4
  187. package/dist/sap/ui/core/FormatSettings.d.ts +1 -2
  188. package/dist/sap/ui/core/FormatSettings.js +0 -2
  189. package/dist/sap/ui/core/FormatSettings.js.map +1 -1
  190. package/dist/sap/ui/core/Lib.js +41 -0
  191. package/dist/sap/ui/core/Locale.js +190 -155
  192. package/dist/sap/ui/core/LocaleData.js +2824 -1351
  193. package/dist/sap/ui/core/Supportability.js +5 -0
  194. package/dist/sap/ui/core/Theming.js +39 -0
  195. package/dist/sap/ui/core/_UrlResolver.js +11 -0
  196. package/dist/sap/ui/core/date/Buddhist.js +162 -87
  197. package/dist/sap/ui/core/date/CalendarUtils.js +63 -32
  198. package/dist/sap/ui/core/date/CalendarWeekNumbering.js +30 -7
  199. package/dist/sap/ui/core/date/Gregorian.js +25 -10
  200. package/dist/sap/ui/core/date/Islamic.js +298 -185
  201. package/dist/sap/ui/core/date/Japanese.js +210 -115
  202. package/dist/sap/ui/core/date/Persian.js +324 -195
  203. package/dist/sap/ui/core/date/UI5Date.js +970 -236
  204. package/dist/sap/ui/core/date/UniversalDate.js +1228 -264
  205. package/dist/sap/ui/core/date/_Calendars.js +10 -1
  206. package/dist/sap/ui/core/format/DateFormat.js +3168 -2111
  207. package/dist/sap/ui/core/format/FormatUtils.js +30 -0
  208. package/dist/sap/ui/core/format/NumberFormat.js +3164 -0
  209. package/dist/sap/ui/core/format/TimezoneUtil.js +93 -89
  210. package/dist/sap/ui/core/getCompatibilityVersion.js +7 -0
  211. package/dist/sap/ui/core/theming/ThemeHelper.js +14 -0
  212. package/dist/sap/ui/security/Security.js +12 -0
  213. package/dist/sap/ui/util/XMLHelper.js +11 -0
  214. package/dist/sap/ui/util/_URL.js +1 -0
  215. package/dist/ui5loader-autoconfig.js +1 -0
  216. package/package-scripts.cjs +22 -24
  217. package/package.json +20 -15
  218. package/tsconfig.json +20 -10
  219. package/used-modules.txt +30 -2
  220. package/dist/Assets-static.d.ts +0 -1
  221. package/dist/Assets-static.js +0 -3
  222. package/dist/Assets-static.js.map +0 -1
  223. package/dist/dates/calculateWeekNumber.d.ts +0 -5
  224. package/dist/dates/calculateWeekNumber.js +0 -45
  225. package/dist/dates/calculateWeekNumber.js.map +0 -1
  226. package/dist/generated/json-imports/LocaleData-static.js +0 -90
@@ -1,1409 +1,2882 @@
1
- import Core from './Core.js';
2
- import extend from '../../base/util/extend.js';
3
- import BaseObject from '../base/Object.js';
4
- import CalendarType from './CalendarType.js';
5
- import Locale from './Locale.js';
6
- import assert from '../../base/assert.js';
7
- import LoaderExtensions from '../../base/util/LoaderExtensions.js';
8
- import Configuration from './Configuration.js';
9
- var rEIgnoreCase = /e/i, mLegacyUnit2CurrentUnit = {
10
- 'acceleration-meter-per-second-squared': 'acceleration-meter-per-square-second',
11
- 'concentr-milligram-per-deciliter': 'concentr-milligram-ofglucose-per-deciliter',
12
- 'concentr-part-per-million': 'concentr-permillion',
13
- 'consumption-liter-per-100kilometers': 'consumption-liter-per-100-kilometer',
14
- 'pressure-millimeter-of-mercury': 'pressure-millimeter-ofhg',
15
- 'pressure-pound-per-square-inch': 'pressure-pound-force-per-square-inch',
16
- 'pressure-inch-hg': 'pressure-inch-ofhg',
17
- 'torque-pound-foot': 'torque-pound-force-foot'
18
- }, rNumberInScientificNotation = /^([+-]?)((\d+)(?:\.(\d+))?)[eE]([+-]?\d+)$/, rTrailingZeroes = /0+$/;
19
- var LocaleData = BaseObject.extend('sap.ui.core.LocaleData', {
20
- constructor: function (oLocale) {
21
- this.oLocale = oLocale;
22
- BaseObject.apply(this);
23
- var oDataLoaded = getData(oLocale);
24
- this.mData = oDataLoaded.mData;
25
- this.sCLDRLocaleId = oDataLoaded.sCLDRLocaleId;
26
- },
27
- _get: function () {
28
- return this._getDeep(this.mData, arguments);
29
- },
30
- _getMerged: function () {
31
- return this._get.apply(this, arguments);
32
- },
33
- _getDeep: function (oObject, aPropertyNames) {
34
- var oResult = oObject;
35
- for (var i = 0; i < aPropertyNames.length; i++) {
36
- oResult = oResult[aPropertyNames[i]];
37
- if (oResult === undefined) {
38
- break;
39
- }
40
- }
41
- return oResult;
42
- },
43
- getOrientation: function () {
44
- return this._get('orientation');
45
- },
46
- getCurrentLanguageName: function () {
47
- var oLanguages = this.getLanguages();
48
- var sCurrentLanguage;
49
- var sLanguage = this.oLocale.getModernLanguage();
50
- var sScript = this.oLocale.getScript();
51
- if (sLanguage === 'sr' && sScript === 'Latn') {
52
- sLanguage = 'sh';
53
- sScript = null;
54
- }
55
- if (this.oLocale.getRegion()) {
56
- sCurrentLanguage = oLanguages[sLanguage + '_' + this.oLocale.getRegion()];
57
- }
58
- if (!sCurrentLanguage && sScript) {
59
- sCurrentLanguage = oLanguages[sLanguage + '_' + sScript];
60
- }
61
- if (!sCurrentLanguage) {
62
- sCurrentLanguage = oLanguages[sLanguage];
63
- }
64
- return sCurrentLanguage;
65
- },
66
- getLanguages: function () {
67
- return this._get('languages');
68
- },
69
- getScripts: function () {
70
- return this._get('scripts');
71
- },
72
- getTerritories: function () {
73
- return this._get('territories');
74
- },
75
- getMonths: function (sWidth, sCalendarType) {
76
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide', 'sWidth must be narrow, abbreviated or wide');
77
- return this._get(getCLDRCalendarName(sCalendarType), 'months', 'format', sWidth);
78
- },
79
- getMonthsStandAlone: function (sWidth, sCalendarType) {
80
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide', 'sWidth must be narrow, abbreviated or wide');
81
- return this._get(getCLDRCalendarName(sCalendarType), 'months', 'stand-alone', sWidth);
82
- },
83
- getDays: function (sWidth, sCalendarType) {
84
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide' || sWidth == 'short', 'sWidth must be narrow, abbreviate, wide or short');
85
- return this._get(getCLDRCalendarName(sCalendarType), 'days', 'format', sWidth);
86
- },
87
- getDaysStandAlone: function (sWidth, sCalendarType) {
88
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide' || sWidth == 'short', 'sWidth must be narrow, abbreviated, wide or short');
89
- return this._get(getCLDRCalendarName(sCalendarType), 'days', 'stand-alone', sWidth);
90
- },
91
- getQuarters: function (sWidth, sCalendarType) {
92
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide', 'sWidth must be narrow, abbreviated or wide');
93
- return this._get(getCLDRCalendarName(sCalendarType), 'quarters', 'format', sWidth);
94
- },
95
- getQuartersStandAlone: function (sWidth, sCalendarType) {
96
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide', 'sWidth must be narrow, abbreviated or wide');
97
- return this._get(getCLDRCalendarName(sCalendarType), 'quarters', 'stand-alone', sWidth);
98
- },
99
- getDayPeriods: function (sWidth, sCalendarType) {
100
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide', 'sWidth must be narrow, abbreviated or wide');
101
- return this._get(getCLDRCalendarName(sCalendarType), 'dayPeriods', 'format', sWidth);
102
- },
103
- getDayPeriodsStandAlone: function (sWidth, sCalendarType) {
104
- assert(sWidth == 'narrow' || sWidth == 'abbreviated' || sWidth == 'wide', 'sWidth must be narrow, abbreviated or wide');
105
- return this._get(getCLDRCalendarName(sCalendarType), 'dayPeriods', 'stand-alone', sWidth);
106
- },
107
- getDatePattern: function (sStyle, sCalendarType) {
108
- assert(sStyle == 'short' || sStyle == 'medium' || sStyle == 'long' || sStyle == 'full', 'sStyle must be short, medium, long or full');
109
- return this._get(getCLDRCalendarName(sCalendarType), 'dateFormats', sStyle);
110
- },
111
- getFlexibleDayPeriods: function (sWidth, sCalendarType) {
112
- return this._get(getCLDRCalendarName(sCalendarType), 'flexibleDayPeriods', 'format', sWidth);
113
- },
114
- getFlexibleDayPeriodsStandAlone: function (sWidth, sCalendarType) {
115
- return this._get(getCLDRCalendarName(sCalendarType), 'flexibleDayPeriods', 'stand-alone', sWidth);
116
- },
117
- getFlexibleDayPeriodOfTime: function (iHour, iMinute) {
118
- var iAbsoluteMinutes, oDayPeriodRules, sPeriodMatch;
119
- iAbsoluteMinutes = (iHour * 60 + iMinute) % 1440;
120
- oDayPeriodRules = this._get('dayPeriodRules');
121
- function parseToAbsoluteMinutes(sValue) {
122
- var aSplit = sValue.split(':'), sHour = aSplit[0], sMinute = aSplit[1];
123
- return parseInt(sHour) * 60 + parseInt(sMinute);
124
- }
125
- sPeriodMatch = Object.keys(oDayPeriodRules).find(function (sDayPeriodRule) {
126
- var oDayPeriodRule = oDayPeriodRules[sDayPeriodRule];
127
- return oDayPeriodRule['_at'] && parseToAbsoluteMinutes(oDayPeriodRule['_at']) === iAbsoluteMinutes;
128
- });
129
- if (sPeriodMatch) {
130
- return sPeriodMatch;
1
+ /*!
2
+ * OpenUI5
3
+ * (c) Copyright 2026 SAP SE or an SAP affiliate company.
4
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
5
+ */
6
+ //Provides the locale object sap.ui.core.LocaleData
7
+ import Locale from "./Locale.js";
8
+ import assert from "../../base/assert.js";
9
+ import Formatting from "../../base/i18n/Formatting.js";
10
+ import LanguageTag from "../../base/i18n/LanguageTag.js";
11
+ import Localization from "../../base/i18n/Localization.js";
12
+ import CalendarType from "../../base/i18n/date/CalendarType.js";
13
+ import CalendarWeekNumbering from "../../base/i18n/date/CalendarWeekNumbering.js";
14
+ import extend from "../../base/util/extend.js";
15
+ import LoaderExtensions from "../../base/util/LoaderExtensions.js";
16
+ import BaseObject from "../base/Object.js";
17
+ import SyncPromise from "../base/SyncPromise.js";
18
+ var rCIgnoreCase = /c/i,
19
+ rEIgnoreCase = /e/i,
20
+ rNumberInScientificNotation = /^([+-]?)((\d+)(?:\.(\d+))?)[eE]([+-]?\d+)$/,
21
+ rTrailingZeroes = /0+$/;
22
+ const rFallbackPatternTextParts = /(.*)?\{[0|1]}(.*)?\{[0|1]}(.*)?/;
23
+ const rOnlyZeros = /^0+$/;
24
+ const aSupportedWidths = ["narrow", "abbreviated", "wide"];
25
+ /**
26
+ * With the upgrade of the CLDR to version 41 some unit keys have changed.
27
+ * For compatibility reasons this map is used for formatting units.
28
+ * It maps a legacy unit key to its renamed key.
29
+ *
30
+ * @deprecated As of version 1.122.0, this map is no longer maintained and stays for compatibility reasons
31
+ * only. Reason for the depreciation: The assumption of homogeneous unit keys in the CLDR data has been proven
32
+ * wrong. Additionally, it is unclear if, those CLDR unit keys are actually used. Implementing a complex logic
33
+ * to maintain potentially unused entries did not seem reasonable. Therefore, it was decided to deprecate this
34
+ * feature.
35
+ * This map was last updated with CLDR V43, in 1.119.0.
36
+ * @private
37
+ */
38
+ const mLegacyUnit2CurrentUnit = {
39
+ "acceleration-meter-per-second-squared": "acceleration-meter-per-square-second",
40
+ "concentr-milligram-per-deciliter": "concentr-milligram-ofglucose-per-deciliter",
41
+ "concentr-part-per-million": "concentr-permillion",
42
+ "consumption-liter-per-100kilometers": "consumption-liter-per-100-kilometer",
43
+ "mass-metric-ton": "mass-tonne",
44
+ "pressure-millimeter-of-mercury": "pressure-millimeter-ofhg",
45
+ "pressure-pound-per-square-inch": "pressure-pound-force-per-square-inch",
46
+ "pressure-inch-hg": "pressure-inch-ofhg",
47
+ "torque-pound-foot": "torque-pound-force-foot"
48
+ };
49
+
50
+ /**
51
+ * The locale data cache. Maps a locale ID, formatted as either the language_region (e.g. "ar_SA"),
52
+ * language_script (e.g. "sr_Latn") or just the language code (e.g. "de") to its set of loaded
53
+ * CLDR data. In case of asynchronous loading, the locale ID is mapped to a <code>Promise</code> which resolves
54
+ * with the loaded CLDR data. As soon as the data is loaded the <code>Promise</code> is replaced by it.
55
+ *
56
+ * @type {Object<string, Object<string, any>|Promise<Object<string, any>>>}
57
+ * @private
58
+ */
59
+ let mLocaleIdToData = {};
60
+
61
+ /**
62
+ * DO NOT call the constructor for <code>LocaleData</code>; use <code>LocaleData.getInstance</code> instead.
63
+ *
64
+ * @param {sap.ui.core.Locale} oLocale The locale
65
+ * @param {boolean} bAsync Whether to load the data asynchronously
66
+ *
67
+ * @alias sap.ui.core.LocaleData
68
+ * @author SAP SE
69
+ * @extends sap.ui.base.Object
70
+ * @class Provides access to locale-specific data, such as date formats, number formats, and currencies. For more
71
+ * information on terminology, such as field names used in the methods of this class, see
72
+ * {@link https://cldr.unicode.org/ Unicode CLDR}.
73
+ * @hideconstructor
74
+ * @public
75
+ * @version 1.146.0
76
+ */
77
+ var LocaleData = BaseObject.extend("sap.ui.core.LocaleData", /** @lends sap.ui.core.LocaleData.prototype */{
78
+ constructor: function (oLocale, bAsync) {
79
+ BaseObject.apply(this);
80
+ this.oLocale = Locale._getCoreLocale(oLocale);
81
+ this.loaded = loadData(this.oLocale, bAsync).then(oResult => {
82
+ this.mData = oResult.mData;
83
+ this.sCLDRLocaleId = oResult.sCLDRLocaleId;
84
+ return this;
85
+ });
86
+ this.loaded.finally(() => {
87
+ delete this.loaded;
88
+ });
89
+ },
90
+ /**
91
+ * @private
92
+ * @ui5-restricted UI5 Web Components
93
+ */
94
+ _get: function () {
95
+ return this._getDeep(this.mData, arguments);
96
+ },
97
+ /**
98
+ * Retrieves merged object if overlay data is available
99
+ * @private
100
+ * @return {object} merged object
101
+ */
102
+ _getMerged: function () {
103
+ return this._get.apply(this, arguments);
104
+ },
105
+ /**
106
+ * Get month names in the given width. Result may contain alternative month names.
107
+ *
108
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth
109
+ * The required width for the month names
110
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
111
+ * The type of calendar; defaults to the calendar type either set in configuration or calculated from the
112
+ * locale
113
+ * @returns {array}
114
+ * The array of month names; if no alternative exists the entry for the month is its name as a string; if
115
+ * there are alternative month names the entry for the month is an array of strings with the alternative names
116
+ * @private
117
+ */
118
+ _getMonthsWithAlternatives: function (sWidth, sCalendarType) {
119
+ return this._get(getCLDRCalendarName(sCalendarType), "months", "format", sWidth);
120
+ },
121
+ /**
122
+ * Get standalone month names in the given width. Result may contain alternative month
123
+ * names.
124
+ *
125
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth
126
+ * The required width for the month names
127
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
128
+ * The type of calendar; defaults to the calendar type either set in configuration or calculated from the
129
+ * locale
130
+ * @returns {array}
131
+ * The array of month names; if no alternative exists the entry for the month is its name as a string; if
132
+ * there are alternative month names the entry for the month is an array of strings with the alternative names
133
+ * @private
134
+ */
135
+ _getMonthsStandAloneWithAlternatives: function (sWidth, sCalendarType) {
136
+ return this._get(getCLDRCalendarName(sCalendarType), "months", "stand-alone", sWidth);
137
+ },
138
+ _getDeep: function (oObject, aPropertyNames) {
139
+ var oResult = oObject;
140
+ for (var i = 0; i < aPropertyNames.length; i++) {
141
+ oResult = oResult[aPropertyNames[i]];
142
+ if (oResult === undefined) {
143
+ break;
144
+ }
145
+ }
146
+ return oResult;
147
+ },
148
+ /**
149
+ * Gets the text orientation.
150
+ *
151
+ * @returns {"left-to-right"|"right-to-left"} text orientation
152
+ * @public
153
+ */
154
+ getOrientation: function () {
155
+ return this._get("orientation");
156
+ },
157
+ /**
158
+ * Get a display name for the language of the Locale of this LocaleData, using
159
+ * the CLDR display names for languages.
160
+ *
161
+ * The lookup logic works as follows:
162
+ * 1. language code and region is checked (e.g. "en-GB")
163
+ * 2. If not found: language code and script is checked (e.g. "zh-Hant")
164
+ * 3. If not found language code is checked (e.g. "en")
165
+ * 4. If it is then still not found <code>undefined</code> is returned.
166
+ *
167
+ * @returns {string} language name, e.g. "English", "British English", "American English"
168
+ * or <code>undefined</code> if language cannot be found
169
+ * @private
170
+ * @ui5-restricted sap.ushell
171
+ */
172
+ getCurrentLanguageName: function () {
173
+ return this.getLanguageName(this.oLocale.toString());
174
+ },
175
+ /**
176
+ * Gets the locale-specific language name for the given language tag.
177
+ *
178
+ * The languages returned by {@link #getLanguages} from the CLDR raw data do not contain the
179
+ * language names if they can be derived from the language and the script or the territory.
180
+ * If the map of languages contains no entry for the given language tag, derive the language
181
+ * name from the used script or region.
182
+ *
183
+ * @param {string} sLanguageTag
184
+ * The language tag, for example "en", "en-US", "en_US", "zh-Hant", or "zh_Hant"
185
+ * @returns {string|undefined}
186
+ * The language name, or <code>undefined</code> if the name cannot be determined
187
+ * @throws {TypeError} When the given language tag isn't valid
188
+ *
189
+ * @public
190
+ */
191
+ getLanguageName: function (sLanguageTag) {
192
+ const oLanguageTag = new LanguageTag(sLanguageTag);
193
+ let sLanguage = Localization.getModernLanguage(oLanguageTag.language);
194
+ let sScript = oLanguageTag.script;
195
+ // special case for "sr_Latn" language: "sh" should then be used
196
+ if (sLanguage === "sr" && sScript === "Latn") {
197
+ sLanguage = "sh";
198
+ sScript = null;
199
+ }
200
+ const sRegion = oLanguageTag.region;
201
+ const oLanguages = this._get("languages");
202
+ const sLanguageText = oLanguages[sLanguage];
203
+ if (!sScript && !sRegion || !sLanguageText) {
204
+ return sLanguageText;
205
+ }
206
+ const sResult = oLanguages[sLanguage + "_" + sRegion] || oLanguages[sLanguage + "_" + sScript];
207
+ if (sResult) {
208
+ return sResult;
209
+ }
210
+ if (sScript) {
211
+ const sScriptText = this._get("scripts")[sScript];
212
+ if (sScriptText) {
213
+ return sLanguageText + " (" + sScriptText + ")";
214
+ }
215
+ }
216
+ if (sRegion) {
217
+ const sRegionText = this._get("territories")[sRegion];
218
+ if (sRegionText) {
219
+ return sLanguageText + " (" + sRegionText + ")";
220
+ }
221
+ }
222
+ return sLanguageText;
223
+ },
224
+ /**
225
+ * Gets locale-specific language names, as available in the CLDR raw data.
226
+ *
227
+ * To avoid redundancies, with CLDR version 43 only language names are contained which cannot be derived from
228
+ * the language and the script or the territory. If a language tag is not contained in the map, use
229
+ * {@link #getLanguageName} to get the derived locale-specific language name for that language tag.
230
+ *
231
+ * @returns {Object<string, string>} Maps a language tag to the locale-specific language name
232
+ *
233
+ * @public
234
+ */
235
+ getLanguages: function () {
236
+ const oLanguages = this._get("languages");
237
+ /** @deprecated As of version 1.120.0 */
238
+ ["ar_001", "de_AT", "de_CH", "en_AU", "en_CA", "en_GB", "en_US", "es_419", "es_ES", "es_MX", "fa_AF", "fr_CA", "fr_CH", "nds_NL", "nl_BE", "pt_BR", "pt_PT", "ro_MD", "sw_CD", "zh_Hans", "zh_Hant"].forEach(sLanguageTag => {
239
+ // for compatibility reasons, ensure that for these language tags the corresponding language names are
240
+ // available
241
+ if (!oLanguages[sLanguageTag]) {
242
+ oLanguages[sLanguageTag] = this.getLanguageName(sLanguageTag);
243
+ }
244
+ });
245
+ return oLanguages;
246
+ },
247
+ /**
248
+ * Gets locale-specific script names, as available in the CLDR raw data.
249
+ *
250
+ * To avoid redundancies, with CLDR version 43 only scripts are contained for which the language-specific name
251
+ * is different from the script key. If a script key is not contained in the map, use the script key as script
252
+ * name.
253
+ *
254
+ * @returns {Object<string, string>} Maps a script key to the locale-specific script name
255
+ *
256
+ * @public
257
+ */
258
+ getScripts: function () {
259
+ return this._get("scripts");
260
+ },
261
+ /**
262
+ * Gets locale-specific territory names, as available in the CLDR raw data.
263
+ *
264
+ * To avoid redundancies, with CLDR version 43 only territories are contained for which the language-specific
265
+ * name is different from the territory key.
266
+ *
267
+ * @returns {Object<string, string>} Maps a territory key to the locale-specific territory name
268
+ *
269
+ * @public
270
+ */
271
+ getTerritories: function () {
272
+ return this._get("territories");
273
+ },
274
+ /**
275
+ * Get month names in the given width.
276
+ *
277
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth
278
+ * The required width for the month names
279
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
280
+ * The type of calendar; defaults to the calendar type either set in configuration or calculated from the
281
+ * locale
282
+ * @returns {string[]}
283
+ * The array of month names
284
+ * @public
285
+ */
286
+ getMonths: function (sWidth, sCalendarType) {
287
+ assert(aSupportedWidths.includes(sWidth), "sWidth must be narrow, abbreviated or wide");
288
+ return this._get(getCLDRCalendarName(sCalendarType), "months", "format", sWidth).map(vMonthName => {
289
+ return Array.isArray(vMonthName) ? vMonthName[0] : vMonthName;
290
+ });
291
+ },
292
+ /**
293
+ * Get standalone month names in the given width.
294
+ *
295
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth
296
+ * The required width for the month names
297
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
298
+ * The type of calendar; defaults to the calendar type either set in configuration or calculated from the
299
+ * locale
300
+ * @returns {string[]}
301
+ * The array of standalone month names
302
+ * @public
303
+ */
304
+ getMonthsStandAlone: function (sWidth, sCalendarType) {
305
+ assert(aSupportedWidths.includes(sWidth), "sWidth must be narrow, abbreviated or wide");
306
+ return this._get(getCLDRCalendarName(sCalendarType), "months", "stand-alone", sWidth).map(vMonthName => {
307
+ return Array.isArray(vMonthName) ? vMonthName[0] : vMonthName;
308
+ });
309
+ },
310
+ /**
311
+ * Get day names in the given width.
312
+ *
313
+ * @param {"abbreviated"|"narrow"|"short"|"wide"} sWidth the required width for the day names
314
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
315
+ * @returns {string[]} array of day names (starting with Sunday)
316
+ * @public
317
+ */
318
+ getDays: function (sWidth, sCalendarType) {
319
+ assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide" || sWidth == "short", "sWidth must be narrow, abbreviate, wide or short");
320
+ return this._get(getCLDRCalendarName(sCalendarType), "days", "format", sWidth);
321
+ },
322
+ /**
323
+ * Get standalone day names in the given width.
324
+ *
325
+ * @param {"abbreviated"|"narrow"|"short"|"wide"} sWidth the required width for the day names
326
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
327
+ * @returns {string[]} array of day names (starting with Sunday)
328
+ * @public
329
+ */
330
+ getDaysStandAlone: function (sWidth, sCalendarType) {
331
+ assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide" || sWidth == "short", "sWidth must be narrow, abbreviated, wide or short");
332
+ return this._get(getCLDRCalendarName(sCalendarType), "days", "stand-alone", sWidth);
333
+ },
334
+ /**
335
+ * Get quarter names in the given width.
336
+ *
337
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth the required width for the quarter names
338
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
339
+ * @returns {string[]} array of quarters
340
+ * @public
341
+ */
342
+ getQuarters: function (sWidth, sCalendarType) {
343
+ assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide", "sWidth must be narrow, abbreviated or wide");
344
+ return this._get(getCLDRCalendarName(sCalendarType), "quarters", "format", sWidth);
345
+ },
346
+ /**
347
+ * Get standalone quarter names in the given width.
348
+ *
349
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth the required width for the quarter names
350
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
351
+ * @returns {string[]} array of quarters
352
+ * @public
353
+ */
354
+ getQuartersStandAlone: function (sWidth, sCalendarType) {
355
+ assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide", "sWidth must be narrow, abbreviated or wide");
356
+ return this._get(getCLDRCalendarName(sCalendarType), "quarters", "stand-alone", sWidth);
357
+ },
358
+ /**
359
+ * Get day periods in the given width.
360
+ *
361
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth the required width for the day period names
362
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
363
+ * @returns {string[]} array of day periods (AM, PM)
364
+ * @public
365
+ */
366
+ getDayPeriods: function (sWidth, sCalendarType) {
367
+ assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide", "sWidth must be narrow, abbreviated or wide");
368
+ return this._get(getCLDRCalendarName(sCalendarType), "dayPeriods", "format", sWidth);
369
+ },
370
+ /**
371
+ * Get standalone day periods in the given width.
372
+ *
373
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth the required width for the day period names
374
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
375
+ * @returns {string[]} array of day periods (AM, PM)
376
+ * @public
377
+ */
378
+ getDayPeriodsStandAlone: function (sWidth, sCalendarType) {
379
+ assert(sWidth == "narrow" || sWidth == "abbreviated" || sWidth == "wide", "sWidth must be narrow, abbreviated or wide");
380
+ return this._get(getCLDRCalendarName(sCalendarType), "dayPeriods", "stand-alone", sWidth);
381
+ },
382
+ /**
383
+ * Get date pattern in the given style.
384
+ *
385
+ * @param {"full"|"long"|"medium"|"short"} sStyle the required style for the date pattern
386
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
387
+ * @returns {string} the selected date pattern
388
+ * @public
389
+ */
390
+ getDatePattern: function (sStyle, sCalendarType) {
391
+ assert(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full");
392
+ return this._get(getCLDRCalendarName(sCalendarType), "dateFormats", sStyle);
393
+ },
394
+ /**
395
+ * Get flexible day periods in style format "abbreviated", "narrow" or "wide".
396
+ *
397
+ * @param {string} sWidth
398
+ * The required width for the flexible day period names
399
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
400
+ * The type of calendar. If it's not set, it falls back to the calendar type either set in
401
+ * configuration or calculated from locale.
402
+ * @returns {object|undefined}
403
+ * Object of flexible day periods or 'undefined' if none can be found
404
+ *
405
+ * @example <caption>Output</caption>
406
+ * {
407
+ * "midnight": "midnight",
408
+ * "noon": "noon",
409
+ * "morning1": "in the morning",
410
+ * "afternoon1": "in the afternoon",
411
+ * "evening1": "in the evening",
412
+ * "night1": "at night"
413
+ * }
414
+ *
415
+ * @private
416
+ */
417
+ getFlexibleDayPeriods: function (sWidth, sCalendarType) {
418
+ return this._get(getCLDRCalendarName(sCalendarType), "flexibleDayPeriods", "format", sWidth);
419
+ },
420
+ /**
421
+ * Get flexible day periods in style format "abbreviated", "narrow" or "wide" for case
422
+ * "stand-alone".
423
+ *
424
+ * @param {string} sWidth
425
+ * The required width for the flexible day period names
426
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
427
+ * The type of calendar. If it's not set, it falls back to the calendar type either set in
428
+ * configuration or calculated from locale.
429
+ * @returns {object|undefined}
430
+ * Object of flexible day periods or 'undefined' if none can be found
431
+ *
432
+ * @example <caption>Output</caption>
433
+ * {
434
+ * "midnight": "midnight",
435
+ * "noon": "noon",
436
+ * "morning1": "in the morning",
437
+ * "afternoon1": "in the afternoon",
438
+ * "evening1": "in the evening",
439
+ * "night1": "at night"
440
+ * }
441
+ *
442
+ * @private
443
+ */
444
+ getFlexibleDayPeriodsStandAlone: function (sWidth, sCalendarType) {
445
+ return this._get(getCLDRCalendarName(sCalendarType), "flexibleDayPeriods", "stand-alone", sWidth);
446
+ },
447
+ /**
448
+ * Get flexible day period of time or a point in time
449
+ *
450
+ * @param {int} iHour Hour
451
+ * @param {int} iMinute Minute
452
+ * @returns {string} Key of flexible day period of time e.g. <code>afternoon2</code>
453
+ *
454
+ * @private
455
+ */
456
+ getFlexibleDayPeriodOfTime: function (iHour, iMinute) {
457
+ var iAbsoluteMinutes, oDayPeriodRules, sPeriodMatch;
458
+ iAbsoluteMinutes = (iHour * 60 + iMinute) % 1440;
459
+ oDayPeriodRules = this._get("dayPeriodRules");
460
+ function parseToAbsoluteMinutes(sValue) {
461
+ var aSplit = sValue.split(":"),
462
+ sHour = aSplit[0],
463
+ sMinute = aSplit[1];
464
+ return parseInt(sHour) * 60 + parseInt(sMinute);
465
+ }
466
+
467
+ // unfortunately there are some overlaps:
468
+ // e.g. en.json
469
+ // "afternoon1": {
470
+ // "_before": "18:00",
471
+ // "_from": "12:00"
472
+ // },
473
+ // "noon": {
474
+ // "_at": "12:00"
475
+ // }
476
+ // -> 12:00 can be either "noon" or "afternoon1" because "_from" is inclusive
477
+ // therefore first check all exact periods
478
+
479
+ sPeriodMatch = Object.keys(oDayPeriodRules).find(function (sDayPeriodRule) {
480
+ var oDayPeriodRule = oDayPeriodRules[sDayPeriodRule];
481
+ return oDayPeriodRule["_at"] && parseToAbsoluteMinutes(oDayPeriodRule["_at"]) === iAbsoluteMinutes;
482
+ });
483
+ if (sPeriodMatch) {
484
+ return sPeriodMatch;
485
+ }
486
+ return Object.keys(oDayPeriodRules).find(function (sDayPeriodRule) {
487
+ var iEndValue,
488
+ aIntervals,
489
+ iStartValue,
490
+ oDayPeriodRule = oDayPeriodRules[sDayPeriodRule];
491
+ if (oDayPeriodRule["_at"]) {
492
+ return false;
493
+ }
494
+ iStartValue = parseToAbsoluteMinutes(oDayPeriodRule["_from"]);
495
+ iEndValue = parseToAbsoluteMinutes(oDayPeriodRule["_before"]);
496
+
497
+ // periods which span across days need to be split into individual intervals
498
+ // e.g. "22:00 - 03:00" becomes "22:00 - 24:00" and "00:00 - 03:00"
499
+ if (iStartValue > iEndValue) {
500
+ aIntervals = [{
501
+ start: iStartValue,
502
+ end: 1440
503
+ },
504
+ // 24 * 60
505
+ {
506
+ start: 0,
507
+ end: iEndValue
508
+ }];
509
+ } else {
510
+ aIntervals = [{
511
+ start: iStartValue,
512
+ end: iEndValue
513
+ }];
514
+ }
515
+ return aIntervals.some(function (oInterval) {
516
+ return oInterval.start <= iAbsoluteMinutes && oInterval.end > iAbsoluteMinutes;
517
+ });
518
+ });
519
+ },
520
+ /**
521
+ * Get time pattern in the given style.
522
+ *
523
+ * @param {"full"|"long"|"medium"|"short"} sStyle the required style for the time pattern
524
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
525
+ * @returns {string} the selected time pattern
526
+ * @public
527
+ */
528
+ getTimePattern: function (sStyle, sCalendarType) {
529
+ assert(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full");
530
+ return this._get(getCLDRCalendarName(sCalendarType), "timeFormats", sStyle);
531
+ },
532
+ /**
533
+ * Get datetime pattern in the given style.
534
+ *
535
+ * @param {"full"|"long"|"medium"|"short"} sStyle the required style for the datetime pattern
536
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
537
+ * @returns {string} the selected datetime pattern
538
+ * @public
539
+ */
540
+ getDateTimePattern: function (sStyle, sCalendarType) {
541
+ assert(sStyle == "short" || sStyle == "medium" || sStyle == "long" || sStyle == "full", "sStyle must be short, medium, long or full");
542
+ return this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", sStyle);
543
+ },
544
+ /**
545
+ * Get combined datetime pattern with given date and time style. The combined datetime pattern is the datetime
546
+ * pattern as returned by {@link #getDateTimePattern}, where date and time placeholder are replaced with
547
+ * the corresponding patterns for the given styles.
548
+ *
549
+ * @param {"full"|"long"|"medium"|"short"} sDateStyle the required style for the date part
550
+ * @param {"full"|"long"|"medium"|"short"} sTimeStyle the required style for the time part
551
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
552
+ * @returns {string} the combined datetime pattern
553
+ * @public
554
+ */
555
+ getCombinedDateTimePattern: function (sDateStyle, sTimeStyle, sCalendarType) {
556
+ assert(sDateStyle == "short" || sDateStyle == "medium" || sDateStyle == "long" || sDateStyle == "full", "sStyle must be short, medium, long or full");
557
+ assert(sTimeStyle == "short" || sTimeStyle == "medium" || sTimeStyle == "long" || sTimeStyle == "full", "sStyle must be short, medium, long or full");
558
+ var sDateTimePattern = this.getDateTimePattern(sDateStyle, sCalendarType),
559
+ sDatePattern = this.getDatePattern(sDateStyle, sCalendarType),
560
+ sTimePattern = this.getTimePattern(sTimeStyle, sCalendarType);
561
+ return sDateTimePattern.replace("{0}", sTimePattern).replace("{1}", sDatePattern);
562
+ },
563
+ /**
564
+ * Get combined pattern with datetime and timezone for the given date and time style.
565
+ *
566
+ * @example
567
+ * // locale de
568
+ * oLocaleData.getCombinedDateTimeWithTimezonePattern("long", "long");
569
+ * // "d. MMMM y 'um' HH:mm:ss z VV"
570
+ *
571
+ * // locale en_GB
572
+ * oLocaleData.getCombinedDateTimeWithTimezonePattern("long", "long");
573
+ * // "d MMMM y 'at' HH:mm:ss z VV"
574
+ *
575
+ * @param {string} sDateStyle The required style for the date part
576
+ * @param {string} sTimeStyle The required style for the time part
577
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] The type of calendar. If it's not set,
578
+ * it falls back to the calendar type either set in the configuration or calculated from
579
+ * the locale.
580
+ * @returns {string} the combined pattern with datetime and timezone
581
+ * @private
582
+ * @ui5-restricted sap.ui.core.format.DateFormat
583
+ * @since 1.101
584
+ */
585
+ getCombinedDateTimeWithTimezonePattern: function (sDateStyle, sTimeStyle, sCalendarType) {
586
+ return this.applyTimezonePattern(this.getCombinedDateTimePattern(sDateStyle, sTimeStyle, sCalendarType));
587
+ },
588
+ /**
589
+ * Applies the timezone to the pattern
590
+ *
591
+ * @param {string} sPattern pattern, e.g. <code>y</code>
592
+ * @returns {string} applied timezone, e.g. <code>y VV</code>
593
+ * @private
594
+ * @ui5-restricted sap.ui.core.format.DateFormat
595
+ * @since 1.101
596
+ */
597
+ applyTimezonePattern: function (sPattern) {
598
+ var aPatterns = [sPattern];
599
+ var aMissingTokens = [{
600
+ group: "Timezone",
601
+ length: 2,
602
+ field: "zone",
603
+ symbol: "V"
604
+ }];
605
+ this._appendItems(aPatterns, aMissingTokens);
606
+ return aPatterns[0];
607
+ },
608
+ /**
609
+ * Retrieves all timezone translations.
610
+ *
611
+ * E.g. for locale "en"
612
+ * <pre>
613
+ * {
614
+ * "America/New_York": "Americas, New York"
615
+ * ...
616
+ * }
617
+ * </pre>
618
+ *
619
+ * @return {Object<string, string>} the mapping, with 'key' being the IANA timezone ID, and
620
+ * 'value' being the translation.
621
+ * @ui5-restricted sap.ui.core.format.DateFormat, sap.ui.export, sap.ushell
622
+ * @private
623
+ */
624
+ getTimezoneTranslations: function () {
625
+ var sLocale = this.oLocale.toString();
626
+ var mTranslations = LocaleData._mTimezoneTranslations[sLocale];
627
+ if (!mTranslations) {
628
+ LocaleData._mTimezoneTranslations[sLocale] = mTranslations = _resolveTimezoneTranslationStructure(this._get("timezoneNames"));
629
+ }
630
+
631
+ // retrieve a copy such that the original object won't be modified.
632
+ return Object.assign({}, mTranslations);
633
+ },
634
+ /**
635
+ * Get custom datetime pattern for a given skeleton format.
636
+ *
637
+ * The format string does contain pattern symbols (e.g. "yMMMd" or "Hms") and will be converted into the pattern in the used
638
+ * locale, which matches the wanted symbols best. The symbols must be in canonical order, that is:
639
+ * Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w/W), Day-Of-Week (E/e/c), Day (d/D),
640
+ * Hour (h/H/k/K/), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x)
641
+ *
642
+ * See https://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
643
+ *
644
+ * @param {string} sSkeleton the wanted skeleton format for the datetime pattern
645
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
646
+ * @returns {string} the best matching datetime pattern
647
+ * @since 1.34
648
+ * @public
649
+ */
650
+ getCustomDateTimePattern: function (sSkeleton, sCalendarType) {
651
+ var oAvailableFormats = this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", "availableFormats");
652
+ return this._getFormatPattern(sSkeleton, oAvailableFormats, sCalendarType);
653
+ },
654
+ /**
655
+ * Returns the interval format with the given Id (see CLDR documentation for valid Ids)
656
+ * or the fallback format if no interval format with that Id is known.
657
+ *
658
+ * The empty Id ("") might be used to retrieve the interval format fallback.
659
+ *
660
+ * @param {string} sId Id of the interval format, e.g. "d-d"
661
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
662
+ * @returns {string} interval format string with placeholders {0} and {1}
663
+ * @public
664
+ * @since 1.17.0
665
+ */
666
+ getIntervalPattern: function (sId, sCalendarType) {
667
+ var oIntervalFormats = this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", "intervalFormats"),
668
+ aIdParts,
669
+ sIntervalId,
670
+ sDifference,
671
+ oInterval,
672
+ sPattern;
673
+ if (sId) {
674
+ aIdParts = sId.split("-");
675
+ sIntervalId = aIdParts[0];
676
+ sDifference = aIdParts[1];
677
+ oInterval = oIntervalFormats[sIntervalId];
678
+ if (oInterval) {
679
+ sPattern = oInterval[sDifference];
680
+ if (sPattern) {
681
+ return sPattern;
131
682
  }
132
- return Object.keys(oDayPeriodRules).find(function (sDayPeriodRule) {
133
- var iEndValue, aIntervals, iStartValue, oDayPeriodRule = oDayPeriodRules[sDayPeriodRule];
134
- if (oDayPeriodRule['_at']) {
135
- return false;
136
- }
137
- iStartValue = parseToAbsoluteMinutes(oDayPeriodRule['_from']);
138
- iEndValue = parseToAbsoluteMinutes(oDayPeriodRule['_before']);
139
- if (iStartValue > iEndValue) {
140
- aIntervals = [
141
- {
142
- start: iStartValue,
143
- end: 1440
144
- },
145
- {
146
- start: 0,
147
- end: iEndValue
148
- }
149
- ];
150
- } else {
151
- aIntervals = [{
152
- start: iStartValue,
153
- end: iEndValue
154
- }];
155
- }
156
- return aIntervals.some(function (oInterval) {
157
- return oInterval.start <= iAbsoluteMinutes && oInterval.end > iAbsoluteMinutes;
158
- });
683
+ }
684
+ }
685
+ return oIntervalFormats.intervalFormatFallback;
686
+ },
687
+ /**
688
+ * Get combined interval pattern using a given pattern and the fallback interval pattern.
689
+ *
690
+ * If a skeleton based pattern is not available or not wanted, this method can be used to create an interval
691
+ * pattern based on a given pattern, using the fallback interval pattern.
692
+ *
693
+ * @param {string} sPattern the single date pattern to use within the interval pattern
694
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
695
+ * @returns {string} the calculated interval pattern
696
+ * @since 1.46
697
+ * @public
698
+ */
699
+ getCombinedIntervalPattern: function (sPattern, sCalendarType) {
700
+ const oIntervalFormats = this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", "intervalFormats");
701
+ const [/*sAll*/, sTextBefore, sTextBetween, sTextAfter] = rFallbackPatternTextParts.exec(oIntervalFormats.intervalFormatFallback);
702
+
703
+ // text part of intervalFormatFallback is not escaped
704
+ return LocaleData._escapeIfNeeded(sTextBefore) + sPattern + LocaleData._escapeIfNeeded(sTextBetween) + sPattern + LocaleData._escapeIfNeeded(sTextAfter);
705
+ },
706
+ /**
707
+ * @typedef {object} sap.ui.core.LocaleData.DateFieldGroupsDifference
708
+ *
709
+ * Type which describes the difference in the date field groups of the two dates of an date time interval.
710
+ * The keys are the names of the date field symbol groups. If one of them is set, the value should be set to
711
+ * <code>true</code>.
712
+ *
713
+ * @property {boolean} [Era] The era date field symbol group
714
+ * @property {boolean} [Year] The year date field symbol group
715
+ * @property {boolean} [Quarter] The quarter date field symbol group
716
+ * @property {boolean} [Month] The month date field symbol group
717
+ * @property {boolean} [Week] The week date field symbol group
718
+ * @property {boolean} [Day] The day date field symbol group
719
+ * @property {boolean} [DayPeriod] The day period date field symbol group
720
+ * @property {boolean} [Hour] The hour date field symbol group
721
+ * @property {boolean} [Minute] The minute date field symbol group
722
+ * @property {boolean} [Second] The second date field symbol group
723
+ *
724
+ * @public
725
+ */
726
+
727
+ /**
728
+ * Get interval pattern for a given skeleton format.
729
+ *
730
+ * The format string does contain pattern symbols (e.g. "yMMMd" or "Hms") and will be converted into the pattern in the used
731
+ * locale, which matches the wanted symbols best. The symbols must be in canonical order, that is:
732
+ * Era (G), Year (y/Y), Quarter (q/Q), Month (M/L), Week (w/W), Day-Of-Week (E/e/c), Day (d/D),
733
+ * Hour (h/H/k/K/), Minute (m), Second (s), Timezone (z/Z/v/V/O/X/x)
734
+ *
735
+ * See {@link https://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
736
+ * Unicode - Available Formats}
737
+ *
738
+ * @param {string} sSkeleton the wanted skeleton format for the datetime pattern
739
+ * @param {sap.ui.core.LocaleData.DateFieldGroupsDifference|string} vGreatestDiff
740
+ * is either a string which represents the symbol matching the greatest difference in the two dates to
741
+ * format or an object which contains key-value pairs. The value is always <code>true</code>. The key is one
742
+ * of the date field symbol groups whose value are different between the two dates. The key can only be set
743
+ * with:
744
+ * <code>'Era', 'Year', 'Quarter', 'Month', 'Week', 'Day', 'DayPeriod', 'Hour','Minute', 'Second'</code>.
745
+ * For more information, see {@link https://unicode.org/reports/tr35/tr35-dates.html#element-intervalformats
746
+ * Unicode - Element intervalFormats}.
747
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType] the type of calendar. If it's not set, it falls back to the calendar type either set in configuration or calculated from locale.
748
+ * @returns {string|string[]} the best matching interval pattern if interval difference is given otherwise an array with all possible interval patterns which match the given skeleton format
749
+ * @since 1.46
750
+ * @public
751
+ */
752
+ getCustomIntervalPattern: function (sSkeleton, vGreatestDiff, sCalendarType) {
753
+ var oAvailableFormats = this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", "intervalFormats");
754
+ return this._getFormatPattern(sSkeleton, oAvailableFormats, sCalendarType, vGreatestDiff);
755
+ },
756
+ /* Helper functions for skeleton pattern processing */
757
+ _getFormatPattern: function (sSkeleton, oAvailableFormats, sCalendarType, vDiff) {
758
+ var vPattern, aPatterns, oIntervalFormats;
759
+ if (!vDiff) {
760
+ // the call is from getCustomDateTimePattern
761
+ vPattern = oAvailableFormats[sSkeleton];
762
+ } else if (typeof vDiff === "string") {
763
+ // vDiff is given as a symbol
764
+ if (vDiff == "j" || vDiff == "J") {
765
+ vDiff = this.getPreferredHourSymbol();
766
+ }
767
+ oIntervalFormats = oAvailableFormats[sSkeleton];
768
+ vPattern = oIntervalFormats && oIntervalFormats[vDiff];
769
+ }
770
+ if (vPattern) {
771
+ if (typeof vPattern === "object") {
772
+ aPatterns = Object.keys(vPattern).map(function (sKey) {
773
+ return vPattern[sKey];
159
774
  });
160
- },
161
- getTimePattern: function (sStyle, sCalendarType) {
162
- assert(sStyle == 'short' || sStyle == 'medium' || sStyle == 'long' || sStyle == 'full', 'sStyle must be short, medium, long or full');
163
- return this._get(getCLDRCalendarName(sCalendarType), 'timeFormats', sStyle);
164
- },
165
- getDateTimePattern: function (sStyle, sCalendarType) {
166
- assert(sStyle == 'short' || sStyle == 'medium' || sStyle == 'long' || sStyle == 'full', 'sStyle must be short, medium, long or full');
167
- return this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', sStyle);
168
- },
169
- getCombinedDateTimePattern: function (sDateStyle, sTimeStyle, sCalendarType) {
170
- assert(sDateStyle == 'short' || sDateStyle == 'medium' || sDateStyle == 'long' || sDateStyle == 'full', 'sStyle must be short, medium, long or full');
171
- assert(sTimeStyle == 'short' || sTimeStyle == 'medium' || sTimeStyle == 'long' || sTimeStyle == 'full', 'sStyle must be short, medium, long or full');
172
- var sDateTimePattern = this.getDateTimePattern(sDateStyle, sCalendarType), sDatePattern = this.getDatePattern(sDateStyle, sCalendarType), sTimePattern = this.getTimePattern(sTimeStyle, sCalendarType);
173
- return sDateTimePattern.replace('{0}', sTimePattern).replace('{1}', sDatePattern);
174
- },
175
- getCombinedDateTimeWithTimezonePattern: function (sDateStyle, sTimeStyle, sCalendarType) {
176
- return this.applyTimezonePattern(this.getCombinedDateTimePattern(sDateStyle, sTimeStyle, sCalendarType));
177
- },
178
- applyTimezonePattern: function (sPattern) {
179
- var aPatterns = [sPattern];
180
- var aMissingTokens = [{
181
- group: 'Timezone',
182
- length: 2,
183
- field: 'zone',
184
- symbol: 'V'
185
- }];
186
- this._appendItems(aPatterns, aMissingTokens);
187
- return aPatterns[0];
188
- },
189
- getTimezoneTranslations: function () {
190
- this.mTimezoneTranslations = this.mTimezoneTranslations || _resolveTimezoneTranslationStructure(this._get('timezoneNames'));
191
- return Object.assign({}, this.mTimezoneTranslations);
192
- },
193
- getCustomDateTimePattern: function (sSkeleton, sCalendarType) {
194
- var oAvailableFormats = this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', 'availableFormats');
195
- return this._getFormatPattern(sSkeleton, oAvailableFormats, sCalendarType);
196
- },
197
- getIntervalPattern: function (sId, sCalendarType) {
198
- var oIntervalFormats = this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', 'intervalFormats'), aIdParts, sIntervalId, sDifference, oInterval, sPattern;
199
- if (sId) {
200
- aIdParts = sId.split('-');
201
- sIntervalId = aIdParts[0];
202
- sDifference = aIdParts[1];
203
- oInterval = oIntervalFormats[sIntervalId];
204
- if (oInterval) {
205
- sPattern = oInterval[sDifference];
206
- if (sPattern) {
207
- return sPattern;
208
- }
209
- }
210
- }
211
- return oIntervalFormats.intervalFormatFallback;
212
- },
213
- getCombinedIntervalPattern: function (sPattern, sCalendarType) {
214
- var oIntervalFormats = this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', 'intervalFormats'), sFallbackPattern = oIntervalFormats.intervalFormatFallback;
215
- return sFallbackPattern.replace(/\{(0|1)\}/g, sPattern);
216
- },
217
- getCustomIntervalPattern: function (sSkeleton, vGreatestDiff, sCalendarType) {
218
- var oAvailableFormats = this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', 'intervalFormats');
219
- return this._getFormatPattern(sSkeleton, oAvailableFormats, sCalendarType, vGreatestDiff);
220
- },
221
- _getFormatPattern: function (sSkeleton, oAvailableFormats, sCalendarType, vDiff) {
222
- var vPattern, aPatterns, oIntervalFormats;
223
- if (!vDiff) {
224
- vPattern = oAvailableFormats[sSkeleton];
225
- } else if (typeof vDiff === 'string') {
226
- if (vDiff == 'j' || vDiff == 'J') {
227
- vDiff = this.getPreferredHourSymbol();
228
- }
229
- oIntervalFormats = oAvailableFormats[sSkeleton];
230
- vPattern = oIntervalFormats && oIntervalFormats[vDiff];
231
- }
232
- if (vPattern) {
233
- if (typeof vPattern === 'object') {
234
- aPatterns = Object.keys(vPattern).map(function (sKey) {
235
- return vPattern[sKey];
236
- });
237
- } else {
238
- return vPattern;
239
- }
240
- }
241
- if (!aPatterns) {
242
- aPatterns = this._createFormatPattern(sSkeleton, oAvailableFormats, sCalendarType, vDiff);
243
- }
244
- if (aPatterns && aPatterns.length === 1) {
245
- return aPatterns[0];
775
+ } else {
776
+ return vPattern;
777
+ }
778
+ }
779
+ if (!aPatterns) {
780
+ aPatterns = this._createFormatPattern(sSkeleton, oAvailableFormats, sCalendarType, vDiff);
781
+ }
782
+ if (aPatterns && aPatterns.length === 1) {
783
+ return aPatterns[0];
784
+ }
785
+ return aPatterns;
786
+ },
787
+ _createFormatPattern: function (sSkeleton, oAvailableFormats, sCalendarType, vDiff) {
788
+ var aTokens = this._parseSkeletonFormat(sSkeleton),
789
+ aPatterns,
790
+ oBestMatch = this._findBestMatch(aTokens, sSkeleton, oAvailableFormats),
791
+ oToken,
792
+ oAvailableDateTimeFormats,
793
+ oSymbol,
794
+ oGroup,
795
+ sPattern,
796
+ sSinglePattern,
797
+ sDiffSymbol,
798
+ sDiffGroup,
799
+ rMixedSkeleton = /^([GyYqQMLwWEecdD]+)([hHkKjJmszZvVOXx]+)$/,
800
+ bSingleDate,
801
+ i;
802
+ if (vDiff) {
803
+ if (typeof vDiff === "string") {
804
+ sDiffGroup = mCLDRSymbols[vDiff] ? mCLDRSymbols[vDiff].group : "";
805
+ if (sDiffGroup) {
806
+ // if the index of interval diff is greater than the index of the last field
807
+ // in the sSkeleton, which means the diff unit is smaller than all units in
808
+ // the skeleton, return a single date pattern which is generated using the
809
+ // given skeleton
810
+ bSingleDate = mCLDRSymbolGroups[sDiffGroup].index > aTokens[aTokens.length - 1].index;
246
811
  }
247
- return aPatterns;
248
- },
249
- _createFormatPattern: function (sSkeleton, oAvailableFormats, sCalendarType, vDiff) {
250
- var aTokens = this._parseSkeletonFormat(sSkeleton), aPatterns, oBestMatch = this._findBestMatch(aTokens, sSkeleton, oAvailableFormats), oToken, oAvailableDateTimeFormats, oSymbol, oGroup, sPattern, sSinglePattern, sDiffSymbol, sDiffGroup, rMixedSkeleton = /^([GyYqQMLwWEecdD]+)([hHkKjJmszZvVOXx]+)$/, bSingleDate, i;
251
- if (vDiff) {
252
- if (typeof vDiff === 'string') {
253
- sDiffGroup = mCLDRSymbols[vDiff] ? mCLDRSymbols[vDiff].group : '';
254
- if (sDiffGroup) {
255
- bSingleDate = mCLDRSymbolGroups[sDiffGroup].index > aTokens[aTokens.length - 1].index;
256
- }
257
- sDiffSymbol = vDiff;
258
- } else {
259
- bSingleDate = true;
260
- if (aTokens[0].symbol === 'y' && oBestMatch && oBestMatch.pattern.G) {
261
- oSymbol = mCLDRSymbols['G'];
262
- oGroup = mCLDRSymbolGroups[oSymbol.group];
263
- aTokens.splice(0, 0, {
264
- symbol: 'G',
265
- group: oSymbol.group,
266
- match: oSymbol.match,
267
- index: oGroup.index,
268
- field: oGroup.field,
269
- length: 1
270
- });
271
- }
272
- for (i = aTokens.length - 1; i >= 0; i--) {
273
- oToken = aTokens[i];
274
- if (vDiff[oToken.group]) {
275
- bSingleDate = false;
276
- break;
277
- }
278
- }
279
- for (i = 0; i < aTokens.length; i++) {
280
- oToken = aTokens[i];
281
- if (vDiff[oToken.group]) {
282
- sDiffSymbol = oToken.symbol;
283
- break;
284
- }
285
- }
286
- if ((sDiffSymbol == 'h' || sDiffSymbol == 'K') && vDiff.DayPeriod) {
287
- sDiffSymbol = 'a';
288
- }
289
- }
290
- if (bSingleDate) {
291
- return [this.getCustomDateTimePattern(sSkeleton, sCalendarType)];
292
- }
293
- if (oBestMatch && oBestMatch.missingTokens.length === 0) {
294
- sPattern = oBestMatch.pattern[sDiffSymbol];
295
- if (sPattern && oBestMatch.distance > 0) {
296
- sPattern = this._expandFields(sPattern, oBestMatch.patternTokens, aTokens);
297
- }
298
- }
299
- if (!sPattern) {
300
- oAvailableDateTimeFormats = this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', 'availableFormats');
301
- if (rMixedSkeleton.test(sSkeleton) && 'ahHkKjJms'.indexOf(sDiffSymbol) >= 0) {
302
- sPattern = this._getMixedFormatPattern(sSkeleton, oAvailableDateTimeFormats, sCalendarType, vDiff);
303
- } else {
304
- sSinglePattern = this._getFormatPattern(sSkeleton, oAvailableDateTimeFormats, sCalendarType);
305
- sPattern = this.getCombinedIntervalPattern(sSinglePattern, sCalendarType);
306
- }
307
- }
308
- aPatterns = [sPattern];
309
- } else if (!oBestMatch) {
310
- sPattern = sSkeleton;
311
- aPatterns = [sPattern];
312
- } else {
313
- if (typeof oBestMatch.pattern === 'string') {
314
- aPatterns = [oBestMatch.pattern];
315
- } else if (typeof oBestMatch.pattern === 'object') {
316
- aPatterns = [];
317
- for (var sKey in oBestMatch.pattern) {
318
- sPattern = oBestMatch.pattern[sKey];
319
- aPatterns.push(sPattern);
320
- }
321
- }
322
- if (oBestMatch.distance > 0) {
323
- if (oBestMatch.missingTokens.length > 0) {
324
- if (rMixedSkeleton.test(sSkeleton)) {
325
- aPatterns = [this._getMixedFormatPattern(sSkeleton, oAvailableFormats, sCalendarType)];
326
- } else {
327
- aPatterns = this._expandFields(aPatterns, oBestMatch.patternTokens, aTokens);
328
- aPatterns = this._appendItems(aPatterns, oBestMatch.missingTokens, sCalendarType);
329
- }
330
- } else {
331
- aPatterns = this._expandFields(aPatterns, oBestMatch.patternTokens, aTokens);
332
- }
333
- }
812
+ sDiffSymbol = vDiff;
813
+ } else {
814
+ bSingleDate = true;
815
+ // Special handling of "y" (Year) in case patterns contains also "G" (Era)
816
+ if (aTokens[0].symbol === "y" && oBestMatch && oBestMatch.pattern.G) {
817
+ oSymbol = mCLDRSymbols["G"];
818
+ oGroup = mCLDRSymbolGroups[oSymbol.group];
819
+ aTokens.splice(0, 0, {
820
+ symbol: "G",
821
+ group: oSymbol.group,
822
+ match: oSymbol.match,
823
+ index: oGroup.index,
824
+ field: oGroup.field,
825
+ length: 1
826
+ });
334
827
  }
335
- if (sSkeleton.indexOf('J') >= 0) {
336
- aPatterns.forEach(function (sPattern, iIndex) {
337
- aPatterns[iIndex] = sPattern.replace(/ ?[abB](?=([^']*'[^']*')*[^']*)$/g, '');
338
- });
828
+
829
+ // Check if at least one token's group appears in the interval diff
830
+ // If not, a single date pattern is returned
831
+ for (i = aTokens.length - 1; i >= 0; i--) {
832
+ oToken = aTokens[i];
833
+ if (vDiff[oToken.group]) {
834
+ bSingleDate = false;
835
+ break;
836
+ }
339
837
  }
340
- return aPatterns;
341
- },
342
- _parseSkeletonFormat: function (sSkeleton) {
343
- var aTokens = [], oToken = { index: -1 }, sSymbol, oSymbol, oGroup;
344
- for (var i = 0; i < sSkeleton.length; i++) {
345
- sSymbol = sSkeleton.charAt(i);
346
- if (sSymbol == 'j' || sSymbol == 'J') {
347
- sSymbol = this.getPreferredHourSymbol();
348
- }
349
- if (sSymbol == oToken.symbol) {
350
- oToken.length++;
351
- continue;
352
- }
353
- oSymbol = mCLDRSymbols[sSymbol];
354
- oGroup = mCLDRSymbolGroups[oSymbol.group];
355
- if (oSymbol.group == 'Other' || oGroup.diffOnly) {
356
- throw new Error('Symbol \'' + sSymbol + '\' is not allowed in skeleton format \'' + sSkeleton + '\'');
357
- }
358
- if (oGroup.index <= oToken.index) {
359
- throw new Error('Symbol \'' + sSymbol + '\' at wrong position or duplicate in skeleton format \'' + sSkeleton + '\'');
360
- }
361
- oToken = {
362
- symbol: sSymbol,
363
- group: oSymbol.group,
364
- match: oSymbol.match,
365
- index: oGroup.index,
366
- field: oGroup.field,
367
- length: 1
368
- };
369
- aTokens.push(oToken);
838
+
839
+ // select the greatest diff symbol
840
+ for (i = 0; i < aTokens.length; i++) {
841
+ oToken = aTokens[i];
842
+ if (vDiff[oToken.group]) {
843
+ sDiffSymbol = oToken.symbol;
844
+ break;
845
+ }
370
846
  }
371
- return aTokens;
372
- },
373
- _findBestMatch: function (aTokens, sSkeleton, oAvailableFormats) {
374
- var aTestTokens, aMissingTokens, oToken, oTestToken, iTest, iDistance, bMatch, iFirstDiffPos, oTokenSymbol, oTestTokenSymbol, oBestMatch = {
375
- distance: 10000,
376
- firstDiffPos: -1
377
- };
378
- for (var sTestSkeleton in oAvailableFormats) {
379
- if (sTestSkeleton === 'intervalFormatFallback' || sTestSkeleton.indexOf('B') > -1) {
380
- continue;
381
- }
382
- aTestTokens = this._parseSkeletonFormat(sTestSkeleton);
383
- iDistance = 0;
384
- aMissingTokens = [];
385
- bMatch = true;
386
- if (aTokens.length < aTestTokens.length) {
387
- continue;
388
- }
389
- iTest = 0;
390
- iFirstDiffPos = aTokens.length;
391
- for (var i = 0; i < aTokens.length; i++) {
392
- oToken = aTokens[i];
393
- oTestToken = aTestTokens[iTest];
394
- if (iFirstDiffPos === aTokens.length) {
395
- iFirstDiffPos = i;
396
- }
397
- if (oTestToken) {
398
- oTokenSymbol = mCLDRSymbols[oToken.symbol];
399
- oTestTokenSymbol = mCLDRSymbols[oTestToken.symbol];
400
- if (oToken.symbol === oTestToken.symbol) {
401
- if (oToken.length === oTestToken.length) {
402
- if (iFirstDiffPos === i) {
403
- iFirstDiffPos = aTokens.length;
404
- }
405
- } else {
406
- if (oToken.length < oTokenSymbol.numericCeiling ? oTestToken.length < oTestTokenSymbol.numericCeiling : oTestToken.length >= oTestTokenSymbol.numericCeiling) {
407
- iDistance += Math.abs(oToken.length - oTestToken.length);
408
- } else {
409
- iDistance += 5;
410
- }
411
- }
412
- iTest++;
413
- continue;
414
- } else {
415
- if (oToken.match == oTestToken.match) {
416
- iDistance += Math.abs(oToken.length - oTestToken.length) + 10;
417
- iTest++;
418
- continue;
419
- }
420
- }
421
- }
422
- aMissingTokens.push(oToken);
423
- iDistance += 50 - i;
424
- }
425
- if (iTest < aTestTokens.length) {
426
- bMatch = false;
427
- }
428
- if (bMatch && (iDistance < oBestMatch.distance || iDistance === oBestMatch.distance && iFirstDiffPos > oBestMatch.firstDiffPos)) {
429
- oBestMatch.distance = iDistance;
430
- oBestMatch.firstDiffPos = iFirstDiffPos;
431
- oBestMatch.missingTokens = aMissingTokens;
432
- oBestMatch.pattern = oAvailableFormats[sTestSkeleton];
433
- oBestMatch.patternTokens = aTestTokens;
434
- }
847
+ // Special handling of "a" (Dayperiod)
848
+ // Find out whether dayperiod is different between the dates
849
+ // If yes, set the diff symbol with 'a' Dayperiod symbol
850
+ if ((sDiffSymbol == "h" || sDiffSymbol == "K") && vDiff.DayPeriod) {
851
+ sDiffSymbol = "a";
435
852
  }
436
- if (oBestMatch.pattern) {
437
- return oBestMatch;
853
+ }
854
+ if (bSingleDate) {
855
+ return [this.getCustomDateTimePattern(sSkeleton, sCalendarType)];
856
+ }
857
+
858
+ // Only use best match, if there are no missing tokens, as there is no possibility
859
+ // to append items on interval formats
860
+ if (oBestMatch && oBestMatch.missingTokens.length === 0) {
861
+ sPattern = oBestMatch.pattern[sDiffSymbol];
862
+ // if there is no exact match, we need to do further processing
863
+ if (sPattern && oBestMatch.distance > 0) {
864
+ sPattern = this._expandFields(sPattern, oBestMatch.patternTokens, aTokens);
438
865
  }
439
- },
440
- _expandFields: function (vPattern, aPatternTokens, aTokens) {
441
- var bSinglePattern = typeof vPattern === 'string';
442
- var aPatterns;
443
- if (bSinglePattern) {
444
- aPatterns = [vPattern];
866
+ }
867
+ // If no pattern could be found, get the best availableFormat for the skeleton
868
+ // and use the fallbackIntervalFormat to create the pattern
869
+ if (!sPattern) {
870
+ oAvailableDateTimeFormats = this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", "availableFormats");
871
+ // If it is a mixed skeleton and the greatest interval on time, create a mixed pattern
872
+ if (rMixedSkeleton.test(sSkeleton) && "ahHkKjJms".indexOf(sDiffSymbol) >= 0) {
873
+ sPattern = this._getMixedFormatPattern(sSkeleton, oAvailableDateTimeFormats, sCalendarType, vDiff);
445
874
  } else {
446
- aPatterns = vPattern;
875
+ sSinglePattern = this._getFormatPattern(sSkeleton, oAvailableDateTimeFormats, sCalendarType);
876
+ sPattern = this.getCombinedIntervalPattern(sSinglePattern, sCalendarType);
447
877
  }
448
- var aResult = aPatterns.map(function (sPattern) {
449
- var mGroups = {}, mPatternGroups = {}, sResultPatterm = '', bQuoted = false, i = 0, iSkeletonLength, iPatternLength, iBestLength, iNewLength, oSkeletonToken, oBestToken, oSymbol, sChar;
450
- aTokens.forEach(function (oToken) {
451
- mGroups[oToken.group] = oToken;
452
- });
453
- aPatternTokens.forEach(function (oToken) {
454
- mPatternGroups[oToken.group] = oToken;
455
- });
456
- while (i < sPattern.length) {
457
- sChar = sPattern.charAt(i);
458
- if (bQuoted) {
459
- sResultPatterm += sChar;
460
- if (sChar == '\'') {
461
- bQuoted = false;
462
- }
463
- } else {
464
- oSymbol = mCLDRSymbols[sChar];
465
- if (oSymbol && mGroups[oSymbol.group] && mPatternGroups[oSymbol.group]) {
466
- oSkeletonToken = mGroups[oSymbol.group];
467
- oBestToken = mPatternGroups[oSymbol.group];
468
- iSkeletonLength = oSkeletonToken.length;
469
- iBestLength = oBestToken.length;
470
- iPatternLength = 1;
471
- while (sPattern.charAt(i + 1) == sChar) {
472
- i++;
473
- iPatternLength++;
474
- }
475
- if (iSkeletonLength === iBestLength || (iSkeletonLength < oSymbol.numericCeiling ? iPatternLength >= oSymbol.numericCeiling : iPatternLength < oSymbol.numericCeiling)) {
476
- iNewLength = iPatternLength;
477
- } else {
478
- iNewLength = Math.max(iPatternLength, iSkeletonLength);
479
- }
480
- for (var j = 0; j < iNewLength; j++) {
481
- sResultPatterm += sChar;
482
- }
483
- } else {
484
- sResultPatterm += sChar;
485
- if (sChar == '\'') {
486
- bQuoted = true;
487
- }
488
- }
489
- }
490
- i++;
491
- }
492
- return sResultPatterm;
493
- });
494
- return bSinglePattern ? aResult[0] : aResult;
495
- },
496
- _appendItems: function (aPatterns, aMissingTokens, sCalendarType) {
497
- var oAppendItems = this._get(getCLDRCalendarName(sCalendarType), 'dateTimeFormats', 'appendItems');
498
- aPatterns.forEach(function (sPattern, iIndex) {
499
- var sDisplayName, sAppendPattern, sAppendField;
500
- aMissingTokens.forEach(function (oToken) {
501
- sAppendPattern = oAppendItems[oToken.group];
502
- sDisplayName = '\'' + this.getDisplayName(oToken.field) + '\'';
503
- sAppendField = '';
504
- for (var i = 0; i < oToken.length; i++) {
505
- sAppendField += oToken.symbol;
506
- }
507
- aPatterns[iIndex] = sAppendPattern.replace(/\{0\}/, sPattern).replace(/\{1\}/, sAppendField).replace(/\{2\}/, sDisplayName);
508
- }.bind(this));
509
- }.bind(this));
510
- return aPatterns;
511
- },
512
- _getMixedFormatPattern: function (sSkeleton, oAvailableFormats, sCalendarType, vDiff) {
513
- var rMixedSkeleton = /^([GyYqQMLwWEecdD]+)([hHkKjJmszZvVOXx]+)$/, rWideMonth = /MMMM|LLLL/, rAbbrevMonth = /MMM|LLL/, rWeekDay = /E|e|c/, oResult, sDateSkeleton, sTimeSkeleton, sStyle, sDatePattern, sTimePattern, sDateTimePattern, sResultPattern;
514
- oResult = rMixedSkeleton.exec(sSkeleton);
515
- sDateSkeleton = oResult[1];
516
- sTimeSkeleton = oResult[2];
517
- sDatePattern = this._getFormatPattern(sDateSkeleton, oAvailableFormats, sCalendarType);
518
- if (vDiff) {
519
- sTimePattern = this.getCustomIntervalPattern(sTimeSkeleton, vDiff, sCalendarType);
520
- } else {
521
- sTimePattern = this._getFormatPattern(sTimeSkeleton, oAvailableFormats, sCalendarType);
878
+ }
879
+ aPatterns = [sPattern];
880
+ } else if (!oBestMatch) {
881
+ sPattern = sSkeleton;
882
+ aPatterns = [sPattern];
883
+ } else {
884
+ if (typeof oBestMatch.pattern === "string") {
885
+ aPatterns = [oBestMatch.pattern];
886
+ } else if (typeof oBestMatch.pattern === "object") {
887
+ aPatterns = [];
888
+ for (var sKey in oBestMatch.pattern) {
889
+ sPattern = oBestMatch.pattern[sKey];
890
+ aPatterns.push(sPattern);
522
891
  }
523
- if (rWideMonth.test(sDateSkeleton)) {
524
- sStyle = rWeekDay.test(sDateSkeleton) ? 'full' : 'long';
525
- } else if (rAbbrevMonth.test(sDateSkeleton)) {
526
- sStyle = 'medium';
892
+ }
893
+ // if there is no exact match, we need to do further processing
894
+ if (oBestMatch.distance > 0) {
895
+ if (oBestMatch.missingTokens.length > 0) {
896
+ // if tokens are missing create a pattern containing all, otherwise just adjust pattern
897
+ if (rMixedSkeleton.test(sSkeleton)) {
898
+ aPatterns = [this._getMixedFormatPattern(sSkeleton, oAvailableFormats, sCalendarType)];
899
+ } else {
900
+ aPatterns = this._expandFields(aPatterns, oBestMatch.patternTokens, aTokens);
901
+ aPatterns = this._appendItems(aPatterns, oBestMatch.missingTokens, sCalendarType);
902
+ }
527
903
  } else {
528
- sStyle = 'short';
529
- }
530
- sDateTimePattern = this.getDateTimePattern(sStyle, sCalendarType);
531
- sResultPattern = sDateTimePattern.replace(/\{1\}/, sDatePattern).replace(/\{0\}/, sTimePattern);
532
- return sResultPattern;
533
- },
534
- getNumberSymbol: function (sType) {
535
- assert(sType == 'decimal' || sType == 'group' || sType == 'plusSign' || sType == 'minusSign' || sType == 'percentSign', 'sType must be decimal, group, plusSign, minusSign or percentSign');
536
- return this._get('symbols-latn-' + sType);
537
- },
538
- getLenientNumberSymbols: function (sType) {
539
- assert(sType == 'plusSign' || sType == 'minusSign', 'sType must be plusSign or minusSign');
540
- return this._get('lenient-scope-number')[sType];
541
- },
542
- getDecimalPattern: function () {
543
- return this._get('decimalFormat').standard;
544
- },
545
- getCurrencyPattern: function (sContext) {
546
- return this._get('currencyFormat')[sContext] || this._get('currencyFormat').standard;
547
- },
548
- getCurrencySpacing: function (sPosition) {
549
- return this._get('currencyFormat', 'currencySpacing', sPosition === 'after' ? 'afterCurrency' : 'beforeCurrency');
550
- },
551
- getPercentPattern: function () {
552
- return this._get('percentFormat').standard;
553
- },
554
- getMiscPattern: function (sName) {
555
- assert(sName == 'approximately' || sName == 'atLeast' || sName == 'atMost' || sName == 'range', 'sName must be approximately, atLeast, atMost or range');
556
- return this._get('miscPattern')[sName];
557
- },
558
- getMinimalDaysInFirstWeek: function () {
559
- return this._get('weekData-minDays');
560
- },
561
- getFirstDayOfWeek: function () {
562
- return this._get('weekData-firstDay');
563
- },
564
- getWeekendStart: function () {
565
- return this._get('weekData-weekendStart');
566
- },
567
- getWeekendEnd: function () {
568
- return this._get('weekData-weekendEnd');
569
- },
570
- getCustomCurrencyCodes: function () {
571
- var mCustomCurrencies = this._get('currency') || {}, mCustomCurrencyCodes = {};
572
- Object.keys(mCustomCurrencies).forEach(function (sCurrencyKey) {
573
- mCustomCurrencyCodes[sCurrencyKey] = sCurrencyKey;
574
- });
575
- return mCustomCurrencyCodes;
576
- },
577
- getCurrencyDigits: function (sCurrency) {
578
- var mCustomCurrencies = this._get('currency');
579
- if (mCustomCurrencies) {
580
- if (mCustomCurrencies[sCurrency] && mCustomCurrencies[sCurrency].hasOwnProperty('digits')) {
581
- return mCustomCurrencies[sCurrency].digits;
582
- } else if (mCustomCurrencies['DEFAULT'] && mCustomCurrencies['DEFAULT'].hasOwnProperty('digits')) {
583
- return mCustomCurrencies['DEFAULT'].digits;
584
- }
904
+ aPatterns = this._expandFields(aPatterns, oBestMatch.patternTokens, aTokens);
585
905
  }
586
- var iDigits = this._get('currencyDigits', sCurrency);
587
- if (iDigits == null) {
588
- iDigits = this._get('currencyDigits', 'DEFAULT');
589
- if (iDigits == null) {
590
- iDigits = 2;
591
- }
592
- }
593
- return iDigits;
594
- },
595
- getCurrencySymbol: function (sCurrency) {
596
- var oCurrencySymbols = this.getCurrencySymbols();
597
- return oCurrencySymbols && oCurrencySymbols[sCurrency] || sCurrency;
598
- },
599
- getCurrencyCodeBySymbol: function (sCurrencySymbol) {
600
- var oCurrencySymbols = this._get('currencySymbols'), sCurrencyCode;
601
- for (sCurrencyCode in oCurrencySymbols) {
602
- if (oCurrencySymbols[sCurrencyCode] === sCurrencySymbol) {
603
- return sCurrencyCode;
604
- }
605
- }
606
- return sCurrencySymbol;
607
- },
608
- getCurrencySymbols: function () {
609
- var mCustomCurrencies = this._get('currency'), mCustomCurrencySymbols = {}, sIsoCode;
610
- for (var sCurrencyKey in mCustomCurrencies) {
611
- sIsoCode = mCustomCurrencies[sCurrencyKey].isoCode;
612
- if (mCustomCurrencies[sCurrencyKey].symbol) {
613
- mCustomCurrencySymbols[sCurrencyKey] = mCustomCurrencies[sCurrencyKey].symbol;
614
- } else if (sIsoCode) {
615
- mCustomCurrencySymbols[sCurrencyKey] = this._get('currencySymbols')[sIsoCode];
616
- }
617
- }
618
- return Object.assign({}, this._get('currencySymbols'), mCustomCurrencySymbols);
619
- },
620
- getUnitDisplayName: function (sUnit) {
621
- var mUnitFormat = this.getUnitFormat(sUnit);
622
- return mUnitFormat && mUnitFormat['displayName'] || '';
623
- },
624
- getRelativePatterns: function (aScales, sStyle) {
625
- if (sStyle === undefined) {
626
- sStyle = 'wide';
627
- }
628
- assert(sStyle === 'wide' || sStyle === 'short' || sStyle === 'narrow', 'sStyle is only allowed to be set with \'wide\', \'short\' or \'narrow\'');
629
- var aPatterns = [], aPluralCategories = this.getPluralCategories(), oScale, oTimeEntry, iValue, iSign;
630
- if (!aScales) {
631
- aScales = [
632
- 'year',
633
- 'month',
634
- 'week',
635
- 'day',
636
- 'hour',
637
- 'minute',
638
- 'second'
639
- ];
640
- }
641
- aScales.forEach(function (sScale) {
642
- oScale = this._get('dateFields', sScale + '-' + sStyle);
643
- for (var sEntry in oScale) {
644
- if (sEntry.indexOf('relative-type-') === 0) {
645
- iValue = parseInt(sEntry.substr(14));
646
- aPatterns.push({
647
- scale: sScale,
648
- value: iValue,
649
- pattern: oScale[sEntry]
650
- });
651
- } else if (sEntry.indexOf('relativeTime-type-') == 0) {
652
- oTimeEntry = oScale[sEntry];
653
- iSign = sEntry.substr(18) === 'past' ? -1 : 1;
654
- aPluralCategories.forEach(function (sKey) {
655
- var sPattern = oTimeEntry['relativeTimePattern-count-' + sKey];
656
- if (sPattern) {
657
- aPatterns.push({
658
- scale: sScale,
659
- sign: iSign,
660
- pattern: sPattern
661
- });
662
- }
663
- });
664
- }
665
- }
666
- }.bind(this));
667
- return aPatterns;
668
- },
669
- getRelativePattern: function (sScale, iDiff, bFuture, sStyle) {
670
- var sPattern, oTypes, sKey, sPluralCategory;
671
- if (typeof bFuture === 'string') {
672
- sStyle = bFuture;
673
- bFuture = undefined;
674
- }
675
- if (bFuture === undefined) {
676
- bFuture = iDiff > 0;
677
- }
678
- if (sStyle === undefined) {
679
- sStyle = 'wide';
680
- }
681
- assert(sStyle === 'wide' || sStyle === 'short' || sStyle === 'narrow', 'sStyle is only allowed to be set with \'wide\', \'short\' or \'narrow\'');
682
- sKey = sScale + '-' + sStyle;
683
- if (iDiff === 0 || iDiff === -2 || iDiff === 2) {
684
- sPattern = this._get('dateFields', sKey, 'relative-type-' + iDiff);
685
- }
686
- if (!sPattern) {
687
- oTypes = this._get('dateFields', sKey, 'relativeTime-type-' + (bFuture ? 'future' : 'past'));
688
- sPluralCategory = this.getPluralCategory(Math.abs(iDiff).toString());
689
- sPattern = oTypes['relativeTimePattern-count-' + sPluralCategory];
690
- }
691
- return sPattern;
692
- },
693
- getRelativeSecond: function (iDiff, sStyle) {
694
- return this.getRelativePattern('second', iDiff, sStyle);
695
- },
696
- getRelativeMinute: function (iDiff, sStyle) {
697
- if (iDiff == 0) {
698
- return null;
699
- }
700
- return this.getRelativePattern('minute', iDiff, sStyle);
701
- },
702
- getRelativeHour: function (iDiff, sStyle) {
703
- if (iDiff == 0) {
704
- return null;
705
- }
706
- return this.getRelativePattern('hour', iDiff, sStyle);
707
- },
708
- getRelativeDay: function (iDiff, sStyle) {
709
- return this.getRelativePattern('day', iDiff, sStyle);
710
- },
711
- getRelativeWeek: function (iDiff, sStyle) {
712
- return this.getRelativePattern('week', iDiff, sStyle);
713
- },
714
- getRelativeMonth: function (iDiff, sStyle) {
715
- return this.getRelativePattern('month', iDiff, sStyle);
716
- },
717
- getDisplayName: function (sType, sStyle) {
718
- assert(sType == 'second' || sType == 'minute' || sType == 'hour' || sType == 'zone' || sType == 'day' || sType == 'weekday' || sType == 'week' || sType == 'month' || sType == 'quarter' || sType == 'year' || sType == 'era', 'sType must be second, minute, hour, zone, day, weekday, week, month, quarter, year, era');
719
- if (sStyle === undefined) {
720
- sStyle = 'wide';
721
- }
722
- assert(sStyle === 'wide' || sStyle === 'short' || sStyle === 'narrow', 'sStyle is only allowed to be set with \'wide\', \'short\' or \'narrow\'');
723
- var aSingleFormFields = [
724
- 'era',
725
- 'weekday',
726
- 'zone'
727
- ], sKey = aSingleFormFields.indexOf(sType) === -1 ? sType + '-' + sStyle : sType;
728
- return this._get('dateFields', sKey, 'displayName');
729
- },
730
- getRelativeYear: function (iDiff, sStyle) {
731
- return this.getRelativePattern('year', iDiff, sStyle);
732
- },
733
- getDecimalFormat: function (sStyle, sNumber, sPlural) {
734
- var sFormat;
735
- var oFormats;
736
- switch (sStyle) {
737
- case 'long':
738
- oFormats = this._get('decimalFormat-long');
739
- break;
740
- default:
741
- oFormats = this._get('decimalFormat-short');
742
- break;
743
- }
744
- if (oFormats) {
745
- var sName = sNumber + '-' + sPlural;
746
- sFormat = oFormats[sName];
747
- if (!sFormat) {
748
- sName = sNumber + '-other';
749
- sFormat = oFormats[sName];
750
- }
751
- }
752
- return sFormat;
753
- },
754
- getCurrencyFormat: function (sStyle, sNumber, sPlural) {
755
- var sFormat;
756
- var oFormats = this._get('currencyFormat-' + sStyle);
757
- if (!oFormats) {
758
- if (sStyle === 'sap-short') {
759
- throw new Error('Failed to get CLDR data for property "currencyFormat-sap-short"');
760
- }
761
- oFormats = this._get('currencyFormat-short');
906
+ }
907
+ }
908
+
909
+ // If special input token "J" was used, remove dayperiod from pattern
910
+ if (sSkeleton.indexOf("J") >= 0) {
911
+ aPatterns.forEach(function (sPattern, iIndex) {
912
+ aPatterns[iIndex] = sPattern.replace(/ ?[abB](?=([^']*'[^']*')*[^']*)$/g, "");
913
+ });
914
+ }
915
+ return aPatterns;
916
+ },
917
+ _parseSkeletonFormat: function (sSkeleton) {
918
+ var aTokens = [],
919
+ oToken = {
920
+ index: -1
921
+ },
922
+ sSymbol,
923
+ oSymbol,
924
+ oGroup;
925
+ for (var i = 0; i < sSkeleton.length; i++) {
926
+ sSymbol = sSkeleton.charAt(i);
927
+ // Handle special input symbols
928
+ if (sSymbol == "j" || sSymbol == "J") {
929
+ sSymbol = this.getPreferredHourSymbol();
930
+ }
931
+ // if the symbol is the same as current token, increase the length
932
+ if (sSymbol == oToken.symbol) {
933
+ oToken.length++;
934
+ continue;
935
+ }
936
+ // get symbol group
937
+ oSymbol = mCLDRSymbols[sSymbol];
938
+ oGroup = mCLDRSymbolGroups[oSymbol.group];
939
+ // if group is other, the symbol is not allowed in skeleton tokens
940
+ if (oSymbol.group == "Other" || oGroup.diffOnly) {
941
+ throw new Error("Symbol '" + sSymbol + "' is not allowed in skeleton format '" + sSkeleton + "'");
942
+ }
943
+ // if group index the same or lower, format is invalid
944
+ if (oGroup.index <= oToken.index) {
945
+ throw new Error("Symbol '" + sSymbol + "' at wrong position or duplicate in skeleton format '" + sSkeleton + "'");
946
+ }
947
+ // create token and add it the token array
948
+ oToken = {
949
+ symbol: sSymbol,
950
+ group: oSymbol.group,
951
+ match: oSymbol.match,
952
+ index: oGroup.index,
953
+ field: oGroup.field,
954
+ length: 1
955
+ };
956
+ aTokens.push(oToken);
957
+ }
958
+ return aTokens;
959
+ },
960
+ _findBestMatch: function (aTokens, sSkeleton, oAvailableFormats) {
961
+ var aTestTokens,
962
+ aMissingTokens,
963
+ oToken,
964
+ oTestToken,
965
+ iTest,
966
+ iDistance,
967
+ bMatch,
968
+ iFirstDiffPos,
969
+ oTokenSymbol,
970
+ oTestTokenSymbol,
971
+ oBestMatch = {
972
+ distance: 10000,
973
+ firstDiffPos: -1
974
+ };
975
+ // Loop through all available tokens, find matches and calculate distance
976
+ for (var sTestSkeleton in oAvailableFormats) {
977
+ // Skip patterns with symbol "B" (which is introduced from CLDR v32.0.0) which isn't supported in DateFormat yet
978
+ if (sTestSkeleton === "intervalFormatFallback" || sTestSkeleton.indexOf("B") > -1) {
979
+ continue;
980
+ }
981
+ aTestTokens = this._parseSkeletonFormat(sTestSkeleton);
982
+ iDistance = 0;
983
+ aMissingTokens = [];
984
+ bMatch = true;
985
+ // if test format contains more tokens, it cannot be a best match
986
+ if (aTokens.length < aTestTokens.length) {
987
+ continue;
988
+ }
989
+ iTest = 0;
990
+ iFirstDiffPos = aTokens.length;
991
+ for (var i = 0; i < aTokens.length; i++) {
992
+ oToken = aTokens[i];
993
+ oTestToken = aTestTokens[iTest];
994
+ if (iFirstDiffPos === aTokens.length) {
995
+ iFirstDiffPos = i;
762
996
  }
763
- if (oFormats) {
764
- var sName = sNumber + '-' + sPlural;
765
- sFormat = oFormats[sName];
766
- if (!sFormat) {
767
- sName = sNumber + '-other';
768
- sFormat = oFormats[sName];
997
+ if (oTestToken) {
998
+ oTokenSymbol = mCLDRSymbols[oToken.symbol];
999
+ oTestTokenSymbol = mCLDRSymbols[oTestToken.symbol];
1000
+ // if the symbol matches, just add the length difference to the distance
1001
+ if (oToken.symbol === oTestToken.symbol) {
1002
+ if (oToken.length === oTestToken.length) {
1003
+ // both symbol and length match, check the next token
1004
+ // clear the first difference position
1005
+ if (iFirstDiffPos === i) {
1006
+ iFirstDiffPos = aTokens.length;
1007
+ }
1008
+ } else {
1009
+ if (oToken.length < oTokenSymbol.numericCeiling ? oTestToken.length < oTestTokenSymbol.numericCeiling : oTestToken.length >= oTestTokenSymbol.numericCeiling) {
1010
+ // if the symbols are in the same category (either numeric or text representation), add the length diff
1011
+ iDistance += Math.abs(oToken.length - oTestToken.length);
1012
+ } else {
1013
+ // otherwise add 5 which is bigger than any length difference
1014
+ iDistance += 5;
1015
+ }
769
1016
  }
770
- }
771
- return sFormat;
772
- },
773
- getListFormat: function (sType, sStyle) {
774
- var oFormats = this._get('listPattern-' + (sType || 'standard') + '-' + (sStyle || 'wide'));
775
- if (oFormats) {
776
- return oFormats;
777
- }
778
- return {};
779
- },
780
- getResolvedUnitFormat: function (sUnit) {
781
- sUnit = this.getUnitFromMapping(sUnit) || sUnit;
782
- return this.getUnitFormat(sUnit);
783
- },
784
- getUnitFormat: function (sUnit) {
785
- var oResult = this._get('units', 'short', sUnit);
786
- if (!oResult && mLegacyUnit2CurrentUnit[sUnit]) {
787
- oResult = this._get('units', 'short', mLegacyUnit2CurrentUnit[sUnit]);
788
- }
789
- return oResult;
790
- },
791
- getUnitFormats: function () {
792
- return this._getMerged('units', 'short');
793
- },
794
- getUnitFromMapping: function (sMapping) {
795
- return this._get('unitMappings', sMapping);
796
- },
797
- getEras: function (sWidth, sCalendarType) {
798
- assert(sWidth == 'wide' || sWidth == 'abbreviated' || sWidth == 'narrow', 'sWidth must be wide, abbreviate or narrow');
799
- var oEras = this._get(getCLDRCalendarName(sCalendarType), 'era-' + sWidth), aEras = [];
800
- for (var i in oEras) {
801
- aEras[parseInt(i)] = oEras[i];
802
- }
803
- return aEras;
804
- },
805
- getEraDates: function (sCalendarType) {
806
- var oEraDates = this._get('eras-' + sCalendarType.toLowerCase()), aEraDates = [];
807
- for (var i in oEraDates) {
808
- aEraDates[parseInt(i)] = oEraDates[i];
809
- }
810
- return aEraDates;
811
- },
812
- getCalendarWeek: function (sStyle, iWeekNumber) {
813
- assert(sStyle == 'wide' || sStyle == 'narrow', 'sStyle must be wide or narrow');
814
- var oMessageBundle = Core.getLibraryResourceBundle('sap.ui.core', this.oLocale.toString()), sKey = 'date.week.calendarweek.' + sStyle;
815
- return oMessageBundle.getText(sKey, iWeekNumber);
816
- },
817
- firstDayStartsFirstWeek: function () {
818
- return this.oLocale.getLanguage() === 'en' && this.oLocale.getRegion() === 'US';
819
- },
820
- getPreferredCalendarType: function () {
821
- var sCalendarName, sType, i, aCalendars = this._get('calendarPreference') || [];
822
- for (i = 0; i < aCalendars.length; i++) {
823
- sCalendarName = aCalendars[i].split('-')[0];
824
- for (sType in CalendarType) {
825
- if (sCalendarName === sType.toLowerCase()) {
826
- return sType;
827
- }
1017
+ iTest++;
1018
+ continue;
1019
+ } else {
1020
+ // if only the group matches, add some more distance in addition to length difference
1021
+ if (oToken.match == oTestToken.match) {
1022
+ iDistance += Math.abs(oToken.length - oTestToken.length) + 10;
1023
+ iTest++;
1024
+ continue;
828
1025
  }
1026
+ }
829
1027
  }
830
- return CalendarType.Gregorian;
831
- },
832
- getPreferredHourSymbol: function () {
833
- return this._get('timeData', '_preferred');
834
- },
835
- getPluralCategories: function () {
836
- var oPlurals = this._get('plurals'), aCategories = Object.keys(oPlurals);
837
- aCategories.push('other');
838
- return aCategories;
839
- },
840
- getPluralCategory: function (sNumber) {
841
- var oPlurals = this._get('plurals');
842
- if (typeof sNumber === 'number') {
843
- sNumber = sNumber.toString();
844
- }
845
- if (!this._pluralTest) {
846
- this._pluralTest = {};
847
- }
848
- for (var sCategory in oPlurals) {
849
- var fnTest = this._pluralTest[sCategory];
850
- if (!fnTest) {
851
- fnTest = this._parsePluralRule(oPlurals[sCategory]);
852
- this._pluralTest[sCategory] = fnTest;
853
- }
854
- if (fnTest(sNumber).bMatch) {
855
- return sCategory;
1028
+ // if neither symbol nor group matched, add it to the missing tokens and add distance
1029
+ aMissingTokens.push(oToken);
1030
+ iDistance += 50 - i;
1031
+ }
1032
+
1033
+ // if not all test tokens have been found, the format does not match
1034
+ if (iTest < aTestTokens.length) {
1035
+ bMatch = false;
1036
+ }
1037
+
1038
+ // The current pattern is saved as the best pattern when there is a match and
1039
+ // 1. the distance is smaller than the best distance or
1040
+ // 2. the distance equals the best distance and the position of the token in the given skeleton which
1041
+ // isn't the same between the given skeleton and the available skeleton is bigger than the best one's.
1042
+ if (bMatch && (iDistance < oBestMatch.distance || iDistance === oBestMatch.distance && iFirstDiffPos > oBestMatch.firstDiffPos)) {
1043
+ oBestMatch.distance = iDistance;
1044
+ oBestMatch.firstDiffPos = iFirstDiffPos;
1045
+ oBestMatch.missingTokens = aMissingTokens;
1046
+ oBestMatch.pattern = oAvailableFormats[sTestSkeleton];
1047
+ oBestMatch.patternTokens = aTestTokens;
1048
+ }
1049
+ }
1050
+ if (oBestMatch.pattern) {
1051
+ return oBestMatch;
1052
+ }
1053
+ },
1054
+ _expandFields: function (vPattern, aPatternTokens, aTokens) {
1055
+ var bSinglePattern = typeof vPattern === "string";
1056
+ var aPatterns;
1057
+ if (bSinglePattern) {
1058
+ aPatterns = [vPattern];
1059
+ } else {
1060
+ aPatterns = vPattern;
1061
+ }
1062
+ var aResult = aPatterns.map(function (sPattern) {
1063
+ var mGroups = {},
1064
+ mPatternGroups = {},
1065
+ sResultPatterm = "",
1066
+ bQuoted = false,
1067
+ i = 0,
1068
+ iSkeletonLength,
1069
+ iPatternLength,
1070
+ iBestLength,
1071
+ iNewLength,
1072
+ oSkeletonToken,
1073
+ oBestToken,
1074
+ oSymbol,
1075
+ sChar;
1076
+
1077
+ // Create a map of group names to token
1078
+ aTokens.forEach(function (oToken) {
1079
+ mGroups[oToken.group] = oToken;
1080
+ });
1081
+ // Create a map of group names to token in best pattern
1082
+ aPatternTokens.forEach(function (oToken) {
1083
+ mPatternGroups[oToken.group] = oToken;
1084
+ });
1085
+ // Loop through pattern and adjust symbol length
1086
+ while (i < sPattern.length) {
1087
+ sChar = sPattern.charAt(i);
1088
+ if (bQuoted) {
1089
+ sResultPatterm += sChar;
1090
+ if (sChar == "'") {
1091
+ bQuoted = false;
1092
+ }
1093
+ } else {
1094
+ oSymbol = mCLDRSymbols[sChar];
1095
+ // If symbol is a CLDR symbol and is contained in the group, expand length
1096
+ if (oSymbol && mGroups[oSymbol.group] && mPatternGroups[oSymbol.group]) {
1097
+ oSkeletonToken = mGroups[oSymbol.group];
1098
+ oBestToken = mPatternGroups[oSymbol.group];
1099
+ iSkeletonLength = oSkeletonToken.length;
1100
+ iBestLength = oBestToken.length;
1101
+ iPatternLength = 1;
1102
+ while (sPattern.charAt(i + 1) == sChar) {
1103
+ i++;
1104
+ iPatternLength++;
856
1105
  }
857
- }
858
- return 'other';
859
- },
860
- _parsePluralRule: function (sRule) {
861
- var OP_OR = 'or', OP_AND = 'and', OP_MOD = '%', OP_EQ = '=', OP_NEQ = '!=', OPD_N = 'n', OPD_I = 'i', OPD_F = 'f', OPD_T = 't', OPD_V = 'v', OPD_W = 'w', OPD_C = 'c', OPD_E = 'e', RANGE = '..', SEP = ',';
862
- var i = 0, aTokens;
863
- aTokens = sRule.split(' ');
864
- function accept(sToken) {
865
- if (aTokens[i] === sToken) {
866
- i++;
867
- return true;
1106
+
1107
+ // Prevent expanding the length of the field when:
1108
+ // 1. The length in the best matching skeleton (iBestLength) matches the length of the application provided skeleton (iSkeletonLength) or
1109
+ // 2. The length of the provided skeleton (iSkeletonLength) and the length of the result pattern (iPatternLength) are not in the same category (numeric or text)
1110
+ // because switching between numeric to text representation is wrong in all cases
1111
+ if (iSkeletonLength === iBestLength || (iSkeletonLength < oSymbol.numericCeiling ? iPatternLength >= oSymbol.numericCeiling : iPatternLength < oSymbol.numericCeiling)) {
1112
+ iNewLength = iPatternLength;
1113
+ } else {
1114
+ iNewLength = Math.max(iPatternLength, iSkeletonLength);
868
1115
  }
869
- return false;
870
- }
871
- function consume() {
872
- var sToken = aTokens[i];
873
- i++;
874
- return sToken;
875
- }
876
- function or_condition() {
877
- var fnAnd, fnOr;
878
- fnAnd = and_condition();
879
- if (accept(OP_OR)) {
880
- fnOr = or_condition();
881
- return function (o) {
882
- return fnAnd(o) || fnOr(o);
883
- };
1116
+ for (var j = 0; j < iNewLength; j++) {
1117
+ sResultPatterm += sChar;
884
1118
  }
885
- return fnAnd;
886
- }
887
- function and_condition() {
888
- var fnRelation, fnAnd;
889
- fnRelation = relation();
890
- if (accept(OP_AND)) {
891
- fnAnd = and_condition();
892
- return function (o) {
893
- return fnRelation(o) && fnAnd(o);
894
- };
1119
+ } else {
1120
+ sResultPatterm += sChar;
1121
+ if (sChar == "'") {
1122
+ bQuoted = true;
895
1123
  }
896
- return fnRelation;
1124
+ }
897
1125
  }
898
- function relation() {
899
- var fnExpr, fnRangeList, bEq;
900
- fnExpr = expr();
901
- if (accept(OP_EQ)) {
902
- bEq = true;
903
- } else if (accept(OP_NEQ)) {
904
- bEq = false;
905
- } else {
906
- throw new Error('Expected \'=\' or \'!=\'');
907
- }
908
- fnRangeList = range_list();
909
- if (bEq) {
910
- return function (o) {
911
- return fnRangeList(o).indexOf(fnExpr(o)) >= 0;
912
- };
913
- } else {
914
- return function (o) {
915
- return fnRangeList(o).indexOf(fnExpr(o)) === -1;
916
- };
917
- }
1126
+ i++;
1127
+ }
1128
+ return sResultPatterm;
1129
+ });
1130
+ return bSinglePattern ? aResult[0] : aResult;
1131
+ },
1132
+ _appendItems: function (aPatterns, aMissingTokens, sCalendarType) {
1133
+ var oAppendItems = this._get(getCLDRCalendarName(sCalendarType), "dateTimeFormats", "appendItems");
1134
+ aPatterns.forEach(function (sPattern, iIndex) {
1135
+ var sDisplayName, sAppendPattern, sAppendField;
1136
+ aMissingTokens.forEach(function (oToken) {
1137
+ sAppendPattern = oAppendItems[oToken.group];
1138
+ sDisplayName = "'" + this.getDisplayName(oToken.field) + "'";
1139
+ sAppendField = "";
1140
+ for (var i = 0; i < oToken.length; i++) {
1141
+ sAppendField += oToken.symbol;
918
1142
  }
919
- function expr() {
920
- var fnOperand;
921
- fnOperand = operand();
922
- if (accept(OP_MOD)) {
923
- var iDivisor = parseInt(consume());
924
- return function (o) {
925
- return fnOperand(o) % iDivisor;
926
- };
927
- }
928
- return fnOperand;
1143
+ aPatterns[iIndex] = sAppendPattern.replace(/\{0\}/, sPattern).replace(/\{1\}/, sAppendField).replace(/\{2\}/, sDisplayName);
1144
+ }.bind(this));
1145
+ }.bind(this));
1146
+ return aPatterns;
1147
+ },
1148
+ _getMixedFormatPattern: function (sSkeleton, oAvailableFormats, sCalendarType, vDiff) {
1149
+ var rMixedSkeleton = /^([GyYqQMLwWEecdD]+)([hHkKjJmszZvVOXx]+)$/,
1150
+ rWideMonth = /MMMM|LLLL/,
1151
+ rAbbrevMonth = /MMM|LLL/,
1152
+ rWeekDay = /E|e|c/,
1153
+ oResult,
1154
+ sDateSkeleton,
1155
+ sTimeSkeleton,
1156
+ sStyle,
1157
+ sDatePattern,
1158
+ sTimePattern,
1159
+ sDateTimePattern,
1160
+ sResultPattern;
1161
+
1162
+ // Split skeleton into date and time part
1163
+ oResult = rMixedSkeleton.exec(sSkeleton);
1164
+ sDateSkeleton = oResult[1];
1165
+ sTimeSkeleton = oResult[2];
1166
+ // Get patterns for date and time separately
1167
+ sDatePattern = this._getFormatPattern(sDateSkeleton, oAvailableFormats, sCalendarType);
1168
+ if (vDiff) {
1169
+ sTimePattern = this.getCustomIntervalPattern(sTimeSkeleton, vDiff, sCalendarType);
1170
+ } else {
1171
+ sTimePattern = this._getFormatPattern(sTimeSkeleton, oAvailableFormats, sCalendarType);
1172
+ }
1173
+ // Combine patterns with datetime pattern, dependent on month and weekday
1174
+ if (rWideMonth.test(sDateSkeleton)) {
1175
+ sStyle = rWeekDay.test(sDateSkeleton) ? "full" : "long";
1176
+ } else if (rAbbrevMonth.test(sDateSkeleton)) {
1177
+ sStyle = "medium";
1178
+ } else {
1179
+ sStyle = "short";
1180
+ }
1181
+ sDateTimePattern = this.getDateTimePattern(sStyle, sCalendarType);
1182
+ sResultPattern = sDateTimePattern.replace(/\{1\}/, sDatePattern).replace(/\{0\}/, sTimePattern);
1183
+ return sResultPattern;
1184
+ },
1185
+ /**
1186
+ * Get number symbol for the given type.
1187
+ *
1188
+ * @param {"decimal"|"group"|"minusSign"|"percentSign"|"plusSign"} sType the required type of symbol
1189
+ * @returns {string} the selected number symbol
1190
+ * @public
1191
+ */
1192
+ getNumberSymbol: function (sType) {
1193
+ assert(sType == "decimal" || sType == "group" || sType == "plusSign" || sType == "minusSign" || sType == "percentSign", "sType must be decimal, group, plusSign, minusSign or percentSign");
1194
+ return this._get("symbols-latn-" + sType);
1195
+ },
1196
+ /**
1197
+ * Get lenient symbols for the sign of a number for the given symbol type.
1198
+ *
1199
+ * @param {"minusSign"|"plusSign"} sType the required type of symbol
1200
+ * @returns {string} the selected lenient symbols for the sign of a number, e.g. "-‒⁻₋−➖﹣"
1201
+ * @public
1202
+ */
1203
+ getLenientNumberSymbols: function (sType) {
1204
+ assert(sType == "plusSign" || sType == "minusSign", "sType must be plusSign or minusSign");
1205
+ return this._get("lenient-scope-number")[sType];
1206
+ },
1207
+ /**
1208
+ * Get decimal format pattern.
1209
+ *
1210
+ * @returns {string} The pattern
1211
+ * @public
1212
+ */
1213
+ getDecimalPattern: function () {
1214
+ return this._get("decimalFormat").standard;
1215
+ },
1216
+ /**
1217
+ * Gets the currency format pattern for the given context or selects an alternative pattern if desired.
1218
+ *
1219
+ * CLDR format pattern:
1220
+ *
1221
+ * @example standard with currency symbol in front of the number
1222
+ * ¤#,##0.00
1223
+ * $100,000.00
1224
+ * $-100,000.00
1225
+ *
1226
+ * @example accounting with negative number pattern after the semicolon
1227
+ * ¤#,##0.00;(¤#,##0.00)
1228
+ * $100,000.00
1229
+ * ($100,000.00)
1230
+ *
1231
+ * @see https://cldr.unicode.org/translation/numbers-currency/number-patterns
1232
+ *
1233
+ * @param {"accounting"|"sap-accounting"|"sap-standard"|"standard"} sContext
1234
+ * The context of the currency pattern; "sap-" prefix is used for the trailing currency code variant
1235
+ * @param {"alphaNextToNumber"|"noCurrency"} [sAlternative]
1236
+ * The alternate currency pattern; since 1.133.0
1237
+ * @returns {string|undefined}
1238
+ * The currency format pattern for the given parameters; <code>undefined</code> if no corresponding pattern is
1239
+ * found
1240
+ *
1241
+ * @public
1242
+ */
1243
+ getCurrencyPattern: function (sContext, sAlternative) {
1244
+ return this._get("currencyFormat")[sAlternative ? sContext + "-" + sAlternative : sContext];
1245
+ },
1246
+ /**
1247
+ * Get percent format pattern.
1248
+ *
1249
+ * @returns {string} The pattern
1250
+ * @public
1251
+ */
1252
+ getPercentPattern: function () {
1253
+ return this._get("percentFormat").standard;
1254
+ },
1255
+ /**
1256
+ * Get miscellaneous pattern for the given name.
1257
+ *
1258
+ * @param {"approximately"|"atLeast"|"atMost"|"range"} sName the name of the misc pattern
1259
+ * @returns {string} The pattern
1260
+ * @public
1261
+ */
1262
+ getMiscPattern: function (sName) {
1263
+ assert(sName == "approximately" || sName == "atLeast" || sName == "atMost" || sName == "range", "sName must be approximately, atLeast, atMost or range");
1264
+ return this._get("miscPattern")[sName];
1265
+ },
1266
+ /**
1267
+ * Returns the required minimal number of days for the first week of a year.
1268
+ *
1269
+ * This is the minimal number of days of the week which must be contained in the new year
1270
+ * for the week to become the first week of the year. Depending on the country, this
1271
+ * is just a single day (in the US) or at least 4 days (in most of Europe).
1272
+ *
1273
+ * All week data information in the CLDR is provided for territories (countries).
1274
+ * If the locale of this LocaleData doesn't contain country information (e.g. if it
1275
+ * contains only a language), then the "likelySubtag" information of the CLDR
1276
+ * is taken into account to guess the "most likely" territory for the locale.
1277
+ *
1278
+ * @returns {int} minimal number of days
1279
+ * @public
1280
+ */
1281
+ getMinimalDaysInFirstWeek: function () {
1282
+ return this._get("weekData-minDays");
1283
+ },
1284
+ /**
1285
+ * Returns the day that usually is regarded as the first day
1286
+ * of a week in the current locale.
1287
+ *
1288
+ * Days are encoded as integer where Sunday=0, Monday=1 etc.
1289
+ *
1290
+ * All week data information in the CLDR is provided for territories (countries).
1291
+ * If the locale of this LocaleData doesn't contain country information (e.g. if it
1292
+ * contains only a language), then the "likelySubtag" information of the CLDR
1293
+ * is taken into account to guess the "most likely" territory for the locale.
1294
+ *
1295
+ * @returns {int} first day of week
1296
+ * @public
1297
+ */
1298
+ getFirstDayOfWeek: function () {
1299
+ return this._get("weekData-firstDay");
1300
+ },
1301
+ /**
1302
+ * Returns the first day of a weekend for the given locale.
1303
+ *
1304
+ * Days are encoded in the same way as for {@link #getFirstDayOfWeek}.
1305
+ *
1306
+ * All week data information in the CLDR is provided for territories (countries).
1307
+ * If the locale of this LocaleData doesn't contain country information (e.g. if it
1308
+ * contains only a language), then the "likelySubtag" information of the CLDR
1309
+ * is taken into account to guess the "most likely" territory for the locale.
1310
+ *
1311
+ * @returns {int} first day of weekend
1312
+ * @public
1313
+ */
1314
+ getWeekendStart: function () {
1315
+ return this._get("weekData-weekendStart");
1316
+ },
1317
+ /**
1318
+ * Returns the last day of a weekend for the given locale.
1319
+ *
1320
+ * Days are encoded in the same way as for {@link #getFirstDayOfWeek}.
1321
+ *
1322
+ * All week data information in the CLDR is provided for territories (countries).
1323
+ * If the locale of this LocaleData doesn't contain country information (e.g. if it
1324
+ * contains only a language), then the "likelySubtag" information of the CLDR
1325
+ * is taken into account to guess the "most likely" territory for the locale.
1326
+ *
1327
+ * @returns {int} last day of weekend
1328
+ * @public
1329
+ */
1330
+ getWeekendEnd: function () {
1331
+ return this._get("weekData-weekendEnd");
1332
+ },
1333
+ /**
1334
+ * Returns a map of custom currency codes, defined via global configuration.
1335
+ * @returns {object} map of custom currency codes, e.g.
1336
+ * {
1337
+ * "AUD": "AUD",
1338
+ * "BRL": "BRL",
1339
+ * "EUR": "EUR",
1340
+ * "GBP": "GBP",
1341
+ * }
1342
+ * @private
1343
+ * @ui5-restricted sap.ui.core.format.NumberFormat
1344
+ * @since 1.63
1345
+ */
1346
+ getCustomCurrencyCodes: function () {
1347
+ var mCustomCurrencies = this._get("currency") || {},
1348
+ mCustomCurrencyCodes = {};
1349
+ Object.keys(mCustomCurrencies).forEach(function (sCurrencyKey) {
1350
+ mCustomCurrencyCodes[sCurrencyKey] = sCurrencyKey;
1351
+ });
1352
+ return mCustomCurrencyCodes;
1353
+ },
1354
+ /**
1355
+ * Returns the number of digits of the given currency considering a custom currency first and falling
1356
+ * back to the CLDR data if no custom currency is defined.
1357
+ *
1358
+ * @param {string} sCurrency The ISO 4217 currency code
1359
+ * @returns {int} The number of digits for the given currency
1360
+ * @public
1361
+ * @since 1.21.1
1362
+ */
1363
+ getCurrencyDigits: function (sCurrency) {
1364
+ const mCurrencyDigits = this.getAllCurrencyDigits();
1365
+ return mCurrencyDigits[sCurrency] ?? mCurrencyDigits["DEFAULT"];
1366
+ },
1367
+ /**
1368
+ * Returns a language dependent map of ISO 4217 currency codes to the number of digits from the CLDR. The map
1369
+ * only contains currency codes for which the number of digits deviates from the value with the key
1370
+ * <code>DEFAULT</code>. If custom currencies are defined which contain the key <code>DEFAULT</code>, only the
1371
+ * custom currencies are used to create the map of currency codes to the number of digits and the map from
1372
+ * CLDR is ignored.
1373
+ * If custom currencies are defined which do <em>not</em> contain the key <code>DEFAULT</code>, they are merged
1374
+ * into the map from CLDR overwriting the CLDR values.
1375
+ *
1376
+ * @returns {Object<string, number>} The map of currency codes to the number of digits
1377
+ * @private
1378
+ * @ui5-restricted sap.ui.export.Spreadsheet
1379
+ * @since 1.135
1380
+ */
1381
+ getAllCurrencyDigits() {
1382
+ const mCustomCurrencies = this._get("currency");
1383
+ const mCurrencyDigits = mCustomCurrencies?.["DEFAULT"] ? {} : {
1384
+ ...this._get("currencyDigits")
1385
+ };
1386
+ if (mCustomCurrencies) {
1387
+ for (const sCurrencyCode in mCustomCurrencies) {
1388
+ if (mCustomCurrencies[sCurrencyCode].digits !== undefined) {
1389
+ mCurrencyDigits[sCurrencyCode] = mCustomCurrencies[sCurrencyCode].digits;
929
1390
  }
930
- function operand() {
931
- if (accept(OPD_N)) {
932
- return function (o) {
933
- return o.n;
934
- };
935
- } else if (accept(OPD_I)) {
936
- return function (o) {
937
- return o.i;
938
- };
939
- } else if (accept(OPD_F)) {
940
- return function (o) {
941
- return o.f;
942
- };
943
- } else if (accept(OPD_T)) {
944
- return function (o) {
945
- return o.t;
946
- };
947
- } else if (accept(OPD_V)) {
948
- return function (o) {
949
- return o.v;
950
- };
951
- } else if (accept(OPD_W)) {
952
- return function (o) {
953
- return o.w;
954
- };
955
- } else if (accept(OPD_C)) {
956
- return function (o) {
957
- return o.c;
958
- };
959
- } else if (accept(OPD_E)) {
960
- return function (o) {
961
- return o.c;
962
- };
963
- } else {
964
- throw new Error('Unknown operand: ' + consume());
1391
+ }
1392
+ }
1393
+ return mCurrencyDigits;
1394
+ },
1395
+ /**
1396
+ * Returns the currency symbol for the specified currency, if no symbol is found the ISO 4217 currency code is returned.
1397
+ *
1398
+ * @param {string} sCurrency ISO 4217 currency code
1399
+ * @returns {string} the currency symbol
1400
+ * @public
1401
+ * @since 1.21.1
1402
+ */
1403
+ getCurrencySymbol: function (sCurrency) {
1404
+ var oCurrencySymbols = this.getCurrencySymbols();
1405
+ return oCurrencySymbols && oCurrencySymbols[sCurrency] || sCurrency;
1406
+ },
1407
+ /**
1408
+ * Returns the currency code which is corresponded with the given currency symbol.
1409
+ *
1410
+ * @param {string} sCurrencySymbol The currency symbol which needs to be converted to currency code
1411
+ * @return {string} The corresponded currency code defined for the given currency symbol. The given currency symbol is returned if no currency code can be found by using the given currency symbol.
1412
+ * @public
1413
+ * @since 1.27.0
1414
+ */
1415
+ getCurrencyCodeBySymbol: function (sCurrencySymbol) {
1416
+ var oCurrencySymbols = this._get("currencySymbols"),
1417
+ sCurrencyCode;
1418
+ for (sCurrencyCode in oCurrencySymbols) {
1419
+ if (oCurrencySymbols[sCurrencyCode] === sCurrencySymbol) {
1420
+ return sCurrencyCode;
1421
+ }
1422
+ }
1423
+ return sCurrencySymbol;
1424
+ },
1425
+ /**
1426
+ * Returns the currency symbols available for this locale.
1427
+ * Currency symbols get accumulated by custom currency symbols.
1428
+ *
1429
+ * @returns {Object<string, string>} the map of all currency symbols available in this locale, e.g.
1430
+ * {
1431
+ * "AUD": "A$",
1432
+ * "BRL": "R$",
1433
+ * "EUR": "€",
1434
+ * "GBP": "£",
1435
+ * }
1436
+ * @public
1437
+ * @since 1.60
1438
+ */
1439
+ getCurrencySymbols: function () {
1440
+ // Lookup into global Config
1441
+ var mCustomCurrencies = this._get("currency"),
1442
+ mCustomCurrencySymbols = {},
1443
+ sIsoCode;
1444
+ for (var sCurrencyKey in mCustomCurrencies) {
1445
+ sIsoCode = mCustomCurrencies[sCurrencyKey].isoCode;
1446
+ if (mCustomCurrencies[sCurrencyKey].symbol) {
1447
+ mCustomCurrencySymbols[sCurrencyKey] = mCustomCurrencies[sCurrencyKey].symbol;
1448
+ } else if (sIsoCode) {
1449
+ mCustomCurrencySymbols[sCurrencyKey] = this._get("currencySymbols")[sIsoCode];
1450
+ }
1451
+ }
1452
+ return Object.assign({}, this._get("currencySymbols"), mCustomCurrencySymbols);
1453
+ },
1454
+ /**
1455
+ * Retrieves the localized display name of a unit by sUnit, e.g. "duration-hour".
1456
+ * @param {string} sUnit the unit key, e.g. "duration-hour"
1457
+ * @return {string} The localized display name for the requested unit, e.g. <code>"Hour"</code>. Return empty string <code>""</code> if not found
1458
+ * @public
1459
+ * @since 1.54
1460
+ */
1461
+ getUnitDisplayName: function (sUnit) {
1462
+ var mUnitFormat = this.getUnitFormat(sUnit);
1463
+ return mUnitFormat && mUnitFormat["displayName"] || "";
1464
+ },
1465
+ /**
1466
+ * @typedef {object} sap.ui.core.LocaleData.RelativeTimePattern
1467
+ *
1468
+ * A relative time pattern.
1469
+ *
1470
+ * @property {string} pattern
1471
+ * The string with the locale-specific representation of the relative time pattern
1472
+ * @property {"day"|"hour"|"minute"|"month"|"second"|"week"|"year"} scale
1473
+ * The scale of the pattern
1474
+ * @property {number} sign
1475
+ * <code>-1</code>, if the pattern is for the past; <code>1</code> otherwise
1476
+ *
1477
+ * @public
1478
+ */
1479
+
1480
+ /**
1481
+ * Returns relative time patterns for the given scales as an array of objects containing scale, value and pattern.
1482
+ *
1483
+ * The array may contain the following values: "year", "month", "week", "day", "hour", "minute" and "second". If
1484
+ * no scales are given, patterns for all available scales will be returned.
1485
+ *
1486
+ * The return array will contain objects looking like:
1487
+ * <pre>
1488
+ * {
1489
+ * scale: "minute",
1490
+ * sign: 1,
1491
+ * pattern: "in {0} minutes"
1492
+ * }
1493
+ * </pre>
1494
+ *
1495
+ * @param {Array<"day"|"hour"|"minute"|"month"|"second"|"week"|"year">} aScales The scales for which the available patterns should be returned
1496
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1497
+ * Since 1.32.10 and 1.34.4, the style of the scale patterns
1498
+ * @returns {Array<sap.ui.core.LocaleData.RelativeTimePattern>} An array of all relative time patterns
1499
+ * @public
1500
+ * @since 1.34
1501
+ */
1502
+ getRelativePatterns: function (aScales, sStyle) {
1503
+ if (sStyle === undefined) {
1504
+ sStyle = "wide";
1505
+ }
1506
+ assert(sStyle === "wide" || sStyle === "short" || sStyle === "narrow", "sStyle is only allowed to be set with 'wide', 'short' or 'narrow'");
1507
+ var aPatterns = [],
1508
+ aPluralCategories = this.getPluralCategories(),
1509
+ oScale,
1510
+ oTimeEntry,
1511
+ iValue,
1512
+ iSign;
1513
+ if (!aScales) {
1514
+ aScales = ["year", "month", "week", "day", "hour", "minute", "second"];
1515
+ }
1516
+ aScales.forEach(function (sScale) {
1517
+ oScale = this._get("dateFields", sScale + "-" + sStyle);
1518
+ for (var sEntry in oScale) {
1519
+ if (sEntry.indexOf("relative-type-") === 0) {
1520
+ iValue = parseInt(sEntry.substr(14));
1521
+ aPatterns.push({
1522
+ scale: sScale,
1523
+ value: iValue,
1524
+ pattern: oScale[sEntry]
1525
+ });
1526
+ } else if (sEntry.indexOf("relativeTime-type-") == 0) {
1527
+ oTimeEntry = oScale[sEntry];
1528
+ iSign = sEntry.substr(18) === "past" ? -1 : 1;
1529
+ aPluralCategories.forEach(function (sKey) {
1530
+ // eslint-disable-line no-loop-func
1531
+ var sPattern = oTimeEntry["relativeTimePattern-count-" + sKey];
1532
+ if (sPattern) {
1533
+ aPatterns.push({
1534
+ scale: sScale,
1535
+ sign: iSign,
1536
+ pattern: sPattern
1537
+ });
965
1538
  }
1539
+ });
966
1540
  }
967
- function range_list() {
968
- var aValues = [], sRangeList = consume(), aParts = sRangeList.split(SEP), aRange, iFrom, iTo;
969
- aParts.forEach(function (sPart) {
970
- aRange = sPart.split(RANGE);
971
- if (aRange.length === 1) {
972
- aValues.push(parseInt(sPart));
973
- } else {
974
- iFrom = parseInt(aRange[0]);
975
- iTo = parseInt(aRange[1]);
976
- for (var i = iFrom; i <= iTo; i++) {
977
- aValues.push(i);
978
- }
979
- }
980
- });
981
- return function (o) {
982
- return aValues;
983
- };
984
- }
985
- var fnOr = or_condition();
986
- if (i != aTokens.length) {
987
- throw new Error('Not completely parsed');
1541
+ }
1542
+ }.bind(this));
1543
+ return aPatterns;
1544
+ },
1545
+ /**
1546
+ * Returns the relative format pattern with given scale (year, month, week, ...) and difference value.
1547
+ *
1548
+ * @param {"day"|"hour"|"minute"|"month"|"second"|"week"|"year"} sScale the scale the relative pattern is needed for
1549
+ * @param {int} iDiff the difference in the given scale unit
1550
+ * @param {boolean} [bFuture] whether a future or past pattern should be used
1551
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1552
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1553
+ * @returns {string} the relative format pattern
1554
+ * @public
1555
+ * @since 1.34
1556
+ */
1557
+ getRelativePattern: function (sScale, iDiff, bFuture, sStyle) {
1558
+ var sPattern, oTypes, sKey, sPluralCategory;
1559
+ if (typeof bFuture === "string") {
1560
+ sStyle = bFuture;
1561
+ bFuture = undefined;
1562
+ }
1563
+ if (bFuture === undefined) {
1564
+ bFuture = iDiff > 0;
1565
+ }
1566
+ if (sStyle === undefined) {
1567
+ sStyle = "wide";
1568
+ }
1569
+ assert(sStyle === "wide" || sStyle === "short" || sStyle === "narrow", "sStyle is only allowed to be set with 'wide', 'short' or 'narrow'");
1570
+ sKey = sScale + "-" + sStyle;
1571
+ if (iDiff === 0 || iDiff === -2 || iDiff === 2) {
1572
+ sPattern = this._get("dateFields", sKey, "relative-type-" + iDiff);
1573
+ }
1574
+ if (!sPattern) {
1575
+ oTypes = this._get("dateFields", sKey, "relativeTime-type-" + (bFuture ? "future" : "past"));
1576
+ sPluralCategory = this.getPluralCategory(Math.abs(iDiff).toString());
1577
+ sPattern = oTypes["relativeTimePattern-count-" + sPluralCategory];
1578
+ }
1579
+ return sPattern;
1580
+ },
1581
+ /**
1582
+ * Returns the relative resource pattern with unit 'second' (like now, "in {0} seconds", "{0} seconds ago" under locale 'en') based on the given
1583
+ * difference value (0 means now, positive value means in the future and negative value means in the past).
1584
+ *
1585
+ * @param {int} iDiff the difference in seconds
1586
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1587
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1588
+ * @returns {string} the relative resource pattern in unit 'second'
1589
+ * @public
1590
+ * @since 1.31.0
1591
+ */
1592
+ getRelativeSecond: function (iDiff, sStyle) {
1593
+ return this.getRelativePattern("second", iDiff, sStyle);
1594
+ },
1595
+ /**
1596
+ * Returns the relative resource pattern with unit 'minute' (like "in {0} minute(s)", "{0} minute(s) ago" under locale 'en') based on the given
1597
+ * difference value (positive value means in the future and negative value means in the past).
1598
+ *
1599
+ * There's no pattern defined for 0 difference and the function returns null if 0 is given. In the 0 difference case, you can use the getRelativeSecond
1600
+ * function to format the difference using unit 'second'.
1601
+ *
1602
+ * @param {int} iDiff the difference in minutes
1603
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1604
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1605
+ * @returns {string|null} the relative resource pattern in unit 'minute'. The method returns null if 0 is given as parameter.
1606
+ * @public
1607
+ * @since 1.31.0
1608
+ */
1609
+ getRelativeMinute: function (iDiff, sStyle) {
1610
+ if (iDiff == 0) {
1611
+ return null;
1612
+ }
1613
+ return this.getRelativePattern("minute", iDiff, sStyle);
1614
+ },
1615
+ /**
1616
+ * Returns the relative resource pattern with unit 'hour' (like "in {0} hour(s)", "{0} hour(s) ago" under locale 'en') based on the given
1617
+ * difference value (positive value means in the future and negative value means in the past).
1618
+ *
1619
+ * There's no pattern defined for 0 difference and the function returns null if 0 is given. In the 0 difference case, you can use the getRelativeMinute or getRelativeSecond
1620
+ * function to format the difference using unit 'minute' or 'second'.
1621
+ *
1622
+ * @param {int} iDiff the difference in hours
1623
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1624
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1625
+ * @returns {string|null} the relative resource pattern in unit 'hour'. The method returns null if 0 is given as parameter.
1626
+ * @public
1627
+ * @since 1.31.0
1628
+ */
1629
+ getRelativeHour: function (iDiff, sStyle) {
1630
+ if (iDiff == 0) {
1631
+ return null;
1632
+ }
1633
+ return this.getRelativePattern("hour", iDiff, sStyle);
1634
+ },
1635
+ /**
1636
+ * Returns the relative day resource pattern (like "Today", "Yesterday", "{0} days ago") based on the given
1637
+ * difference of days (0 means today, 1 means tomorrow, -1 means yesterday, ...).
1638
+ *
1639
+ * @param {int} iDiff the difference in days
1640
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1641
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1642
+ * @returns {string} the relative day resource pattern
1643
+ * @public
1644
+ * @since 1.25.0
1645
+ */
1646
+ getRelativeDay: function (iDiff, sStyle) {
1647
+ return this.getRelativePattern("day", iDiff, sStyle);
1648
+ },
1649
+ /**
1650
+ * Returns the relative week resource pattern (like "This week", "Last week", "{0} weeks ago") based on the given
1651
+ * difference of weeks (0 means this week, 1 means next week, -1 means last week, ...).
1652
+ *
1653
+ * @param {int} iDiff the difference in weeks
1654
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1655
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1656
+ * @returns {string} the relative week resource pattern
1657
+ * @public
1658
+ * @since 1.31.0
1659
+ */
1660
+ getRelativeWeek: function (iDiff, sStyle) {
1661
+ return this.getRelativePattern("week", iDiff, sStyle);
1662
+ },
1663
+ /**
1664
+ * Returns the relative month resource pattern (like "This month", "Last month", "{0} months ago") based on the given
1665
+ * difference of months (0 means this month, 1 means next month, -1 means last month, ...).
1666
+ *
1667
+ * @param {int} iDiff the difference in months
1668
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1669
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1670
+ * @returns {string} the relative month resource pattern
1671
+ * @public
1672
+ * @since 1.25.0
1673
+ */
1674
+ getRelativeMonth: function (iDiff, sStyle) {
1675
+ return this.getRelativePattern("month", iDiff, sStyle);
1676
+ },
1677
+ /**
1678
+ * Returns the display name for a time unit of the given type.
1679
+ *
1680
+ * @param {"day"|"era"|"hour"|"minute"|"month"|"quarter"|"second"|"week"|"weekday"|"year"|"zone"} sType the type
1681
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1682
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1683
+ * @returns {string} display name
1684
+ * @public
1685
+ * @since 1.34.0
1686
+ */
1687
+ getDisplayName: function (sType, sStyle) {
1688
+ assert(sType == "second" || sType == "minute" || sType == "hour" || sType == "zone" || sType == "day" || sType == "weekday" || sType == "week" || sType == "month" || sType == "quarter" || sType == "year" || sType == "era", "sType must be second, minute, hour, zone, day, weekday, week, month, quarter, year, era");
1689
+ if (sStyle === undefined) {
1690
+ sStyle = "wide";
1691
+ }
1692
+ assert(sStyle === "wide" || sStyle === "short" || sStyle === "narrow", "sStyle is only allowed to be set with 'wide', 'short' or 'narrow'");
1693
+ var aSingleFormFields = ["era", "weekday", "zone"],
1694
+ sKey = aSingleFormFields.indexOf(sType) === -1 ? sType + "-" + sStyle : sType;
1695
+ return this._get("dateFields", sKey, "displayName");
1696
+ },
1697
+ /**
1698
+ * Returns the relative year resource pattern (like "This year", "Last year", "{0} year ago") based on the given
1699
+ * difference of years (0 means this year, 1 means next year, -1 means last year, ...).
1700
+ *
1701
+ * @param {int} iDiff the difference in years
1702
+ * @param {"narrow"|"short"|"wide"} [sStyle="wide"]
1703
+ * Since 1.32.10 and 1.34.4, the style of the pattern
1704
+ * @returns {string} the relative year resource pattern
1705
+ * @public
1706
+ * @since 1.25.0
1707
+ */
1708
+ getRelativeYear: function (iDiff, sStyle) {
1709
+ return this.getRelativePattern("year", iDiff, sStyle);
1710
+ },
1711
+ /**
1712
+ * Returns the compact decimal format pattern (like "000K" or "0M") for the given power of ten in the given
1713
+ * style and plural category, see {@link topic:91f2f2866f4d1014b6dd926db0e91070 Number Format - Compact Format}.
1714
+ *
1715
+ * @param {"long"|"short"|"short-indian"} sStyle
1716
+ * The style
1717
+ * @param {string} sPowerOfTen
1718
+ * The power of ten, for example "1000" or "10000"
1719
+ * @param {"few"|"many"|"one"|"other"|"two"|"zero"} [sPlural="other"]
1720
+ * The plural category; defaults to "other" if the given plural category does not exist for this locale
1721
+ * @returns {string|undefined}
1722
+ * The compact decimal format pattern, or <code>undefined</code> if no decimal format for the given parameters
1723
+ * is found
1724
+ *
1725
+ * @public
1726
+ * @since 1.133.0
1727
+ */
1728
+ getCompactDecimalPattern: function (sStyle, sPowerOfTen, sPlural = "other") {
1729
+ const oFormats = this._get("decimalFormat-" + sStyle);
1730
+ return oFormats && (oFormats[sPowerOfTen + "-" + sPlural] || oFormats[sPowerOfTen + "-other"]);
1731
+ },
1732
+ /**
1733
+ * Returns the compact currency format pattern (like "¤000K" or "¤0M") for the given power of ten in the given
1734
+ * style, plural category, and in an optional alternative format if desired, see
1735
+ * {@link topic:91f2f2866f4d1014b6dd926db0e91070 Number Format - Compact Format}.
1736
+ *
1737
+ * @param {"short"|"sap-short"|"short-indian"|"sap-short-indian"} sStyle
1738
+ * The style; "sap-" prefix is used for the trailing currency code variant
1739
+ * @param {string} sPowerOfTen
1740
+ * The power of ten, for example "1000" or "10000"
1741
+ * @param {"few"|"many"|"one"|"other"|"two"|"zero"} [sPlural="other"]
1742
+ * The plural category; defaults to "other" if the given plural category does not exist for this locale
1743
+ * @param {"alphaNextToNumber"|"noCurrency"} [sAlternative]
1744
+ * The alternate currency format
1745
+ * @returns {string|undefined}
1746
+ * The compact currency format pattern, or <code>undefined</code> if no currency format pattern for the given
1747
+ * parameters is found
1748
+ *
1749
+ * @public
1750
+ * @since 1.133.0
1751
+ */
1752
+ getCompactCurrencyPattern: function (sStyle, sPowerOfTen, sPlural = "other", sAlternative = undefined) {
1753
+ const oFormats = this._get("currencyFormat-" + sStyle);
1754
+ const sAlternativeSuffix = sAlternative ? "-" + sAlternative : "";
1755
+ return oFormats && (oFormats[sPowerOfTen + "-" + sPlural + sAlternativeSuffix] || oFormats[sPowerOfTen + "-other" + sAlternativeSuffix]);
1756
+ },
1757
+ /**
1758
+ * Returns a map containing patterns for formatting lists
1759
+ *
1760
+ *@param {string} [sType='standard'] The type of the list pattern. It can be 'standard' or 'or'.
1761
+ *@param {string} [sStyle='wide'] The style of the list pattern. It can be 'wide' or 'short'.
1762
+ * @return {object} Map with list patterns
1763
+ */
1764
+ getListFormat: function (sType, sStyle) {
1765
+ var oFormats = this._get("listPattern-" + (sType || "standard") + "-" + (sStyle || "wide"));
1766
+ if (oFormats) {
1767
+ return oFormats;
1768
+ }
1769
+ return {};
1770
+ },
1771
+ /**
1772
+ * Retrieves the unit format pattern for a specific unit name considering the unit mappings.
1773
+ *
1774
+ * @example <caption>A unit format pattern which may be returned for the unit "duration-hour"</caption>
1775
+ * {
1776
+ * displayName: "hours",
1777
+ * unitPattern-count-one: "{0} hr",
1778
+ * unitPattern-count-other: "{0} hr",
1779
+ * perUnitPattern: "{0}/h"
1780
+ * }
1781
+ *
1782
+ * @param {string} sUnit unit name, e.g. "duration-hour" or "my"
1783
+ * @return {Object<string, string>}
1784
+ * The unit format pattern for the given unit name as a map from a pattern key like
1785
+ * <code>"unitPattern-count-other"</code> to the corresponding pattern
1786
+ * @public
1787
+ * @since 1.54
1788
+ * @see sap.ui.core.LocaleData#getUnitFromMapping
1789
+ */
1790
+ getResolvedUnitFormat: function (sUnit) {
1791
+ sUnit = this.getUnitFromMapping(sUnit) || sUnit;
1792
+ return this.getUnitFormat(sUnit);
1793
+ },
1794
+ /**
1795
+ * Retrieves the unit format pattern for a specific unit name, see {@link #getResolvedUnitFormat} for an example
1796
+ * of a unit format pattern.
1797
+ *
1798
+ * Note: Does not take unit mapping into consideration.
1799
+ *
1800
+ * @param {string} sUnit unit name, e.g. "duration-hour"
1801
+ * @return {Object<string, string>|undefined}
1802
+ * The unit format pattern for the given unit name as a map from a pattern key like
1803
+ * <code>"unitPattern-count-other"</code> to the corresponding pattern or <code>undefined</code> if no
1804
+ * corresponding pattern is found
1805
+ * @public
1806
+ * @since 1.54
1807
+ */
1808
+ getUnitFormat: function (sUnit) {
1809
+ var oResult = this._get("units", "short", sUnit);
1810
+
1811
+ /** @deprecated As of version 1.122.0, reason mLegacyUnit2CurrentUnit */
1812
+ if (!oResult && mLegacyUnit2CurrentUnit[sUnit]) {
1813
+ oResult = this._get("units", "short", mLegacyUnit2CurrentUnit[sUnit]);
1814
+ }
1815
+ return oResult;
1816
+ },
1817
+ /**
1818
+ * Retrieves unit format patterns for all units see {@link #getResolvedUnitFormat} for an example of a unit
1819
+ * format pattern.
1820
+ *
1821
+ * Note: Does not take unit mapping into consideration.
1822
+ *
1823
+ * @return {Object<string, Object<string, string>>} The unit format patterns as a map from a unit key to a map
1824
+ * from a pattern key like <code>"unitPattern-count-other"</code> to the corresponding pattern
1825
+ * @public
1826
+ * @since 1.54
1827
+ */
1828
+ getUnitFormats: function () {
1829
+ return this._getMerged("units", "short");
1830
+ },
1831
+ /**
1832
+ * Looks up the unit from defined unit mapping.
1833
+ * E.g. for defined unit mapping
1834
+ * <code>
1835
+ * {
1836
+ * "my": "my-custom-unit",
1837
+ * "cm": "length-centimeter"
1838
+ * }
1839
+ * </code>
1840
+ *
1841
+ * Call:
1842
+ * <code>getUnitFromMapping("my")</code> would result in <code>"my-custom-unit"</code>
1843
+ * @param {string} sMapping mapping identifier
1844
+ * @return {string} unit from the mapping
1845
+ * @public
1846
+ * @since 1.54
1847
+ */
1848
+ getUnitFromMapping: function (sMapping) {
1849
+ return this._get("unitMappings", sMapping);
1850
+ },
1851
+ /**
1852
+ * Returns array of eras in the given width.
1853
+ *
1854
+ * @param {"abbreviated"|"narrow"|"wide"} sWidth the width of the era name
1855
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
1856
+ * The type of calendar; defaults to the calendar type either set in configuration or calculated from the
1857
+ * locale
1858
+ * @return {string[]} the array of eras
1859
+ * @public
1860
+ * @since 1.32.0
1861
+ */
1862
+ getEras: function (sWidth, sCalendarType) {
1863
+ assert(sWidth == "wide" || sWidth == "abbreviated" || sWidth == "narrow", "sWidth must be wide, abbreviate or narrow");
1864
+
1865
+ //TODO Adapt generation so that eras are an array instead of object
1866
+ var oEras = this._get(getCLDRCalendarName(sCalendarType), "era-" + sWidth),
1867
+ aEras = [];
1868
+ for (var i in oEras) {
1869
+ aEras[parseInt(i)] = oEras[i];
1870
+ }
1871
+ return aEras;
1872
+ },
1873
+ /**
1874
+ * Returns the map of era IDs to era dates.
1875
+ *
1876
+ * @param {module:sap/base/i18n/date/CalendarType} [sCalendarType]
1877
+ * The type of calendar; defaults to the calendar type either set via the "calendar-type" formatting
1878
+ * configuration option, see {@link topic:91f2d03b6f4d1014b6dd926db0e91070 Configuration Options and URL
1879
+ * Parameters}, or determined from the current locale
1880
+ * @return {object[]} the array of eras containing objects with either an _end or _start property with a date
1881
+ * @public
1882
+ * @since 1.32.0
1883
+ */
1884
+ getEraDates: function (sCalendarType = Formatting.getCalendarType()) {
1885
+ //TODO Adapt generation so that eradates are an array instead of object
1886
+ var oEraDates = this._get("eras-" + sCalendarType.toLowerCase()),
1887
+ aEraDates = [];
1888
+ for (var i in oEraDates) {
1889
+ aEraDates[parseInt(i)] = oEraDates[i];
1890
+ }
1891
+ return aEraDates;
1892
+ },
1893
+ /**
1894
+ * Returns the pattern for representing the calendar week number in the given style. If
1895
+ * <code>iWeekNumber</code> is given, the week number placeholder will be replaced by it.
1896
+ *
1897
+ * @param {"narrow"|"wide"} sStyle The style of the pattern
1898
+ * @param {string} [sWeekNumber] The week number, e.g. "01" or "42"
1899
+ * @returns {string}
1900
+ * The calendar week with the week number placeholder or the week number e.g. "Calendar Week {0}" or "CW 01"
1901
+ *
1902
+ * @public
1903
+ * @since 1.32.0
1904
+ */
1905
+ getCalendarWeek: function (sStyle, iWeekNumber) {
1906
+ assert(sStyle == "wide" || sStyle == "narrow", "sStyle must be wide or narrow");
1907
+ const sText = this._get("sap-calendarWeek")[sStyle];
1908
+ return iWeekNumber ? sText.replace("{0}", iWeekNumber) : sText;
1909
+ },
1910
+ /**
1911
+ * Whether 1 January is the first day of the first calendar week.
1912
+ * This is the definition of the calendar week in the US.
1913
+ *
1914
+ * @return {boolean} true if the first week of the year starts with 1 January.
1915
+ * @public
1916
+ * @since 1.92.0
1917
+ */
1918
+ firstDayStartsFirstWeek: function () {
1919
+ return this.oLocale.getLanguage() === "en" && this.oLocale.getRegion() === "US";
1920
+ },
1921
+ /**
1922
+ * Returns the preferred calendar type for the current locale which exists in
1923
+ * {@link module:sap/base/i18n/date/CalendarType}
1924
+ *
1925
+ * @returns {module:sap/base/i18n/date/CalendarType} the preferred calendar type
1926
+ * @public
1927
+ * @since 1.28.6
1928
+ */
1929
+ getPreferredCalendarType: function () {
1930
+ var sCalendarName,
1931
+ sType,
1932
+ i,
1933
+ aCalendars = this._get("calendarPreference") || [];
1934
+ for (i = 0; i < aCalendars.length; i++) {
1935
+ // No support for calendar subtypes (islamic) yet, so ignore part after -
1936
+ sCalendarName = aCalendars[i].split("-")[0];
1937
+ for (sType in CalendarType) {
1938
+ if (sCalendarName === sType.toLowerCase()) {
1939
+ return sType;
988
1940
  }
989
- return function (sValue) {
990
- var iDotPos, iExponent, sFraction, sFractionNoZeros, sInteger, o, iExponentPos = sValue.search(rEIgnoreCase);
991
- iExponent = iExponentPos < 0 ? 0 : parseInt(sValue.slice(iExponentPos + 1));
992
- sValue = LocaleData.convertToDecimal(sValue);
993
- iDotPos = sValue.indexOf('.');
994
- if (iDotPos === -1) {
995
- sInteger = sValue;
996
- sFraction = '';
997
- sFractionNoZeros = '';
998
- } else {
999
- sInteger = sValue.slice(0, iDotPos);
1000
- sFraction = sValue.slice(iDotPos + 1);
1001
- sFractionNoZeros = sFraction.replace(rTrailingZeroes, '');
1002
- }
1003
- o = {
1004
- n: parseFloat(sValue),
1005
- i: parseInt(sInteger),
1006
- v: sFraction.length,
1007
- w: sFractionNoZeros.length,
1008
- f: sFraction === '' ? 0 : parseInt(sFraction),
1009
- t: sFractionNoZeros === '' ? 0 : parseInt(sFractionNoZeros),
1010
- c: iExponent
1011
- };
1012
- return {
1013
- bMatch: fnOr(o),
1014
- oOperands: o
1015
- };
1941
+ }
1942
+ }
1943
+ return CalendarType.Gregorian;
1944
+ },
1945
+ /**
1946
+ * Returns the preferred hour pattern symbol ("h" for 12, "H" for 24 hours) for the current locale.
1947
+ *
1948
+ * @returns {"h"|"H"} the preferred hour symbol
1949
+ * @public
1950
+ * @since 1.34
1951
+ */
1952
+ getPreferredHourSymbol: function () {
1953
+ return this._get("timeData", "_preferred");
1954
+ },
1955
+ /**
1956
+ * Returns an array of all plural categories available in this language.
1957
+ *
1958
+ * @returns {string[]} The array of plural categories
1959
+ * @public
1960
+ * @since 1.50
1961
+ */
1962
+ getPluralCategories: function () {
1963
+ var oPlurals = this._get("plurals"),
1964
+ aCategories = Object.keys(oPlurals);
1965
+ aCategories.push("other");
1966
+ return aCategories;
1967
+ },
1968
+ /**
1969
+ * Returns the plural category (zero, one, two, few, many or other) for the given number value.
1970
+ * The number must be passed as an unformatted number string with dot as decimal
1971
+ * separator (for example "12345.67"). To determine the correct plural category, it
1972
+ * is also necessary to keep the same number of decimal digits as given in the formatted
1973
+ * output string. For example "1" and "1.0" could be in different plural categories as
1974
+ * the number of decimal digits is different.
1975
+ *
1976
+ * Compact numbers (for example in "short" format) must be provided in the
1977
+ * locale-independent CLDR compact notation. This notation uses the plural rule operand "c"
1978
+ * for the compact decimal exponent, for example "1.2c3" for "1.2K" (1200) or "4c6" for
1979
+ * "4M" (4000000).
1980
+ *
1981
+ * Note that the operand "e" is deprecated, but is a synonym corresponding to the CLDR
1982
+ * specification for "c" and may be redefined in the future.
1983
+ *
1984
+ * @param {string|number} vNumber The number to find the plural category for
1985
+ * @returns {string} The plural category
1986
+ * @public
1987
+ * @since 1.50
1988
+ */
1989
+ getPluralCategory: function (vNumber) {
1990
+ var sNumber = typeof vNumber === "number" ? vNumber.toString() : vNumber,
1991
+ oPlurals = this._get("plurals");
1992
+ if (!this._pluralTest) {
1993
+ this._pluralTest = {};
1994
+ }
1995
+ for (var sCategory in oPlurals) {
1996
+ var fnTest = this._pluralTest[sCategory];
1997
+ if (!fnTest) {
1998
+ fnTest = this._parsePluralRule(oPlurals[sCategory]);
1999
+ this._pluralTest[sCategory] = fnTest;
2000
+ }
2001
+ if (fnTest(sNumber).bMatch) {
2002
+ return sCategory;
2003
+ }
2004
+ }
2005
+ return "other";
2006
+ },
2007
+ /**
2008
+ * Parses a language plural rule as specified in
2009
+ * https://unicode.org/reports/tr35/tr35-numbers.html#table-plural-operand-meanings
2010
+ *
2011
+ * @param {string} sRule The plural rule as a string
2012
+ * @returns {function(string)} A function to determine for a number given as string parameter if it matches the
2013
+ * plural rule.
2014
+ *
2015
+ * @private
2016
+ */
2017
+ _parsePluralRule: function (sRule) {
2018
+ var OP_OR = "or",
2019
+ OP_AND = "and",
2020
+ OP_MOD = "%",
2021
+ OP_EQ = "=",
2022
+ OP_NEQ = "!=",
2023
+ OPD_N = "n",
2024
+ OPD_I = "i",
2025
+ OPD_F = "f",
2026
+ OPD_T = "t",
2027
+ OPD_V = "v",
2028
+ OPD_W = "w",
2029
+ OPD_C = "c",
2030
+ OPD_E = "e",
2031
+ RANGE = "..",
2032
+ SEP = ",";
2033
+ var i = 0,
2034
+ aTokens;
2035
+ aTokens = sRule.split(" ");
2036
+ function accept(sToken) {
2037
+ if (aTokens[i] === sToken) {
2038
+ i++;
2039
+ return true;
2040
+ }
2041
+ return false;
2042
+ }
2043
+ function consume() {
2044
+ var sToken = aTokens[i];
2045
+ i++;
2046
+ return sToken;
2047
+ }
2048
+ function or_condition() {
2049
+ var fnAnd, fnOr;
2050
+ fnAnd = and_condition();
2051
+ if (accept(OP_OR)) {
2052
+ fnOr = or_condition();
2053
+ return function (o) {
2054
+ return fnAnd(o) || fnOr(o);
1016
2055
  };
2056
+ }
2057
+ return fnAnd;
1017
2058
  }
1018
- });
1019
- LocaleData.convertToDecimal = function (vValue) {
1020
- var iIntegerLength, iExponent, iFractionLength, bNegative, iNewIntegerLength, aResult, sValue = String(vValue);
1021
- if (!sValue.includes('e') && !sValue.includes('E')) {
1022
- return sValue;
2059
+ function and_condition() {
2060
+ var fnRelation, fnAnd;
2061
+ fnRelation = relation();
2062
+ if (accept(OP_AND)) {
2063
+ fnAnd = and_condition();
2064
+ return function (o) {
2065
+ return fnRelation(o) && fnAnd(o);
2066
+ };
2067
+ }
2068
+ return fnRelation;
1023
2069
  }
1024
- aResult = sValue.match(rNumberInScientificNotation);
1025
- bNegative = aResult[1] === '-';
1026
- sValue = aResult[2].replace('.', '');
1027
- iIntegerLength = aResult[3] ? aResult[3].length : 0;
1028
- iFractionLength = aResult[4] ? aResult[4].length : 0;
1029
- iExponent = parseInt(aResult[5]);
1030
- iNewIntegerLength = iIntegerLength + iExponent;
1031
- if (iExponent > 0) {
1032
- sValue = iExponent < iFractionLength ? sValue.slice(0, iNewIntegerLength) + '.' + sValue.slice(iNewIntegerLength) : sValue = sValue.padEnd(iNewIntegerLength, '0');
1033
- } else {
1034
- sValue = -iExponent < iIntegerLength ? sValue = sValue.slice(0, iNewIntegerLength) + '.' + sValue.slice(iNewIntegerLength) : sValue = '0.' + sValue.padStart(iFractionLength - iExponent, '0');
2070
+ function relation() {
2071
+ var fnExpr, fnRangeList, bEq;
2072
+ fnExpr = expr();
2073
+ if (accept(OP_EQ)) {
2074
+ bEq = true;
2075
+ } else if (accept(OP_NEQ)) {
2076
+ bEq = false;
2077
+ } else {
2078
+ throw new Error("Expected '=' or '!='");
2079
+ }
2080
+ fnRangeList = range_list();
2081
+ if (bEq) {
2082
+ return function (o) {
2083
+ return fnRangeList(o).indexOf(fnExpr(o)) >= 0;
2084
+ };
2085
+ } else {
2086
+ return function (o) {
2087
+ return fnRangeList(o).indexOf(fnExpr(o)) === -1;
2088
+ };
2089
+ }
1035
2090
  }
1036
- if (bNegative) {
1037
- sValue = '-' + sValue;
2091
+ function expr() {
2092
+ var fnOperand;
2093
+ fnOperand = operand();
2094
+ if (accept(OP_MOD)) {
2095
+ var iDivisor = parseInt(consume());
2096
+ return function (o) {
2097
+ return fnOperand(o) % iDivisor;
2098
+ };
2099
+ }
2100
+ return fnOperand;
1038
2101
  }
2102
+ function operand() {
2103
+ if (accept(OPD_N)) {
2104
+ return function (o) {
2105
+ return o.n;
2106
+ };
2107
+ } else if (accept(OPD_I)) {
2108
+ return function (o) {
2109
+ return o.i;
2110
+ };
2111
+ } else if (accept(OPD_F)) {
2112
+ return function (o) {
2113
+ return o.f;
2114
+ };
2115
+ } else if (accept(OPD_T)) {
2116
+ return function (o) {
2117
+ return o.t;
2118
+ };
2119
+ } else if (accept(OPD_V)) {
2120
+ return function (o) {
2121
+ return o.v;
2122
+ };
2123
+ } else if (accept(OPD_W)) {
2124
+ return function (o) {
2125
+ return o.w;
2126
+ };
2127
+ } else if (accept(OPD_C)) {
2128
+ return function (o) {
2129
+ return o.c;
2130
+ };
2131
+ } else if (accept(OPD_E)) {
2132
+ return function (o) {
2133
+ return o.c; // c is an alias for e
2134
+ };
2135
+ } else {
2136
+ throw new Error("Unknown operand: " + consume());
2137
+ }
2138
+ }
2139
+ function range_list() {
2140
+ var aValues = [],
2141
+ sRangeList = consume(),
2142
+ aParts = sRangeList.split(SEP),
2143
+ aRange,
2144
+ iFrom,
2145
+ iTo;
2146
+ aParts.forEach(function (sPart) {
2147
+ aRange = sPart.split(RANGE);
2148
+ if (aRange.length === 1) {
2149
+ aValues.push(parseInt(sPart));
2150
+ } else {
2151
+ iFrom = parseInt(aRange[0]);
2152
+ iTo = parseInt(aRange[1]);
2153
+ for (var i = iFrom; i <= iTo; i++) {
2154
+ aValues.push(i);
2155
+ }
2156
+ }
2157
+ });
2158
+ return function (o) {
2159
+ return aValues;
2160
+ };
2161
+ }
2162
+ var fnOr = or_condition();
2163
+ if (i != aTokens.length) {
2164
+ throw new Error("Not completely parsed");
2165
+ }
2166
+ return function (sValue) {
2167
+ var iDotPos, iExponent, iExponentPos, sFraction, sFractionNoZeros, sInteger, o;
2168
+
2169
+ // replace compact operand "c" to scientific "e" to be convertible in LocaleData.convertToDecimal
2170
+ sValue = sValue.replace(rCIgnoreCase, "e");
2171
+ iExponentPos = sValue.search(rEIgnoreCase);
2172
+ iExponent = iExponentPos < 0 ? 0 : parseInt(sValue.slice(iExponentPos + 1));
2173
+ sValue = LocaleData.convertToDecimal(sValue);
2174
+ iDotPos = sValue.indexOf(".");
2175
+ if (iDotPos === -1) {
2176
+ sInteger = sValue;
2177
+ sFraction = "";
2178
+ sFractionNoZeros = "";
2179
+ } else {
2180
+ sInteger = sValue.slice(0, iDotPos);
2181
+ sFraction = sValue.slice(iDotPos + 1);
2182
+ sFractionNoZeros = sFraction.replace(rTrailingZeroes, "");
2183
+ }
2184
+ o = {
2185
+ n: parseFloat(sValue),
2186
+ i: parseInt(sInteger),
2187
+ v: sFraction.length,
2188
+ w: sFractionNoZeros.length,
2189
+ f: sFraction === "" ? 0 : parseInt(sFraction),
2190
+ t: sFractionNoZeros === "" ? 0 : parseInt(sFractionNoZeros),
2191
+ c: iExponent
2192
+ };
2193
+ return {
2194
+ bMatch: fnOr(o),
2195
+ oOperands: o
2196
+ };
2197
+ };
2198
+ }
2199
+ });
2200
+
2201
+ /**
2202
+ * Returns the non-scientific (=decimal) notation of the given numeric value which does not contain an exponent
2203
+ * value.
2204
+ * For numbers with a magnitude (ignoring sign) greater than or equal to 1e+21 or less than 1e-6, a conversion is
2205
+ * required, as Number#toString formats these in scientific notation.
2206
+ *
2207
+ * @param {float|string} vValue
2208
+ * A number such as 10.1 or a string containing a number based on radix 10
2209
+ * @return {string} The number in decimal notation
2210
+ *
2211
+ * @private
2212
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString#description
2213
+ */
2214
+ LocaleData.convertToDecimal = function (vValue) {
2215
+ var iIntegerLength,
2216
+ iExponent,
2217
+ iFractionLength,
2218
+ bNegative,
2219
+ iNewIntegerLength,
2220
+ aResult,
2221
+ sValue = String(vValue);
2222
+ if (!sValue.includes("e") && !sValue.includes("E")) {
1039
2223
  return sValue;
2224
+ }
2225
+ aResult = sValue.match(rNumberInScientificNotation);
2226
+ bNegative = aResult[1] === "-";
2227
+ sValue = aResult[2].replace(".", "");
2228
+ if (rOnlyZeros.test(sValue)) {
2229
+ return "0";
2230
+ }
2231
+ iIntegerLength = aResult[3] ? aResult[3].length : 0;
2232
+ iFractionLength = aResult[4] ? aResult[4].length : 0;
2233
+ iExponent = parseInt(aResult[5]);
2234
+ iNewIntegerLength = iIntegerLength + iExponent;
2235
+ if (iExponent > 0) {
2236
+ sValue = iExponent < iFractionLength ? sValue.slice(0, iNewIntegerLength) + "." + sValue.slice(iNewIntegerLength) : sValue = sValue.padEnd(iNewIntegerLength, "0");
2237
+ } else {
2238
+ sValue = -iExponent < iIntegerLength ? sValue = sValue.slice(0, iNewIntegerLength) + "." + sValue.slice(iNewIntegerLength) : sValue = "0." + sValue.padStart(iFractionLength - iExponent, "0");
2239
+ }
2240
+ if (bNegative) {
2241
+ sValue = "-" + sValue;
2242
+ }
2243
+ return sValue;
1040
2244
  };
1041
2245
  var mCLDRSymbolGroups = {
1042
- 'Era': {
1043
- field: 'era',
1044
- index: 0
1045
- },
1046
- 'Year': {
1047
- field: 'year',
1048
- index: 1
1049
- },
1050
- 'Quarter': {
1051
- field: 'quarter',
1052
- index: 2
1053
- },
1054
- 'Month': {
1055
- field: 'month',
1056
- index: 3
1057
- },
1058
- 'Week': {
1059
- field: 'week',
1060
- index: 4
1061
- },
1062
- 'Day-Of-Week': {
1063
- field: 'weekday',
1064
- index: 5
1065
- },
1066
- 'Day': {
1067
- field: 'day',
1068
- index: 6
1069
- },
1070
- 'DayPeriod': {
1071
- field: 'hour',
1072
- index: 7,
1073
- diffOnly: true
1074
- },
1075
- 'Hour': {
1076
- field: 'hour',
1077
- index: 8
1078
- },
1079
- 'Minute': {
1080
- field: 'minute',
1081
- index: 9
1082
- },
1083
- 'Second': {
1084
- field: 'second',
1085
- index: 10
1086
- },
1087
- 'Timezone': {
1088
- field: 'zone',
1089
- index: 11
1090
- }
2246
+ "Era": {
2247
+ field: "era",
2248
+ index: 0
2249
+ },
2250
+ "Year": {
2251
+ field: "year",
2252
+ index: 1
2253
+ },
2254
+ "Quarter": {
2255
+ field: "quarter",
2256
+ index: 2
2257
+ },
2258
+ "Month": {
2259
+ field: "month",
2260
+ index: 3
2261
+ },
2262
+ "Week": {
2263
+ field: "week",
2264
+ index: 4
2265
+ },
2266
+ "Day-Of-Week": {
2267
+ field: "weekday",
2268
+ index: 5
2269
+ },
2270
+ "Day": {
2271
+ field: "day",
2272
+ index: 6
2273
+ },
2274
+ "DayPeriod": {
2275
+ field: "hour",
2276
+ index: 7,
2277
+ diffOnly: true
2278
+ },
2279
+ "Hour": {
2280
+ field: "hour",
2281
+ index: 8
2282
+ },
2283
+ "Minute": {
2284
+ field: "minute",
2285
+ index: 9
2286
+ },
2287
+ "Second": {
2288
+ field: "second",
2289
+ index: 10
2290
+ },
2291
+ "Timezone": {
2292
+ field: "zone",
2293
+ index: 11
2294
+ }
1091
2295
  };
1092
2296
  var mCLDRSymbols = {
1093
- 'G': {
1094
- group: 'Era',
1095
- match: 'Era',
1096
- numericCeiling: 1
1097
- },
1098
- 'y': {
1099
- group: 'Year',
1100
- match: 'Year',
1101
- numericCeiling: 100
1102
- },
1103
- 'Y': {
1104
- group: 'Year',
1105
- match: 'Year',
1106
- numericCeiling: 100
1107
- },
1108
- 'Q': {
1109
- group: 'Quarter',
1110
- match: 'Quarter',
1111
- numericCeiling: 3
1112
- },
1113
- 'q': {
1114
- group: 'Quarter',
1115
- match: 'Quarter',
1116
- numericCeiling: 3
1117
- },
1118
- 'M': {
1119
- group: 'Month',
1120
- match: 'Month',
1121
- numericCeiling: 3
1122
- },
1123
- 'L': {
1124
- group: 'Month',
1125
- match: 'Month',
1126
- numericCeiling: 3
1127
- },
1128
- 'w': {
1129
- group: 'Week',
1130
- match: 'Week',
1131
- numericCeiling: 100
1132
- },
1133
- 'W': {
1134
- group: 'Week',
1135
- match: 'Week',
1136
- numericCeiling: 100
1137
- },
1138
- 'd': {
1139
- group: 'Day',
1140
- match: 'Day',
1141
- numericCeiling: 100
1142
- },
1143
- 'D': {
1144
- group: 'Day',
1145
- match: 'Day',
1146
- numericCeiling: 100
1147
- },
1148
- 'E': {
1149
- group: 'Day-Of-Week',
1150
- match: 'Day-Of-Week',
1151
- numericCeiling: 1
1152
- },
1153
- 'e': {
1154
- group: 'Day-Of-Week',
1155
- match: 'Day-Of-Week',
1156
- numericCeiling: 3
1157
- },
1158
- 'c': {
1159
- group: 'Day-Of-Week',
1160
- match: 'Day-Of-Week',
1161
- numericCeiling: 2
1162
- },
1163
- 'h': {
1164
- group: 'Hour',
1165
- match: 'Hour12',
1166
- numericCeiling: 100
1167
- },
1168
- 'H': {
1169
- group: 'Hour',
1170
- match: 'Hour24',
1171
- numericCeiling: 100
1172
- },
1173
- 'k': {
1174
- group: 'Hour',
1175
- match: 'Hour24',
1176
- numericCeiling: 100
1177
- },
1178
- 'K': {
1179
- group: 'Hour',
1180
- match: 'Hour12',
1181
- numericCeiling: 100
1182
- },
1183
- 'm': {
1184
- group: 'Minute',
1185
- match: 'Minute',
1186
- numericCeiling: 100
1187
- },
1188
- 's': {
1189
- group: 'Second',
1190
- match: 'Second',
1191
- numericCeiling: 100
1192
- },
1193
- 'z': {
1194
- group: 'Timezone',
1195
- match: 'Timezone',
1196
- numericCeiling: 1
1197
- },
1198
- 'Z': {
1199
- group: 'Timezone',
1200
- match: 'Timezone',
1201
- numericCeiling: 1
1202
- },
1203
- 'O': {
1204
- group: 'Timezone',
1205
- match: 'Timezone',
1206
- numericCeiling: 1
1207
- },
1208
- 'v': {
1209
- group: 'Timezone',
1210
- match: 'Timezone',
1211
- numericCeiling: 1
1212
- },
1213
- 'V': {
1214
- group: 'Timezone',
1215
- match: 'Timezone',
1216
- numericCeiling: 1
1217
- },
1218
- 'X': {
1219
- group: 'Timezone',
1220
- match: 'Timezone',
1221
- numericCeiling: 1
1222
- },
1223
- 'x': {
1224
- group: 'Timezone',
1225
- match: 'Timezone',
1226
- numericCeiling: 1
1227
- },
1228
- 'S': {
1229
- group: 'Other',
1230
- numericCeiling: 100
1231
- },
1232
- 'u': {
1233
- group: 'Other',
1234
- numericCeiling: 100
1235
- },
1236
- 'U': {
1237
- group: 'Other',
1238
- numericCeiling: 1
1239
- },
1240
- 'r': {
1241
- group: 'Other',
1242
- numericCeiling: 100
1243
- },
1244
- 'F': {
1245
- group: 'Other',
1246
- numericCeiling: 100
1247
- },
1248
- 'g': {
1249
- group: 'Other',
1250
- numericCeiling: 100
1251
- },
1252
- 'a': {
1253
- group: 'DayPeriod',
1254
- numericCeiling: 1
1255
- },
1256
- 'b': {
1257
- group: 'Other',
1258
- numericCeiling: 1
1259
- },
1260
- 'B': {
1261
- group: 'Other',
1262
- numericCeiling: 1
1263
- },
1264
- 'A': {
1265
- group: 'Other',
1266
- numericCeiling: 100
1267
- }
1268
- };
1269
- var M_ISO639_OLD_TO_NEW = {
1270
- 'iw': 'he',
1271
- 'ji': 'yi'
2297
+ "G": {
2298
+ group: "Era",
2299
+ match: "Era",
2300
+ numericCeiling: 1
2301
+ },
2302
+ "y": {
2303
+ group: "Year",
2304
+ match: "Year",
2305
+ numericCeiling: 100
2306
+ },
2307
+ "Y": {
2308
+ group: "Year",
2309
+ match: "Year",
2310
+ numericCeiling: 100
2311
+ },
2312
+ "Q": {
2313
+ group: "Quarter",
2314
+ match: "Quarter",
2315
+ numericCeiling: 3
2316
+ },
2317
+ "q": {
2318
+ group: "Quarter",
2319
+ match: "Quarter",
2320
+ numericCeiling: 3
2321
+ },
2322
+ "M": {
2323
+ group: "Month",
2324
+ match: "Month",
2325
+ numericCeiling: 3
2326
+ },
2327
+ "L": {
2328
+ group: "Month",
2329
+ match: "Month",
2330
+ numericCeiling: 3
2331
+ },
2332
+ "w": {
2333
+ group: "Week",
2334
+ match: "Week",
2335
+ numericCeiling: 100
2336
+ },
2337
+ "W": {
2338
+ group: "Week",
2339
+ match: "Week",
2340
+ numericCeiling: 100
2341
+ },
2342
+ "d": {
2343
+ group: "Day",
2344
+ match: "Day",
2345
+ numericCeiling: 100
2346
+ },
2347
+ "D": {
2348
+ group: "Day",
2349
+ match: "Day",
2350
+ numericCeiling: 100
2351
+ },
2352
+ "E": {
2353
+ group: "Day-Of-Week",
2354
+ match: "Day-Of-Week",
2355
+ numericCeiling: 1
2356
+ },
2357
+ "e": {
2358
+ group: "Day-Of-Week",
2359
+ match: "Day-Of-Week",
2360
+ numericCeiling: 3
2361
+ },
2362
+ "c": {
2363
+ group: "Day-Of-Week",
2364
+ match: "Day-Of-Week",
2365
+ numericCeiling: 2
2366
+ },
2367
+ "h": {
2368
+ group: "Hour",
2369
+ match: "Hour12",
2370
+ numericCeiling: 100
2371
+ },
2372
+ "H": {
2373
+ group: "Hour",
2374
+ match: "Hour24",
2375
+ numericCeiling: 100
2376
+ },
2377
+ "k": {
2378
+ group: "Hour",
2379
+ match: "Hour24",
2380
+ numericCeiling: 100
2381
+ },
2382
+ "K": {
2383
+ group: "Hour",
2384
+ match: "Hour12",
2385
+ numericCeiling: 100
2386
+ },
2387
+ "m": {
2388
+ group: "Minute",
2389
+ match: "Minute",
2390
+ numericCeiling: 100
2391
+ },
2392
+ "s": {
2393
+ group: "Second",
2394
+ match: "Second",
2395
+ numericCeiling: 100
2396
+ },
2397
+ "z": {
2398
+ group: "Timezone",
2399
+ match: "Timezone",
2400
+ numericCeiling: 1
2401
+ },
2402
+ "Z": {
2403
+ group: "Timezone",
2404
+ match: "Timezone",
2405
+ numericCeiling: 1
2406
+ },
2407
+ "O": {
2408
+ group: "Timezone",
2409
+ match: "Timezone",
2410
+ numericCeiling: 1
2411
+ },
2412
+ "v": {
2413
+ group: "Timezone",
2414
+ match: "Timezone",
2415
+ numericCeiling: 1
2416
+ },
2417
+ "V": {
2418
+ group: "Timezone",
2419
+ match: "Timezone",
2420
+ numericCeiling: 1
2421
+ },
2422
+ "X": {
2423
+ group: "Timezone",
2424
+ match: "Timezone",
2425
+ numericCeiling: 1
2426
+ },
2427
+ "x": {
2428
+ group: "Timezone",
2429
+ match: "Timezone",
2430
+ numericCeiling: 1
2431
+ },
2432
+ "S": {
2433
+ group: "Other",
2434
+ numericCeiling: 100
2435
+ },
2436
+ "u": {
2437
+ group: "Other",
2438
+ numericCeiling: 100
2439
+ },
2440
+ "U": {
2441
+ group: "Other",
2442
+ numericCeiling: 1
2443
+ },
2444
+ "r": {
2445
+ group: "Other",
2446
+ numericCeiling: 100
2447
+ },
2448
+ "F": {
2449
+ group: "Other",
2450
+ numericCeiling: 100
2451
+ },
2452
+ "g": {
2453
+ group: "Other",
2454
+ numericCeiling: 100
2455
+ },
2456
+ "a": {
2457
+ group: "DayPeriod",
2458
+ numericCeiling: 1
2459
+ },
2460
+ "b": {
2461
+ group: "Other",
2462
+ numericCeiling: 1
2463
+ },
2464
+ "B": {
2465
+ group: "Other",
2466
+ numericCeiling: 1
2467
+ },
2468
+ "A": {
2469
+ group: "Other",
2470
+ numericCeiling: 100
2471
+ }
1272
2472
  };
1273
- var M_SUPPORTED_LOCALES = function () {
1274
- var LOCALES = Locale._cldrLocales, result = {}, i;
1275
- if (LOCALES) {
1276
- for (i = 0; i < LOCALES.length; i++) {
1277
- result[LOCALES[i]] = true;
1278
- }
1279
- }
1280
- return result;
1281
- }();
1282
- var mLocaleDatas = {};
2473
+
2474
+ /**
2475
+ * A list of locales for which CLDR data is bundled with the UI5 runtime.
2476
+ * The value of this constant must only be updated by the CLDR generator; do not modify it manually.
2477
+ *
2478
+ * @private
2479
+ */
2480
+ const A_SUPPORTED_LOCALES = ["ar", "ar_EG", "ar_SA", "bg", "ca", "cnr", "cs", "cy", "da", "de", "de_AT", "de_CH", "el", "el_CY", "en", "en_AU", "en_GB", "en_HK", "en_IE", "en_IN", "en_NZ", "en_PG", "en_SG", "en_ZA", "es", "es_AR", "es_BO", "es_CL", "es_CO", "es_MX", "es_PE", "es_UY", "es_VE", "et", "fa", "fi", "fr", "fr_BE", "fr_CA", "fr_CH", "fr_LU", "he", "hi", "hr", "hu", "id", "it", "it_CH", "ja", "kk", "ko", "lt", "lv", "mk", "ms", "nb", "nl", "nl_BE", "pl", "pt", "pt_PT", "ro", "ru", "ru_UA", "sk", "sl", "sr", "sr_Latn", "sv", "th", "tr", "uk", "vi", "zh_CN", "zh_HK", "zh_SG", "zh_TW"];
2481
+
2482
+ /**
2483
+ * Creates a flat map from an object structure which contains a link to the parent ("_parent").
2484
+ * The values should contain the parent(s) and the element joined by <code>", "</code>.
2485
+ * The keys are the keys of the object structure joined by "/" excluding "_parent".
2486
+ *
2487
+ * E.g. input
2488
+ * <code>
2489
+ * {
2490
+ * a: {
2491
+ * a1: {
2492
+ * a11: "A11",
2493
+ * _parent: "A1"
2494
+ * },
2495
+ * _parent: "A"
2496
+ * }
2497
+ * }
2498
+ * </code>
2499
+ *
2500
+ * output:
2501
+ * <code>
2502
+ * {
2503
+ * "a/a1/a11": "A, A1, A11"
2504
+ * }
2505
+ * </code>
2506
+ *
2507
+ * @param {object} oNode the node which will be processed
2508
+ * @param {string} [sKey=""] the key inside the node which should be processed
2509
+ * @param {object} [oResult={}] the result which is passed through the recursion
2510
+ * @param {string[]} [aParentTranslations=[]] the list of parent translations, e.g. ["A", "A1"]
2511
+ * @returns {Object<string, string>} object map with key being the keys joined by "/" and the values joined by ", ".
2512
+ * @private
2513
+ */
1283
2514
  function _resolveTimezoneTranslationStructure(oNode, sKey, oResult, aParentTranslations) {
1284
- aParentTranslations = aParentTranslations ? aParentTranslations.slice() : [];
1285
- oResult = oResult || {};
1286
- sKey = sKey || '';
1287
- Object.keys(oNode).forEach(function (sChildKey) {
1288
- var vChildNode = oNode[sChildKey];
1289
- if (typeof vChildNode === 'object') {
1290
- var aParentTranslationForChild = aParentTranslations.slice();
1291
- var sParent = vChildNode['_parent'];
1292
- if (sParent) {
1293
- aParentTranslationForChild.push(sParent);
1294
- }
1295
- _resolveTimezoneTranslationStructure(vChildNode, sKey + sChildKey + '/', oResult, aParentTranslationForChild);
1296
- } else if (typeof vChildNode === 'string' && sChildKey !== '_parent') {
1297
- var sParents = aParentTranslations.length ? aParentTranslations.join(', ') + ', ' : '';
1298
- oResult[sKey + sChildKey] = sParents + vChildNode;
1299
- }
1300
- });
1301
- return oResult;
2515
+ aParentTranslations = aParentTranslations ? aParentTranslations.slice() : [];
2516
+ oResult = oResult || {};
2517
+ sKey = sKey || "";
2518
+ Object.keys(oNode).forEach(function (sChildKey) {
2519
+ var vChildNode = oNode[sChildKey];
2520
+ if (typeof vChildNode === "object") {
2521
+ var aParentTranslationForChild = aParentTranslations.slice();
2522
+ var sParent = vChildNode["_parent"];
2523
+ if (sParent) {
2524
+ aParentTranslationForChild.push(sParent);
2525
+ }
2526
+ _resolveTimezoneTranslationStructure(vChildNode, sKey + sChildKey + "/", oResult, aParentTranslationForChild);
2527
+ } else if (typeof vChildNode === "string" && sChildKey !== "_parent") {
2528
+ var sParents = aParentTranslations.length ? aParentTranslations.join(", ") + ", " : "";
2529
+ oResult[sKey + sChildKey] = sParents + vChildNode;
2530
+ }
2531
+ });
2532
+ return oResult;
1302
2533
  }
2534
+
2535
+ /**
2536
+ * Returns the corresponding calendar name in CLDR of the given calendar type, or the calendar type
2537
+ * from the configuration, in case sCalendarType is undefined.
2538
+ *
2539
+ * @param {module:sap/base/i18n/date/CalendarType} sCalendarType
2540
+ * The type defined in {@link module:sap/base/i18n/date/CalendarType}.
2541
+ * @returns {string} calendar name
2542
+ * @private
2543
+ */
1303
2544
  function getCLDRCalendarName(sCalendarType) {
1304
- if (!sCalendarType) {
1305
- sCalendarType = Configuration.getCalendarType();
1306
- }
1307
- return 'ca-' + sCalendarType.toLowerCase();
2545
+ if (!sCalendarType) {
2546
+ sCalendarType = Formatting.getCalendarType();
2547
+ }
2548
+ return "ca-" + sCalendarType.toLowerCase();
1308
2549
  }
1309
- function getData(oLocale) {
1310
- var sLanguage = oLocale.getLanguage() || '', sScript = oLocale.getScript() || '', sRegion = oLocale.getRegion() || '', mData;
1311
- function merge(obj, fallbackObj) {
1312
- var name, value, fallbackValue;
1313
- if (!fallbackObj) {
1314
- return;
1315
- }
1316
- for (name in fallbackObj) {
1317
- if (fallbackObj.hasOwnProperty(name)) {
1318
- value = obj[name];
1319
- fallbackValue = fallbackObj[name];
1320
- if (value === undefined) {
1321
- obj[name] = fallbackValue;
1322
- } else if (value === null) {
1323
- delete obj[name];
1324
- } else if (typeof value === 'object' && typeof fallbackValue === 'object' && !Array.isArray(value)) {
1325
- merge(value, fallbackValue);
1326
- }
1327
- }
1328
- }
2550
+
2551
+ /**
2552
+ * Loads data from the generated CLDR files.
2553
+ *
2554
+ * @param {sap.ui.core.Locale} oLocale
2555
+ * The locale to load the CLDR data for
2556
+ * @param {boolean} [bAsync]
2557
+ * Whether to load the data asynchronously
2558
+ *
2559
+ * @returns {SyncPromise<{mData: Object<string, any>, sCLDRLocaleId: string}>}
2560
+ * A <code>SyncPromise</code> which resolves with an object with two properties: <code>mData</code>
2561
+ * containing the loaded CLDR data and <code>sCLDRLocaleId</code>, the used CLDR locale ID (e.g. "ar-SA");
2562
+ * the <code>SyncPromise</code> never rejects; if neither the <language>_<region>.json nor the
2563
+ * <language>.json data can be loaded via the second try, the English CLDR data is used as final fallback
2564
+ */
2565
+ function loadData(oLocale, bAsync) {
2566
+ var sLanguage = oLocale.getLanguage() || "",
2567
+ sRegion = oLocale.getRegion() || "",
2568
+ sScript = oLocale.getScript() || "";
2569
+
2570
+ /*
2571
+ * Merge a CLDR delta file and a CLDR fallback file.
2572
+ *
2573
+ * Note: this function can't be replaced by sap/base/util/extend or sap/base/util/merge
2574
+ * as its contract for null values differs from those modules.
2575
+ */
2576
+ function merge(obj, fallbackObj) {
2577
+ var name, value, fallbackValue;
2578
+ if (!fallbackObj) {
2579
+ return;
1329
2580
  }
1330
- function getOrLoad(sId) {
1331
- if (!mLocaleDatas[sId] && (!M_SUPPORTED_LOCALES || M_SUPPORTED_LOCALES[sId] === true)) {
1332
- var data = mLocaleDatas[sId] = LoaderExtensions.loadResource('sap/ui/core/cldr/' + sId + '.json', {
1333
- dataType: 'json',
1334
- failOnError: false
1335
- });
1336
- if (data && data.__fallbackLocale) {
1337
- merge(data, getOrLoad(data.__fallbackLocale));
1338
- delete data.__fallbackLocale;
1339
- }
2581
+ for (name in fallbackObj) {
2582
+ if (fallbackObj.hasOwnProperty(name)) {
2583
+ value = obj[name];
2584
+ fallbackValue = fallbackObj[name];
2585
+ if (value === undefined) {
2586
+ // 'undefined': value doesn't exist in delta, so take it from the fallback object
2587
+ // Note: undefined is not a valid value in JSON, so we can't misunderstand an existing undefined
2588
+ obj[name] = fallbackValue;
2589
+ } else if (value === null) {
2590
+ // 'null' is used by the delta tooling as a marker that a value must not be taken form the fallback
2591
+ delete obj[name];
2592
+ } else if (typeof value === 'object' && typeof fallbackValue === 'object' && !Array.isArray(value)) {
2593
+ // both values are objects, merge them recursively
2594
+ merge(value, fallbackValue);
1340
2595
  }
1341
- return mLocaleDatas[sId];
1342
- }
1343
- sLanguage = sLanguage && M_ISO639_OLD_TO_NEW[sLanguage] || sLanguage;
1344
- if (sLanguage === 'no') {
1345
- sLanguage = 'nb';
2596
+ }
1346
2597
  }
1347
- if (sLanguage === 'zh' && !sRegion) {
1348
- if (sScript === 'Hans') {
1349
- sRegion = 'CN';
1350
- } else if (sScript === 'Hant') {
1351
- sRegion = 'TW';
2598
+ }
2599
+ function getOrLoad(sId) {
2600
+ if (!mLocaleIdToData[sId] && A_SUPPORTED_LOCALES.includes(sId) || mLocaleIdToData[sId] instanceof Promise && !bAsync) {
2601
+ mLocaleIdToData[sId] = SyncPromise.resolve(LoaderExtensions.loadResource(`sap/ui/core/cldr/${sId}.json`, {
2602
+ "async": bAsync,
2603
+ dataType: "json",
2604
+ failOnError: false
2605
+ })).then(oData => {
2606
+ // Note: When preload bundles are created the files in those bundles are optimized, i.e. for
2607
+ // language bundles similar entries/parts are aggregated inside a <language>.json
2608
+ // (e.g. 'ar.json') and only the region specific entries remain in the <language>_<region>.json
2609
+ // (e.g. 'ar_SA.json').
2610
+ // When a <language>_<region>.json is loaded the "__fallbackLocale" property inside the bundle
2611
+ // indicates that further CLDR data/entries have to be loaded from the referenced
2612
+ // <fallbackLocale>.json.
2613
+ if (oData) {
2614
+ return getOrLoad(oData.__fallbackLocale).then(oFallBackData => {
2615
+ merge(oData, oFallBackData);
2616
+ mLocaleIdToData[sId] = oData;
2617
+ delete oData.__fallbackLocale;
2618
+ return oData;
2619
+ });
1352
2620
  }
2621
+ return oData;
2622
+ }).unwrap();
1353
2623
  }
1354
- if (sLanguage === 'sh' || sLanguage === 'sr' && sScript === 'Latn') {
1355
- sLanguage = 'sr_Latn';
2624
+ return SyncPromise.resolve(mLocaleIdToData[sId]);
2625
+ }
2626
+
2627
+ // normalize language and handle special cases
2628
+ sLanguage = sLanguage && Localization.getModernLanguage(sLanguage) || sLanguage;
2629
+ // Special case 1: in an SAP context, the inclusive language code "no" always means Norwegian Bokmal ("nb")
2630
+ if (sLanguage === "no") {
2631
+ sLanguage = "nb";
2632
+ }
2633
+ // Special case 2: for Chinese, derive a default region from the script (this behavior is inherited from Java)
2634
+ if (sLanguage === "zh" && !sRegion) {
2635
+ if (sScript === "Hans") {
2636
+ sRegion = "CN";
2637
+ } else if (sScript === "Hant") {
2638
+ sRegion = "TW";
1356
2639
  }
1357
- var sId = sLanguage + '_' + sRegion;
1358
- var sCLDRLocaleId = sId;
1359
- if (sLanguage && sRegion) {
1360
- mData = getOrLoad(sId);
1361
- }
1362
- if (!mData && sLanguage) {
1363
- mData = getOrLoad(sLanguage);
1364
- sCLDRLocaleId = sLanguage;
2640
+ }
2641
+
2642
+ // Special case 3: for Serbian, there is script cyrillic and latin, "sh" and "sr-latn" map to "latin", "sr" maps to cyrillic
2643
+ // CLDR files: sr.json (cyrillic) and sr_Latn.json (latin)
2644
+ if (sLanguage === "sh" || sLanguage === "sr" && sScript === "Latn") {
2645
+ sLanguage = "sr_Latn";
2646
+ }
2647
+
2648
+ // sId is the originally requested locale.
2649
+ // this is the key under which the result (even a fallback one) will be stored in the end
2650
+ const sId = sLanguage + "_" + sRegion;
2651
+
2652
+ // the locale of the loaded json file
2653
+ let sCLDRLocaleId = sId;
2654
+
2655
+ // first try: load CLDR data for specific language/region combination
2656
+ return getOrLoad(sId).then(mData => {
2657
+ if (!mData) {
2658
+ // second try: no data was found for the language/region combination, try with only the language
2659
+ sCLDRLocaleId = sLanguage;
2660
+ return getOrLoad(sLanguage);
1365
2661
  }
2662
+ return mData;
2663
+ }).then(mData => {
1366
2664
  if (!mData) {
1367
- mData = getOrLoad('en');
1368
- sCLDRLocaleId = 'en';
2665
+ // last try: no data was found for language/region combination nor the language, load "en" locale data
2666
+ sCLDRLocaleId = "en";
2667
+ return getOrLoad("en");
1369
2668
  }
1370
- mLocaleDatas[sId] = mData;
1371
- sCLDRLocaleId = sCLDRLocaleId.replace(/_/g, '-');
2669
+ return mData;
2670
+ }).then(mData => {
1372
2671
  return {
1373
- mData: mData,
1374
- sCLDRLocaleId: sCLDRLocaleId
2672
+ mData: mData,
2673
+ sCLDRLocaleId: sCLDRLocaleId.replace(/_/g, "-")
1375
2674
  };
2675
+ });
1376
2676
  }
1377
- var CustomLocaleData = LocaleData.extend('sap.ui.core.CustomLocaleData', {
1378
- constructor: function (oLocale) {
1379
- LocaleData.apply(this, arguments);
1380
- this.mCustomData = Configuration.getFormatSettings().getCustomLocaleData();
1381
- },
1382
- _get: function () {
1383
- var aArguments = Array.prototype.slice.call(arguments), sCalendar, sKey;
1384
- if (aArguments[0].indexOf('ca-') == 0) {
1385
- sCalendar = aArguments[0];
1386
- if (sCalendar == getCLDRCalendarName()) {
1387
- aArguments = aArguments.slice(1);
1388
- }
1389
- }
1390
- sKey = aArguments.join('-');
1391
- var vValue = this.mCustomData[sKey];
1392
- if (vValue == null) {
1393
- vValue = this._getDeep(this.mCustomData, arguments);
1394
- if (vValue == null) {
1395
- vValue = this._getDeep(this.mData, arguments);
1396
- }
1397
- }
1398
- return vValue;
1399
- },
1400
- _getMerged: function () {
1401
- var mData = this._getDeep(this.mData, arguments);
1402
- var mCustomData = this._getDeep(this.mCustomData, arguments);
1403
- return extend({}, mData, mCustomData);
2677
+
2678
+ /**
2679
+ * @classdesc A specialized subclass of LocaleData that merges custom settings.
2680
+ * @extends sap.ui.core.LocaleData
2681
+ * @alias sap.ui.core.CustomLocaleData
2682
+ * @private
2683
+ */
2684
+ var CustomLocaleData = LocaleData.extend("sap.ui.core.CustomLocaleData", {
2685
+ constructor: function (oLocale) {
2686
+ LocaleData.apply(this, arguments);
2687
+ this.mCustomData = Formatting.getCustomLocaleData();
2688
+ },
2689
+ /**
2690
+ * Retrieves the value for the given arguments by checking first <code>mCustomData</code> and if not
2691
+ * found <code>mData</code>
2692
+ * @returns {*} value
2693
+ * @private
2694
+ */
2695
+ _get: function () {
2696
+ var aArguments = Array.prototype.slice.call(arguments),
2697
+ sCalendar,
2698
+ sKey;
2699
+ // Calendar data needs special handling, as CustomLocaleData does have one version of calendar data only
2700
+ if (aArguments[0].indexOf("ca-") == 0) {
2701
+ sCalendar = aArguments[0];
2702
+ if (sCalendar == getCLDRCalendarName()) {
2703
+ aArguments = aArguments.slice(1);
2704
+ }
1404
2705
  }
2706
+ sKey = aArguments.join("-");
2707
+ // first try customdata with special formatted key
2708
+ // afterwards try customdata lookup
2709
+ // afterwards try mData lookup
2710
+ var vValue = this.mCustomData[sKey];
2711
+ if (vValue == null) {
2712
+ vValue = this._getDeep(this.mCustomData, arguments);
2713
+ if (vValue == null) {
2714
+ vValue = this._getDeep(this.mData, arguments);
2715
+ }
2716
+ }
2717
+ return vValue;
2718
+ },
2719
+ /**
2720
+ * Retrieves merged object from <code>mData</code> extended with <code>mCustomData</code>.
2721
+ * This function merges the content of <code>mData</code> and <code>mCustomData</code> instead of returning one or the other like <code>_get()</code> does.
2722
+ *
2723
+ * Note: Properties defined in <code>mCustomData</code> overwrite the ones from <code>mData</code>.
2724
+ * @private
2725
+ * @return {object} merged object
2726
+ */
2727
+ _getMerged: function () {
2728
+ var mData = this._getDeep(this.mData, arguments);
2729
+ var mCustomData = this._getDeep(this.mCustomData, arguments);
2730
+ return extend({}, mData, mCustomData);
2731
+ },
2732
+ /**
2733
+ * Returns the first day of the week defined by the calendar week numbering algorithm
2734
+ * set in the configuration, or if no specific calendar week numbering algorithm is configured, see
2735
+ * {@link module:sap/base/i18n/Formatting.setCalendarWeekNumbering Formatting.setCalendarWeekNumbering}.
2736
+ * Otherwise, the first day of the week is determined by the current locale, see
2737
+ * {@link sap.ui.core.LocaleData#getFirstDayOfWeek}.
2738
+ *
2739
+ * Days are encoded as integer where Sunday=0, Monday=1 etc.
2740
+ *
2741
+ * @returns {int} The first day of week
2742
+ * @override sap.ui.core.LocaleData#getFirstDayOfWeek
2743
+ * @since 1.113.0
2744
+ */
2745
+ getFirstDayOfWeek: function () {
2746
+ var sCalendarWeekNumbering = Formatting.getCalendarWeekNumbering();
2747
+ if (sCalendarWeekNumbering === CalendarWeekNumbering.Default) {
2748
+ return LocaleData.prototype.getFirstDayOfWeek.call(this);
2749
+ }
2750
+ return CalendarWeekNumbering.getWeekConfigurationValues(sCalendarWeekNumbering).firstDayOfWeek;
2751
+ },
2752
+ /**
2753
+ * Returns the required minimal number of days for the first week of a year defined by the
2754
+ * calendar week numbering algorithm set in the configuration,
2755
+ * see {@link module:sap/base/i18n/Formatting.setCalendarWeekNumbering Formatting.setCalendarWeekNumbering}.
2756
+ * If no specific calendar week numbering algorithm is configured the required minimal number
2757
+ * of days for the first week of a year is determined by the current locale,
2758
+ * see {@link sap.ui.core.LocaleData#getMinimalDaysInFirstWeek}.
2759
+ *
2760
+ * @returns {int} The required minimal number of days for the first week of a year
2761
+ * @override sap.ui.core.LocaleData#getMinimalDaysInFirstWeek
2762
+ * @since 1.113.0
2763
+ */
2764
+ getMinimalDaysInFirstWeek: function () {
2765
+ var sCalendarWeekNumbering = Formatting.getCalendarWeekNumbering();
2766
+ if (sCalendarWeekNumbering === CalendarWeekNumbering.Default) {
2767
+ return LocaleData.prototype.getMinimalDaysInFirstWeek.call(this);
2768
+ }
2769
+ return CalendarWeekNumbering.getWeekConfigurationValues(sCalendarWeekNumbering).minimalDaysInFirstWeek;
2770
+ }
1405
2771
  });
1406
- LocaleData.getInstance = function (oLocale) {
1407
- return oLocale.hasPrivateUseSubtag('sapufmt') ? new CustomLocaleData(oLocale) : new LocaleData(oLocale);
2772
+
2773
+ /**
2774
+ * Resets the locale data cache.
2775
+ *
2776
+ * @private
2777
+ */
2778
+ LocaleData._resetLocaleDataCache = function () {
2779
+ mLocaleIdToData = {};
2780
+ };
2781
+
2782
+ /**
2783
+ * Creates an instance of <code>LocaleData</code> for the given locale.
2784
+ *
2785
+ * @param {sap.ui.core.Locale|module:sap/base/i18n/LanguageTag} vLocale The locale or language tag
2786
+ * @returns {sap.ui.core.LocaleData} An instance of <code>LocaleData</code>
2787
+ *
2788
+ * @public
2789
+ * @since 1.123
2790
+ */
2791
+ LocaleData.getInstance = function (vLocale) {
2792
+ vLocale = Locale._getCoreLocale(vLocale);
2793
+ return vLocale.hasPrivateUseSubtag("sapufmt") ? new CustomLocaleData(vLocale) : new LocaleData(vLocale);
2794
+ };
2795
+
2796
+ /**
2797
+ * Creates an instance of <code>LocaleData</code> asynchronously for the given language tag.
2798
+ *
2799
+ * @param {module:sap/base/i18n/LanguageTag} oLanguageTag
2800
+ * The language tag
2801
+ * @returns {Promise<sap.ui.core.LocaleData>}
2802
+ * A <code>Promise</code> which resolves with an instance of <code>LocaleData</code>; the <code>Promise</code>
2803
+ * never rejects
2804
+ *
2805
+ * @private
2806
+ * @ui5-restricted sap.ui.core
2807
+ * @since 1.127
2808
+ */
2809
+ LocaleData.requestInstance = function (oLanguageTag) {
2810
+ const oLocale = Locale._getCoreLocale(oLanguageTag);
2811
+ const oLocaleData = oLocale.hasPrivateUseSubtag("sapufmt") ? new CustomLocaleData(oLocale, true) : new LocaleData(oLocale, true);
2812
+ return Promise.resolve(oLocaleData.loaded);
2813
+ };
2814
+ LocaleData._cldrLocales = A_SUPPORTED_LOCALES;
2815
+ // maps a locale to a map of time zone translations, which maps an IANA time zone ID to the translated time zone
2816
+ // name
2817
+ LocaleData._mTimezoneTranslations = {};
2818
+ const rContainsSymbol = new RegExp("[" + Object.keys(mCLDRSymbols).join("") + "]");
2819
+ const rTextWithOptionalSpacesAtStartAndEnd = /^(\s)?(.*?)(\s)?$/;
2820
+
2821
+ /**
2822
+ * Returns the escaped value if the given value contains CLDR symbols.
2823
+ *
2824
+ * @param {string} [sValue=""]
2825
+ * The value to be checked and escaped if needed; the value must not contain '
2826
+ * @returns {string}
2827
+ * The escaped value; only the string between one optional space at the beginning and at the
2828
+ * end is escaped
2829
+ */
2830
+ LocaleData._escapeIfNeeded = function (sValue) {
2831
+ if (sValue === undefined) {
2832
+ return "";
2833
+ }
2834
+ if (rContainsSymbol.test(sValue)) {
2835
+ return sValue.replace(rTextWithOptionalSpacesAtStartAndEnd, "$1'$2'$3");
2836
+ }
2837
+ return sValue;
1408
2838
  };
2839
+
2840
+ /**
2841
+ * Replaced by {@link #getCompactCurrencyPattern}.
2842
+ *
2843
+ * @param {"short"|"sap-short"|"short-indian"|"sap-short-indian"} sStyle
2844
+ * See {@link #getCompactCurrencyPattern}; "short-indian" and "sap-short-indian" are only available since 1.133.0
2845
+ * for the "en-IN" locale
2846
+ * @param {string} sPowerOfTen
2847
+ * See {@link #getCompactCurrencyPattern}
2848
+ * @param {"few"|"many"|"one"|"other"|"two"|"zero"} [sPlural="other"]
2849
+ * See {@link #getCompactCurrencyPattern}
2850
+ * @param {"alphaNextToNumber"|"noCurrency"} [sAlternative]
2851
+ * See {@link #getCompactCurrencyPattern}; since 1.133.0
2852
+ * @returns {string|undefined}
2853
+ * See {@link #getCompactCurrencyPattern}
2854
+ *
2855
+ * @function
2856
+ * @name sap.ui.core.LocaleData.prototype.getCurrencyFormat
2857
+ * @public
2858
+ * @since 1.51.0
2859
+ * @deprecated since 1.133.0, use {@link #getCompactCurrencyPattern} instead
2860
+ */
2861
+ LocaleData.prototype.getCurrencyFormat = LocaleData.prototype.getCompactCurrencyPattern;
2862
+
2863
+ /**
2864
+ * Replaced by {@link #getCompactDecimalPattern}.
2865
+ *
2866
+ * @param {"long"|"short"|"short-indian"} sStyle
2867
+ * See {@link #getCompactDecimalPattern}; "short-indian" is only available since 1.133.0 for the "en-IN" locale
2868
+ * @param {string} sPowerOfTen
2869
+ * See {@link #getCompactDecimalPattern}
2870
+ * @param {"few"|"many"|"one"|"other"|"two"|"zero"} [sPlural="other"]
2871
+ * See {@link #getCompactDecimalPattern}
2872
+ * @returns {string|undefined}
2873
+ * See {@link #getCompactDecimalPattern}
2874
+ *
2875
+ * @function
2876
+ * @name sap.ui.core.LocaleData.prototype.getDecimalFormat
2877
+ * @public
2878
+ * @since 1.25.0
2879
+ * @deprecated since 1.133.0, use {@link #getCompactDecimalPattern} instead
2880
+ */
2881
+ LocaleData.prototype.getDecimalFormat = LocaleData.prototype.getCompactDecimalPattern;
1409
2882
  export default LocaleData;