@brightspace-ui/intl 3.28.0 → 3.30.0
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/lib/_timeZones/data/_test.js +16 -0
- package/lib/_timeZones/data/africa.js +217 -0
- package/lib/_timeZones/data/america.js +601 -0
- package/lib/_timeZones/data/antarctica.js +49 -0
- package/lib/_timeZones/data/asia.js +341 -0
- package/lib/_timeZones/data/atlantic.js +49 -0
- package/lib/_timeZones/data/australia.js +57 -0
- package/lib/_timeZones/data/europe.js +249 -0
- package/lib/_timeZones/data/index.js +9 -0
- package/lib/_timeZones/data/indian.js +53 -0
- package/lib/_timeZones/data/pacific.js +161 -0
- package/lib/_timeZones/mapper.js +236 -0
- package/lib/common.js +4 -2
- package/lib/timeZones.js +59 -0
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indian Ocean Timezone Mappings
|
|
3
|
+
* Maps IANA timezone identifiers to country codes and source files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const indianTimezones = {
|
|
7
|
+
'Indian/Antananarivo': {
|
|
8
|
+
regionCode: 'MG',
|
|
9
|
+
ianaSource: 'africa'
|
|
10
|
+
},
|
|
11
|
+
'Indian/Chagos': {
|
|
12
|
+
regionCode: 'IO',
|
|
13
|
+
ianaSource: 'asia'
|
|
14
|
+
},
|
|
15
|
+
'Indian/Christmas': {
|
|
16
|
+
regionCode: 'CX',
|
|
17
|
+
ianaSource: 'australasia'
|
|
18
|
+
},
|
|
19
|
+
'Indian/Cocos': {
|
|
20
|
+
regionCode: 'CC',
|
|
21
|
+
ianaSource: 'australasia'
|
|
22
|
+
},
|
|
23
|
+
'Indian/Comoro': {
|
|
24
|
+
regionCode: 'KM',
|
|
25
|
+
ianaSource: 'africa'
|
|
26
|
+
},
|
|
27
|
+
'Indian/Kerguelen': {
|
|
28
|
+
regionCode: 'TF',
|
|
29
|
+
ianaSource: 'antarctica'
|
|
30
|
+
},
|
|
31
|
+
'Indian/Mahe': {
|
|
32
|
+
regionCode: 'SC',
|
|
33
|
+
ianaSource: 'africa'
|
|
34
|
+
},
|
|
35
|
+
'Indian/Maldives': {
|
|
36
|
+
regionCode: 'MV',
|
|
37
|
+
ianaSource: 'asia'
|
|
38
|
+
},
|
|
39
|
+
'Indian/Mauritius': {
|
|
40
|
+
regionCode: 'MU',
|
|
41
|
+
ianaSource: 'africa'
|
|
42
|
+
},
|
|
43
|
+
'Indian/Mayotte': {
|
|
44
|
+
regionCode: 'YT',
|
|
45
|
+
ianaSource: 'africa'
|
|
46
|
+
},
|
|
47
|
+
'Indian/Reunion': {
|
|
48
|
+
regionCode: 'RE',
|
|
49
|
+
ianaSource: 'africa'
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default indianTimezones;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pacific Timezone Mappings
|
|
3
|
+
* Maps IANA timezone identifiers to country codes and source files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const pacificTimezones = {
|
|
7
|
+
'Pacific/Apia': {
|
|
8
|
+
regionCode: 'WS',
|
|
9
|
+
ianaSource: 'australasia'
|
|
10
|
+
},
|
|
11
|
+
'Pacific/Auckland': {
|
|
12
|
+
regionCode: 'NZ',
|
|
13
|
+
ianaSource: 'australasia'
|
|
14
|
+
},
|
|
15
|
+
'Pacific/Bougainville': {
|
|
16
|
+
regionCode: 'PG',
|
|
17
|
+
ianaSource: 'australasia'
|
|
18
|
+
},
|
|
19
|
+
'Pacific/Chatham': {
|
|
20
|
+
regionCode: 'NZ',
|
|
21
|
+
ianaSource: 'australasia'
|
|
22
|
+
},
|
|
23
|
+
'Pacific/Chuuk': {
|
|
24
|
+
regionCode: 'FM',
|
|
25
|
+
ianaSource: 'australasia'
|
|
26
|
+
},
|
|
27
|
+
'Pacific/Easter': {
|
|
28
|
+
regionCode: 'CL',
|
|
29
|
+
ianaSource: 'southamerica'
|
|
30
|
+
},
|
|
31
|
+
'Pacific/Efate': {
|
|
32
|
+
regionCode: 'VU',
|
|
33
|
+
ianaSource: 'australasia'
|
|
34
|
+
},
|
|
35
|
+
'Pacific/Enderbury': {
|
|
36
|
+
regionCode: 'KI',
|
|
37
|
+
ianaSource: 'australasia'
|
|
38
|
+
},
|
|
39
|
+
'Pacific/Fakaofo': {
|
|
40
|
+
regionCode: 'TK',
|
|
41
|
+
ianaSource: 'australasia'
|
|
42
|
+
},
|
|
43
|
+
'Pacific/Fiji': {
|
|
44
|
+
regionCode: 'FJ',
|
|
45
|
+
ianaSource: 'australasia'
|
|
46
|
+
},
|
|
47
|
+
'Pacific/Funafuti': {
|
|
48
|
+
regionCode: 'TV',
|
|
49
|
+
ianaSource: 'australasia'
|
|
50
|
+
},
|
|
51
|
+
'Pacific/Galapagos': {
|
|
52
|
+
regionCode: 'EC',
|
|
53
|
+
ianaSource: 'southamerica'
|
|
54
|
+
},
|
|
55
|
+
'Pacific/Gambier': {
|
|
56
|
+
regionCode: 'PF',
|
|
57
|
+
ianaSource: 'australasia'
|
|
58
|
+
},
|
|
59
|
+
'Pacific/Guadalcanal': {
|
|
60
|
+
regionCode: 'SB',
|
|
61
|
+
ianaSource: 'australasia'
|
|
62
|
+
},
|
|
63
|
+
'Pacific/Guam': {
|
|
64
|
+
regionCode: 'GU',
|
|
65
|
+
ianaSource: 'australasia'
|
|
66
|
+
},
|
|
67
|
+
'Pacific/Honolulu': {
|
|
68
|
+
regionCode: 'US',
|
|
69
|
+
ianaSource: 'northamerica'
|
|
70
|
+
},
|
|
71
|
+
'Pacific/Kiritimati': {
|
|
72
|
+
regionCode: 'KI',
|
|
73
|
+
ianaSource: 'australasia'
|
|
74
|
+
},
|
|
75
|
+
'Pacific/Kosrae': {
|
|
76
|
+
regionCode: 'FM',
|
|
77
|
+
ianaSource: 'australasia'
|
|
78
|
+
},
|
|
79
|
+
'Pacific/Kwajalein': {
|
|
80
|
+
regionCode: 'MH',
|
|
81
|
+
ianaSource: 'australasia'
|
|
82
|
+
},
|
|
83
|
+
'Pacific/Majuro': {
|
|
84
|
+
regionCode: 'MH',
|
|
85
|
+
ianaSource: 'australasia'
|
|
86
|
+
},
|
|
87
|
+
'Pacific/Marquesas': {
|
|
88
|
+
regionCode: 'PF',
|
|
89
|
+
ianaSource: 'australasia'
|
|
90
|
+
},
|
|
91
|
+
'Pacific/Midway': {
|
|
92
|
+
regionCode: 'UM',
|
|
93
|
+
ianaSource: 'australasia'
|
|
94
|
+
},
|
|
95
|
+
'Pacific/Nauru': {
|
|
96
|
+
regionCode: 'NR',
|
|
97
|
+
ianaSource: 'australasia'
|
|
98
|
+
},
|
|
99
|
+
'Pacific/Niue': {
|
|
100
|
+
regionCode: 'NU',
|
|
101
|
+
ianaSource: 'australasia'
|
|
102
|
+
},
|
|
103
|
+
'Pacific/Norfolk': {
|
|
104
|
+
regionCode: 'NF',
|
|
105
|
+
ianaSource: 'australasia'
|
|
106
|
+
},
|
|
107
|
+
'Pacific/Noumea': {
|
|
108
|
+
regionCode: 'NC',
|
|
109
|
+
ianaSource: 'australasia'
|
|
110
|
+
},
|
|
111
|
+
'Pacific/Pago_Pago': {
|
|
112
|
+
regionCode: 'AS',
|
|
113
|
+
ianaSource: 'australasia'
|
|
114
|
+
},
|
|
115
|
+
'Pacific/Palau': {
|
|
116
|
+
regionCode: 'PW',
|
|
117
|
+
ianaSource: 'australasia'
|
|
118
|
+
},
|
|
119
|
+
'Pacific/Pitcairn': {
|
|
120
|
+
regionCode: 'PN',
|
|
121
|
+
ianaSource: 'australasia'
|
|
122
|
+
},
|
|
123
|
+
'Pacific/Pohnpei': {
|
|
124
|
+
regionCode: 'FM',
|
|
125
|
+
ianaSource: 'australasia'
|
|
126
|
+
},
|
|
127
|
+
'Pacific/Port_Moresby': {
|
|
128
|
+
regionCode: 'PG',
|
|
129
|
+
ianaSource: 'australasia'
|
|
130
|
+
},
|
|
131
|
+
'Pacific/Rarotonga': {
|
|
132
|
+
regionCode: 'CK',
|
|
133
|
+
ianaSource: 'australasia'
|
|
134
|
+
},
|
|
135
|
+
'Pacific/Saipan': {
|
|
136
|
+
regionCode: 'MP',
|
|
137
|
+
ianaSource: 'australasia'
|
|
138
|
+
},
|
|
139
|
+
'Pacific/Tahiti': {
|
|
140
|
+
regionCode: 'PF',
|
|
141
|
+
ianaSource: 'australasia'
|
|
142
|
+
},
|
|
143
|
+
'Pacific/Tarawa': {
|
|
144
|
+
regionCode: 'KI',
|
|
145
|
+
ianaSource: 'australasia'
|
|
146
|
+
},
|
|
147
|
+
'Pacific/Tongatapu': {
|
|
148
|
+
regionCode: 'TO',
|
|
149
|
+
ianaSource: 'australasia'
|
|
150
|
+
},
|
|
151
|
+
'Pacific/Wake': {
|
|
152
|
+
regionCode: 'UM',
|
|
153
|
+
ianaSource: 'australasia'
|
|
154
|
+
},
|
|
155
|
+
'Pacific/Wallis': {
|
|
156
|
+
regionCode: 'WF',
|
|
157
|
+
ianaSource: 'australasia'
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export default pacificTimezones;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TimeZone Utilities
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for working with IANA timeZone identifiers
|
|
5
|
+
* and their corresponding region information using ES modules.
|
|
6
|
+
*
|
|
7
|
+
* Data is based on the IANA Time Zone Database (tzdata) and excludes
|
|
8
|
+
* backward compatibility and etcetera entries.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { getDocumentLocaleSettings } from '../common.js';
|
|
12
|
+
|
|
13
|
+
export class TimeZoneMapper {
|
|
14
|
+
constructor(modules) {
|
|
15
|
+
this.mappings = new Map();
|
|
16
|
+
this.loaded = false;
|
|
17
|
+
this.modules = modules ? [].concat(modules).map(m => m.toLowerCase()) : [
|
|
18
|
+
'africa',
|
|
19
|
+
'america',
|
|
20
|
+
'asia',
|
|
21
|
+
'europe',
|
|
22
|
+
'pacific',
|
|
23
|
+
'australia',
|
|
24
|
+
'antarctica',
|
|
25
|
+
'atlantic',
|
|
26
|
+
'indian'
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get all countries with their localized names
|
|
32
|
+
* @param {string|string[]} locales - Locale(s) for display names
|
|
33
|
+
* @returns {Array<{code: string, name: string}>} Array of region objects
|
|
34
|
+
*/
|
|
35
|
+
getAllCountries(locales = 'en') {
|
|
36
|
+
const regionCodes = this.getAllRegionCodes();
|
|
37
|
+
const displayNames = new Intl.DisplayNames(locales, { type: 'region' });
|
|
38
|
+
|
|
39
|
+
return regionCodes.map(code => ({
|
|
40
|
+
code,
|
|
41
|
+
name: displayNames.of(code)
|
|
42
|
+
})).sort((a, b) => a.name.localeCompare(b.name, locales));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get all unique region codes
|
|
46
|
+
* @returns {string[]} Sorted array of all region codes
|
|
47
|
+
*/
|
|
48
|
+
getAllRegionCodes() {
|
|
49
|
+
this._ensureLoaded();
|
|
50
|
+
const regionCodes = new Set();
|
|
51
|
+
|
|
52
|
+
for (const info of this.mappings.values()) {
|
|
53
|
+
regionCodes.add(info.regionCode);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Array.from(regionCodes).sort();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get all available timeZone identifiers
|
|
60
|
+
* @returns {string[]} Sorted array of all timeZone identifiers
|
|
61
|
+
*/
|
|
62
|
+
getAllTimeZones() {
|
|
63
|
+
this._ensureLoaded();
|
|
64
|
+
return Array.from(this.mappings.keys()).sort();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get IANA source file for a timeZone
|
|
68
|
+
* @param {string} timeZoneId - IANA timeZone identifier
|
|
69
|
+
* @returns {string|null} Source file name or null if not found
|
|
70
|
+
*/
|
|
71
|
+
getIanaSource(timeZoneId) {
|
|
72
|
+
this._ensureLoaded();
|
|
73
|
+
const mapping = this.mappings.get(timeZoneId);
|
|
74
|
+
return mapping ? mapping.ianaSource : null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get region code for a timeZone
|
|
78
|
+
* @param {string} timeZoneId - IANA timeZone identifier (e.g., "America/New_York")
|
|
79
|
+
* @returns {string|null} ISO 3166-1 alpha-2 region code or null if not found
|
|
80
|
+
*/
|
|
81
|
+
getRegionCode(timeZoneId) {
|
|
82
|
+
this._ensureLoaded();
|
|
83
|
+
const mapping = this.mappings.get(timeZoneId);
|
|
84
|
+
return mapping ? mapping.regionCode : null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get localized region name using Intl.DisplayNames
|
|
88
|
+
* @param {string} timeZoneId - IANA timeZone identifier
|
|
89
|
+
* @param {string|string[]} locales - Locale(s) for display names
|
|
90
|
+
* @returns {string|null} Localized region name or null if not found
|
|
91
|
+
*/
|
|
92
|
+
getRegionName(timeZoneId, locale = getDocumentLocaleSettings().language) {
|
|
93
|
+
const regionCode = this.getRegionCode(timeZoneId);
|
|
94
|
+
if (!regionCode) return null;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const displayNames = new Intl.DisplayNames(locale, { type: 'region' });
|
|
98
|
+
return displayNames.of(regionCode);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.warn('Failed to get localized region name:', error);
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get complete mapping information for a timeZone
|
|
107
|
+
* @param {string} timeZoneId - IANA timeZone identifier
|
|
108
|
+
* @returns {Object|null} Complete mapping object or null if not found
|
|
109
|
+
*/
|
|
110
|
+
getTimeZoneInfo(timeZoneId) {
|
|
111
|
+
this._ensureLoaded();
|
|
112
|
+
return this.mappings.get(timeZoneId) || null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Group timeZones by region
|
|
116
|
+
* @param {string|string[]} locales - Locale(s) for region names
|
|
117
|
+
* @returns {Object} Object with region codes as keys and timeZone arrays as values
|
|
118
|
+
*/
|
|
119
|
+
getTimeZonesByRegion(locales = 'en') {
|
|
120
|
+
this._ensureLoaded();
|
|
121
|
+
const result = {};
|
|
122
|
+
|
|
123
|
+
for (const [timeZone, info] of this.mappings.entries()) {
|
|
124
|
+
const regionCode = info.regionCode;
|
|
125
|
+
if (!result[regionCode]) {
|
|
126
|
+
result[regionCode] = {
|
|
127
|
+
name: this.getRegionName(timeZone, locales),
|
|
128
|
+
timeZones: []
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
result[regionCode].timeZones.push(timeZone);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Sort timeZones within each region
|
|
135
|
+
for (const region of Object.values(result)) {
|
|
136
|
+
region.timeZones.sort();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get all timeZones for a specific region
|
|
143
|
+
* @param {string} regionCode - ISO 3166-1 alpha-2 region code
|
|
144
|
+
* @returns {string[]} Array of timeZone identifiers
|
|
145
|
+
*/
|
|
146
|
+
getTimeZonesForRegion(regionCode) {
|
|
147
|
+
this._ensureLoaded();
|
|
148
|
+
const timeZones = [];
|
|
149
|
+
|
|
150
|
+
for (const [timeZone, info] of this.mappings.entries()) {
|
|
151
|
+
if (info.regionCode === regionCode.toUpperCase()) {
|
|
152
|
+
timeZones.push(timeZone);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return timeZones.sort();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Load timeZone mappings from a single combined object
|
|
160
|
+
* @param {Object} timeZoneData - Combined timeZone data object
|
|
161
|
+
*/
|
|
162
|
+
loadFromData(timeZoneData) {
|
|
163
|
+
this.mappings.clear();
|
|
164
|
+
for (const [timeZone, info] of Object.entries(timeZoneData)) {
|
|
165
|
+
this.mappings.set(timeZone, info);
|
|
166
|
+
}
|
|
167
|
+
this.loaded = true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Load timeZone mappings from JavaScript modules
|
|
172
|
+
* @param {string} basePath - Base path to the timeZone mappings directory
|
|
173
|
+
* @returns {Promise<void>}
|
|
174
|
+
*/
|
|
175
|
+
async loadMappings(basePath = './data/') {
|
|
176
|
+
if (this.loaded) return;
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
for (const moduleName of this.modules) {
|
|
180
|
+
const module = await import(`${basePath}${moduleName}.js`);
|
|
181
|
+
const timeZoneData = module.default || module[`${moduleName}TimeZones`];
|
|
182
|
+
|
|
183
|
+
// Merge all timeZone data into the main mappings
|
|
184
|
+
for (const [timeZone, info] of Object.entries(timeZoneData)) {
|
|
185
|
+
this.mappings.set(timeZone, info);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.loaded = true;
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error('Failed to load timeZone mappings:', error);
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Search timeZones by partial name match
|
|
197
|
+
* @param {string} query - Search query
|
|
198
|
+
* @param {string|string[]} locales - Locale(s) for region name matching
|
|
199
|
+
* @returns {string[]} Array of matching timeZone identifiers
|
|
200
|
+
*/
|
|
201
|
+
searchTimeZones(query, locales = 'en') {
|
|
202
|
+
this._ensureLoaded();
|
|
203
|
+
const lowerQuery = query.toLowerCase();
|
|
204
|
+
const results = [];
|
|
205
|
+
|
|
206
|
+
for (const [timeZone] of this.mappings.entries()) {
|
|
207
|
+
// Match timeZone identifier
|
|
208
|
+
if (timeZone.toLowerCase().includes(lowerQuery)) {
|
|
209
|
+
results.push(timeZone);
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Match region name
|
|
214
|
+
try {
|
|
215
|
+
const regionName = this.getRegionName(timeZone, locales);
|
|
216
|
+
if (regionName && regionName.toLowerCase().includes(lowerQuery)) {
|
|
217
|
+
results.push(timeZone);
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
// Continue if region name lookup fails
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return results.sort();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Check if mappings are loaded
|
|
229
|
+
* @private
|
|
230
|
+
*/
|
|
231
|
+
_ensureLoaded() {
|
|
232
|
+
if (!this.loaded) {
|
|
233
|
+
throw new Error('TimeZone mappings not loaded. Call loadMappings() first.');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
package/lib/common.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DocumentLocaleSettings } from './document-locale-settings.js';
|
|
2
2
|
|
|
3
3
|
export const defaultLocale = 'en';
|
|
4
|
-
export const supportedBaseLocales = ['ar', 'cy', 'da', 'de', 'en', 'es', 'fr', 'haw', 'hi', 'ja', 'ko', 'mi', 'nl', 'pt', 'sv', 'tr', 'zh'];
|
|
5
|
-
export const supportedLangpacks = ['ar', 'cy', 'da', 'de', 'en', 'en-gb', 'es', 'es-es', 'fr', 'fr-fr', 'fr-on', 'haw', 'hi', 'ja', 'ko', 'mi', 'nl', 'pt', 'sv', 'tr', 'zh-cn', 'zh-tw'];
|
|
4
|
+
export const supportedBaseLocales = ['ar', 'cy', 'da', 'de', 'en', 'es', 'fr', 'haw', 'hi', 'ja', 'ko', 'mi', 'nl', 'pt', 'sv', 'th', 'tr', 'vi', 'zh'];
|
|
5
|
+
export const supportedLangpacks = ['ar', 'cy', 'da', 'de', 'en', 'en-gb', 'es', 'es-es', 'fr', 'fr-fr', 'fr-on', 'haw', 'hi', 'ja', 'ko', 'mi', 'nl', 'pt', 'sv', 'th', 'tr', 'vi', 'zh-cn', 'zh-tw'];
|
|
6
6
|
|
|
7
7
|
export const supportedLocalesDetails = [
|
|
8
8
|
{ code: 'ar-sa', dir: 'rtl', name: 'العربية (المملكة العربية السعودية)' },
|
|
@@ -25,7 +25,9 @@ export const supportedLocalesDetails = [
|
|
|
25
25
|
{ code: 'nl-nl', dir: 'ltr', name: 'Nederlands (Nederland)' },
|
|
26
26
|
{ code: 'pt-br', dir: 'ltr', name: 'Português (Brasil)' },
|
|
27
27
|
{ code: 'sv-se', dir: 'ltr', name: 'Svenska (Sverige)' },
|
|
28
|
+
{ code: 'th-th', dir: 'ltr', name: 'ไทย (ไทย)' },
|
|
28
29
|
{ code: 'tr-tr', dir: 'ltr', name: 'Türkçe (Türkiye)' },
|
|
30
|
+
{ code: 'vi-vn', dir: 'ltr', name: 'Tiếng Việt (Việt Nam)' },
|
|
29
31
|
{ code: 'zh-cn', overrideCode: 'zh-Hans', dir: 'ltr', name: '中文(简体)' },
|
|
30
32
|
{ code: 'zh-tw', overrideCode: 'zh-Hant', dir: 'ltr', name: '中文(繁体)' }
|
|
31
33
|
];
|
package/lib/timeZones.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getDocumentLocaleSettings } from './common.js';
|
|
2
|
+
import { TimeZoneMapper } from './_timeZones/mapper.js';
|
|
3
|
+
|
|
4
|
+
let timeZoneData;
|
|
5
|
+
getDocumentLocaleSettings().addChangeListener(() => timeZoneData = null);
|
|
6
|
+
|
|
7
|
+
const tzMap = {
|
|
8
|
+
'Asia/Calcutta': 'Asia/Kolkata',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const timeZoneIdentifiers = Intl.supportedValuesOf('timeZone').map(t => tzMap[t] || t);
|
|
12
|
+
|
|
13
|
+
export async function getTimeZonesData(region, modules) {
|
|
14
|
+
let timeZones;
|
|
15
|
+
const mapper = new TimeZoneMapper(modules);
|
|
16
|
+
await mapper.loadMappings();
|
|
17
|
+
|
|
18
|
+
if (region) {
|
|
19
|
+
timeZones = new Intl.Locale(`en-${region}`).getTimeZones?.();
|
|
20
|
+
if (!timeZones?.length) {
|
|
21
|
+
timeZones = mapper.getTimeZonesForRegion(region);
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
if (timeZoneData) return timeZoneData;
|
|
25
|
+
timeZones = timeZoneIdentifiers;
|
|
26
|
+
}
|
|
27
|
+
return await Promise.all(timeZones.map(l => getTimeZoneData(l, { mapper })));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function getTimeZoneData(
|
|
31
|
+
identifier = getDocumentLocaleSettings().timezone.identifier,
|
|
32
|
+
{
|
|
33
|
+
modules,
|
|
34
|
+
mapper,
|
|
35
|
+
locale = getDocumentLocaleSettings().language || 'en'
|
|
36
|
+
} = {}) {
|
|
37
|
+
mapper ??= new TimeZoneMapper(modules);
|
|
38
|
+
await mapper.loadMappings();
|
|
39
|
+
const [localName, abbreviation, offset] = ['long', 'short', 'longOffset'].map(timeZoneName => new Intl.DateTimeFormat(locale, { timeZone: identifier, timeZoneName }).formatToParts().find(({ type }) => type === 'timeZoneName').value);
|
|
40
|
+
const city = identifier.replace(/[^/]*\//, '').replace('_', ' ');
|
|
41
|
+
const country = mapper.getRegionName(identifier) || '';
|
|
42
|
+
const friendlyName = `${country && `${country} - `}${city}`;
|
|
43
|
+
const inputName = `(${offset}) ${city} - ${localName}`;
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
identifier,
|
|
47
|
+
abbreviation,
|
|
48
|
+
city,
|
|
49
|
+
country,
|
|
50
|
+
friendlyName,
|
|
51
|
+
inputName,
|
|
52
|
+
localName,
|
|
53
|
+
offset
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function validateTimeZone(identifier = getDocumentLocaleSettings().timezone.identifier) {
|
|
58
|
+
return timeZoneIdentifiers.includes(identifier);
|
|
59
|
+
}
|
package/package.json
CHANGED