@tolgee/core 4.10.0-rc.f068ae1.0 → 5.0.0-alpha.1
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 +551 -277
- 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.mjs → tolgee.esm.js} +551 -273
- package/dist/tolgee.esm.js.map +1 -0
- package/dist/tolgee.esm.min.mjs +1 -1
- package/dist/tolgee.esm.min.mjs.map +1 -1
- package/dist/tolgee.umd.js +551 -277
- 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 +9 -7
- package/lib/Controller/Controller.d.ts +85 -84
- package/lib/Controller/Events/EventEmitter.d.ts +6 -6
- package/lib/Controller/Events/EventEmitterSelective.d.ts +7 -15
- package/lib/Controller/Events/Events.d.ts +12 -49
- package/lib/Controller/Plugins/Plugins.d.ts +11 -19
- package/lib/Controller/State/State.d.ts +14 -15
- package/lib/Controller/State/initState.d.ts +35 -11
- package/lib/Controller/State/observerOptions.d.ts +41 -0
- package/lib/Controller/ValueObserver.d.ts +5 -5
- package/lib/FormatSimple/FormatError.d.ts +7 -0
- package/lib/FormatSimple/FormatSimple.d.ts +2 -0
- package/lib/FormatSimple/formatParser.d.ts +1 -0
- package/lib/FormatSimple/formatter.d.ts +2 -0
- package/lib/Tolgee.d.ts +195 -2
- package/lib/TranslateParams.d.ts +1 -1
- package/lib/helpers.d.ts +7 -0
- package/lib/index.d.ts +3 -3
- package/lib/types/cache.d.ts +25 -0
- package/lib/types/events.d.ts +66 -0
- package/lib/types/general.d.ts +34 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/plugin.d.ts +130 -0
- package/package.json +5 -4
- package/src/Controller/Cache/Cache.ts +29 -22
- package/src/Controller/Cache/helpers.ts +3 -1
- package/src/Controller/Controller.ts +49 -43
- package/src/Controller/Events/EventEmitter.ts +9 -6
- package/src/Controller/Events/EventEmitterSelective.test.ts +36 -74
- package/src/Controller/Events/EventEmitterSelective.ts +60 -110
- package/src/Controller/Events/Events.ts +21 -29
- package/src/Controller/Plugins/Plugins.ts +131 -95
- package/src/Controller/State/State.ts +37 -30
- package/src/Controller/State/initState.ts +81 -20
- package/src/Controller/State/observerOptions.ts +66 -0
- package/src/Controller/ValueObserver.ts +5 -2
- package/src/FormatSimple/FormatError.ts +26 -0
- package/src/FormatSimple/FormatSimple.ts +13 -0
- package/src/FormatSimple/formatParser.ts +133 -0
- package/src/FormatSimple/formatter.test.ts +190 -0
- package/src/FormatSimple/formatter.ts +19 -0
- package/src/Tolgee.ts +210 -36
- package/src/TranslateParams.test.ts +9 -12
- package/src/TranslateParams.ts +6 -5
- package/src/__test/backend.test.ts +4 -4
- package/src/__test/cache.test.ts +51 -12
- package/src/__test/client.test.ts +1 -1
- package/src/__test/events.test.ts +4 -4
- package/src/__test/format.simple.test.ts +26 -0
- package/src/__test/initialization.test.ts +4 -4
- package/src/__test/languages.test.ts +24 -6
- package/src/__test/loading.test.ts +1 -1
- package/src/__test/{namespacesFallback.test.ts → namespaces.fallback.test.ts} +8 -7
- package/src/__test/namespaces.test.ts +29 -6
- package/src/__test/options.test.ts +64 -0
- package/src/__test/plugins.test.ts +22 -49
- package/src/helpers.ts +45 -0
- package/src/index.ts +3 -9
- package/src/types/cache.ts +37 -0
- package/src/types/events.ts +85 -0
- package/src/types/general.ts +50 -0
- package/src/types/index.ts +19 -0
- package/src/types/plugin.ts +181 -0
- package/dist/tolgee.esm.mjs.map +0 -1
- package/lib/Controller/State/helpers.d.ts +0 -6
- package/lib/Controller/State/initObserverOptions.d.ts +0 -13
- package/lib/constants.d.ts +0 -5
- package/lib/types.d.ts +0 -283
- package/src/Controller/State/helpers.ts +0 -41
- package/src/Controller/State/initObserverOptions.ts +0 -38
- package/src/constants.ts +0 -7
- package/src/types.ts +0 -392
package/dist/tolgee.cjs.js
CHANGED
|
@@ -2,25 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
const emit = (data) => {
|
|
19
|
-
handlers.forEach((handler) => handler({ value: data }));
|
|
20
|
-
};
|
|
21
|
-
return Object.freeze({ listen, emit });
|
|
5
|
+
function isPromise(value) {
|
|
6
|
+
return Boolean(value && typeof value.then === 'function');
|
|
7
|
+
}
|
|
8
|
+
const valueOrPromise = (value, callback) => {
|
|
9
|
+
if (isPromise(value)) {
|
|
10
|
+
return Promise.resolve(value).then(callback);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
return callback(value);
|
|
14
|
+
}
|
|
22
15
|
};
|
|
23
|
-
|
|
16
|
+
const missingOptionError = (option) => `Tolgee: You need to specify '${option}' option`;
|
|
24
17
|
function isObject(item) {
|
|
25
18
|
return typeof item === 'object' && !Array.isArray(item) && item !== null;
|
|
26
19
|
}
|
|
@@ -47,22 +40,30 @@ function getFallbackFromStruct(language, fallbackLanguage) {
|
|
|
47
40
|
function unique(arr) {
|
|
48
41
|
return Array.from(new Set(arr));
|
|
49
42
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const currNum = map.get(value) || 0;
|
|
53
|
-
map.set(value, currNum + 1);
|
|
43
|
+
function sanitizeUrl(url) {
|
|
44
|
+
return url ? url.replace(/\/+$/, '') : url;
|
|
54
45
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
46
|
+
|
|
47
|
+
const EventEmitter = () => {
|
|
48
|
+
let handlers = [];
|
|
49
|
+
const listen = (handler) => {
|
|
50
|
+
const handlerWrapper = (e) => {
|
|
51
|
+
handler(e);
|
|
52
|
+
};
|
|
53
|
+
handlers.push(handlerWrapper);
|
|
54
|
+
return {
|
|
55
|
+
unsubscribe: () => {
|
|
56
|
+
handlers = handlers.filter((i) => handlerWrapper !== i);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const emit = (data) => {
|
|
61
|
+
handlers.forEach((handler) => handler({ value: data }));
|
|
62
|
+
};
|
|
63
|
+
return Object.freeze({ listen, emit });
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const EventEmitterSelective = (getFallbackNs, getDefaultNs) => {
|
|
66
67
|
const listeners = new Set();
|
|
67
68
|
const partialListeners = new Set();
|
|
68
69
|
const listen = (handler) => {
|
|
@@ -79,8 +80,7 @@ const EventEmitterSelective = (getFallbackNamespaces) => {
|
|
|
79
80
|
fn: (e) => {
|
|
80
81
|
handler(e);
|
|
81
82
|
},
|
|
82
|
-
|
|
83
|
-
namespaces: new Map(),
|
|
83
|
+
namespaces: new Set(),
|
|
84
84
|
};
|
|
85
85
|
partialListeners.add(handlerWrapper);
|
|
86
86
|
const result = {
|
|
@@ -88,52 +88,24 @@ const EventEmitterSelective = (getFallbackNamespaces) => {
|
|
|
88
88
|
partialListeners.delete(handlerWrapper);
|
|
89
89
|
},
|
|
90
90
|
subscribeNs: (ns) => {
|
|
91
|
-
getFallbackArray(ns).forEach((val) =>
|
|
92
|
-
return result;
|
|
93
|
-
},
|
|
94
|
-
unsubscribeNs: (ns) => {
|
|
95
|
-
getFallbackArray(ns).forEach((val) => decrementInMap(handlerWrapper.namespaces, val));
|
|
96
|
-
return result;
|
|
97
|
-
},
|
|
98
|
-
subscribeKey: (descriptor) => {
|
|
99
|
-
const { key, ns } = descriptor;
|
|
100
|
-
incrementInMap(handlerWrapper.keys, key);
|
|
101
|
-
getFallbackArray(ns).forEach((val) => incrementInMap(handlerWrapper.namespaces, val));
|
|
102
|
-
if (ns === undefined) {
|
|
103
|
-
// subscribing to all namespaces
|
|
104
|
-
incrementInMap(handlerWrapper.namespaces, undefined);
|
|
105
|
-
}
|
|
106
|
-
return result;
|
|
107
|
-
},
|
|
108
|
-
unsubscribeKey: (descriptor) => {
|
|
109
|
-
const { key, ns } = descriptor;
|
|
110
|
-
decrementInMap(handlerWrapper.keys, key);
|
|
111
|
-
getFallbackArray(ns).forEach((val) => decrementInMap(handlerWrapper.namespaces, val));
|
|
91
|
+
getFallbackArray(ns).forEach((val) => handlerWrapper.namespaces.add(val));
|
|
112
92
|
if (ns === undefined) {
|
|
113
|
-
// subscribing to
|
|
114
|
-
|
|
93
|
+
// subscribing to default ns
|
|
94
|
+
handlerWrapper.namespaces.add(getDefaultNs());
|
|
115
95
|
}
|
|
116
96
|
return result;
|
|
117
97
|
},
|
|
118
98
|
};
|
|
119
99
|
return result;
|
|
120
100
|
};
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
getFallbackNamespaces().forEach((ns) => result.add(ns));
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
128
|
-
return namespaces;
|
|
129
|
-
};
|
|
130
|
-
const callHandlers = (key, ns) => {
|
|
101
|
+
const callHandlers = (ns) => {
|
|
102
|
+
// everything is implicitly subscribed to fallbacks
|
|
103
|
+
// as it can always fall through to it
|
|
104
|
+
const fallbackNamespaces = new Set(getFallbackNs());
|
|
131
105
|
partialListeners.forEach((handler) => {
|
|
132
|
-
const handlerNamespaces = namespacesWithFallbacks(handler.namespaces);
|
|
133
106
|
const nsMatches = ns === undefined ||
|
|
134
|
-
(ns === null || ns === void 0 ? void 0 : ns.findIndex((ns) =>
|
|
135
|
-
|
|
136
|
-
if (nsMatches && keyMatches) {
|
|
107
|
+
(ns === null || ns === void 0 ? void 0 : ns.findIndex((ns) => fallbackNamespaces.has(ns) || handler.namespaces.has(ns))) !== -1;
|
|
108
|
+
if (nsMatches) {
|
|
137
109
|
handler.fn({ value: undefined });
|
|
138
110
|
}
|
|
139
111
|
});
|
|
@@ -144,61 +116,51 @@ const EventEmitterSelective = (getFallbackNamespaces) => {
|
|
|
144
116
|
if (queue.length === 0) {
|
|
145
117
|
return;
|
|
146
118
|
}
|
|
119
|
+
const queueCopy = queue;
|
|
120
|
+
queue = [];
|
|
147
121
|
listeners.forEach((handler) => {
|
|
148
122
|
handler({ value: undefined });
|
|
149
123
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
namespaces.add(undefined);
|
|
124
|
+
let namespaces = new Set();
|
|
125
|
+
queueCopy.forEach((ns) => {
|
|
126
|
+
if (ns === undefined) {
|
|
127
|
+
// when no ns specified, it affects all namespaces
|
|
128
|
+
namespaces = undefined;
|
|
156
129
|
}
|
|
157
|
-
else {
|
|
158
|
-
|
|
130
|
+
else if (namespaces !== undefined) {
|
|
131
|
+
ns.forEach((ns) => namespaces.add(ns));
|
|
159
132
|
}
|
|
160
|
-
if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.key) === undefined) {
|
|
161
|
-
// when no key specified, it affects all keys
|
|
162
|
-
keys = undefined;
|
|
163
|
-
}
|
|
164
|
-
else if (keys !== undefined) {
|
|
165
|
-
keys.add(descriptor.key);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
const namespacesArray = Array.from(namespacesWithFallbacks(namespaces).keys());
|
|
169
|
-
(keys || [undefined]).forEach((key) => {
|
|
170
|
-
callHandlers(key, namespacesArray);
|
|
171
133
|
});
|
|
172
|
-
|
|
134
|
+
const namespacesArray = namespaces
|
|
135
|
+
? Array.from(namespaces.keys())
|
|
136
|
+
: undefined;
|
|
137
|
+
callHandlers(namespacesArray);
|
|
173
138
|
};
|
|
174
|
-
const emit = (
|
|
175
|
-
queue.push(
|
|
139
|
+
const emit = (ns, delayed) => {
|
|
140
|
+
queue.push(ns);
|
|
176
141
|
if (!delayed) {
|
|
177
142
|
solveQueue();
|
|
178
143
|
}
|
|
179
144
|
else {
|
|
180
|
-
|
|
181
|
-
solveQueue();
|
|
182
|
-
});
|
|
145
|
+
setTimeout(solveQueue, 0);
|
|
183
146
|
}
|
|
184
147
|
};
|
|
185
148
|
return Object.freeze({ listenSome, listen, emit });
|
|
186
149
|
};
|
|
187
150
|
|
|
188
|
-
const Events = (
|
|
151
|
+
const Events = (getFallbackNs, getDefaultNs) => {
|
|
189
152
|
const onPendingLanguageChange = EventEmitter();
|
|
190
153
|
const onLanguageChange = EventEmitter();
|
|
191
|
-
const onKeyChange = EventEmitter();
|
|
192
154
|
const onLoadingChange = EventEmitter();
|
|
193
155
|
const onFetchingChange = EventEmitter();
|
|
194
156
|
const onInitialLoaded = EventEmitter();
|
|
195
|
-
const onKeyUpdate = EventEmitterSelective(getFallbackNamespaces);
|
|
196
|
-
const onCacheChange = EventEmitter();
|
|
197
157
|
const onRunningChange = EventEmitter();
|
|
198
|
-
|
|
199
|
-
|
|
158
|
+
const onCacheChange = EventEmitter();
|
|
159
|
+
const onUpdate = EventEmitterSelective(getFallbackNs, getDefaultNs);
|
|
160
|
+
onInitialLoaded.listen(() => onUpdate.emit());
|
|
161
|
+
onLanguageChange.listen(() => onUpdate.emit());
|
|
200
162
|
onCacheChange.listen(({ value }) => {
|
|
201
|
-
|
|
163
|
+
onUpdate.emit([value.namespace], true);
|
|
202
164
|
});
|
|
203
165
|
const on = (event, handler) => {
|
|
204
166
|
switch (event) {
|
|
@@ -216,20 +178,19 @@ const Events = (getFallbackNamespaces) => {
|
|
|
216
178
|
return onRunningChange.listen(handler);
|
|
217
179
|
case 'cache':
|
|
218
180
|
return onCacheChange.listen(handler);
|
|
219
|
-
case '
|
|
220
|
-
return
|
|
181
|
+
case 'update':
|
|
182
|
+
return onUpdate.listen(handler);
|
|
221
183
|
}
|
|
222
184
|
};
|
|
223
185
|
return Object.freeze({
|
|
224
186
|
onPendingLanguageChange,
|
|
225
187
|
onLanguageChange,
|
|
226
|
-
onKeyChange,
|
|
227
|
-
onKeyUpdate,
|
|
228
188
|
onLoadingChange,
|
|
229
189
|
onFetchingChange,
|
|
230
190
|
onInitialLoaded,
|
|
231
191
|
onRunningChange,
|
|
232
192
|
onCacheChange,
|
|
193
|
+
onUpdate,
|
|
233
194
|
on,
|
|
234
195
|
});
|
|
235
196
|
};
|
|
@@ -252,7 +213,9 @@ const flattenTranslations = (data) => {
|
|
|
252
213
|
return result;
|
|
253
214
|
};
|
|
254
215
|
const decodeCacheKey = (key) => {
|
|
255
|
-
const [firstPart,
|
|
216
|
+
const [firstPart, ...rest] = key.split(':');
|
|
217
|
+
// if namespaces contains ":" it won't get lost
|
|
218
|
+
const secondPart = rest.join(':');
|
|
256
219
|
return { language: firstPart, namespace: secondPart || '' };
|
|
257
220
|
};
|
|
258
221
|
const encodeCacheKey = ({ language, namespace, }) => {
|
|
@@ -320,11 +283,11 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
320
283
|
const value = (_a = cache
|
|
321
284
|
.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
322
285
|
if (value !== undefined && value !== null) {
|
|
323
|
-
return namespace;
|
|
286
|
+
return [namespace];
|
|
324
287
|
}
|
|
325
288
|
}
|
|
326
289
|
}
|
|
327
|
-
return
|
|
290
|
+
return unique(namespaces);
|
|
328
291
|
}
|
|
329
292
|
function getTranslationFallback(namespaces, languages, key) {
|
|
330
293
|
var _a;
|
|
@@ -367,7 +330,10 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
367
330
|
}));
|
|
368
331
|
}));
|
|
369
332
|
}
|
|
370
|
-
|
|
333
|
+
/**
|
|
334
|
+
* Fetches production data
|
|
335
|
+
*/
|
|
336
|
+
function fetchProd(keyObject) {
|
|
371
337
|
let dataPromise = undefined;
|
|
372
338
|
if (!dataPromise) {
|
|
373
339
|
const staticDataValue = staticData[encodeCacheKey(keyObject)];
|
|
@@ -378,10 +344,6 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
378
344
|
if (!dataPromise) {
|
|
379
345
|
dataPromise = backendGetRecord(keyObject);
|
|
380
346
|
}
|
|
381
|
-
if (!dataPromise) {
|
|
382
|
-
// return empty data, so we know it has already been attempted to fetch
|
|
383
|
-
dataPromise = Promise.resolve({});
|
|
384
|
-
}
|
|
385
347
|
return dataPromise;
|
|
386
348
|
}
|
|
387
349
|
function fetchData(keyObject, isDev) {
|
|
@@ -391,12 +353,12 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
391
353
|
dataPromise = (_a = backendGetDevRecord(keyObject)) === null || _a === void 0 ? void 0 : _a.catch(() => {
|
|
392
354
|
// eslint-disable-next-line no-console
|
|
393
355
|
console.warn(`Tolgee: Failed to fetch data from dev backend`);
|
|
394
|
-
// fallback to
|
|
395
|
-
return
|
|
356
|
+
// fallback to prod fetch if dev fails
|
|
357
|
+
return fetchProd(keyObject);
|
|
396
358
|
});
|
|
397
359
|
}
|
|
398
360
|
if (!dataPromise) {
|
|
399
|
-
dataPromise =
|
|
361
|
+
dataPromise = fetchProd(keyObject);
|
|
400
362
|
}
|
|
401
363
|
return dataPromise;
|
|
402
364
|
}
|
|
@@ -413,7 +375,7 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
413
375
|
cacheKey,
|
|
414
376
|
};
|
|
415
377
|
}
|
|
416
|
-
const dataPromise = fetchData(keyObject, isDev);
|
|
378
|
+
const dataPromise = fetchData(keyObject, isDev) || Promise.resolve(undefined);
|
|
417
379
|
asyncRequests.set(cacheKey, dataPromise);
|
|
418
380
|
return {
|
|
419
381
|
new: true,
|
|
@@ -435,6 +397,10 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
435
397
|
if (data) {
|
|
436
398
|
addRecord(value.keyObject, data);
|
|
437
399
|
}
|
|
400
|
+
else if (!getRecord(value.keyObject)) {
|
|
401
|
+
// if no data exist, put empty object
|
|
402
|
+
addRecord(value.keyObject, {});
|
|
403
|
+
}
|
|
438
404
|
}
|
|
439
405
|
});
|
|
440
406
|
fetchingObserver.notify();
|
|
@@ -464,20 +430,9 @@ const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefault
|
|
|
464
430
|
});
|
|
465
431
|
};
|
|
466
432
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const valueOrPromise = (value, callback) => {
|
|
471
|
-
if (isPromise(value)) {
|
|
472
|
-
return Promise.resolve(value).then(callback);
|
|
473
|
-
}
|
|
474
|
-
else {
|
|
475
|
-
return callback(value);
|
|
476
|
-
}
|
|
477
|
-
};
|
|
478
|
-
const missingOptionError = (option) => `Tolgee: You need to specify '${option}' option`;
|
|
479
|
-
|
|
480
|
-
const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation) => {
|
|
433
|
+
const Plugins = (getLanguage, getInitialOptions, getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation) => {
|
|
434
|
+
let prepared = false;
|
|
435
|
+
let onPrepareQueue = [];
|
|
481
436
|
const plugins = {
|
|
482
437
|
ui: undefined,
|
|
483
438
|
observer: undefined,
|
|
@@ -492,37 +447,20 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
492
447
|
languageDetector: undefined,
|
|
493
448
|
languageStorage: undefined,
|
|
494
449
|
};
|
|
495
|
-
const onClick = async (
|
|
450
|
+
const onClick = async ({ keysAndDefaults, event }) => {
|
|
496
451
|
var _a;
|
|
497
|
-
const withNs = keysAndDefaults.map(({ key, ns, defaultValue }) =>
|
|
498
|
-
|
|
499
|
-
defaultValue,
|
|
500
|
-
ns: getFallbackArray(getTranslationNs({ key, ns, defaultValue })),
|
|
501
|
-
translation: getTranslation({
|
|
452
|
+
const withNs = keysAndDefaults.map(({ key, ns, defaultValue }) => {
|
|
453
|
+
return {
|
|
502
454
|
key,
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
new plugins.ui({
|
|
513
|
-
apiKey: getInitialOptions().apiKey,
|
|
514
|
-
apiUrl: getInitialOptions().apiUrl,
|
|
515
|
-
highlight,
|
|
516
|
-
changeTranslation,
|
|
517
|
-
});
|
|
518
|
-
if (!instances.observer) {
|
|
519
|
-
instances.observer = (_a = plugins.observer) === null || _a === void 0 ? void 0 : _a.call(plugins, {
|
|
520
|
-
translate,
|
|
521
|
-
onClick,
|
|
522
|
-
options: getObserverOptions(),
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
(_b = instances.observer) === null || _b === void 0 ? void 0 : _b.run({ mouseHighlight: isDev });
|
|
455
|
+
defaultValue,
|
|
456
|
+
ns: getTranslationNs({ key, ns }),
|
|
457
|
+
translation: getTranslation({
|
|
458
|
+
key,
|
|
459
|
+
ns,
|
|
460
|
+
}),
|
|
461
|
+
};
|
|
462
|
+
});
|
|
463
|
+
(_a = instances.ui) === null || _a === void 0 ? void 0 : _a.handleElementClick(withNs, event);
|
|
526
464
|
};
|
|
527
465
|
const stop = () => {
|
|
528
466
|
var _a;
|
|
@@ -534,7 +472,10 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
534
472
|
return ((_b = (_a = instances.observer) === null || _a === void 0 ? void 0 : _a.highlight) === null || _b === void 0 ? void 0 : _b.call(_a, key, ns)) || { unhighlight() { } };
|
|
535
473
|
};
|
|
536
474
|
const translate = (props) => {
|
|
537
|
-
const translation = getTranslation(
|
|
475
|
+
const translation = getTranslation({
|
|
476
|
+
key: props.key,
|
|
477
|
+
ns: props.ns,
|
|
478
|
+
});
|
|
538
479
|
return formatTranslation(Object.assign(Object.assign({}, props), { translation, formatEnabled: true }));
|
|
539
480
|
};
|
|
540
481
|
const setObserver = (observer) => {
|
|
@@ -560,9 +501,6 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
560
501
|
const setLanguageStorage = (storage) => {
|
|
561
502
|
instances.languageStorage = storage;
|
|
562
503
|
};
|
|
563
|
-
const getLanguageStorage = () => {
|
|
564
|
-
return instances.languageStorage;
|
|
565
|
-
};
|
|
566
504
|
const setStoredLanguage = (language) => {
|
|
567
505
|
var _a;
|
|
568
506
|
(_a = instances.languageStorage) === null || _a === void 0 ? void 0 : _a.setLanguage(language);
|
|
@@ -602,14 +540,37 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
602
540
|
const setDevBackend = (backend) => {
|
|
603
541
|
instances.devBackend = backend;
|
|
604
542
|
};
|
|
543
|
+
const run = (isDev) => {
|
|
544
|
+
var _a, _b;
|
|
545
|
+
if (!instances.ui && plugins.ui) {
|
|
546
|
+
const { apiKey, apiUrl, projectId } = getInitialOptions();
|
|
547
|
+
instances.ui = new plugins.ui({
|
|
548
|
+
apiKey: apiKey,
|
|
549
|
+
apiUrl: apiUrl,
|
|
550
|
+
projectId,
|
|
551
|
+
highlight,
|
|
552
|
+
changeTranslation,
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
if (!instances.observer) {
|
|
556
|
+
instances.observer = (_a = plugins.observer) === null || _a === void 0 ? void 0 : _a.call(plugins, {
|
|
557
|
+
translate,
|
|
558
|
+
onClick,
|
|
559
|
+
options: getInitialOptions().observerOptions,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
(_b = instances.observer) === null || _b === void 0 ? void 0 : _b.run({ mouseHighlight: isDev });
|
|
563
|
+
};
|
|
605
564
|
const getDevBackend = () => {
|
|
606
565
|
return instances.devBackend;
|
|
607
566
|
};
|
|
608
567
|
const getBackendDevRecord = ({ language, namespace }) => {
|
|
609
568
|
var _a;
|
|
569
|
+
const { apiKey, apiUrl, projectId } = getInitialOptions();
|
|
610
570
|
return (_a = instances.devBackend) === null || _a === void 0 ? void 0 : _a.getRecord({
|
|
611
|
-
apiKey
|
|
612
|
-
apiUrl
|
|
571
|
+
apiKey,
|
|
572
|
+
apiUrl,
|
|
573
|
+
projectId,
|
|
613
574
|
language,
|
|
614
575
|
namespace,
|
|
615
576
|
});
|
|
@@ -630,7 +591,40 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
630
591
|
}
|
|
631
592
|
return undefined;
|
|
632
593
|
};
|
|
633
|
-
const
|
|
594
|
+
const unwrap = (text) => {
|
|
595
|
+
var _a;
|
|
596
|
+
if (instances.observer) {
|
|
597
|
+
return (_a = instances.observer) === null || _a === void 0 ? void 0 : _a.unwrap(text);
|
|
598
|
+
}
|
|
599
|
+
return { text, keys: [] };
|
|
600
|
+
};
|
|
601
|
+
const retranslate = () => {
|
|
602
|
+
var _a;
|
|
603
|
+
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.retranslate();
|
|
604
|
+
};
|
|
605
|
+
const onPrepare = (callback) => {
|
|
606
|
+
onPrepareQueue.push(callback);
|
|
607
|
+
};
|
|
608
|
+
function addPlugin(tolgeeInstance, plugin) {
|
|
609
|
+
const pluginTools = Object.freeze({
|
|
610
|
+
setFinalFormatter,
|
|
611
|
+
addFormatter,
|
|
612
|
+
setObserver,
|
|
613
|
+
hasObserver,
|
|
614
|
+
setUi,
|
|
615
|
+
hasUi,
|
|
616
|
+
setDevBackend,
|
|
617
|
+
addBackend,
|
|
618
|
+
setLanguageDetector,
|
|
619
|
+
setLanguageStorage,
|
|
620
|
+
onPrepare,
|
|
621
|
+
});
|
|
622
|
+
plugin(tolgeeInstance, pluginTools);
|
|
623
|
+
if (prepared) {
|
|
624
|
+
prepare();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
function formatTranslation({ key, translation, defaultValue, noWrap, params, orEmpty, ns, formatEnabled, }) {
|
|
634
628
|
var _a;
|
|
635
629
|
const formattableTranslation = translation || defaultValue;
|
|
636
630
|
let result = formattableTranslation || (orEmpty ? '' : key);
|
|
@@ -665,7 +659,10 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
665
659
|
});
|
|
666
660
|
}
|
|
667
661
|
return result;
|
|
668
|
-
}
|
|
662
|
+
}
|
|
663
|
+
function hasDevBackend() {
|
|
664
|
+
return Boolean(getDevBackend());
|
|
665
|
+
}
|
|
669
666
|
const wrap = (params) => {
|
|
670
667
|
var _a;
|
|
671
668
|
if (instances.observer) {
|
|
@@ -673,42 +670,31 @@ const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAv
|
|
|
673
670
|
}
|
|
674
671
|
return params.translation;
|
|
675
672
|
};
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
673
|
+
function prepare() {
|
|
674
|
+
prepared = true;
|
|
675
|
+
while (onPrepareQueue.length) {
|
|
676
|
+
const queue = onPrepareQueue;
|
|
677
|
+
onPrepareQueue = [];
|
|
678
|
+
queue.forEach((callback) => callback());
|
|
680
679
|
}
|
|
681
|
-
|
|
682
|
-
};
|
|
683
|
-
const retranslate = () => {
|
|
684
|
-
var _a;
|
|
685
|
-
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.retranslate();
|
|
686
|
-
};
|
|
680
|
+
}
|
|
687
681
|
return Object.freeze({
|
|
688
|
-
|
|
689
|
-
|
|
682
|
+
prepare,
|
|
683
|
+
addPlugin,
|
|
690
684
|
formatTranslation,
|
|
691
|
-
setObserver,
|
|
692
|
-
hasObserver,
|
|
693
|
-
setUi,
|
|
694
|
-
hasUi,
|
|
695
|
-
addBackend,
|
|
696
|
-
setDevBackend,
|
|
697
685
|
getDevBackend,
|
|
698
686
|
getBackendRecord,
|
|
699
687
|
getBackendDevRecord,
|
|
700
|
-
setLanguageDetector,
|
|
701
688
|
getLanguageDetector,
|
|
702
|
-
setLanguageStorage,
|
|
703
|
-
getLanguageStorage,
|
|
704
689
|
getInitialLanguage,
|
|
705
690
|
setStoredLanguage,
|
|
706
691
|
run,
|
|
707
692
|
stop,
|
|
708
693
|
retranslate,
|
|
709
694
|
highlight,
|
|
710
|
-
wrap,
|
|
711
695
|
unwrap,
|
|
696
|
+
wrap,
|
|
697
|
+
hasDevBackend,
|
|
712
698
|
});
|
|
713
699
|
};
|
|
714
700
|
|
|
@@ -730,7 +716,7 @@ const ValueObserver = (initialValue, valueGetter, handler) => {
|
|
|
730
716
|
});
|
|
731
717
|
};
|
|
732
718
|
|
|
733
|
-
const
|
|
719
|
+
const defaultObserverOptions = {
|
|
734
720
|
tagAttributes: {
|
|
735
721
|
textarea: ['placeholder'],
|
|
736
722
|
input: ['value', 'placeholder'],
|
|
@@ -745,19 +731,23 @@ const defaultValues$1 = {
|
|
|
745
731
|
inputSuffix: '%-%',
|
|
746
732
|
passToParent: ['option', 'optgroup'],
|
|
747
733
|
};
|
|
748
|
-
const initObserverOptions = (options) => {
|
|
749
|
-
return Object.assign(Object.assign({}, defaultValues$1), options);
|
|
750
|
-
};
|
|
751
734
|
|
|
752
735
|
const defaultValues = {
|
|
753
736
|
defaultNs: '',
|
|
754
|
-
|
|
737
|
+
observerOptions: defaultObserverOptions,
|
|
738
|
+
observerType: 'invisible',
|
|
739
|
+
};
|
|
740
|
+
const combineOptions = (...states) => {
|
|
741
|
+
let result = {};
|
|
742
|
+
states.forEach((state) => {
|
|
743
|
+
result = Object.assign(Object.assign(Object.assign({}, result), state), { observerOptions: Object.assign(Object.assign({}, result.observerOptions), state === null || state === void 0 ? void 0 : state.observerOptions) });
|
|
744
|
+
});
|
|
745
|
+
return result;
|
|
755
746
|
};
|
|
756
747
|
const initState = (options, previousState) => {
|
|
757
|
-
const initialOptions =
|
|
748
|
+
const initialOptions = combineOptions(defaultValues, previousState === null || previousState === void 0 ? void 0 : previousState.initialOptions, options);
|
|
758
749
|
// remove extra '/' from url end
|
|
759
|
-
|
|
760
|
-
initialOptions.apiUrl = apiUrl ? apiUrl.replace(/\/+$/, '') : apiUrl;
|
|
750
|
+
initialOptions.apiUrl = sanitizeUrl(initialOptions.apiUrl);
|
|
761
751
|
return {
|
|
762
752
|
initialOptions,
|
|
763
753
|
activeNamespaces: (previousState === null || previousState === void 0 ? void 0 : previousState.activeNamespaces) || new Map(),
|
|
@@ -770,8 +760,7 @@ const initState = (options, previousState) => {
|
|
|
770
760
|
|
|
771
761
|
const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
772
762
|
let state = initState();
|
|
773
|
-
let
|
|
774
|
-
let devCredentials = {};
|
|
763
|
+
let devCredentials = undefined;
|
|
775
764
|
function init(options) {
|
|
776
765
|
state = initState(options, state);
|
|
777
766
|
}
|
|
@@ -838,6 +827,7 @@ const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
|
838
827
|
function getRequiredNamespaces() {
|
|
839
828
|
return unique([
|
|
840
829
|
...(state.initialOptions.ns || [state.initialOptions.defaultNs]),
|
|
830
|
+
...getFallbackArray(state.initialOptions.fallbackNs),
|
|
841
831
|
...state.activeNamespaces.keys(),
|
|
842
832
|
]);
|
|
843
833
|
}
|
|
@@ -851,11 +841,11 @@ const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
|
851
841
|
...getFallbackFromStruct(language, state.initialOptions.fallbackLanguage),
|
|
852
842
|
]);
|
|
853
843
|
}
|
|
854
|
-
function
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
return
|
|
844
|
+
function getFallbackNs() {
|
|
845
|
+
return getFallbackArray(state.initialOptions.fallbackNs);
|
|
846
|
+
}
|
|
847
|
+
function getDefaultNs(ns) {
|
|
848
|
+
return ns === undefined ? state.initialOptions.defaultNs : ns;
|
|
859
849
|
}
|
|
860
850
|
function getAvailableLanguages() {
|
|
861
851
|
if (state.initialOptions.availableLanguages) {
|
|
@@ -875,13 +865,12 @@ const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
|
875
865
|
};
|
|
876
866
|
}
|
|
877
867
|
function overrideCredentials(credentials) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
return observerOptions;
|
|
868
|
+
if (credentials) {
|
|
869
|
+
devCredentials = Object.assign(Object.assign({}, credentials), { apiUrl: sanitizeUrl(credentials.apiUrl) });
|
|
870
|
+
}
|
|
871
|
+
else {
|
|
872
|
+
devCredentials = undefined;
|
|
873
|
+
}
|
|
885
874
|
}
|
|
886
875
|
return Object.freeze({
|
|
887
876
|
init,
|
|
@@ -898,12 +887,11 @@ const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
|
898
887
|
removeActiveNs,
|
|
899
888
|
getRequiredNamespaces,
|
|
900
889
|
getFallbackLangs,
|
|
901
|
-
|
|
890
|
+
getFallbackNs,
|
|
891
|
+
getDefaultNs,
|
|
902
892
|
getAvailableLanguages,
|
|
903
893
|
withDefaultNs,
|
|
904
894
|
overrideCredentials,
|
|
905
|
-
setObserverOptions,
|
|
906
|
-
getObserverOptions,
|
|
907
895
|
});
|
|
908
896
|
};
|
|
909
897
|
|
|
@@ -940,11 +928,10 @@ function parseCombinedOptions(_a) {
|
|
|
940
928
|
ns: ns,
|
|
941
929
|
noWrap: noWrap,
|
|
942
930
|
orEmpty: orEmpty,
|
|
943
|
-
params: Object.assign(Object.assign({}, rest), params),
|
|
944
931
|
};
|
|
945
|
-
return options;
|
|
932
|
+
return Object.assign(Object.assign({}, options), { params: Object.assign({}, rest) });
|
|
946
933
|
}
|
|
947
|
-
const
|
|
934
|
+
const getTranslateProps = (keyOrProps, ...params) => {
|
|
948
935
|
let result = {};
|
|
949
936
|
let options;
|
|
950
937
|
if (typeof keyOrProps === 'object') {
|
|
@@ -967,20 +954,39 @@ const getTranslateParams = (keyOrProps, ...params) => {
|
|
|
967
954
|
};
|
|
968
955
|
|
|
969
956
|
const Controller = ({ options }) => {
|
|
970
|
-
const events = Events(
|
|
957
|
+
const events = Events(getFallbackNs, getDefaultNs);
|
|
971
958
|
const fetchingObserver = ValueObserver(false, () => cache.isFetching(), events.onFetchingChange.emit);
|
|
972
959
|
const loadingObserver = ValueObserver(false, () => isLoading(), events.onLoadingChange.emit);
|
|
973
960
|
const state = State(events.onLanguageChange, events.onPendingLanguageChange, events.onRunningChange);
|
|
974
|
-
const pluginService =
|
|
961
|
+
const pluginService = Plugins(state.getLanguage, state.getInitialOptions, state.getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation);
|
|
975
962
|
const cache = Cache(events.onCacheChange, pluginService.getBackendRecord, pluginService.getBackendDevRecord, state.withDefaultNs, state.isInitialLoading, fetchingObserver, loadingObserver);
|
|
976
963
|
if (options) {
|
|
977
964
|
init(options);
|
|
978
965
|
}
|
|
979
|
-
events.
|
|
966
|
+
events.onUpdate.listen(() => {
|
|
980
967
|
if (state.isRunning()) {
|
|
981
968
|
pluginService.retranslate();
|
|
982
969
|
}
|
|
983
970
|
});
|
|
971
|
+
function getFallbackNs() {
|
|
972
|
+
return state.getFallbackNs();
|
|
973
|
+
}
|
|
974
|
+
function getDefaultNs(ns) {
|
|
975
|
+
return state.getDefaultNs(ns);
|
|
976
|
+
}
|
|
977
|
+
// gets all namespaces where translation could be located
|
|
978
|
+
// takes (ns|default, fallback ns)
|
|
979
|
+
function getDefaultAndFallbackNs(ns) {
|
|
980
|
+
return [...getFallbackArray(getDefaultNs(ns)), ...getFallbackNs()];
|
|
981
|
+
}
|
|
982
|
+
// gets all namespaces which need to be loaded
|
|
983
|
+
// takes (ns|default, initial ns, fallback ns, active ns)
|
|
984
|
+
function getRequiredNamespaces(ns) {
|
|
985
|
+
return [
|
|
986
|
+
...getFallbackArray(ns || getDefaultNs()),
|
|
987
|
+
...state.getRequiredNamespaces(),
|
|
988
|
+
];
|
|
989
|
+
}
|
|
984
990
|
function changeTranslation(descriptor, key, value) {
|
|
985
991
|
const keyObject = state.withDefaultNs(descriptor);
|
|
986
992
|
const previousValue = cache.getTranslation(keyObject, key);
|
|
@@ -991,9 +997,6 @@ const Controller = ({ options }) => {
|
|
|
991
997
|
},
|
|
992
998
|
};
|
|
993
999
|
}
|
|
994
|
-
function getFallbackNamespaces() {
|
|
995
|
-
return state.getFallbackNamespaces();
|
|
996
|
-
}
|
|
997
1000
|
function init(options) {
|
|
998
1001
|
state.init(options);
|
|
999
1002
|
cache.addStaticData(state.getInitialOptions().staticData);
|
|
@@ -1002,9 +1005,7 @@ const Controller = ({ options }) => {
|
|
|
1002
1005
|
return cache.isLoading(state.getLanguage(), ns);
|
|
1003
1006
|
}
|
|
1004
1007
|
function isDev() {
|
|
1005
|
-
return Boolean(state.getInitialOptions().apiKey &&
|
|
1006
|
-
state.getInitialOptions().apiUrl &&
|
|
1007
|
-
pluginService.getDevBackend());
|
|
1008
|
+
return Boolean(state.getInitialOptions().apiKey && state.getInitialOptions().apiUrl);
|
|
1008
1009
|
}
|
|
1009
1010
|
async function addActiveNs(ns, forget) {
|
|
1010
1011
|
if (!forget) {
|
|
@@ -1016,7 +1017,7 @@ const Controller = ({ options }) => {
|
|
|
1016
1017
|
}
|
|
1017
1018
|
function getRequiredRecords(lang, ns) {
|
|
1018
1019
|
const languages = state.getFallbackLangs(lang);
|
|
1019
|
-
const namespaces =
|
|
1020
|
+
const namespaces = getRequiredNamespaces(ns);
|
|
1020
1021
|
const result = [];
|
|
1021
1022
|
languages.forEach((language) => {
|
|
1022
1023
|
namespaces.forEach((namespace) => {
|
|
@@ -1033,7 +1034,7 @@ const Controller = ({ options }) => {
|
|
|
1033
1034
|
return false;
|
|
1034
1035
|
}
|
|
1035
1036
|
const languages = state.getFallbackLangs(language);
|
|
1036
|
-
const namespaces =
|
|
1037
|
+
const namespaces = getRequiredNamespaces(ns);
|
|
1037
1038
|
const result = [];
|
|
1038
1039
|
languages.forEach((language) => {
|
|
1039
1040
|
namespaces.forEach((namespace) => {
|
|
@@ -1066,13 +1067,13 @@ const Controller = ({ options }) => {
|
|
|
1066
1067
|
pluginService.setStoredLanguage(language);
|
|
1067
1068
|
}
|
|
1068
1069
|
}
|
|
1069
|
-
function getTranslationNs({ key, ns
|
|
1070
|
-
const namespaces = ns !== undefined ? getFallbackArray(ns) : state.getFallbackNamespaces();
|
|
1070
|
+
function getTranslationNs({ key, ns }) {
|
|
1071
1071
|
const languages = state.getFallbackLangs();
|
|
1072
|
+
const namespaces = getDefaultAndFallbackNs(ns);
|
|
1072
1073
|
return cache.getTranslationNs(namespaces, languages, key);
|
|
1073
1074
|
}
|
|
1074
|
-
function getTranslation({ key, ns
|
|
1075
|
-
const namespaces =
|
|
1075
|
+
function getTranslation({ key, ns }) {
|
|
1076
|
+
const namespaces = getDefaultAndFallbackNs(ns);
|
|
1076
1077
|
const languages = state.getFallbackLangs();
|
|
1077
1078
|
return cache.getTranslationFallback(namespaces, languages, key);
|
|
1078
1079
|
}
|
|
@@ -1155,7 +1156,7 @@ const Controller = ({ options }) => {
|
|
|
1155
1156
|
}
|
|
1156
1157
|
const t = (...args) => {
|
|
1157
1158
|
// @ts-ignore
|
|
1158
|
-
const params =
|
|
1159
|
+
const params = getTranslateProps(...args);
|
|
1159
1160
|
const translation = getTranslation(params);
|
|
1160
1161
|
return pluginService.formatTranslation(Object.assign(Object.assign({}, params), { translation }));
|
|
1161
1162
|
};
|
|
@@ -1164,7 +1165,6 @@ const Controller = ({ options }) => {
|
|
|
1164
1165
|
getTranslation,
|
|
1165
1166
|
changeTranslation,
|
|
1166
1167
|
addActiveNs,
|
|
1167
|
-
loadRequiredRecords,
|
|
1168
1168
|
loadRecords,
|
|
1169
1169
|
loadRecord,
|
|
1170
1170
|
isLoading,
|
|
@@ -1175,23 +1175,11 @@ const Controller = ({ options }) => {
|
|
|
1175
1175
|
stop }));
|
|
1176
1176
|
};
|
|
1177
1177
|
|
|
1178
|
-
const
|
|
1178
|
+
const createTolgee = (options) => {
|
|
1179
1179
|
const controller = Controller({
|
|
1180
1180
|
options,
|
|
1181
1181
|
});
|
|
1182
|
-
|
|
1183
|
-
setFinalFormatter: controller.setFinalFormatter,
|
|
1184
|
-
addFormatter: controller.addFormatter,
|
|
1185
|
-
setObserver: controller.setObserver,
|
|
1186
|
-
hasObserver: controller.hasObserver,
|
|
1187
|
-
setUi: controller.setUi,
|
|
1188
|
-
hasUi: controller.hasUi,
|
|
1189
|
-
setDevBackend: controller.setDevBackend,
|
|
1190
|
-
addBackend: controller.addBackend,
|
|
1191
|
-
setLanguageDetector: controller.setLanguageDetector,
|
|
1192
|
-
setLanguageStorage: controller.setLanguageStorage,
|
|
1193
|
-
overrideCredentials: controller.overrideCredentials,
|
|
1194
|
-
});
|
|
1182
|
+
// restarts tolgee while applying callback
|
|
1195
1183
|
const withRestart = (callback) => {
|
|
1196
1184
|
const wasRunning = controller.isRunning();
|
|
1197
1185
|
wasRunning && controller.stop();
|
|
@@ -1199,67 +1187,353 @@ const Tolgee = (options) => {
|
|
|
1199
1187
|
wasRunning && controller.run();
|
|
1200
1188
|
};
|
|
1201
1189
|
const tolgee = Object.freeze({
|
|
1202
|
-
|
|
1190
|
+
/**
|
|
1191
|
+
* Listen to tolgee events.
|
|
1192
|
+
*/
|
|
1203
1193
|
on: controller.on,
|
|
1204
|
-
|
|
1205
|
-
|
|
1194
|
+
/**
|
|
1195
|
+
* Listen for specific namespaces changes.
|
|
1196
|
+
*
|
|
1197
|
+
* ```
|
|
1198
|
+
* const sub = tolgee.onUpdate(handler)
|
|
1199
|
+
*
|
|
1200
|
+
* // subscribe to selected namespace
|
|
1201
|
+
* sub.subscribeNs(['common'])
|
|
1202
|
+
*
|
|
1203
|
+
* // unsubscribe
|
|
1204
|
+
* sub.unsubscribe()
|
|
1205
|
+
* ```
|
|
1206
|
+
*/
|
|
1207
|
+
onNsUpdate: controller.onUpdate.listenSome,
|
|
1208
|
+
/**
|
|
1209
|
+
* @return current language if set.
|
|
1210
|
+
*/
|
|
1206
1211
|
getLanguage: controller.getLanguage,
|
|
1212
|
+
/**
|
|
1213
|
+
* `pendingLanguage` represents language which is currently being loaded.
|
|
1214
|
+
* @return current `pendingLanguage` if set.
|
|
1215
|
+
*/
|
|
1207
1216
|
getPendingLanguage: controller.getPendingLanguage,
|
|
1217
|
+
/**
|
|
1218
|
+
* Change current language.
|
|
1219
|
+
* - if not running sets `pendingLanguage`, `language` to the new value
|
|
1220
|
+
* - if running sets `pendingLanguage` to the value, fetches necessary data and then changes `language`
|
|
1221
|
+
*
|
|
1222
|
+
* @return Promise which is resolved when `language` is changed.
|
|
1223
|
+
*/
|
|
1208
1224
|
changeLanguage: controller.changeLanguage,
|
|
1225
|
+
/**
|
|
1226
|
+
* Temporarily change translation in cache.
|
|
1227
|
+
* @return object with revert method.
|
|
1228
|
+
*/
|
|
1209
1229
|
changeTranslation: controller.changeTranslation,
|
|
1230
|
+
/**
|
|
1231
|
+
* Adds namespace(s) list of active namespaces. And if tolgee is running, loads required data.
|
|
1232
|
+
*/
|
|
1210
1233
|
addActiveNs: controller.addActiveNs,
|
|
1234
|
+
/**
|
|
1235
|
+
* Remove namespace(s) from active namespaces.
|
|
1236
|
+
*
|
|
1237
|
+
* Tolgee internally counts how many times was each active namespace added,
|
|
1238
|
+
* so this method will remove namespace only if the counter goes down to 0.
|
|
1239
|
+
*/
|
|
1211
1240
|
removeActiveNs: controller.removeActiveNs,
|
|
1241
|
+
/**
|
|
1242
|
+
* Manually load multiple records from `Backend` (or `DevBackend` when in dev mode)
|
|
1243
|
+
*
|
|
1244
|
+
* It loads data together and adds them to cache in one operation, to prevent partly loaded state.
|
|
1245
|
+
*/
|
|
1212
1246
|
loadRecords: controller.loadRecords,
|
|
1247
|
+
/**
|
|
1248
|
+
* Manually load record from `Backend` (or `DevBackend` when in dev mode)
|
|
1249
|
+
*/
|
|
1213
1250
|
loadRecord: controller.loadRecord,
|
|
1251
|
+
/**
|
|
1252
|
+
*
|
|
1253
|
+
*/
|
|
1214
1254
|
addStaticData: controller.addStaticData,
|
|
1255
|
+
/**
|
|
1256
|
+
* Get record from cache.
|
|
1257
|
+
*/
|
|
1215
1258
|
getRecord: controller.getRecord,
|
|
1259
|
+
/**
|
|
1260
|
+
* Get all records from cache.
|
|
1261
|
+
*/
|
|
1216
1262
|
getAllRecords: controller.getAllRecords,
|
|
1263
|
+
/**
|
|
1264
|
+
* @param ns optional list of namespaces that you are interested in
|
|
1265
|
+
* @return `true` if there are data that need to be fetched.
|
|
1266
|
+
*/
|
|
1217
1267
|
isLoaded: controller.isLoaded,
|
|
1268
|
+
/**
|
|
1269
|
+
* @return `true` if tolgee is loading initial data (triggered by `run`).
|
|
1270
|
+
*/
|
|
1218
1271
|
isInitialLoading: controller.isInitialLoading,
|
|
1272
|
+
/**
|
|
1273
|
+
* @param ns optional list of namespaces that you are interested in
|
|
1274
|
+
* @return `true` if tolgee is loading some translations for the first time.
|
|
1275
|
+
*/
|
|
1219
1276
|
isLoading: controller.isLoading,
|
|
1277
|
+
/**
|
|
1278
|
+
* @param ns optional list of namespaces that you are interested in
|
|
1279
|
+
* @return `true` if tolgee is fetching some translations.
|
|
1280
|
+
*/
|
|
1220
1281
|
isFetching: controller.isFetching,
|
|
1282
|
+
/**
|
|
1283
|
+
* @return `true` if tolgee is running.
|
|
1284
|
+
*/
|
|
1221
1285
|
isRunning: controller.isRunning,
|
|
1286
|
+
/**
|
|
1287
|
+
* Changes internal state to running: true and loads initial files.
|
|
1288
|
+
* Runs runnable plugins mainly Observer if present.
|
|
1289
|
+
*/
|
|
1222
1290
|
run: controller.run,
|
|
1291
|
+
/**
|
|
1292
|
+
* Changes internal state to running: false and stops runnable plugins.
|
|
1293
|
+
*/
|
|
1223
1294
|
stop: controller.stop,
|
|
1295
|
+
/**
|
|
1296
|
+
* Returns translated and formatted key.
|
|
1297
|
+
* If Observer is present and tolgee is running, wraps result to be identifiable in the DOM.
|
|
1298
|
+
*/
|
|
1224
1299
|
t: controller.t,
|
|
1300
|
+
/**
|
|
1301
|
+
* Highlight keys that match selection.
|
|
1302
|
+
*/
|
|
1225
1303
|
highlight: controller.highlight,
|
|
1304
|
+
/**
|
|
1305
|
+
* @return current Tolgee options.
|
|
1306
|
+
*/
|
|
1226
1307
|
getInitialOptions: controller.getInitialOptions,
|
|
1308
|
+
/**
|
|
1309
|
+
* Tolgee is in dev mode if `DevTools` plugin is used and `apiKey` + `apiUrl` are specified.
|
|
1310
|
+
* @return `true` if tolgee is in dev mode.
|
|
1311
|
+
*/
|
|
1227
1312
|
isDev: controller.isDev,
|
|
1313
|
+
/**
|
|
1314
|
+
* Wraps translation if there is `Observer` plugin
|
|
1315
|
+
*/
|
|
1228
1316
|
wrap: controller.wrap,
|
|
1317
|
+
/**
|
|
1318
|
+
* Unwrap translation
|
|
1319
|
+
*/
|
|
1229
1320
|
unwrap: controller.unwrap,
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1321
|
+
/**
|
|
1322
|
+
* Override creadentials passed on initialization
|
|
1323
|
+
*/
|
|
1324
|
+
overrideCredentials(credentials) {
|
|
1325
|
+
withRestart(() => controller.overrideCredentials(credentials));
|
|
1234
1326
|
},
|
|
1235
|
-
|
|
1327
|
+
/**
|
|
1328
|
+
* Add tolgee plugin.
|
|
1329
|
+
*/
|
|
1330
|
+
addPlugin(plugin) {
|
|
1236
1331
|
if (plugin) {
|
|
1237
|
-
withRestart(() =>
|
|
1332
|
+
withRestart(() => controller.addPlugin(tolgee, plugin));
|
|
1238
1333
|
}
|
|
1239
|
-
return tolgee;
|
|
1240
1334
|
},
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1335
|
+
/**
|
|
1336
|
+
* Updates options after instance creation. Extends existing options,
|
|
1337
|
+
* so it only changes the fields, that are listed.
|
|
1338
|
+
*
|
|
1339
|
+
* When called in running state, tolgee stops and runs again.
|
|
1340
|
+
*/
|
|
1341
|
+
updateOptions(options) {
|
|
1342
|
+
if (options) {
|
|
1343
|
+
withRestart(() => controller.init(options));
|
|
1344
|
+
}
|
|
1244
1345
|
},
|
|
1245
1346
|
});
|
|
1246
1347
|
return tolgee;
|
|
1247
1348
|
};
|
|
1349
|
+
/**
|
|
1350
|
+
* Tolgee chainable constructor.
|
|
1351
|
+
*
|
|
1352
|
+
* Usage:
|
|
1353
|
+
* ```
|
|
1354
|
+
* const tolgee = Tolgee().use(...).init(...)
|
|
1355
|
+
* ```
|
|
1356
|
+
*/
|
|
1357
|
+
const Tolgee = () => {
|
|
1358
|
+
const state = {
|
|
1359
|
+
plugins: [],
|
|
1360
|
+
options: {},
|
|
1361
|
+
};
|
|
1362
|
+
const tolgeeChain = Object.freeze({
|
|
1363
|
+
use(plugin) {
|
|
1364
|
+
state.plugins.push(plugin);
|
|
1365
|
+
return tolgeeChain;
|
|
1366
|
+
},
|
|
1367
|
+
updateDefaults(options) {
|
|
1368
|
+
state.options = combineOptions(state.options, options);
|
|
1369
|
+
return tolgeeChain;
|
|
1370
|
+
},
|
|
1371
|
+
init(options) {
|
|
1372
|
+
const tolgee = createTolgee(combineOptions(state.options, options));
|
|
1373
|
+
state.plugins.forEach(tolgee.addPlugin);
|
|
1374
|
+
return tolgee;
|
|
1375
|
+
},
|
|
1376
|
+
});
|
|
1377
|
+
return tolgeeChain;
|
|
1378
|
+
};
|
|
1379
|
+
|
|
1380
|
+
const ERROR_PARAM_EMPTY = 0, ERROR_UNEXPECTED_CHAR = 1, ERROR_UNEXPECTED_END = 2;
|
|
1381
|
+
class FormatError extends Error {
|
|
1382
|
+
constructor(code, index, text) {
|
|
1383
|
+
let error;
|
|
1384
|
+
if (code === ERROR_PARAM_EMPTY) {
|
|
1385
|
+
error = 'Empty parameter';
|
|
1386
|
+
}
|
|
1387
|
+
else if (code === ERROR_UNEXPECTED_CHAR) {
|
|
1388
|
+
error = 'Unexpected character';
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
error = 'Unexpected end';
|
|
1392
|
+
}
|
|
1393
|
+
super(`Tolgee parser: ${error} at ${index} in "${text}"`);
|
|
1394
|
+
this.code = code;
|
|
1395
|
+
this.index = index;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
function isWhitespace(ch) {
|
|
1400
|
+
return /\s/.test(ch);
|
|
1401
|
+
}
|
|
1402
|
+
const STATE_TEXT = 0, STATE_ESCAPE_MAYBE = 1, STATE_ESCAPE = 2, STATE_PARAM = 3, STATE_PARAM_AFTER = 4;
|
|
1403
|
+
const END_STATES = new Set([
|
|
1404
|
+
STATE_ESCAPE,
|
|
1405
|
+
STATE_ESCAPE_MAYBE,
|
|
1406
|
+
STATE_TEXT,
|
|
1407
|
+
]);
|
|
1408
|
+
const CHAR_ESCAPE = "'";
|
|
1409
|
+
const ESCAPABLE = new Set(['{', '}', CHAR_ESCAPE]);
|
|
1410
|
+
const isAllowedInParam = (char) => {
|
|
1411
|
+
return /[0-9a-zA-Z_]/.test(char);
|
|
1412
|
+
};
|
|
1413
|
+
function formatParser(translation) {
|
|
1414
|
+
let state = STATE_TEXT;
|
|
1415
|
+
let text = '';
|
|
1416
|
+
let param = '';
|
|
1417
|
+
let ch = '';
|
|
1418
|
+
const texts = [];
|
|
1419
|
+
const params = [];
|
|
1420
|
+
let i = 0;
|
|
1421
|
+
function parsingError(code) {
|
|
1422
|
+
throw new FormatError(code, i, translation);
|
|
1423
|
+
}
|
|
1424
|
+
const addText = () => {
|
|
1425
|
+
texts.push(text);
|
|
1426
|
+
text = '';
|
|
1427
|
+
};
|
|
1428
|
+
const addParamChar = () => {
|
|
1429
|
+
if (!isAllowedInParam(ch)) {
|
|
1430
|
+
parsingError(ERROR_UNEXPECTED_CHAR);
|
|
1431
|
+
}
|
|
1432
|
+
param += ch;
|
|
1433
|
+
};
|
|
1434
|
+
const addParam = () => {
|
|
1435
|
+
if (param === '') {
|
|
1436
|
+
parsingError(ERROR_PARAM_EMPTY);
|
|
1437
|
+
}
|
|
1438
|
+
params.push(param);
|
|
1439
|
+
param = '';
|
|
1440
|
+
};
|
|
1441
|
+
for (i = 0; i < translation.length; i++) {
|
|
1442
|
+
ch = translation[i];
|
|
1443
|
+
switch (state) {
|
|
1444
|
+
case STATE_TEXT:
|
|
1445
|
+
if (ch === CHAR_ESCAPE) {
|
|
1446
|
+
text += ch;
|
|
1447
|
+
state = STATE_ESCAPE_MAYBE;
|
|
1448
|
+
}
|
|
1449
|
+
else if (ch === '{') {
|
|
1450
|
+
addText();
|
|
1451
|
+
state = STATE_PARAM;
|
|
1452
|
+
}
|
|
1453
|
+
else {
|
|
1454
|
+
text += ch;
|
|
1455
|
+
state = STATE_TEXT;
|
|
1456
|
+
}
|
|
1457
|
+
break;
|
|
1458
|
+
case STATE_ESCAPE_MAYBE:
|
|
1459
|
+
if (ESCAPABLE.has(ch)) {
|
|
1460
|
+
text = text.slice(0, -1) + ch;
|
|
1461
|
+
state = STATE_ESCAPE;
|
|
1462
|
+
}
|
|
1463
|
+
else {
|
|
1464
|
+
text += ch;
|
|
1465
|
+
state = STATE_TEXT;
|
|
1466
|
+
}
|
|
1467
|
+
break;
|
|
1468
|
+
case STATE_ESCAPE:
|
|
1469
|
+
if (ch === CHAR_ESCAPE) {
|
|
1470
|
+
state = STATE_TEXT;
|
|
1471
|
+
}
|
|
1472
|
+
else {
|
|
1473
|
+
text += ch;
|
|
1474
|
+
state = STATE_ESCAPE;
|
|
1475
|
+
}
|
|
1476
|
+
break;
|
|
1477
|
+
case STATE_PARAM:
|
|
1478
|
+
if (ch === '}') {
|
|
1479
|
+
addParam();
|
|
1480
|
+
state = STATE_TEXT;
|
|
1481
|
+
}
|
|
1482
|
+
else if (!isWhitespace(ch)) {
|
|
1483
|
+
addParamChar();
|
|
1484
|
+
state = STATE_PARAM;
|
|
1485
|
+
}
|
|
1486
|
+
else if (param !== '') {
|
|
1487
|
+
addParam();
|
|
1488
|
+
state = STATE_PARAM_AFTER;
|
|
1489
|
+
}
|
|
1490
|
+
break;
|
|
1491
|
+
case STATE_PARAM_AFTER:
|
|
1492
|
+
if (ch == '}') {
|
|
1493
|
+
state = STATE_TEXT;
|
|
1494
|
+
}
|
|
1495
|
+
else if (isWhitespace(ch)) {
|
|
1496
|
+
state = STATE_PARAM_AFTER;
|
|
1497
|
+
}
|
|
1498
|
+
else {
|
|
1499
|
+
parsingError(ERROR_UNEXPECTED_CHAR);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
if (!END_STATES.has(state)) {
|
|
1504
|
+
parsingError(ERROR_UNEXPECTED_END);
|
|
1505
|
+
}
|
|
1506
|
+
addText();
|
|
1507
|
+
return [texts, params];
|
|
1508
|
+
}
|
|
1248
1509
|
|
|
1249
|
-
|
|
1250
|
-
const
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1510
|
+
function formatter(translation, params) {
|
|
1511
|
+
const [texts, pars] = formatParser(translation);
|
|
1512
|
+
const result = [texts[0]];
|
|
1513
|
+
for (let i = 1; i < texts.length; i++) {
|
|
1514
|
+
const parameter = params === null || params === void 0 ? void 0 : params[pars[i - 1]];
|
|
1515
|
+
if (parameter === undefined) {
|
|
1516
|
+
throw new Error(`Missing parameter "${pars[i - 1]}" in "${translation}"`);
|
|
1517
|
+
}
|
|
1518
|
+
result.push(String(parameter));
|
|
1519
|
+
result.push(texts[i]);
|
|
1520
|
+
}
|
|
1521
|
+
return result.join('');
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
function createFormatSimple() {
|
|
1525
|
+
return {
|
|
1526
|
+
format: ({ translation, params }) => formatter(translation, params),
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
const FormatSimple = () => (tolgee, tools) => {
|
|
1530
|
+
tools.setFinalFormatter(createFormatSimple());
|
|
1531
|
+
return tolgee;
|
|
1532
|
+
};
|
|
1255
1533
|
|
|
1256
|
-
exports.
|
|
1257
|
-
exports.RESTRICTED_ASCENDANT_ATTRIBUTE = RESTRICTED_ASCENDANT_ATTRIBUTE;
|
|
1258
|
-
exports.TOLGEE_ATTRIBUTE_NAME = TOLGEE_ATTRIBUTE_NAME;
|
|
1259
|
-
exports.TOLGEE_HIGHLIGHTER_CLASS = TOLGEE_HIGHLIGHTER_CLASS;
|
|
1260
|
-
exports.TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE = TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE;
|
|
1534
|
+
exports.FormatSimple = FormatSimple;
|
|
1261
1535
|
exports.Tolgee = Tolgee;
|
|
1262
1536
|
exports.getFallback = getFallback;
|
|
1263
1537
|
exports.getFallbackArray = getFallbackArray;
|
|
1264
|
-
exports.
|
|
1538
|
+
exports.getTranslateProps = getTranslateProps;
|
|
1265
1539
|
//# sourceMappingURL=tolgee.cjs.js.map
|