@ui5/webcomponents-localization 1.14.6 → 1.14.7

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 (128) hide show
  1. package/.eslintignore +2 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/generated/assets/cldr/ar.json +102 -62
  4. package/dist/generated/assets/cldr/ar_EG.json +102 -62
  5. package/dist/generated/assets/cldr/ar_SA.json +102 -62
  6. package/dist/generated/assets/cldr/bg.json +364 -325
  7. package/dist/generated/assets/cldr/ca.json +491 -453
  8. package/dist/generated/assets/cldr/cs.json +431 -324
  9. package/dist/generated/assets/cldr/cy.json +608 -340
  10. package/dist/generated/assets/cldr/da.json +290 -227
  11. package/dist/generated/assets/cldr/de.json +348 -241
  12. package/dist/generated/assets/cldr/de_AT.json +348 -241
  13. package/dist/generated/assets/cldr/de_CH.json +347 -240
  14. package/dist/generated/assets/cldr/el.json +128 -100
  15. package/dist/generated/assets/cldr/el_CY.json +128 -100
  16. package/dist/generated/assets/cldr/en.json +538 -512
  17. package/dist/generated/assets/cldr/en_AU.json +583 -520
  18. package/dist/generated/assets/cldr/en_GB.json +485 -441
  19. package/dist/generated/assets/cldr/en_HK.json +519 -474
  20. package/dist/generated/assets/cldr/en_IE.json +485 -440
  21. package/dist/generated/assets/cldr/en_IN.json +465 -420
  22. package/dist/generated/assets/cldr/en_NZ.json +505 -460
  23. package/dist/generated/assets/cldr/en_PG.json +505 -460
  24. package/dist/generated/assets/cldr/en_SG.json +505 -460
  25. package/dist/generated/assets/cldr/en_ZA.json +485 -440
  26. package/dist/generated/assets/cldr/es.json +709 -456
  27. package/dist/generated/assets/cldr/es_AR.json +687 -434
  28. package/dist/generated/assets/cldr/es_BO.json +721 -468
  29. package/dist/generated/assets/cldr/es_CL.json +567 -422
  30. package/dist/generated/assets/cldr/es_CO.json +485 -339
  31. package/dist/generated/assets/cldr/es_MX.json +734 -481
  32. package/dist/generated/assets/cldr/es_PE.json +409 -372
  33. package/dist/generated/assets/cldr/es_UY.json +433 -396
  34. package/dist/generated/assets/cldr/es_VE.json +453 -416
  35. package/dist/generated/assets/cldr/et.json +340 -307
  36. package/dist/generated/assets/cldr/fa.json +96 -34
  37. package/dist/generated/assets/cldr/fi.json +359 -308
  38. package/dist/generated/assets/cldr/fr.json +347 -321
  39. package/dist/generated/assets/cldr/fr_BE.json +347 -321
  40. package/dist/generated/assets/cldr/fr_CA.json +458 -432
  41. package/dist/generated/assets/cldr/fr_CH.json +290 -264
  42. package/dist/generated/assets/cldr/fr_LU.json +347 -321
  43. package/dist/generated/assets/cldr/he.json +241 -130
  44. package/dist/generated/assets/cldr/hi.json +103 -53
  45. package/dist/generated/assets/cldr/hr.json +467 -410
  46. package/dist/generated/assets/cldr/hu.json +246 -195
  47. package/dist/generated/assets/cldr/id.json +478 -406
  48. package/dist/generated/assets/cldr/it.json +418 -362
  49. package/dist/generated/assets/cldr/it_CH.json +418 -362
  50. package/dist/generated/assets/cldr/ja.json +58 -18
  51. package/dist/generated/assets/cldr/kk.json +562 -398
  52. package/dist/generated/assets/cldr/ko.json +36 -15
  53. package/dist/generated/assets/cldr/lt.json +320 -231
  54. package/dist/generated/assets/cldr/lv.json +184 -120
  55. package/dist/generated/assets/cldr/ms.json +460 -388
  56. package/dist/generated/assets/cldr/nb.json +160 -92
  57. package/dist/generated/assets/cldr/nl.json +621 -373
  58. package/dist/generated/assets/cldr/nl_BE.json +621 -373
  59. package/dist/generated/assets/cldr/pl.json +590 -279
  60. package/dist/generated/assets/cldr/pt.json +696 -334
  61. package/dist/generated/assets/cldr/pt_PT.json +730 -454
  62. package/dist/generated/assets/cldr/ro.json +409 -339
  63. package/dist/generated/assets/cldr/ru.json +317 -279
  64. package/dist/generated/assets/cldr/ru_UA.json +312 -274
  65. package/dist/generated/assets/cldr/sk.json +454 -413
  66. package/dist/generated/assets/cldr/sl.json +118 -80
  67. package/dist/generated/assets/cldr/sr.json +294 -142
  68. package/dist/generated/assets/cldr/sr_Latn.json +972 -824
  69. package/dist/generated/assets/cldr/sv.json +382 -338
  70. package/dist/generated/assets/cldr/th.json +56 -36
  71. package/dist/generated/assets/cldr/tr.json +371 -320
  72. package/dist/generated/assets/cldr/uk.json +340 -290
  73. package/dist/generated/assets/cldr/vi.json +352 -328
  74. package/dist/generated/assets/cldr/zh_CN.json +34 -10
  75. package/dist/generated/assets/cldr/zh_HK.json +33 -9
  76. package/dist/generated/assets/cldr/zh_SG.json +33 -9
  77. package/dist/generated/assets/cldr/zh_TW.json +32 -8
  78. package/dist/sap/base/Event.js +59 -0
  79. package/dist/sap/base/Eventing.js +147 -0
  80. package/dist/sap/base/Log.js +2 -239
  81. package/dist/sap/base/assert.js +28 -1
  82. package/dist/sap/base/config/MemoryConfigurationProvider.js +20 -0
  83. package/dist/sap/base/config.js +17 -0
  84. package/dist/sap/base/i18n/Formatting.js +1130 -0
  85. package/dist/sap/base/i18n/LanguageTag.js +173 -0
  86. package/dist/sap/base/i18n/Localization.js +721 -0
  87. package/dist/sap/base/i18n/date/CalendarType.js +43 -0
  88. package/dist/sap/base/i18n/date/CalendarWeekNumbering.js +105 -0
  89. package/dist/sap/base/i18n/date/TimezoneUtils.js +319 -0
  90. package/dist/sap/base/strings/camelize.js +30 -0
  91. package/dist/sap/base/strings/formatMessage.js +88 -15
  92. package/dist/sap/base/util/ObjectPath.js +95 -3
  93. package/dist/sap/base/util/Version.js +157 -0
  94. package/dist/sap/base/util/_merge.js +83 -26
  95. package/dist/sap/base/util/array/uniqueSort.js +37 -15
  96. package/dist/sap/base/util/deepClone.js +102 -0
  97. package/dist/sap/base/util/deepEqual.js +75 -51
  98. package/dist/sap/base/util/extend.js +58 -7
  99. package/dist/sap/base/util/isEmptyObject.js +34 -0
  100. package/dist/sap/base/util/isPlainObject.js +35 -1
  101. package/dist/sap/base/util/now.js +24 -3
  102. package/dist/sap/base/util/resolveReference.js +157 -0
  103. package/dist/sap/base/util/uid.js +27 -0
  104. package/dist/sap/ui/base/DataType.js +657 -0
  105. package/dist/sap/ui/base/Interface.js +47 -1
  106. package/dist/sap/ui/base/Metadata.js +436 -171
  107. package/dist/sap/ui/base/Object.js +284 -48
  108. package/dist/sap/ui/core/CalendarType.js +24 -8
  109. package/dist/sap/ui/core/Locale.js +190 -155
  110. package/dist/sap/ui/core/LocaleData.js +2661 -1351
  111. package/dist/sap/ui/core/Supportability.js +5 -0
  112. package/dist/sap/ui/core/Theming.js +539 -0
  113. package/dist/sap/ui/core/date/Buddhist.js +162 -87
  114. package/dist/sap/ui/core/date/CalendarUtils.js +61 -32
  115. package/dist/sap/ui/core/date/CalendarWeekNumbering.js +30 -7
  116. package/dist/sap/ui/core/date/Gregorian.js +25 -10
  117. package/dist/sap/ui/core/date/Islamic.js +298 -185
  118. package/dist/sap/ui/core/date/Japanese.js +210 -115
  119. package/dist/sap/ui/core/date/Persian.js +324 -195
  120. package/dist/sap/ui/core/date/UI5Date.js +923 -237
  121. package/dist/sap/ui/core/date/UniversalDate.js +1238 -256
  122. package/dist/sap/ui/core/date/_Calendars.js +10 -1
  123. package/dist/sap/ui/core/format/DateFormat.js +3174 -2111
  124. package/dist/sap/ui/core/format/TimezoneUtil.js +24 -89
  125. package/package-scripts.cjs +6 -11
  126. package/package.json +9 -5
  127. package/used-modules.txt +24 -1
  128. package/dist/sap/ui/Device.js +0 -5
