@tolgee/core 5.33.2 → 5.33.3-prerelease.2efc0e6b.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/dist/tolgee.cjs.js +227 -186
- package/dist/tolgee.cjs.js.map +1 -1
- package/dist/tolgee.cjs.min.js +1 -1
- package/dist/tolgee.cjs.min.js.map +1 -1
- package/dist/tolgee.esm.js +227 -186
- package/dist/tolgee.esm.js.map +1 -1
- package/dist/tolgee.esm.min.js +1 -1
- package/dist/tolgee.esm.min.js.map +1 -1
- package/dist/tolgee.esm.min.mjs +1 -1
- package/dist/tolgee.esm.min.mjs.map +1 -1
- package/dist/tolgee.esm.mjs +227 -186
- package/dist/tolgee.esm.mjs.map +1 -1
- package/dist/tolgee.umd.js +227 -186
- package/dist/tolgee.umd.js.map +1 -1
- package/dist/tolgee.umd.min.js +1 -1
- package/dist/tolgee.umd.min.js.map +1 -1
- package/lib/Controller/Cache/Cache.d.ts +8 -12
- package/lib/Controller/Cache/helpers.d.ts +3 -2
- package/lib/Controller/Controller.d.ts +57 -26
- package/lib/Controller/Events/EventEmitter.d.ts +5 -5
- package/lib/Controller/Events/EventEmitterCombined.d.ts +6 -0
- package/lib/Controller/Events/Events.d.ts +39 -12
- package/lib/Controller/State/State.d.ts +10 -4
- package/lib/Controller/State/initState.d.ts +29 -7
- package/lib/TolgeeCore.d.ts +25 -28
- package/lib/helpers.d.ts +2 -2
- package/lib/types/cache.d.ts +19 -1
- package/lib/types/events.d.ts +24 -23
- package/lib/types/index.d.ts +1 -1
- package/package.json +2 -2
- package/src/Controller/Cache/Cache.test.ts +189 -0
- package/src/Controller/Cache/Cache.ts +118 -57
- package/src/Controller/Cache/helpers.ts +12 -3
- package/src/Controller/Controller.ts +81 -27
- package/src/Controller/Events/EventEmitter.ts +23 -15
- package/src/Controller/Events/EventEmitterCombined.ts +55 -0
- package/src/Controller/Events/Events.ts +31 -23
- package/src/Controller/Plugins/Plugins.ts +5 -0
- package/src/Controller/State/State.ts +26 -6
- package/src/Controller/State/initState.ts +35 -7
- package/src/TolgeeCore.ts +14 -17
- package/src/__test/cache.test.ts +2 -26
- package/src/__test/client.test.ts +3 -3
- package/src/__test/events.test.ts +40 -13
- package/src/__test/load.matrix.test.ts +123 -0
- package/src/__test/load.required.test.ts +71 -0
- package/src/__test/namespaces.required.test.ts +52 -0
- package/src/__test/options.test.ts +1 -1
- package/src/__test/testTools.ts +39 -0
- package/src/helpers.ts +2 -1
- package/src/types/cache.ts +24 -1
- package/src/types/events.ts +33 -24
- package/src/types/index.ts +1 -0
- package/lib/Controller/Events/EventEmitterSelective.d.ts +0 -7
- package/src/Controller/Events/EventEmitterSelective.test.ts +0 -110
- package/src/Controller/Events/EventEmitterSelective.ts +0 -133
package/dist/tolgee.umd.js
CHANGED
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
};
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const EventEmitter = (type, isActive) => {
|
|
96
96
|
let handlers = [];
|
|
97
|
-
return
|
|
97
|
+
return {
|
|
98
98
|
listen(handler) {
|
|
99
99
|
const handlerWrapper = (e) => {
|
|
100
100
|
handler(e);
|
|
@@ -108,27 +108,14 @@
|
|
|
108
108
|
},
|
|
109
109
|
emit(data) {
|
|
110
110
|
if (isActive()) {
|
|
111
|
-
handlers.forEach((handler) => handler({ value: data }));
|
|
111
|
+
handlers.forEach((handler) => handler({ type: type, value: data }));
|
|
112
112
|
}
|
|
113
113
|
},
|
|
114
|
-
}
|
|
115
|
-
}
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
116
|
|
|
117
|
-
function
|
|
118
|
-
|
|
119
|
-
const partialListeners = new Set();
|
|
120
|
-
function callHandlers(ns) {
|
|
121
|
-
// everything is implicitly subscribed to fallbacks
|
|
122
|
-
// as it can always fall through to it
|
|
123
|
-
const fallbackNamespaces = new Set(getFallbackNs());
|
|
124
|
-
partialListeners.forEach((handler) => {
|
|
125
|
-
const nsMatches = ns === undefined ||
|
|
126
|
-
(ns === null || ns === void 0 ? void 0 : ns.findIndex((ns) => fallbackNamespaces.has(ns) || handler.namespaces.has(ns))) !== -1;
|
|
127
|
-
if (nsMatches) {
|
|
128
|
-
handler.fn({ value: undefined });
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
}
|
|
117
|
+
function EventEmitterCombined(isActive) {
|
|
118
|
+
let handlers = [];
|
|
132
119
|
let queue = [];
|
|
133
120
|
// merge events in queue into one event
|
|
134
121
|
function solveQueue() {
|
|
@@ -137,87 +124,54 @@
|
|
|
137
124
|
}
|
|
138
125
|
const queueCopy = queue;
|
|
139
126
|
queue = [];
|
|
140
|
-
|
|
141
|
-
handler(
|
|
127
|
+
handlers.forEach((handler) => {
|
|
128
|
+
handler(queueCopy);
|
|
142
129
|
});
|
|
143
|
-
let namespaces = new Set();
|
|
144
|
-
queueCopy.forEach((ns) => {
|
|
145
|
-
if (ns === undefined) {
|
|
146
|
-
// when no ns specified, it affects all namespaces
|
|
147
|
-
namespaces = undefined;
|
|
148
|
-
}
|
|
149
|
-
else if (namespaces !== undefined) {
|
|
150
|
-
ns.forEach((ns) => namespaces.add(ns));
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
const namespacesArray = namespaces
|
|
154
|
-
? Array.from(namespaces.keys())
|
|
155
|
-
: undefined;
|
|
156
|
-
callHandlers(namespacesArray);
|
|
157
130
|
}
|
|
158
131
|
return Object.freeze({
|
|
159
|
-
emit(ns, delayed) {
|
|
160
|
-
if (isActive()) {
|
|
161
|
-
queue.push(ns);
|
|
162
|
-
if (!delayed) {
|
|
163
|
-
solveQueue();
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
setTimeout(solveQueue, 0);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
},
|
|
170
132
|
listen(handler) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
unsubscribe: () => {
|
|
174
|
-
listeners.delete(handler);
|
|
175
|
-
},
|
|
133
|
+
const handlerWrapper = (events) => {
|
|
134
|
+
handler(events);
|
|
176
135
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
fn: (e) => {
|
|
182
|
-
handler(e);
|
|
136
|
+
handlers.push(handlerWrapper);
|
|
137
|
+
return {
|
|
138
|
+
unsubscribe() {
|
|
139
|
+
handlers = handlers.filter((i) => handlerWrapper !== i);
|
|
183
140
|
},
|
|
184
|
-
namespaces: new Set(),
|
|
185
141
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (ns === undefined) {
|
|
194
|
-
// subscribing to default ns
|
|
195
|
-
handlerWrapper.namespaces.add(getDefaultNs());
|
|
142
|
+
},
|
|
143
|
+
emit(e, delayed) {
|
|
144
|
+
if (isActive()) {
|
|
145
|
+
if (isActive()) {
|
|
146
|
+
queue.push(e);
|
|
147
|
+
if (!delayed) {
|
|
148
|
+
solveQueue();
|
|
196
149
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
150
|
+
else {
|
|
151
|
+
setTimeout(solveQueue, 0);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
201
155
|
},
|
|
202
156
|
});
|
|
203
157
|
}
|
|
204
158
|
|
|
205
|
-
function Events(
|
|
159
|
+
function Events() {
|
|
206
160
|
let emitterActive = true;
|
|
207
161
|
function isActive() {
|
|
208
162
|
return emitterActive;
|
|
209
163
|
}
|
|
210
164
|
const self = Object.freeze({
|
|
211
|
-
onPendingLanguageChange: EventEmitter(isActive),
|
|
212
|
-
onLanguageChange: EventEmitter(isActive),
|
|
213
|
-
onLoadingChange: EventEmitter(isActive),
|
|
214
|
-
onFetchingChange: EventEmitter(isActive),
|
|
215
|
-
onInitialLoaded: EventEmitter(isActive),
|
|
216
|
-
onRunningChange: EventEmitter(isActive),
|
|
217
|
-
onCacheChange: EventEmitter(isActive),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
165
|
+
onPendingLanguageChange: EventEmitter('pendingLanguage', isActive),
|
|
166
|
+
onLanguageChange: EventEmitter('language', isActive),
|
|
167
|
+
onLoadingChange: EventEmitter('loading', isActive),
|
|
168
|
+
onFetchingChange: EventEmitter('fetching', isActive),
|
|
169
|
+
onInitialLoaded: EventEmitter('initialLoad', isActive),
|
|
170
|
+
onRunningChange: EventEmitter('running', isActive),
|
|
171
|
+
onCacheChange: EventEmitter('cache', isActive),
|
|
172
|
+
onPermanentChange: EventEmitter('permanentChange', isActive),
|
|
173
|
+
onError: EventEmitter('error', isActive),
|
|
174
|
+
onUpdate: EventEmitterCombined(isActive),
|
|
221
175
|
setEmitterActive(active) {
|
|
222
176
|
emitterActive = active;
|
|
223
177
|
},
|
|
@@ -246,9 +200,9 @@
|
|
|
246
200
|
}
|
|
247
201
|
}),
|
|
248
202
|
});
|
|
249
|
-
self.onInitialLoaded.listen(() => self.onUpdate.emit());
|
|
250
|
-
self.onLanguageChange.listen(() => self.onUpdate.emit());
|
|
251
|
-
self.onCacheChange.listen((
|
|
203
|
+
self.onInitialLoaded.listen((e) => self.onUpdate.emit(e, false));
|
|
204
|
+
self.onLanguageChange.listen((e) => self.onUpdate.emit(e, false));
|
|
205
|
+
self.onCacheChange.listen((e) => self.onUpdate.emit(e, true));
|
|
252
206
|
return self;
|
|
253
207
|
}
|
|
254
208
|
|
|
@@ -278,7 +232,7 @@
|
|
|
278
232
|
}
|
|
279
233
|
}
|
|
280
234
|
|
|
281
|
-
const
|
|
235
|
+
const flattenTranslationsToMap = (data) => {
|
|
282
236
|
const result = new Map();
|
|
283
237
|
Object.entries(data).forEach(([key, value]) => {
|
|
284
238
|
// ignore empty values
|
|
@@ -286,7 +240,7 @@
|
|
|
286
240
|
return;
|
|
287
241
|
}
|
|
288
242
|
if (typeof value === 'object') {
|
|
289
|
-
|
|
243
|
+
flattenTranslationsToMap(value).forEach((flatValue, flatKey) => {
|
|
290
244
|
result.set(key + '.' + flatKey, flatValue);
|
|
291
245
|
});
|
|
292
246
|
return;
|
|
@@ -295,6 +249,9 @@
|
|
|
295
249
|
});
|
|
296
250
|
return result;
|
|
297
251
|
};
|
|
252
|
+
const flattenTranslations = (data) => {
|
|
253
|
+
return Object.fromEntries(flattenTranslationsToMap(data).entries());
|
|
254
|
+
};
|
|
298
255
|
const decodeCacheKey = (key) => {
|
|
299
256
|
const [firstPart, ...rest] = key.split(':');
|
|
300
257
|
// if namespaces contains ":" it won't get lost
|
|
@@ -310,7 +267,7 @@
|
|
|
310
267
|
}
|
|
311
268
|
};
|
|
312
269
|
|
|
313
|
-
function Cache(events, backendGetRecord, backendGetDevRecord, withDefaultNs, isInitialLoading, fetchingObserver, loadingObserver) {
|
|
270
|
+
function Cache(events, backendGetRecord, backendGetDevRecord, withDefaultNs, isInitialLoading, isCacheDisabled, fetchingObserver, loadingObserver) {
|
|
314
271
|
const asyncRequests = new Map();
|
|
315
272
|
const cache = new Map();
|
|
316
273
|
let staticData = {};
|
|
@@ -321,7 +278,7 @@
|
|
|
321
278
|
data: flattenTranslations(data),
|
|
322
279
|
version: recordVersion,
|
|
323
280
|
});
|
|
324
|
-
events.onCacheChange.emit(
|
|
281
|
+
events.onCacheChange.emit(decodeCacheKey(cacheKey));
|
|
325
282
|
}
|
|
326
283
|
/**
|
|
327
284
|
* Fetches production data
|
|
@@ -374,14 +331,23 @@
|
|
|
374
331
|
}
|
|
375
332
|
const self = Object.freeze({
|
|
376
333
|
addStaticData(data) {
|
|
377
|
-
if (data) {
|
|
334
|
+
if (Array.isArray(data)) {
|
|
335
|
+
for (const record of data) {
|
|
336
|
+
const key = encodeCacheKey(record);
|
|
337
|
+
const existing = cache.get(key);
|
|
338
|
+
if (!existing || existing.version === 0) {
|
|
339
|
+
addRecordInternal(record, flattenTranslations(record.data), 0);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else if (data) {
|
|
378
344
|
staticData = Object.assign(Object.assign({}, staticData), data);
|
|
379
345
|
Object.entries(data).forEach(([key, value]) => {
|
|
380
346
|
if (typeof value !== 'function') {
|
|
381
347
|
const descriptor = decodeCacheKey(key);
|
|
382
348
|
const existing = cache.get(key);
|
|
383
349
|
if (!existing || existing.version === 0) {
|
|
384
|
-
addRecordInternal(descriptor, value, 0);
|
|
350
|
+
addRecordInternal(descriptor, flattenTranslations(value), 0);
|
|
385
351
|
}
|
|
386
352
|
}
|
|
387
353
|
});
|
|
@@ -392,7 +358,7 @@
|
|
|
392
358
|
version += 1;
|
|
393
359
|
},
|
|
394
360
|
addRecord(descriptor, data) {
|
|
395
|
-
addRecordInternal(descriptor, data, version);
|
|
361
|
+
addRecordInternal(descriptor, flattenTranslations(data), version);
|
|
396
362
|
},
|
|
397
363
|
exists(descriptor, strict = false) {
|
|
398
364
|
const record = cache.get(encodeCacheKey(descriptor));
|
|
@@ -402,19 +368,27 @@
|
|
|
402
368
|
return Boolean(record);
|
|
403
369
|
},
|
|
404
370
|
getRecord(descriptor) {
|
|
405
|
-
|
|
406
|
-
|
|
371
|
+
const descriptorWithNs = withDefaultNs(descriptor);
|
|
372
|
+
const cacheKey = encodeCacheKey(descriptorWithNs);
|
|
373
|
+
const cacheRecord = cache.get(cacheKey);
|
|
374
|
+
if (!cacheRecord) {
|
|
375
|
+
return undefined;
|
|
376
|
+
}
|
|
377
|
+
return Object.assign(Object.assign({}, descriptorWithNs), { cacheKey, data: cacheRecord.data });
|
|
378
|
+
},
|
|
379
|
+
getAllRecords() {
|
|
380
|
+
const entries = Array.from(cache.entries());
|
|
381
|
+
return entries.map(([key]) => self.getRecord(decodeCacheKey(key)));
|
|
407
382
|
},
|
|
408
383
|
getTranslation(descriptor, key) {
|
|
409
384
|
var _a;
|
|
410
|
-
return (_a = cache.get(encodeCacheKey(descriptor))) === null || _a === void 0 ? void 0 : _a.data
|
|
385
|
+
return (_a = cache.get(encodeCacheKey(descriptor))) === null || _a === void 0 ? void 0 : _a.data[key];
|
|
411
386
|
},
|
|
412
387
|
getTranslationNs(namespaces, languages, key) {
|
|
413
388
|
var _a;
|
|
414
389
|
for (const namespace of namespaces) {
|
|
415
390
|
for (const language of languages) {
|
|
416
|
-
const value = (_a = cache
|
|
417
|
-
.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
391
|
+
const value = (_a = cache.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data[key];
|
|
418
392
|
if (value !== undefined && value !== null) {
|
|
419
393
|
return [namespace];
|
|
420
394
|
}
|
|
@@ -426,8 +400,7 @@
|
|
|
426
400
|
var _a;
|
|
427
401
|
for (const namespace of namespaces) {
|
|
428
402
|
for (const language of languages) {
|
|
429
|
-
const value = (_a = cache
|
|
430
|
-
.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
403
|
+
const value = (_a = cache.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data[key];
|
|
431
404
|
if (value !== undefined && value !== null) {
|
|
432
405
|
return value;
|
|
433
406
|
}
|
|
@@ -438,8 +411,10 @@
|
|
|
438
411
|
changeTranslation(descriptor, key, value) {
|
|
439
412
|
var _a;
|
|
440
413
|
const record = (_a = cache.get(encodeCacheKey(descriptor))) === null || _a === void 0 ? void 0 : _a.data;
|
|
441
|
-
record === null || record === void 0 ? void 0 : record
|
|
442
|
-
|
|
414
|
+
if (record === null || record === void 0 ? void 0 : record[key]) {
|
|
415
|
+
record[key] = value;
|
|
416
|
+
events.onCacheChange.emit(Object.assign(Object.assign({}, descriptor), { key }));
|
|
417
|
+
}
|
|
443
418
|
},
|
|
444
419
|
isFetching(ns) {
|
|
445
420
|
if (isInitialLoading()) {
|
|
@@ -453,66 +428,74 @@
|
|
|
453
428
|
},
|
|
454
429
|
isLoading(language, ns) {
|
|
455
430
|
const namespaces = getFallbackArray(ns);
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
431
|
+
if (isInitialLoading()) {
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
const pendingCacheKeys = Array.from(asyncRequests.keys());
|
|
435
|
+
return Boolean(pendingCacheKeys.find((key) => {
|
|
436
|
+
const descriptor = decodeCacheKey(key);
|
|
437
|
+
return ((!namespaces.length || namespaces.includes(descriptor.namespace)) &&
|
|
438
|
+
!self.exists({
|
|
439
|
+
namespace: descriptor.namespace,
|
|
440
|
+
language: language,
|
|
441
|
+
}));
|
|
442
|
+
}));
|
|
443
|
+
},
|
|
444
|
+
async loadRecords(descriptors, options) {
|
|
468
445
|
const withPromises = descriptors.map((descriptor) => {
|
|
469
446
|
const keyObject = withDefaultNs(descriptor);
|
|
470
447
|
const cacheKey = encodeCacheKey(keyObject);
|
|
448
|
+
if (options === null || options === void 0 ? void 0 : options.useCache) {
|
|
449
|
+
const exists = self.exists(keyObject, true);
|
|
450
|
+
if (exists) {
|
|
451
|
+
return Object.assign(Object.assign({}, keyObject), { new: false, cacheKey, data: self.getRecord(keyObject).data });
|
|
452
|
+
}
|
|
453
|
+
}
|
|
471
454
|
const existingPromise = asyncRequests.get(cacheKey);
|
|
472
455
|
if (existingPromise) {
|
|
473
|
-
return {
|
|
474
|
-
new: false,
|
|
475
|
-
promise: existingPromise,
|
|
476
|
-
keyObject,
|
|
477
|
-
cacheKey,
|
|
478
|
-
};
|
|
456
|
+
return Object.assign(Object.assign({}, keyObject), { new: false, promise: existingPromise, cacheKey });
|
|
479
457
|
}
|
|
480
|
-
const dataPromise = fetchData(keyObject,
|
|
458
|
+
const dataPromise = fetchData(keyObject, !(options === null || options === void 0 ? void 0 : options.noDev)) || Promise.resolve(undefined);
|
|
481
459
|
asyncRequests.set(cacheKey, dataPromise);
|
|
482
|
-
return {
|
|
483
|
-
new: true,
|
|
484
|
-
promise: dataPromise,
|
|
485
|
-
keyObject,
|
|
486
|
-
cacheKey,
|
|
487
|
-
};
|
|
460
|
+
return Object.assign(Object.assign({}, keyObject), { new: true, promise: dataPromise, cacheKey });
|
|
488
461
|
});
|
|
489
462
|
fetchingObserver.notify();
|
|
490
463
|
loadingObserver.notify();
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
464
|
+
const promisesToWait = withPromises
|
|
465
|
+
.map((val) => val.promise)
|
|
466
|
+
.filter(Boolean);
|
|
467
|
+
const fetchedData = await Promise.all(promisesToWait);
|
|
468
|
+
withPromises.forEach((value) => {
|
|
469
|
+
var _a;
|
|
470
|
+
if (value.promise) {
|
|
471
|
+
value.data = flattenTranslations((_a = fetchedData[0]) !== null && _a !== void 0 ? _a : {});
|
|
472
|
+
fetchedData.shift();
|
|
473
|
+
}
|
|
494
474
|
// if promise has changed in between, it means cache been invalidated or
|
|
495
475
|
// new data are being fetched
|
|
476
|
+
const promiseChanged = asyncRequests.get(value.cacheKey) !== value.promise;
|
|
496
477
|
if (value.new && !promiseChanged) {
|
|
497
478
|
asyncRequests.delete(value.cacheKey);
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
self.addRecord(value.keyObject, data);
|
|
479
|
+
if (value.data) {
|
|
480
|
+
self.addRecord(value, value.data);
|
|
501
481
|
}
|
|
502
|
-
else if (!self.getRecord(value
|
|
482
|
+
else if (!self.getRecord(value)) {
|
|
503
483
|
// if no data exist, put empty object
|
|
504
|
-
|
|
484
|
+
// so we know we don't have to fetch again
|
|
485
|
+
self.addRecord(value, {});
|
|
505
486
|
}
|
|
506
487
|
}
|
|
507
488
|
});
|
|
508
489
|
fetchingObserver.notify();
|
|
509
490
|
loadingObserver.notify();
|
|
510
|
-
return withPromises.map((val) =>
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
491
|
+
return withPromises.map((val) => {
|
|
492
|
+
var _a;
|
|
493
|
+
return ({
|
|
494
|
+
language: val.language,
|
|
495
|
+
namespace: val.namespace,
|
|
496
|
+
data: (_a = val.data) !== null && _a !== void 0 ? _a : {},
|
|
497
|
+
cacheKey: val.cacheKey,
|
|
498
|
+
});
|
|
516
499
|
});
|
|
517
500
|
},
|
|
518
501
|
});
|
|
@@ -567,13 +550,14 @@
|
|
|
567
550
|
const DEFAULT_API_URL = 'https://app.tolgee.io';
|
|
568
551
|
const DEFAULT_MISSING_TRANSLATION = ({ key, }) => key;
|
|
569
552
|
const defaultValues = {
|
|
570
|
-
defaultNs: '',
|
|
571
553
|
observerOptions: defaultObserverOptions,
|
|
572
554
|
observerType: 'invisible',
|
|
573
555
|
onFormatError: DEFAULT_FORMAT_ERROR,
|
|
574
556
|
apiUrl: DEFAULT_API_URL,
|
|
557
|
+
autoLoadRequiredData: true,
|
|
575
558
|
fetch: createFetchFunction(),
|
|
576
559
|
onTranslationMissing: DEFAULT_MISSING_TRANSLATION,
|
|
560
|
+
disableCache: false,
|
|
577
561
|
};
|
|
578
562
|
const combineOptions = (...states) => {
|
|
579
563
|
let result = {};
|
|
@@ -767,6 +751,9 @@
|
|
|
767
751
|
getBackendDevRecord: (async ({ language, namespace }) => {
|
|
768
752
|
var _a;
|
|
769
753
|
const { apiKey, apiUrl, projectId, filterTag } = getInitialOptions();
|
|
754
|
+
if (!apiKey || !apiUrl || !self.hasDevBackend()) {
|
|
755
|
+
return undefined;
|
|
756
|
+
}
|
|
770
757
|
return (_a = instances.devBackend) === null || _a === void 0 ? void 0 : _a.getRecord(Object.assign({ apiKey,
|
|
771
758
|
apiUrl,
|
|
772
759
|
projectId,
|
|
@@ -910,6 +897,9 @@
|
|
|
910
897
|
isInitialLoading() {
|
|
911
898
|
return state.isInitialLoading;
|
|
912
899
|
},
|
|
900
|
+
isCacheDisabled() {
|
|
901
|
+
return state.initialOptions.disableCache;
|
|
902
|
+
},
|
|
913
903
|
setInitialLoading(value) {
|
|
914
904
|
state.isInitialLoading = value;
|
|
915
905
|
},
|
|
@@ -960,7 +950,8 @@
|
|
|
960
950
|
},
|
|
961
951
|
getRequiredNamespaces() {
|
|
962
952
|
return unique([
|
|
963
|
-
|
|
953
|
+
self.getDefaultNs(),
|
|
954
|
+
...(state.initialOptions.ns || []),
|
|
964
955
|
...getFallbackArray(state.initialOptions.fallbackNs),
|
|
965
956
|
...state.activeNamespaces.keys(),
|
|
966
957
|
]);
|
|
@@ -978,8 +969,17 @@
|
|
|
978
969
|
getFallbackNs() {
|
|
979
970
|
return getFallbackArray(state.initialOptions.fallbackNs);
|
|
980
971
|
},
|
|
972
|
+
getNs() {
|
|
973
|
+
var _a, _b;
|
|
974
|
+
return ((_a = state.initialOptions.ns) === null || _a === void 0 ? void 0 : _a.length)
|
|
975
|
+
? state.initialOptions.ns
|
|
976
|
+
: [(_b = state.initialOptions.defaultNs) !== null && _b !== void 0 ? _b : ''];
|
|
977
|
+
},
|
|
981
978
|
getDefaultNs(ns) {
|
|
982
|
-
|
|
979
|
+
var _a, _b, _c;
|
|
980
|
+
return ns === undefined
|
|
981
|
+
? (_c = (_a = state.initialOptions.defaultNs) !== null && _a !== void 0 ? _a : (_b = state.initialOptions.ns) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : ''
|
|
982
|
+
: ns;
|
|
983
983
|
},
|
|
984
984
|
getAvailableLanguages() {
|
|
985
985
|
if (state.initialOptions.availableLanguages) {
|
|
@@ -990,10 +990,13 @@
|
|
|
990
990
|
return Array.from(new Set(languagesFromStaticData));
|
|
991
991
|
}
|
|
992
992
|
},
|
|
993
|
+
getAvailableNs() {
|
|
994
|
+
return state.initialOptions.availableNs;
|
|
995
|
+
},
|
|
993
996
|
withDefaultNs(descriptor) {
|
|
994
997
|
return {
|
|
995
998
|
namespace: descriptor.namespace === undefined
|
|
996
|
-
? self.
|
|
999
|
+
? self.getDefaultNs()
|
|
997
1000
|
: descriptor.namespace,
|
|
998
1001
|
language: descriptor.language,
|
|
999
1002
|
};
|
|
@@ -1043,12 +1046,12 @@
|
|
|
1043
1046
|
};
|
|
1044
1047
|
|
|
1045
1048
|
function Controller({ options }) {
|
|
1046
|
-
const events = Events(
|
|
1049
|
+
const events = Events();
|
|
1047
1050
|
const fetchingObserver = ValueObserver(false, () => cache.isFetching(), events.onFetchingChange.emit);
|
|
1048
1051
|
const loadingObserver = ValueObserver(false, () => self.isLoading(), events.onLoadingChange.emit);
|
|
1049
1052
|
const state = State(events.onLanguageChange, events.onPendingLanguageChange, events.onRunningChange);
|
|
1050
1053
|
const pluginService = Plugins(state.getLanguage, state.getInitialOptions, state.getAvailableLanguages, getDefaultAndFallbackNs, getTranslationNs, getTranslation, changeTranslation, events);
|
|
1051
|
-
const cache = Cache(events, pluginService.getBackendRecord, pluginService.getBackendDevRecord, state.withDefaultNs, state.isInitialLoading, fetchingObserver, loadingObserver);
|
|
1054
|
+
const cache = Cache(events, pluginService.getBackendRecord, pluginService.getBackendDevRecord, state.withDefaultNs, state.isInitialLoading, state.isCacheDisabled, fetchingObserver, loadingObserver);
|
|
1052
1055
|
if (options) {
|
|
1053
1056
|
init(options);
|
|
1054
1057
|
}
|
|
@@ -1067,15 +1070,15 @@
|
|
|
1067
1070
|
// gets all namespaces where translation could be located
|
|
1068
1071
|
// takes (ns|default, fallback ns)
|
|
1069
1072
|
function getDefaultAndFallbackNs(ns) {
|
|
1070
|
-
return [...getFallbackArray(getDefaultNs(ns)), ...getFallbackNs()];
|
|
1073
|
+
return unique([...getFallbackArray(getDefaultNs(ns)), ...getFallbackNs()]);
|
|
1071
1074
|
}
|
|
1072
1075
|
// gets all namespaces which need to be loaded
|
|
1073
1076
|
// takes (ns|default, initial ns, fallback ns, active ns)
|
|
1074
1077
|
function getRequiredNamespaces(ns) {
|
|
1075
|
-
return [
|
|
1078
|
+
return unique([
|
|
1076
1079
|
...getFallbackArray(ns !== null && ns !== void 0 ? ns : getDefaultNs()),
|
|
1077
1080
|
...state.getRequiredNamespaces(),
|
|
1078
|
-
];
|
|
1081
|
+
]);
|
|
1079
1082
|
}
|
|
1080
1083
|
function changeTranslation(descriptor, key, value) {
|
|
1081
1084
|
const keyObject = state.withDefaultNs(descriptor);
|
|
@@ -1091,24 +1094,50 @@
|
|
|
1091
1094
|
state.init(options);
|
|
1092
1095
|
cache.addStaticData(state.getInitialOptions().staticData);
|
|
1093
1096
|
}
|
|
1094
|
-
function
|
|
1097
|
+
function getRequiredDescriptors(lang, ns) {
|
|
1095
1098
|
const languages = state.getFallbackLangs(lang);
|
|
1096
1099
|
const namespaces = getRequiredNamespaces(ns);
|
|
1097
1100
|
const result = [];
|
|
1098
1101
|
languages.forEach((language) => {
|
|
1099
1102
|
namespaces.forEach((namespace) => {
|
|
1100
|
-
|
|
1101
|
-
result.push({ language, namespace });
|
|
1102
|
-
}
|
|
1103
|
+
result.push({ language, namespace });
|
|
1103
1104
|
});
|
|
1104
1105
|
});
|
|
1105
1106
|
return result;
|
|
1106
1107
|
}
|
|
1107
|
-
function
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1108
|
+
function getMissingDescriptors(lang, ns) {
|
|
1109
|
+
return getRequiredDescriptors(lang, ns).filter((descriptor) => !cache.exists(descriptor, true));
|
|
1110
|
+
}
|
|
1111
|
+
function getMatrixRecords(options) {
|
|
1112
|
+
let languages = [];
|
|
1113
|
+
let namespaces = [];
|
|
1114
|
+
if (Array.isArray(options.languages)) {
|
|
1115
|
+
languages = options.languages;
|
|
1116
|
+
}
|
|
1117
|
+
else if (options.languages === 'all') {
|
|
1118
|
+
const availableLanguages = self.getAvailableLanguages();
|
|
1119
|
+
if (!availableLanguages) {
|
|
1120
|
+
throw new Error(missingOptionError('availableLanguages'));
|
|
1121
|
+
}
|
|
1122
|
+
languages = availableLanguages;
|
|
1123
|
+
}
|
|
1124
|
+
if (Array.isArray(options.namespaces)) {
|
|
1125
|
+
namespaces = options.namespaces;
|
|
1126
|
+
}
|
|
1127
|
+
else if (options.namespaces === 'all') {
|
|
1128
|
+
const availableNs = self.getAvailableNs();
|
|
1129
|
+
if (!availableNs) {
|
|
1130
|
+
throw new Error(missingOptionError('availableNs'));
|
|
1131
|
+
}
|
|
1132
|
+
namespaces = availableNs;
|
|
1111
1133
|
}
|
|
1134
|
+
const records = [];
|
|
1135
|
+
languages.forEach((language) => {
|
|
1136
|
+
namespaces.forEach((namespace) => {
|
|
1137
|
+
records.push({ language, namespace });
|
|
1138
|
+
});
|
|
1139
|
+
});
|
|
1140
|
+
return records;
|
|
1112
1141
|
}
|
|
1113
1142
|
function getTranslationNs({ key, ns }) {
|
|
1114
1143
|
const languages = state.getFallbackLangs();
|
|
@@ -1122,8 +1151,11 @@
|
|
|
1122
1151
|
}
|
|
1123
1152
|
function loadInitial() {
|
|
1124
1153
|
const data = valueOrPromise(initializeLanguage(), () => {
|
|
1125
|
-
|
|
1126
|
-
|
|
1154
|
+
const missingDescriptors = getMissingDescriptors();
|
|
1155
|
+
if (missingDescriptors.length &&
|
|
1156
|
+
state.getInitialOptions().autoLoadRequiredData) {
|
|
1157
|
+
return cache.loadRecords(missingDescriptors, { useCache: true });
|
|
1158
|
+
}
|
|
1127
1159
|
});
|
|
1128
1160
|
if (isPromise(data)) {
|
|
1129
1161
|
state.setInitialLoading(true);
|
|
@@ -1164,14 +1196,16 @@
|
|
|
1164
1196
|
throw new Error(missingOptionError(['defaultLanguage', 'language']));
|
|
1165
1197
|
}
|
|
1166
1198
|
}
|
|
1167
|
-
const self = Object.freeze(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, events), state), pluginService), cache), { init: init, getTranslation: getTranslation, changeTranslation: changeTranslation, getTranslationNs: getTranslationNs, getDefaultAndFallbackNs: getDefaultAndFallbackNs, findPositions: pluginService.findPositions,
|
|
1199
|
+
const self = Object.freeze(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, events), state), pluginService), cache), { init: init, getTranslation: getTranslation, changeTranslation: changeTranslation, getTranslationNs: getTranslationNs, getDefaultAndFallbackNs: getDefaultAndFallbackNs, findPositions: pluginService.findPositions, getRequiredDescriptors: getRequiredDescriptors, async changeLanguage(language) {
|
|
1168
1200
|
if (state.getPendingLanguage() === language &&
|
|
1169
1201
|
state.getLanguage() === language) {
|
|
1170
1202
|
return;
|
|
1171
1203
|
}
|
|
1172
1204
|
state.setPendingLanguage(language);
|
|
1173
|
-
if (state.isRunning()) {
|
|
1174
|
-
await
|
|
1205
|
+
if (state.isRunning() && state.getInitialOptions().autoLoadRequiredData) {
|
|
1206
|
+
await cache.loadRecords(getRequiredDescriptors(language), {
|
|
1207
|
+
useCache: true,
|
|
1208
|
+
});
|
|
1175
1209
|
}
|
|
1176
1210
|
if (language === state.getPendingLanguage()) {
|
|
1177
1211
|
// there might be parallel language change
|
|
@@ -1185,14 +1219,14 @@
|
|
|
1185
1219
|
state.addActiveNs(ns);
|
|
1186
1220
|
}
|
|
1187
1221
|
if (state.isRunning()) {
|
|
1188
|
-
await
|
|
1222
|
+
await cache.loadRecords(getRequiredDescriptors(undefined, ns), {
|
|
1223
|
+
useCache: true,
|
|
1224
|
+
});
|
|
1189
1225
|
}
|
|
1190
1226
|
},
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
async loadRecord(descriptor) {
|
|
1195
|
-
return (await self.loadRecords([descriptor]))[0];
|
|
1227
|
+
async loadRecord(descriptor, options) {
|
|
1228
|
+
var _a;
|
|
1229
|
+
return (_a = (await self.loadRecords([descriptor], options))[0]) === null || _a === void 0 ? void 0 : _a.data;
|
|
1196
1230
|
},
|
|
1197
1231
|
isLoading(ns) {
|
|
1198
1232
|
return cache.isLoading(state.getLanguage(), ns);
|
|
@@ -1221,6 +1255,17 @@
|
|
|
1221
1255
|
}), isDev() {
|
|
1222
1256
|
return Boolean(state.getInitialOptions().apiKey && state.getInitialOptions().apiUrl);
|
|
1223
1257
|
},
|
|
1258
|
+
async loadRequired(options) {
|
|
1259
|
+
if (!(options === null || options === void 0 ? void 0 : options.language)) {
|
|
1260
|
+
await initializeLanguage();
|
|
1261
|
+
}
|
|
1262
|
+
const requiredRecords = getRequiredDescriptors(options === null || options === void 0 ? void 0 : options.language);
|
|
1263
|
+
return self.loadRecords(requiredRecords, options);
|
|
1264
|
+
},
|
|
1265
|
+
async loadMatrix(options) {
|
|
1266
|
+
const records = getMatrixRecords(options);
|
|
1267
|
+
return self.loadRecords(records, options);
|
|
1268
|
+
},
|
|
1224
1269
|
run() {
|
|
1225
1270
|
checkCorrectConfiguration();
|
|
1226
1271
|
if (!state.isRunning()) {
|
|
@@ -1261,20 +1306,6 @@
|
|
|
1261
1306
|
* Listen to tolgee events.
|
|
1262
1307
|
*/
|
|
1263
1308
|
on: controller.on,
|
|
1264
|
-
/**
|
|
1265
|
-
* Listen for specific namespaces changes.
|
|
1266
|
-
*
|
|
1267
|
-
* ```
|
|
1268
|
-
* const sub = tolgee.onUpdate(handler)
|
|
1269
|
-
*
|
|
1270
|
-
* // subscribe to selected namespace
|
|
1271
|
-
* sub.subscribeNs(['common'])
|
|
1272
|
-
*
|
|
1273
|
-
* // unsubscribe
|
|
1274
|
-
* sub.unsubscribe()
|
|
1275
|
-
* ```
|
|
1276
|
-
*/
|
|
1277
|
-
onNsUpdate: controller.onUpdate.listenSome,
|
|
1278
1309
|
/**
|
|
1279
1310
|
* Turn off/on events emitting. Is on by default.
|
|
1280
1311
|
*/
|
|
@@ -1312,6 +1343,16 @@
|
|
|
1312
1343
|
* so this method will remove namespace only if the counter goes down to 0.
|
|
1313
1344
|
*/
|
|
1314
1345
|
removeActiveNs: controller.removeActiveNs,
|
|
1346
|
+
/**
|
|
1347
|
+
* Load records which would be loaded by `run` function
|
|
1348
|
+
*
|
|
1349
|
+
* You can provide language if not previously set on tolgee instance
|
|
1350
|
+
*/
|
|
1351
|
+
loadRequired: controller.loadRequired,
|
|
1352
|
+
/**
|
|
1353
|
+
* Load records in matrix (languages x namespaces)
|
|
1354
|
+
*/
|
|
1355
|
+
loadMatrix: controller.loadMatrix,
|
|
1315
1356
|
/**
|
|
1316
1357
|
* Manually load multiple records from `Backend` (or `DevBackend` when in dev mode)
|
|
1317
1358
|
*
|
|
@@ -1340,9 +1381,9 @@
|
|
|
1340
1381
|
*/
|
|
1341
1382
|
isLoaded: controller.isLoaded,
|
|
1342
1383
|
/**
|
|
1343
|
-
* Returns records needed for instance to be `loaded`
|
|
1384
|
+
* Returns descriptors of records needed for instance to be `loaded`
|
|
1344
1385
|
*/
|
|
1345
|
-
|
|
1386
|
+
getRequiredDescriptors: controller.getRequiredDescriptors,
|
|
1346
1387
|
/**
|
|
1347
1388
|
* @return `true` if tolgee is loading initial data (triggered by `run`).
|
|
1348
1389
|
*/
|