@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.
- package/.eslintignore +2 -1
- package/CHANGELOG.md +12 -0
- package/dist/generated/assets/cldr/ar.json +102 -62
- package/dist/generated/assets/cldr/ar_EG.json +102 -62
- package/dist/generated/assets/cldr/ar_SA.json +102 -62
- package/dist/generated/assets/cldr/bg.json +364 -325
- package/dist/generated/assets/cldr/ca.json +491 -453
- package/dist/generated/assets/cldr/cs.json +431 -324
- package/dist/generated/assets/cldr/cy.json +608 -340
- package/dist/generated/assets/cldr/da.json +290 -227
- package/dist/generated/assets/cldr/de.json +348 -241
- package/dist/generated/assets/cldr/de_AT.json +348 -241
- package/dist/generated/assets/cldr/de_CH.json +347 -240
- package/dist/generated/assets/cldr/el.json +128 -100
- package/dist/generated/assets/cldr/el_CY.json +128 -100
- package/dist/generated/assets/cldr/en.json +538 -512
- package/dist/generated/assets/cldr/en_AU.json +583 -520
- package/dist/generated/assets/cldr/en_GB.json +485 -441
- package/dist/generated/assets/cldr/en_HK.json +519 -474
- package/dist/generated/assets/cldr/en_IE.json +485 -440
- package/dist/generated/assets/cldr/en_IN.json +465 -420
- package/dist/generated/assets/cldr/en_NZ.json +505 -460
- package/dist/generated/assets/cldr/en_PG.json +505 -460
- package/dist/generated/assets/cldr/en_SG.json +505 -460
- package/dist/generated/assets/cldr/en_ZA.json +485 -440
- package/dist/generated/assets/cldr/es.json +709 -456
- package/dist/generated/assets/cldr/es_AR.json +687 -434
- package/dist/generated/assets/cldr/es_BO.json +721 -468
- package/dist/generated/assets/cldr/es_CL.json +567 -422
- package/dist/generated/assets/cldr/es_CO.json +485 -339
- package/dist/generated/assets/cldr/es_MX.json +734 -481
- package/dist/generated/assets/cldr/es_PE.json +409 -372
- package/dist/generated/assets/cldr/es_UY.json +433 -396
- package/dist/generated/assets/cldr/es_VE.json +453 -416
- package/dist/generated/assets/cldr/et.json +340 -307
- package/dist/generated/assets/cldr/fa.json +96 -34
- package/dist/generated/assets/cldr/fi.json +359 -308
- package/dist/generated/assets/cldr/fr.json +347 -321
- package/dist/generated/assets/cldr/fr_BE.json +347 -321
- package/dist/generated/assets/cldr/fr_CA.json +458 -432
- package/dist/generated/assets/cldr/fr_CH.json +290 -264
- package/dist/generated/assets/cldr/fr_LU.json +347 -321
- package/dist/generated/assets/cldr/he.json +241 -130
- package/dist/generated/assets/cldr/hi.json +103 -53
- package/dist/generated/assets/cldr/hr.json +467 -410
- package/dist/generated/assets/cldr/hu.json +246 -195
- package/dist/generated/assets/cldr/id.json +478 -406
- package/dist/generated/assets/cldr/it.json +418 -362
- package/dist/generated/assets/cldr/it_CH.json +418 -362
- package/dist/generated/assets/cldr/ja.json +58 -18
- package/dist/generated/assets/cldr/kk.json +562 -398
- package/dist/generated/assets/cldr/ko.json +36 -15
- package/dist/generated/assets/cldr/lt.json +320 -231
- package/dist/generated/assets/cldr/lv.json +184 -120
- package/dist/generated/assets/cldr/ms.json +460 -388
- package/dist/generated/assets/cldr/nb.json +160 -92
- package/dist/generated/assets/cldr/nl.json +621 -373
- package/dist/generated/assets/cldr/nl_BE.json +621 -373
- package/dist/generated/assets/cldr/pl.json +590 -279
- package/dist/generated/assets/cldr/pt.json +696 -334
- package/dist/generated/assets/cldr/pt_PT.json +730 -454
- package/dist/generated/assets/cldr/ro.json +409 -339
- package/dist/generated/assets/cldr/ru.json +317 -279
- package/dist/generated/assets/cldr/ru_UA.json +312 -274
- package/dist/generated/assets/cldr/sk.json +454 -413
- package/dist/generated/assets/cldr/sl.json +118 -80
- package/dist/generated/assets/cldr/sr.json +294 -142
- package/dist/generated/assets/cldr/sr_Latn.json +972 -824
- package/dist/generated/assets/cldr/sv.json +382 -338
- package/dist/generated/assets/cldr/th.json +56 -36
- package/dist/generated/assets/cldr/tr.json +371 -320
- package/dist/generated/assets/cldr/uk.json +340 -290
- package/dist/generated/assets/cldr/vi.json +352 -328
- package/dist/generated/assets/cldr/zh_CN.json +34 -10
- package/dist/generated/assets/cldr/zh_HK.json +33 -9
- package/dist/generated/assets/cldr/zh_SG.json +33 -9
- package/dist/generated/assets/cldr/zh_TW.json +32 -8
- package/dist/sap/base/Event.js +59 -0
- package/dist/sap/base/Eventing.js +147 -0
- package/dist/sap/base/Log.js +2 -239
- package/dist/sap/base/assert.js +28 -1
- package/dist/sap/base/config/MemoryConfigurationProvider.js +20 -0
- package/dist/sap/base/config.js +17 -0
- package/dist/sap/base/i18n/Formatting.js +1130 -0
- package/dist/sap/base/i18n/LanguageTag.js +173 -0
- package/dist/sap/base/i18n/Localization.js +721 -0
- package/dist/sap/base/i18n/date/CalendarType.js +43 -0
- package/dist/sap/base/i18n/date/CalendarWeekNumbering.js +105 -0
- package/dist/sap/base/i18n/date/TimezoneUtils.js +319 -0
- package/dist/sap/base/strings/camelize.js +30 -0
- package/dist/sap/base/strings/formatMessage.js +88 -15
- package/dist/sap/base/util/ObjectPath.js +95 -3
- package/dist/sap/base/util/Version.js +157 -0
- package/dist/sap/base/util/_merge.js +83 -26
- package/dist/sap/base/util/array/uniqueSort.js +37 -15
- package/dist/sap/base/util/deepClone.js +102 -0
- package/dist/sap/base/util/deepEqual.js +75 -51
- package/dist/sap/base/util/extend.js +58 -7
- package/dist/sap/base/util/isEmptyObject.js +34 -0
- package/dist/sap/base/util/isPlainObject.js +35 -1
- package/dist/sap/base/util/now.js +24 -3
- package/dist/sap/base/util/resolveReference.js +157 -0
- package/dist/sap/base/util/uid.js +27 -0
- package/dist/sap/ui/base/DataType.js +657 -0
- package/dist/sap/ui/base/Interface.js +47 -1
- package/dist/sap/ui/base/Metadata.js +436 -171
- package/dist/sap/ui/base/Object.js +284 -48
- package/dist/sap/ui/core/CalendarType.js +24 -8
- package/dist/sap/ui/core/Locale.js +190 -155
- package/dist/sap/ui/core/LocaleData.js +2661 -1351
- package/dist/sap/ui/core/Supportability.js +5 -0
- package/dist/sap/ui/core/Theming.js +539 -0
- package/dist/sap/ui/core/date/Buddhist.js +162 -87
- package/dist/sap/ui/core/date/CalendarUtils.js +61 -32
- package/dist/sap/ui/core/date/CalendarWeekNumbering.js +30 -7
- package/dist/sap/ui/core/date/Gregorian.js +25 -10
- package/dist/sap/ui/core/date/Islamic.js +298 -185
- package/dist/sap/ui/core/date/Japanese.js +210 -115
- package/dist/sap/ui/core/date/Persian.js +324 -195
- package/dist/sap/ui/core/date/UI5Date.js +923 -237
- package/dist/sap/ui/core/date/UniversalDate.js +1238 -256
- package/dist/sap/ui/core/date/_Calendars.js +10 -1
- package/dist/sap/ui/core/format/DateFormat.js +3174 -2111
- package/dist/sap/ui/core/format/TimezoneUtil.js +24 -89
- package/package-scripts.cjs +6 -11
- package/package.json +9 -5
- package/used-modules.txt +24 -1
- 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;
|