@@ -0,0 +1,721 @@
1
+ /*!
2
+ * OpenUI5
3
+ * (c) Copyright 2009-2024 SAP SE or an SAP affiliate company.
4
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
5
+ */
6
+ import BaseConfig from "../config.js";
7
+ import Eventing from "../Eventing.js";
8
+ import Log from "../Log.js";
9
+ import LanguageTag from "./LanguageTag.js";
10
+ import CalendarType from "./date/CalendarType.js";
11
+ import TimezoneUtils from "./date/TimezoneUtils.js";
12
+ const oWritableConfig = BaseConfig.getWritableInstance();
13
+ let sLanguageSetByApi;
14
+ const oEventing = new Eventing();
15
+ let mChanges;
16
+ let bLanguageWarningLogged = false;
17
+
18
+ /**
19
+ * A map of preferred Calendar types according to the language.
20
+ * @private
21
+ */
22
+ const _mPreferredCalendar = {
23
+ "ar-SA": CalendarType.Islamic,
24
+ "fa": CalendarType.Persian,
25
+ "th": CalendarType.Buddhist,
26
+ "default": CalendarType.Gregorian
27
+ };
28
+
29
+ // Note: keys must be uppercase
30
+ const M_ABAP_LANGUAGE_TO_LOCALE = {
31
+ "ZH": "zh-Hans",
32
+ "ZF": "zh-Hant",
33
+ "SH": "sr-Latn",
34
+ "6N": "en-GB",
35
+ "1P": "pt-PT",
36
+ "1X": "es-MX",
37
+ "3F": "fr-CA",
38
+ "1Q": "en-US-x-saptrc",
39
+ "2Q": "en-US-x-sappsd",
40
+ "3Q": "en-US-x-saprigi"
41
+ };
42
+ const M_ISO639_OLD_TO_NEW = {
43
+ "iw": "he",
44
+ "ji": "yi"
45
+ };
46
+ const M_LOCALE_TO_ABAP_LANGUAGE = (obj => {
47
+ return Object.keys(obj).reduce((inv, key) => {
48
+ inv[obj[key]] = key;
49
+ return inv;
50
+ }, {});
51
+ })(M_ABAP_LANGUAGE_TO_LOCALE);
52
+
53
+ /**
54
+ * Maps wellknown private use extensions to pseudo language tags.
55
+ * @param {string} sPrivateUse A Locale
56
+ * @returns {string|undefined} the pseudo language tag or undefined
57
+ * @private
58
+ * @since 1.120.0
59
+ */
60
+ function getPseudoLanguageTag(sPrivateUse) {
61
+ let sPseudoLanguageTag;
62
+ if (sPrivateUse) {
63
+ const m = /-(saptrc|sappsd|saprigi)(?:-|$)/i.exec(sPrivateUse);
64
+ sPseudoLanguageTag = m && "en-US-x-" + m[1].toLowerCase();
65
+ }
66
+ return sPseudoLanguageTag;
67
+ }
68
+
69
+ /**
70
+ * Helper to analyze and parse designtime (aka buildtime) variables
71
+ *
72
+ * At buildtime, the build can detect a pattern like $some-variable-name:some-value$
73
+ * and replace 'some-value' with a value determined at buildtime (here: the actual list of locales).
74
+ *
75
+ * At runtime, config method removes the surrounding pattern ('$some-variable-name:' and '$') and leaves only the 'some-value'.
76
+ * Additionally, config value is parsed as a comma-separated list (because config is the only use case here).
77
+ *
78
+ * The mimic of the comments is borrowed from the CVS (Concurrent Versions System),
79
+ * see http://web.mit.edu/gnu/doc/html/cvs_17.html.
80
+ *
81
+ * If no valid <code>sValue</code> is given, <code>null</code> is returned
82
+ *
83
+ * @param {string} sValue The raw designtime property e.g. $cldr-rtl-locales:ar,fa,he$
84
+ * @returns {string[]|null} The designtime property e.g. ['ar', 'fa', 'he']
85
+ * @private
86
+ * @since 1.120.0
87
+ */
88
+ function getDesigntimePropertyAsArray(sValue) {
89
+ const m = /\$([-a-z0-9A-Z._]+)(?::([^$]*))?\$/.exec(sValue);
90
+ return m && m[2] ? m[2].split(/,/) : null;
91
+ }
92
+
93
+ /**
94
+ * A list of locales for which the CLDR specifies "right-to-left"
95
+ * as the character orientation.
96
+ *
97
+ * The string literal below is substituted during the build.
98
+ * The value is determined from the CLDR JSON files which are
99
+ * bundled with the UI5 runtime.
100
+ */
101
+ const A_RTL_LOCALES = getDesigntimePropertyAsArray("$cldr-rtl-locales:ar,fa,he$") || [];
102
+
103
+ /**
104
+ * List of locales for which translated texts have been bundled with the UI5 runtime.
105
+ * @private
106
+ */
107
+ const _coreI18nLocales = getDesigntimePropertyAsArray("$core-i18n-locales:,ar,bg,ca,cs,da,de,el,en,en_GB,es,es_MX,et,fi,fr,hi,hr,hu,it,iw,ja,kk,ko,lt,lv,ms,nl,no,pl,pt,ro,ru,sh,sk,sl,sv,th,tr,uk,vi,zh_CN,zh_TW$");
108
+
109
+ /**
110
+ * Retrieves a Locale for the given SAP logon language or BCP47 tag.
111
+ *
112
+ * @param {string} sSAPLogonLanguage
113
+ * A SAP logon language, e.g. "ZF" or a BCP47 language tag
114
+ * @returns {object} An object containing the mapped LogonLanguage and a LanguageTag if created
115
+ * @private
116
+ * @since 1.120.0
117
+ */
118
+ function fromSAPLogonLanguage(sSAPLogonLanguage) {
119
+ let oLanguageTag;
120
+ if (sSAPLogonLanguage && typeof sSAPLogonLanguage === 'string') {
121
+ sSAPLogonLanguage = M_ABAP_LANGUAGE_TO_LOCALE[sSAPLogonLanguage.toUpperCase()] || sSAPLogonLanguage;
122
+ try {
123
+ oLanguageTag = new LanguageTag(sSAPLogonLanguage);
124
+ } catch (e) {
125
+ // ignore
126
+ }
127
+ }
128
+ return [oLanguageTag, sSAPLogonLanguage];
129
+ }
130
+
131
+ /**
132
+ * Helper that creates a LanguageTag object from the given language
133
+ * or, throws an error for non BCP-47 compliant languages.
134
+ *
135
+ * @param {string} sLanguage A BCP-47 compliant language
136
+ * @returns {module:sap/base/i18n/LanguageTag} The resulting LanguageTag
137
+ * @throws {TypeError} Throws a TypeError for unknown languages
138
+ * @private
139
+ * @since 1.120.0
140
+ */
141
+ function createLanguageTag(sLanguage) {
142
+ let oLanguageTag;
143
+ if (sLanguage) {
144
+ oLanguageTag = new LanguageTag(sLanguage);
145
+ }
146
+ return oLanguageTag;
147
+ }
148
+
149
+ // Helper Functions
150
+ function detectLanguage() {
151
+ return globalThis.navigator ? globalThis.navigator.languages && globalThis.navigator.languages[0] || globalThis.navigator.language || "en" : new Intl.Collator().resolvedOptions().locale || "en";
152
+ }
153
+ function check(bCondition, sMessage) {
154
+ if (!bCondition) {
155
+ throw new TypeError(sMessage);
156
+ }
157
+ }
158
+ function join() {
159
+ return Array.prototype.filter.call(arguments, Boolean).join("-");
160
+ }
161
+
162
+ /**
163
+ * Checks if the provided timezone is valid and logs an error if not.
164
+ *
165
+ * @param {string} sTimezone The IANA timezone ID
166
+ * @returns {boolean} Returns true if the timezone is valid
167
+ * @private
168
+ * @since 1.120.0
169
+ */
170
+ function checkTimezone(sTimezone) {
171
+ const bIsValidTimezone = TimezoneUtils.isValidTimezone(sTimezone);
172
+ if (!bIsValidTimezone) {
173
+ Log.error("The provided timezone '" + sTimezone + "' is not a valid IANA timezone ID." + " Falling back to browser's local timezone '" + TimezoneUtils.getLocalTimezone() + "'.");
174
+ }
175
+ return bIsValidTimezone;
176
+ }
177
+
178
+ /**
179
+ * Configuration for localization specific parameters
180
+ * @public
181
+ * @since 1.118
182
+ * @alias module:sap/base/i18n/Localization
183
+ * @namespace
184
+ */
185
+ const Localization = {
186
+ /**
187
+ * The <code>change</code> event is fired, when the configuration options are changed.
188
+ * For the event parameters please refer to {@link module:sap/base/i18n/Localization$ChangeEvent}.
189
+ *
190
+ * @name module:sap/base/i18n/Localization.change
191
+ * @event
192
+ * @param {module:sap/base/i18n/Localization$ChangeEvent} oEvent
193
+ * @public
194
+ * @since 1.120.0
195
+ */
196
+
197
+ /**
198
+ * The localization change event. Contains only the parameters which were changed.
199
+ *
200
+ * The list below shows the possible combinations of parameters available as part of the change event.
201
+ *
202
+ * <ul>
203
+ * <li>{@link module:sap/base/i18n/Localization.setLanguage Localization.setLanguage}:
204
+ * <ul>
205
+ * <li><code>language</code></li>
206
+ * <li><code>rtl?</code> (only if language change also changed RTL)</li>
207
+ * </ul>
208
+ * </li>
209
+ * <li>{@link module:sap/base/i18n/Localization.setRTL Localization.setRTL}:
210
+ * <ul>
211
+ * <li><code>rtl</code></li>
212
+ * </ul>
213
+ * </li>
214
+ * <li>{@link module:sap/base/i18n/Localization.setTimezone Localization.setTimezone}:
215
+ * <ul>
216
+ * <li><code>timezone</code></li>
217
+ * </ul>
218
+ * </li>
219
+ * </ul>
220
+ *
221
+ * @typedef {object} module:sap/base/i18n/Localization$ChangeEvent
222
+ * @property {string} [language] The newly set language.
223
+ * @property {boolean} [rtl] Whether the page uses the RTL text direction.
224
+ * @property {string} [timezone] The newly set timezone.
225
+ * @public
226
+ * @since 1.120.0
227
+ */
228
+ /**
229
+ * Attaches the <code>fnFunction</code> event handler to the {@link #event:change change} event
230
+ * of <code>module:sap/base/i18n/Localization</code>.
231
+ *
232
+ * @param {function(module:sap/base/i18n/Localization$ChangeEvent)} fnFunction
233
+ * The function to be called when the event occurs
234
+ * @public
235
+ * @since 1.120.0
236
+ * @static
237
+ */
238
+ attachChange: function (fnFunction) {
239
+ oEventing.attachEvent("change", fnFunction);
240
+ },
241
+ /**
242
+ * Detaches event handler <code>fnFunction</code> from the {@link #event:change change} event of
243
+ * this <code>module:sap/base/i18n/Localization</code>.
244
+ *
245
+ * @param {function(module:sap/base/i18n/Localization$ChangeEvent)} fnFunction Function to be called when the event occurs
246
+ * @public
247
+ * @since 1.120.0
248
+ */
249
+ detachChange: function (fnFunction) {
250
+ oEventing.detachEvent("change", fnFunction);
251
+ },
252
+ /**
253
+ * Returns the list of active terminologies defined via the Configuration.
254
+ *
255
+ * @returns {string[]|undefined} if no active terminologies are set, the default value <code>undefined</code> is returned.
256
+ * @public
257
+ * @since 1.119.0
258
+ */
259
+ getActiveTerminologies: function () {
260
+ return oWritableConfig.get({
261
+ name: "sapUiActiveTerminologies",
262
+ type: BaseConfig.Type.StringArray,
263
+ defaultValue: undefined,
264
+ external: true
265
+ });
266
+ },
267
+ /**
268
+ * Returns a string that identifies the current language.
269
+ *
270
+ * The value returned by config method in most cases corresponds to the exact value that has been
271
+ * configured by the user or application or that has been determined from the user agent settings.
272
+ * It has not been normalized, but has been validated against a relaxed version of
273
+ * {@link http://www.ietf.org/rfc/bcp/bcp47.txt BCP47}, allowing underscores ('_') instead of the
274
+ * suggested dashes ('-') and not taking the case of letters into account.
275
+ *
276
+ * The exceptions mentioned above affect languages that have been specified via the URL parameter
277
+ * <code>sap-language</code>. That parameter by definition represents an SAP logon language code
278
+ * ('ABAP language'). Most but not all of these language codes are valid ISO639 two-letter languages
279
+ * and as such are valid BCP47 language tags. For better BCP47 compliance, the framework
280
+ * maps the following non-BCP47 SAP logon codes to a BCP47 substitute:
281
+ * <pre>
282
+ * "ZH" --> "zh-Hans" // script 'Hans' added to distinguish it from zh-Hant
283
+ * "ZF" --> "zh-Hant" // ZF is not a valid ISO639 code, use the compliant language + script 'Hant'
284
+ * "1Q" --> "en-US-x-saptrc" // special language code for supportability (tracing),
285
+ * represented as en-US with a private extension
286
+ * "2Q" --> "en-US-x-sappsd" // special language code for supportability (pseudo translation),
287
+ * represented as en-US with a private extension
288
+ * "3Q" --> "en-US-x-saprigi" // special language code for the Rigi pseudo language,
289
+ * represented as en-US with a private extension
290
+ * </pre>
291
+ *
292
+ * Call {@link moduel:sap/base/i18n/Localization.getLanguageTag getLanguageTag} to get a
293
+ * {@link module:sap/base/i18n/LanguageTag LanguageTag} object matching the language.
294
+ * For a normalized BCP47 tag, call {@link module:sap/base/i18n/LanguageTag.toString toString()}
295
+ * on the returned <code>LanguageTag</code>
296
+ *
297
+ * @returns {string} Language string as configured
298
+ * @public
299
+ * @since 1.120.0
300
+ */
301
+ getLanguage: function () {
302
+ let oLanguageTag, sDerivedLanguage;
303
+ if (sLanguageSetByApi) {
304
+ return sLanguageSetByApi;
305
+ }
306
+ const sLanguage = oWritableConfig.get({
307
+ name: "sapUiLanguage",
308
+ type: BaseConfig.Type.String,
309
+ external: true
310
+ });
311
+ const sSapLocale = oWritableConfig.get({
312
+ name: "sapLocale",
313
+ type: BaseConfig.Type.String,
314
+ external: true
315
+ });
316
+ const sSapLanguage = oWritableConfig.get({
317
+ name: "sapLanguage",
318
+ type: BaseConfig.Type.String,
319
+ external: true
320
+ });
321
+ if (sSapLocale) {
322
+ oLanguageTag = createLanguageTag(sSapLocale);
323
+ sDerivedLanguage = sSapLocale;
324
+ } else if (sSapLanguage) {
325
+ if (!sLanguage && !bLanguageWarningLogged) {
326
+ // only complain about an invalid sap-language if neither sap-locale nor sap-ui-language are given
327
+ Log.warning("sap-language '" + sSapLanguage + "' is not a valid BCP47 language tag and will only be used as SAP logon language");
328
+ // Avoid multiple logging of this warning
329
+ bLanguageWarningLogged = true;
330
+ }
331
+ //fromSAPLogonLanguage catches errors oLanguageTag could be undefined
332
+ [oLanguageTag, sDerivedLanguage] = fromSAPLogonLanguage(sSapLanguage);
333
+ }
334
+ if (!oLanguageTag) {
335
+ if (sLanguage) {
336
+ oLanguageTag = createLanguageTag(sLanguage);
337
+ sDerivedLanguage = sLanguage;
338
+ } else {
339
+ sDerivedLanguage = detectLanguage();
340
+ oLanguageTag = createLanguageTag(sLanguage);
341
+ }
342
+ }
343
+ return sDerivedLanguage;
344
+ },
345
+ /**
346
+ * Get the modern language
347
+ *
348
+ * @param {string} sLanguage The language string
349
+ * @returns {string} The modern language
350
+ * @private
351
+ * @ui5-restricted sap.ui.core
352
+ * @since 1.120.0
353
+ */
354
+ getModernLanguage: function (sLanguage) {
355
+ return M_ISO639_OLD_TO_NEW[sLanguage] || sLanguage;
356
+ },
357
+ /**
358
+ * Sets a new language to be used from now on for language/region dependent
359
+ * functionality (e.g. formatting, data types, translated texts, ...).
360
+ *
361
+ * When the language can't be interpreted as a BCP47 language (using the relaxed syntax
362
+ * described in {@link #getLanguage}, an error will be thrown.
363
+ *
364
+ * When the language has changed, the Localization will fire its
365
+ * {@link module:sap/base/i18n/Localization.change change} event.
366
+ *
367
+ *
368
+ * <h3>Restrictions</h3>
369
+ *
370
+ * The framework <strong>does not</strong> guarantee that already created, language
371
+ * dependent objects will be updated by config call. It therefore remains best practice
372
+ * for applications to switch the language early, e.g. before any language dependent
373
+ * objects are created. Applications that need to support more dynamic changes of
374
+ * the language should listen to the <code>localizationChanged</code> event and adapt
375
+ * all language dependent objects that they use (e.g. by rebuilding their UI).
376
+ *
377
+ * Currently, the framework notifies the following objects about a change of the
378
+ * localization settings before it fires the <code>localizationChanged</code> event:
379
+ *
380
+ * <ul>
381
+ * <li>date and number data types that are used in property bindings or composite
382
+ * bindings in existing Elements, Controls, UIAreas or Components</li>
383
+ * <li>ResourceModels currently assigned to the Core, a UIArea, Component,
384
+ * Element or Control</li>
385
+ * <li>Elements or Controls that implement the <code>onLocalizationChanged</code> hook</li>
386
+ * </ul>
387
+ *
388
+ * It furthermore derives the RTL mode from the new language, if no explicit RTL
389
+ * mode has been set. If the RTL mode changes, the following additional actions will be taken:
390
+ *
391
+ * <ul>
392
+ * <li>the URLs of already loaded library theme files will be changed</li>
393
+ * <li>the <code>dir</code> attribute of the page will be changed to reflect the new mode.</li>
394
+ * <li>all UIAreas will be invalidated (which results in a rendering of the whole UI5 UI)</li>
395
+ * </ul>
396
+ *
397
+ * config method does not accept SAP language codes for <code>sLanguage</code>. Instead, a second
398
+ * parameter <code>sSAPLogonLanguage</code> can be provided with an SAP language code corresponding
399
+ * to the given language. A given value will be returned by the
400
+ * {@link module:sap/base/i18n/Localization.getSAPLogonLanguage getSAPLogonLanguage} method.
401
+ * It is up to the caller to provide a consistent pair of BCP47 language and SAP language code.
402
+ * The SAP language code is only checked to be of length 2 and must consist of letters or digits only.
403
+ *
404
+ * <b>Note</b>: When using config method please take note of and respect the above mentioned restrictions.
405
+ *
406
+ * @param {string} sLanguage the new language as a BCP47 compliant language tag; case doesn't matter
407
+ * and underscores can be used instead of dashes to separate components (compatibility with Java Locale IDs)
408
+ * @param {string} [sSAPLogonLanguage] SAP language code that corresponds to the <code>sLanguage</code>;
409
+ * if a value is specified, future calls to <code>getSAPLogonLanguage</code> will return that value;
410
+ * if no value is specified, the framework will use the ISO639 language part of <code>sLanguage</code>
411
+ * as SAP Logon language.
412
+ * @throws {TypeError} When <code>sLanguage</code> can't be interpreted as a BCP47 language or when
413
+ * <code>sSAPLanguage</code> is given and can't be interpreted as SAP language code.
414
+ *
415
+ * @see http://scn.sap.com/docs/DOC-14377
416
+ * @public
417
+ * @since 1.120.0
418
+ */
419
+ setLanguage: function (sLanguage, sSAPLogonLanguage) {
420
+ const oLanguageTag = createLanguageTag(sLanguage),
421
+ bOldRTL = Localization.getRTL();
422
+ check(oLanguageTag, "Localization.setLanguage: sLanguage must be a valid BCP47 language tag");
423
+ check(sSAPLogonLanguage == null || typeof sSAPLogonLanguage === 'string' && /^[A-Z0-9]{2,2}$/i.test(sSAPLogonLanguage), "Localization.setLanguage: sSAPLogonLanguage must be null or be a string of length 2, consisting of digits and latin characters only");
424
+ sSAPLogonLanguage = sSAPLogonLanguage || "";
425
+ if (oLanguageTag.toString() != Localization.getLanguageTag().toString() || sSAPLogonLanguage !== oWritableConfig.get({
426
+ name: "sapLanguage",
427
+ type: BaseConfig.Type.String,
428
+ external: true
429
+ })) {
430
+ oWritableConfig.set("sapLanguage", sSAPLogonLanguage);
431
+ sLanguageSetByApi = sLanguage;
432
+ mChanges = {};
433
+ mChanges.language = Localization.getLanguageTag().toString();
434
+ const bRtl = Localization.getRTL();
435
+ if (bOldRTL != bRtl) {
436
+ mChanges.rtl = bRtl;
437
+ }
438
+ fireChange();
439
+ }
440
+ },
441
+ /**
442
+ * Retrieves the configured IANA timezone ID.
443
+ *
444
+ * @returns {string} The configured IANA timezone ID, e.g. "America/New_York"
445
+ * @public
446
+ * @since 1.120.0
447
+ */
448
+ getTimezone: function () {
449
+ let sTimezone = oWritableConfig.get({
450
+ name: "sapTimezone",
451
+ type: BaseConfig.Type.String,
452
+ external: true,
453
+ defaultValue: oWritableConfig.get({
454
+ name: "sapUiTimezone",
455
+ type: BaseConfig.Type.String,
456
+ external: true
457
+ })
458
+ });
459
+ if (!sTimezone || !checkTimezone(sTimezone)) {
460
+ sTimezone = TimezoneUtils.getLocalTimezone();
461
+ }
462
+ return sTimezone;
463
+ },
464
+ /**
465
+ * Sets the timezone such that all date and time based calculations use config timezone.
466
+ *
467
+ * <b>Important:</b> It is strongly recommended to only use config API at the earliest point
468
+ * of time while initializing a UI5 app. A later adjustment of the time zone should be
469
+ * avoided. It can lead to unexpected data inconsistencies in a running application,
470
+ * because date objects could still be related to a previously configured time zone.
471
+ * Instead, the app should be completely restarted with the new time zone.
472
+ * For more information, see
473
+ * {@link topic:6c9e61dc157a40c19460660ece8368bc Dates, Times, Timestamps, and Time Zones}.
474
+ *
475
+ * When the timezone has changed, the Localization will fire its {@link #event:change change} event.
476
+ *
477
+ * @param {string|null} [sTimezone] IANA timezone ID, e.g. "America/New_York".
478
+ * Use <code>null</code> to reset the timezone to the browser's local timezone.
479
+ * An invalid IANA timezone ID will fall back to the browser's timezone.
480
+ * @public
481
+ * @since 1.120.0
482
+ */
483
+ setTimezone: function (sTimezone) {
484
+ check(sTimezone == null || typeof sTimezone === 'string', "Localization.setTimezone: sTimezone must be null or be a string");
485
+ const sCurrentTimezone = Localization.getTimezone();
486
+ sTimezone = sTimezone === null || !checkTimezone(sTimezone) ? undefined : sTimezone;
487
+ oWritableConfig.set("sapTimezone", sTimezone);
488
+ if (Localization.getTimezone() !== sCurrentTimezone) {
489
+ mChanges = {};
490
+ mChanges.timezone = Localization.getTimezone();
491
+ fireChange();
492
+ }
493
+ },
494
+ /**
495
+ * Returns a LanguageTag object for the current language.
496
+ *
497
+ * The LanguageTag is derived from {@link modue:sap/base/i18n/Localization.getLanguage Localization.getLanguage}.
498
+ *
499
+ * @returns {module:sap/base/i18n/LanguageTag} The LanguageTag
500
+ * @public
501
+ * @since 1.120.0
502
+ */
503
+ getLanguageTag: function () {
504
+ const oLanguageTag = new LanguageTag(Localization.getLanguage());
505
+ const sLanguage = Localization.getModernLanguage(oLanguageTag.language);
506
+ const sScript = oLanguageTag.script;
507
+ let sLanguageTag = oLanguageTag.toString();
508
+ // special case for "sr_Latn" language: "sh" should then be used
509
+ // config method is used to set the Accept-Language HTTP Header for ODataModel
510
+ // requests and .hdbtextbundle resource bundles.
511
+ // It has to remain backward compatible
512
+ if (sLanguage === "sr" && sScript === "Latn") {
513
+ sLanguageTag = sLanguageTag.replace("sr-Latn", "sh");
514
+ } else {
515
+ sLanguageTag = sLanguageTag.replace(oLanguageTag.language, sLanguage);
516
+ }
517
+ return new LanguageTag(sLanguageTag);
518
+ },
519
+ /**
520
+ * Returns whether the page uses the RTL text direction.
521
+ *
522
+ * If no mode has been explicitly set (neither <code>true</code> nor <code>false</code>),
523
+ * the mode is derived from the current language setting.
524
+ *
525
+ * @returns {boolean} whether the page uses the RTL text direction
526
+ * @public
527
+ * @since 1.120.0
528
+ */
529
+ getRTL: function () {
530
+ // if rtl has not been set (still null), return the rtl mode derived from the language
531
+ return oWritableConfig.get({
532
+ name: "sapRtl",
533
+ type: BaseConfig.Type.Boolean,
534
+ external: true,
535
+ defaultValue: oWritableConfig.get({
536
+ name: "sapUiRtl",
537
+ type: BaseConfig.Type.Boolean,
538
+ defaultValue: function () {
539
+ return impliesRTL(Localization.getLanguageTag());
540
+ },
541
+ external: true
542
+ })
543
+ });
544
+ },
545
+ /**
546
+ * Sets the character orientation mode to be used from now on.
547
+ *
548
+ * Can either be set to a concrete value (true meaning right-to-left,
549
+ * false meaning left-to-right) or to <code>null</code> which means that
550
+ * the character orientation mode should be derived from the current
551
+ * language (incl. region) setting.
552
+ *
553
+ * After changing the character orientation mode, the framework tries
554
+ * to update localization specific parts of the UI. See the documentation of
555
+ * {@link module:sap/base/i18n/Localization.setLanguage setLanguage} for details and restrictions.
556
+ *
557
+ * <b>Note</b>: See documentation of {@link module:sap/base/i18n/Localization.setLanguage setLanguage} for restrictions.
558
+ *
559
+ * @param {boolean|null} bRTL new character orientation mode or <code>null</code>
560
+ * @public
561
+ * @since 1.120.0
562
+ */
563
+ setRTL: function (bRTL) {
564
+ check(bRTL === null || typeof bRTL === "boolean", "bRTL must be null or a boolean");
565
+ bRTL = bRTL === null ? undefined : bRTL;
566
+ const oldRTL = Localization.getRTL();
567
+ oWritableConfig.set("sapRtl", bRTL);
568
+ const bCurrentRTL = Localization.getRTL();
569
+ if (oldRTL != bCurrentRTL) {
570
+ // also take the derived RTL flag into account for the before/after comparison!
571
+ mChanges = {};
572
+ mChanges.rtl = bCurrentRTL;
573
+ fireChange();
574
+ }
575
+ },
576
+ /**
577
+ * Best guess to get a proper SAP Logon Language for a given LanguageTag.
578
+ *
579
+ * Conversions taken into account:
580
+ * <ul>
581
+ * <li>use the language part only</li>
582
+ * <li>convert old ISO639 codes to newer ones (e.g. 'iw' to 'he')</li>
583
+ * <li>for Chinese, map 'Traditional Chinese' or region 'TW' to SAP proprietary code 'zf'</li>
584
+ * <li>map private extensions x-saptrc, x-sappsd and saprigi to SAP pseudo languages '1Q', '2Q' and '3Q'</li>
585
+ * <li>remove ext. language sub tags</li>
586
+ * <li>convert to uppercase</li>
587
+ * </ul>
588
+ *
589
+ * Note that the conversion also returns a result for languages that are not
590
+ * supported by the default set of SAP languages. config method has no knowledge
591
+ * about the concrete languages of any given backend system.
592
+ *
593
+ * @param {module:sap/base/i18n/LanguageTag} oLanguageTag The Locale to calculate the SAPLogonLanguage
594
+ * @returns {string} a language code that should
595
+ * @private
596
+ * @ui5-restricted sap.ui.core
597
+ * @since 1.120.0
598
+ **/
599
+ _getSAPLogonLanguage: function (oLanguageTag) {
600
+ let sLanguage = oLanguageTag.language || "";
601
+
602
+ // cut off any ext. language sub tags
603
+ if (sLanguage.indexOf("-") >= 0) {
604
+ sLanguage = sLanguage.slice(0, sLanguage.indexOf("-"));
605
+ }
606
+
607
+ // convert to new ISO codes
608
+ sLanguage = Localization.getModernLanguage(sLanguage);
609
+
610
+ // handle special case for Chinese: region TW implies Traditional Chinese (ZF)
611
+ if (sLanguage === "zh" && !oLanguageTag.script && oLanguageTag.region === "TW") {
612
+ return "ZF";
613
+ }
614
+ return M_LOCALE_TO_ABAP_LANGUAGE[join(sLanguage, oLanguageTag.script)] || M_LOCALE_TO_ABAP_LANGUAGE[join(sLanguage, oLanguageTag.region)] || M_LOCALE_TO_ABAP_LANGUAGE[getPseudoLanguageTag(oLanguageTag.privateUse)] || sLanguage.toUpperCase();
615
+ },
616
+ /**
617
+ * Returns an SAP logon language for the current language.
618
+ *
619
+ * It will be returned in uppercase.
620
+ * e.g. "EN", "DE"
621
+ *
622
+ * @returns {string} The SAP logon language code for the current language
623
+ * @public
624
+ * @since 1.120.0
625
+ */
626
+ getSAPLogonLanguage: function () {
627
+ let oLanguageTag;
628
+ const sLanguage = oWritableConfig.get({
629
+ name: "sapLanguage",
630
+ type: BaseConfig.Type.String,
631
+ external: true
632
+ }).toUpperCase();
633
+ try {
634
+ [oLanguageTag] = fromSAPLogonLanguage(sLanguage);
635
+ } catch (exc) {
636
+ //do nothing
637
+ }
638
+ if (sLanguage && !oLanguageTag) {
639
+ Log.warning("sap-language '" + sLanguage + "' is not a valid BCP47 language tag and will only be used as SAP logon language");
640
+ }
641
+ return sLanguage || Localization._getSAPLogonLanguage(Localization.getLanguageTag());
642
+ },
643
+ /**
644
+ * @returns {module:sap/base/i18n/date/CalendarType} The preferred Calendar type.
645
+ * @private
646
+ * @ui5-restricted sap.ui.core
647
+ * @since 1.120.0
648
+ */
649
+ getPreferredCalendarType: function () {
650
+ const oLocale = Localization.getLanguageTag();
651
+ return _mPreferredCalendar[oLocale.language + "-" + oLocale.region] || _mPreferredCalendar[oLocale.language] || _mPreferredCalendar["default"];
652
+ },
653
+ /**
654
+ * List of languages that the SAPUI5 core delivers.
655
+ *
656
+ * Might return undefined if the information is not available.
657
+ *
658
+ * @returns {string[]|undefined} List of Languages delivered with core
659
+ * @experimental
660
+ * @private
661
+ * @ui5-restricted sap.ui.core
662
+ * @since 1.120.0
663
+ */
664
+ getLanguagesDeliveredWithCore: function () {
665
+ return _coreI18nLocales;
666
+ },
667
+ /**
668
+ * @returns {string[]} List of supported languages
669
+ * @experimental
670
+ * @private
671
+ * @ui5-restricted sap.ui.core
672
+ * @since 1.120.0
673
+ */
674
+ getSupportedLanguages: function () {
675
+ let aLangs = BaseConfig.get({
676
+ name: "sapUiXxSupportedLanguages",
677
+ type: BaseConfig.Type.StringArray,
678
+ external: true
679
+ });
680
+ if (aLangs.length === 0 || aLangs.length === 1 && aLangs[0] === '*') {
681
+ aLangs = [];
682
+ } else if (aLangs.length === 1 && aLangs[0] === 'default') {
683
+ aLangs = this.getLanguagesDeliveredWithCore() || [];
684
+ }
685
+ return aLangs;
686
+ }
687
+ };
688
+
689
+ /**
690
+ * Checks whether the given language tag implies a character orientation
691
+ * of 'right-to-left' ('RTL').
692
+ *
693
+ * The implementation of config method and the configuration above assume
694
+ * that when a language (e.g. 'ar') is marked as 'RTL', then all language/region
695
+ * combinations for that language (e.g. 'ar_SA') will be 'RTL' as well,
696
+ * even if the combination is not mentioned in the above configuration.
697
+ * There is no means to define RTL=false for a language/region, when RTL=true for
698
+ * the language alone.
699
+ *
700
+ * As of 3/2013 config is true for all locales/regions supported by UI5.
701
+ *
702
+ * @param {module:sap/base/i18n/LanguageTag} oLanguageTag LanguageTag to check
703
+ * @returns {boolean} <code>true</code> if <code>vLanguage</code> implies RTL,
704
+ * otherwise <code>false</code>
705
+ * @private
706
+ * @since 1.120.0
707
+ */
708
+ function impliesRTL(oLanguageTag) {
709
+ let sLanguage = oLanguageTag.language || "";
710
+ sLanguage = Localization.getModernLanguage(oLanguageTag.language);
711
+ const sRegion = oLanguageTag.region || "";
712
+ if (sRegion && A_RTL_LOCALES.indexOf(sLanguage + "_" + sRegion) >= 0) {
713
+ return true;
714
+ }
715
+ return A_RTL_LOCALES.indexOf(sLanguage) >= 0;
716
+ }
717
+ function fireChange() {
718
+ oEventing.fireEvent("change", mChanges);
719
+ mChanges = undefined;
720
+ }
721
+ export default Localization;