@tolgee/core 5.0.0-rc.9be0f0e.0 → 5.0.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/README.md +174 -0
- package/README.njk.md +61 -0
- package/dist/tolgee.cjs.js +723 -351
- 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} +722 -346
- 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 +723 -351
- 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 +10 -9
- package/lib/Controller/Controller.d.ts +104 -45
- package/lib/Controller/Events/EventEmitter.d.ts +6 -0
- package/lib/Controller/Events/EventEmitterSelective.d.ts +7 -0
- package/lib/Controller/Events/Events.d.ts +14 -0
- package/lib/Controller/Plugins/Plugins.d.ts +12 -25
- package/lib/Controller/State/State.d.ts +27 -9
- package/lib/Controller/State/initState.d.ts +46 -15
- 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/TolgeeCore.d.ts +204 -0
- package/lib/TranslateParams.d.ts +1 -1
- package/lib/helpers.d.ts +8 -0
- package/lib/index.d.ts +4 -4
- 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 +127 -0
- package/package.json +5 -4
- package/src/Controller/Cache/Cache.ts +31 -31
- package/src/Controller/Cache/helpers.ts +6 -6
- package/src/Controller/Controller.ts +78 -50
- package/src/Controller/Events/EventEmitter.ts +34 -0
- package/src/Controller/Events/EventEmitterSelective.test.ts +110 -0
- package/src/Controller/Events/EventEmitterSelective.ts +132 -0
- package/src/Controller/Events/Events.ts +69 -0
- package/src/Controller/Plugins/Plugins.ts +182 -133
- package/src/Controller/State/State.ts +43 -26
- package/src/Controller/State/initState.ts +97 -25
- 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/TolgeeCore.ts +267 -0
- package/src/TranslateParams.test.ts +9 -12
- package/src/TranslateParams.ts +6 -5
- package/src/__test/backend.test.ts +6 -6
- package/src/__test/cache.test.ts +190 -0
- package/src/__test/client.test.ts +2 -2
- package/src/__test/events.test.ts +32 -7
- package/src/__test/format.simple.test.ts +14 -0
- package/src/__test/formatError.test.ts +61 -0
- package/src/__test/initialization.test.ts +15 -3
- package/src/__test/languageDetection.test.ts +14 -8
- package/src/__test/languageStorage.test.ts +10 -11
- package/src/__test/languages.test.ts +30 -6
- package/src/__test/loading.test.ts +2 -2
- package/src/__test/{namespacesFallback.test.ts → namespaces.fallback.test.ts} +10 -8
- package/src/__test/namespaces.test.ts +30 -7
- package/src/__test/options.test.ts +64 -0
- package/src/__test/plugins.test.ts +29 -18
- package/src/helpers.ts +53 -0
- package/src/index.ts +4 -10
- 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/Events/EventEmitter.d.ts +0 -6
- package/lib/Events/EventEmitterSelective.d.ts +0 -15
- package/lib/Events/Events.d.ts +0 -50
- package/lib/Tolgee.d.ts +0 -2
- package/lib/constants.d.ts +0 -5
- package/lib/types.d.ts +0 -274
- package/src/Controller/State/helpers.ts +0 -41
- package/src/Events/EventEmitter.ts +0 -27
- package/src/Events/EventEmitterSelective.test.ts +0 -108
- package/src/Events/EventEmitterSelective.ts +0 -160
- package/src/Events/Events.ts +0 -66
- package/src/Tolgee.ts +0 -77
- package/src/constants.ts +0 -7
- package/src/types.ts +0 -380
package/dist/tolgee.umd.js
CHANGED
|
@@ -4,25 +4,18 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tolgee/core"] = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
const emit = (data) => {
|
|
21
|
-
handlers.forEach((handler) => handler({ value: data }));
|
|
22
|
-
};
|
|
23
|
-
return Object.freeze({ listen, emit });
|
|
7
|
+
function isPromise(value) {
|
|
8
|
+
return Boolean(value && typeof value.then === 'function');
|
|
9
|
+
}
|
|
10
|
+
const valueOrPromise = (value, callback) => {
|
|
11
|
+
if (isPromise(value)) {
|
|
12
|
+
return Promise.resolve(value).then(callback);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return callback(value);
|
|
16
|
+
}
|
|
24
17
|
};
|
|
25
|
-
|
|
18
|
+
const missingOptionError = (option) => `Tolgee: You need to specify '${option}' option`;
|
|
26
19
|
function isObject(item) {
|
|
27
20
|
return typeof item === 'object' && !Array.isArray(item) && item !== null;
|
|
28
21
|
}
|
|
@@ -49,22 +42,40 @@
|
|
|
49
42
|
function unique(arr) {
|
|
50
43
|
return Array.from(new Set(arr));
|
|
51
44
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const currNum = map.get(value) || 0;
|
|
55
|
-
map.set(value, currNum + 1);
|
|
45
|
+
function sanitizeUrl(url) {
|
|
46
|
+
return url ? url.replace(/\/+$/, '') : url;
|
|
56
47
|
}
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (currNum <= 0) {
|
|
61
|
-
map.delete(value);
|
|
48
|
+
function getErrorMessage(error) {
|
|
49
|
+
if (typeof error === 'string') {
|
|
50
|
+
return error;
|
|
62
51
|
}
|
|
63
|
-
else {
|
|
64
|
-
|
|
52
|
+
else if (typeof (error === null || error === void 0 ? void 0 : error.message) === 'string') {
|
|
53
|
+
return error.message;
|
|
65
54
|
}
|
|
66
55
|
}
|
|
67
|
-
|
|
56
|
+
|
|
57
|
+
const EventEmitter = (isActive) => {
|
|
58
|
+
let handlers = [];
|
|
59
|
+
const listen = (handler) => {
|
|
60
|
+
const handlerWrapper = (e) => {
|
|
61
|
+
handler(e);
|
|
62
|
+
};
|
|
63
|
+
handlers.push(handlerWrapper);
|
|
64
|
+
return {
|
|
65
|
+
unsubscribe: () => {
|
|
66
|
+
handlers = handlers.filter((i) => handlerWrapper !== i);
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const emit = (data) => {
|
|
71
|
+
if (isActive()) {
|
|
72
|
+
handlers.forEach((handler) => handler({ value: data }));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return Object.freeze({ listen, emit });
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const EventEmitterSelective = (isActive, getFallbackNs, getDefaultNs) => {
|
|
68
79
|
const listeners = new Set();
|
|
69
80
|
const partialListeners = new Set();
|
|
70
81
|
const listen = (handler) => {
|
|
@@ -81,8 +92,7 @@
|
|
|
81
92
|
fn: (e) => {
|
|
82
93
|
handler(e);
|
|
83
94
|
},
|
|
84
|
-
|
|
85
|
-
namespaces: new Map(),
|
|
95
|
+
namespaces: new Set(),
|
|
86
96
|
};
|
|
87
97
|
partialListeners.add(handlerWrapper);
|
|
88
98
|
const result = {
|
|
@@ -90,105 +100,85 @@
|
|
|
90
100
|
partialListeners.delete(handlerWrapper);
|
|
91
101
|
},
|
|
92
102
|
subscribeNs: (ns) => {
|
|
93
|
-
getFallbackArray(ns).forEach((val) =>
|
|
94
|
-
return result;
|
|
95
|
-
},
|
|
96
|
-
unsubscribeNs: (ns) => {
|
|
97
|
-
getFallbackArray(ns).forEach((val) => decrementInMap(handlerWrapper.namespaces, val));
|
|
98
|
-
return result;
|
|
99
|
-
},
|
|
100
|
-
subscribeKey: (descriptor) => {
|
|
101
|
-
const { key, ns } = descriptor;
|
|
102
|
-
incrementInMap(handlerWrapper.keys, key);
|
|
103
|
-
getFallbackArray(ns).forEach((val) => incrementInMap(handlerWrapper.namespaces, val));
|
|
103
|
+
getFallbackArray(ns).forEach((val) => handlerWrapper.namespaces.add(val));
|
|
104
104
|
if (ns === undefined) {
|
|
105
|
-
// subscribing to
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
return result;
|
|
109
|
-
},
|
|
110
|
-
unsubscribeKey: (descriptor) => {
|
|
111
|
-
const { key, ns } = descriptor;
|
|
112
|
-
decrementInMap(handlerWrapper.keys, key);
|
|
113
|
-
getFallbackArray(ns).forEach((val) => decrementInMap(handlerWrapper.namespaces, val));
|
|
114
|
-
if (ns === undefined) {
|
|
115
|
-
// subscribing to all namespaces
|
|
116
|
-
decrementInMap(handlerWrapper.namespaces, undefined);
|
|
105
|
+
// subscribing to default ns
|
|
106
|
+
handlerWrapper.namespaces.add(getDefaultNs());
|
|
117
107
|
}
|
|
118
108
|
return result;
|
|
119
109
|
},
|
|
120
110
|
};
|
|
121
111
|
return result;
|
|
122
112
|
};
|
|
123
|
-
const callHandlers = (
|
|
113
|
+
const callHandlers = (ns) => {
|
|
114
|
+
// everything is implicitly subscribed to fallbacks
|
|
115
|
+
// as it can always fall through to it
|
|
116
|
+
const fallbackNamespaces = new Set(getFallbackNs());
|
|
124
117
|
partialListeners.forEach((handler) => {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const keyMentioned = key !== undefined;
|
|
129
|
-
const keyMatches = key === undefined || handler.keys.has(key) || handler.keys.size === 0;
|
|
130
|
-
if ((!nsMentioned || nsMatches) && (!keyMentioned || keyMatches)) {
|
|
118
|
+
const nsMatches = ns === undefined ||
|
|
119
|
+
(ns === null || ns === void 0 ? void 0 : ns.findIndex((ns) => fallbackNamespaces.has(ns) || handler.namespaces.has(ns))) !== -1;
|
|
120
|
+
if (nsMatches) {
|
|
131
121
|
handler.fn({ value: undefined });
|
|
132
122
|
}
|
|
133
123
|
});
|
|
134
124
|
};
|
|
135
125
|
let queue = [];
|
|
126
|
+
// merge events in queue into one event
|
|
136
127
|
const solveQueue = () => {
|
|
137
128
|
if (queue.length === 0) {
|
|
138
129
|
return;
|
|
139
130
|
}
|
|
131
|
+
const queueCopy = queue;
|
|
132
|
+
queue = [];
|
|
140
133
|
listeners.forEach((handler) => {
|
|
141
134
|
handler({ value: undefined });
|
|
142
135
|
});
|
|
143
|
-
let namespaces =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
let namespaces = new Set();
|
|
137
|
+
queueCopy.forEach((ns) => {
|
|
138
|
+
if (ns === undefined) {
|
|
139
|
+
// when no ns specified, it affects all namespaces
|
|
147
140
|
namespaces = undefined;
|
|
148
141
|
}
|
|
149
142
|
else if (namespaces !== undefined) {
|
|
150
|
-
|
|
143
|
+
ns.forEach((ns) => namespaces.add(ns));
|
|
151
144
|
}
|
|
152
|
-
if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.key) === undefined) {
|
|
153
|
-
keys = undefined;
|
|
154
|
-
}
|
|
155
|
-
else if (keys !== undefined) {
|
|
156
|
-
keys = [...keys, descriptor.key];
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
(keys || [undefined]).forEach((key) => {
|
|
160
|
-
callHandlers(key, namespaces);
|
|
161
145
|
});
|
|
162
|
-
|
|
146
|
+
const namespacesArray = namespaces
|
|
147
|
+
? Array.from(namespaces.keys())
|
|
148
|
+
: undefined;
|
|
149
|
+
callHandlers(namespacesArray);
|
|
163
150
|
};
|
|
164
|
-
const emit = (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
Promise.resolve().then(() => {
|
|
151
|
+
const emit = (ns, delayed) => {
|
|
152
|
+
if (isActive()) {
|
|
153
|
+
queue.push(ns);
|
|
154
|
+
if (!delayed) {
|
|
171
155
|
solveQueue();
|
|
172
|
-
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
setTimeout(solveQueue, 0);
|
|
159
|
+
}
|
|
173
160
|
}
|
|
174
161
|
};
|
|
175
162
|
return Object.freeze({ listenSome, listen, emit });
|
|
176
163
|
};
|
|
177
164
|
|
|
178
|
-
const Events = () => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
165
|
+
const Events = (getFallbackNs, getDefaultNs) => {
|
|
166
|
+
let emitterActive = true;
|
|
167
|
+
function isActive() {
|
|
168
|
+
return emitterActive;
|
|
169
|
+
}
|
|
170
|
+
const onPendingLanguageChange = EventEmitter(isActive);
|
|
171
|
+
const onLanguageChange = EventEmitter(isActive);
|
|
172
|
+
const onLoadingChange = EventEmitter(isActive);
|
|
173
|
+
const onFetchingChange = EventEmitter(isActive);
|
|
174
|
+
const onInitialLoaded = EventEmitter(isActive);
|
|
175
|
+
const onRunningChange = EventEmitter(isActive);
|
|
176
|
+
const onCacheChange = EventEmitter(isActive);
|
|
177
|
+
const onUpdate = EventEmitterSelective(isActive, getFallbackNs, getDefaultNs);
|
|
178
|
+
onInitialLoaded.listen(() => onUpdate.emit());
|
|
179
|
+
onLanguageChange.listen(() => onUpdate.emit());
|
|
190
180
|
onCacheChange.listen(({ value }) => {
|
|
191
|
-
|
|
181
|
+
onUpdate.emit([value.namespace], true);
|
|
192
182
|
});
|
|
193
183
|
const on = (event, handler) => {
|
|
194
184
|
switch (event) {
|
|
@@ -206,20 +196,23 @@
|
|
|
206
196
|
return onRunningChange.listen(handler);
|
|
207
197
|
case 'cache':
|
|
208
198
|
return onCacheChange.listen(handler);
|
|
209
|
-
case '
|
|
210
|
-
return
|
|
199
|
+
case 'update':
|
|
200
|
+
return onUpdate.listen(handler);
|
|
211
201
|
}
|
|
212
202
|
};
|
|
203
|
+
function setEmmiterActive(active) {
|
|
204
|
+
emitterActive = active;
|
|
205
|
+
}
|
|
213
206
|
return Object.freeze({
|
|
214
207
|
onPendingLanguageChange,
|
|
215
208
|
onLanguageChange,
|
|
216
|
-
onKeyChange,
|
|
217
|
-
onKeyUpdate,
|
|
218
209
|
onLoadingChange,
|
|
219
210
|
onFetchingChange,
|
|
220
211
|
onInitialLoaded,
|
|
221
212
|
onRunningChange,
|
|
222
213
|
onCacheChange,
|
|
214
|
+
onUpdate,
|
|
215
|
+
setEmmiterActive,
|
|
223
216
|
on,
|
|
224
217
|
});
|
|
225
218
|
};
|
|
@@ -232,7 +225,7 @@
|
|
|
232
225
|
return;
|
|
233
226
|
}
|
|
234
227
|
if (typeof value === 'object') {
|
|
235
|
-
|
|
228
|
+
flattenTranslations(value).forEach((flatValue, flatKey) => {
|
|
236
229
|
result.set(key + '.' + flatKey, flatValue);
|
|
237
230
|
});
|
|
238
231
|
return;
|
|
@@ -242,7 +235,9 @@
|
|
|
242
235
|
return result;
|
|
243
236
|
};
|
|
244
237
|
const decodeCacheKey = (key) => {
|
|
245
|
-
const [firstPart,
|
|
238
|
+
const [firstPart, ...rest] = key.split(':');
|
|
239
|
+
// if namespaces contains ":" it won't get lost
|
|
240
|
+
const secondPart = rest.join(':');
|
|
246
241
|
return { language: firstPart, namespace: secondPart || '' };
|
|
247
242
|
};
|
|
248
243
|
const encodeCacheKey = ({ language, namespace, }) => {
|
|
@@ -297,7 +292,7 @@
|
|
|
297
292
|
}
|
|
298
293
|
function getRecord(descriptor) {
|
|
299
294
|
var _a;
|
|
300
|
-
return (_a = cache.get(encodeCacheKey(descriptor))) === null || _a === void 0 ? void 0 : _a.data;
|
|
295
|
+
return (_a = cache.get(encodeCacheKey(withDefaultNs(descriptor)))) === null || _a === void 0 ? void 0 : _a.data;
|
|
301
296
|
}
|
|
302
297
|
function getTranslation(descriptor, key) {
|
|
303
298
|
var _a;
|
|
@@ -310,11 +305,11 @@
|
|
|
310
305
|
const value = (_a = cache
|
|
311
306
|
.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
312
307
|
if (value !== undefined && value !== null) {
|
|
313
|
-
return namespace;
|
|
308
|
+
return [namespace];
|
|
314
309
|
}
|
|
315
310
|
}
|
|
316
311
|
}
|
|
317
|
-
return
|
|
312
|
+
return unique(namespaces);
|
|
318
313
|
}
|
|
319
314
|
function getTranslationFallback(namespaces, languages, key) {
|
|
320
315
|
var _a;
|
|
@@ -335,9 +330,6 @@
|
|
|
335
330
|
record === null || record === void 0 ? void 0 : record.set(key, value);
|
|
336
331
|
onCacheChange.emit(Object.assign(Object.assign({}, descriptor), { key }));
|
|
337
332
|
}
|
|
338
|
-
function clear() {
|
|
339
|
-
cache.clear();
|
|
340
|
-
}
|
|
341
333
|
function isFetching(ns) {
|
|
342
334
|
if (isInitialLoading()) {
|
|
343
335
|
return true;
|
|
@@ -360,24 +352,20 @@
|
|
|
360
352
|
}));
|
|
361
353
|
}));
|
|
362
354
|
}
|
|
363
|
-
|
|
355
|
+
/**
|
|
356
|
+
* Fetches production data
|
|
357
|
+
*/
|
|
358
|
+
function fetchProd(keyObject) {
|
|
364
359
|
let dataPromise = undefined;
|
|
365
360
|
if (!dataPromise) {
|
|
366
361
|
const staticDataValue = staticData[encodeCacheKey(keyObject)];
|
|
367
362
|
if (typeof staticDataValue === 'function') {
|
|
368
363
|
dataPromise = staticDataValue();
|
|
369
364
|
}
|
|
370
|
-
else if (staticDataValue) {
|
|
371
|
-
dataPromise = Promise.resolve(staticDataValue);
|
|
372
|
-
}
|
|
373
365
|
}
|
|
374
366
|
if (!dataPromise) {
|
|
375
367
|
dataPromise = backendGetRecord(keyObject);
|
|
376
368
|
}
|
|
377
|
-
if (!dataPromise) {
|
|
378
|
-
// return empty data, so we know it has already been attempted to fetch
|
|
379
|
-
dataPromise = Promise.resolve({});
|
|
380
|
-
}
|
|
381
369
|
return dataPromise;
|
|
382
370
|
}
|
|
383
371
|
function fetchData(keyObject, isDev) {
|
|
@@ -387,12 +375,12 @@
|
|
|
387
375
|
dataPromise = (_a = backendGetDevRecord(keyObject)) === null || _a === void 0 ? void 0 : _a.catch(() => {
|
|
388
376
|
// eslint-disable-next-line no-console
|
|
389
377
|
console.warn(`Tolgee: Failed to fetch data from dev backend`);
|
|
390
|
-
// fallback to
|
|
391
|
-
return
|
|
378
|
+
// fallback to prod fetch if dev fails
|
|
379
|
+
return fetchProd(keyObject);
|
|
392
380
|
});
|
|
393
381
|
}
|
|
394
382
|
if (!dataPromise) {
|
|
395
|
-
dataPromise =
|
|
383
|
+
dataPromise = fetchProd(keyObject);
|
|
396
384
|
}
|
|
397
385
|
return dataPromise;
|
|
398
386
|
}
|
|
@@ -409,7 +397,7 @@
|
|
|
409
397
|
cacheKey,
|
|
410
398
|
};
|
|
411
399
|
}
|
|
412
|
-
const dataPromise = fetchData(keyObject, isDev);
|
|
400
|
+
const dataPromise = fetchData(keyObject, isDev) || Promise.resolve(undefined);
|
|
413
401
|
asyncRequests.set(cacheKey, dataPromise);
|
|
414
402
|
return {
|
|
415
403
|
new: true,
|
|
@@ -431,6 +419,10 @@
|
|
|
431
419
|
if (data) {
|
|
432
420
|
addRecord(value.keyObject, data);
|
|
433
421
|
}
|
|
422
|
+
else if (!getRecord(value.keyObject)) {
|
|
423
|
+
// if no data exist, put empty object
|
|
424
|
+
addRecord(value.keyObject, {});
|
|
425
|
+
}
|
|
434
426
|
}
|
|
435
427
|
});
|
|
436
428
|
fetchingObserver.notify();
|
|
@@ -456,27 +448,85 @@
|
|
|
456
448
|
isFetching,
|
|
457
449
|
isLoading,
|
|
458
450
|
loadRecords,
|
|
459
|
-
clear,
|
|
460
451
|
getAllRecords,
|
|
461
452
|
});
|
|
462
453
|
};
|
|
463
454
|
|
|
464
|
-
|
|
465
|
-
|
|
455
|
+
/******************************************************************************
|
|
456
|
+
Copyright (c) Microsoft Corporation.
|
|
457
|
+
|
|
458
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
459
|
+
purpose with or without fee is hereby granted.
|
|
460
|
+
|
|
461
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
462
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
463
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
464
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
465
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
466
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
467
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
468
|
+
***************************************************************************** */
|
|
469
|
+
|
|
470
|
+
function __rest(s, e) {
|
|
471
|
+
var t = {};
|
|
472
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
473
|
+
t[p] = s[p];
|
|
474
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
475
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
476
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
477
|
+
t[p[i]] = s[p[i]];
|
|
478
|
+
}
|
|
479
|
+
return t;
|
|
466
480
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
481
|
+
|
|
482
|
+
const defaultObserverOptions = {
|
|
483
|
+
tagAttributes: {
|
|
484
|
+
textarea: ['placeholder'],
|
|
485
|
+
input: ['value', 'placeholder'],
|
|
486
|
+
img: ['alt'],
|
|
487
|
+
'*': ['aria-label', 'title'],
|
|
488
|
+
},
|
|
489
|
+
restrictedElements: ['script', 'style'],
|
|
490
|
+
highlightKeys: ['Alt'],
|
|
491
|
+
highlightColor: 'rgb(255, 0, 0)',
|
|
492
|
+
highlightWidth: 5,
|
|
493
|
+
inputPrefix: '%-%tolgee:',
|
|
494
|
+
inputSuffix: '%-%',
|
|
495
|
+
passToParent: ['option', 'optgroup'],
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const DEFAULT_FORMAT_ERROR = 'invalid';
|
|
499
|
+
const defaultValues = {
|
|
500
|
+
defaultNs: '',
|
|
501
|
+
observerOptions: defaultObserverOptions,
|
|
502
|
+
observerType: 'invisible',
|
|
503
|
+
onFormatError: DEFAULT_FORMAT_ERROR,
|
|
504
|
+
};
|
|
505
|
+
const combineOptions = (...states) => {
|
|
506
|
+
let result = {};
|
|
507
|
+
states.forEach((state) => {
|
|
508
|
+
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) });
|
|
509
|
+
});
|
|
510
|
+
return result;
|
|
511
|
+
};
|
|
512
|
+
const initState = (options, previousState) => {
|
|
513
|
+
const initialOptions = combineOptions(defaultValues, previousState === null || previousState === void 0 ? void 0 : previousState.initialOptions, options);
|
|
514
|
+
// remove extra '/' from url end
|
|
515
|
+
initialOptions.apiUrl = sanitizeUrl(initialOptions.apiUrl);
|
|
516
|
+
return {
|
|
517
|
+
initialOptions,
|
|
518
|
+
activeNamespaces: (previousState === null || previousState === void 0 ? void 0 : previousState.activeNamespaces) || new Map(),
|
|
519
|
+
language: previousState === null || previousState === void 0 ? void 0 : previousState.language,
|
|
520
|
+
pendingLanguage: previousState === null || previousState === void 0 ? void 0 : previousState.language,
|
|
521
|
+
isInitialLoading: false,
|
|
522
|
+
isRunning: false,
|
|
523
|
+
};
|
|
474
524
|
};
|
|
475
|
-
const missingOptionError = (option) => `Tolgee: You need to specify '${option}' option`;
|
|
476
525
|
|
|
477
|
-
const
|
|
526
|
+
const Plugins = (getLanguage, getInitialOptions, getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation) => {
|
|
478
527
|
const plugins = {
|
|
479
528
|
ui: undefined,
|
|
529
|
+
observer: undefined,
|
|
480
530
|
};
|
|
481
531
|
const instances = {
|
|
482
532
|
formatters: [],
|
|
@@ -488,39 +538,20 @@
|
|
|
488
538
|
languageDetector: undefined,
|
|
489
539
|
languageStorage: undefined,
|
|
490
540
|
};
|
|
491
|
-
const onClick = async (
|
|
541
|
+
const onClick = async ({ keysAndDefaults, event }) => {
|
|
492
542
|
var _a;
|
|
493
|
-
const withNs = keysAndDefaults.map(({ key, ns, defaultValue }) =>
|
|
494
|
-
|
|
495
|
-
defaultValue,
|
|
496
|
-
ns: getFallbackArray(getTranslationNs({ key, ns, defaultValue })),
|
|
497
|
-
translation: getTranslation({
|
|
543
|
+
const withNs = keysAndDefaults.map(({ key, ns, defaultValue }) => {
|
|
544
|
+
return {
|
|
498
545
|
key,
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
new plugins.ui({
|
|
509
|
-
apiKey: getInitialOptions().apiKey,
|
|
510
|
-
apiUrl: getInitialOptions().apiUrl,
|
|
511
|
-
highlight,
|
|
512
|
-
changeTranslation,
|
|
513
|
-
});
|
|
514
|
-
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.run({ mouseHighlight: Boolean(instances.ui) });
|
|
515
|
-
checkCorrectConfiguration();
|
|
516
|
-
};
|
|
517
|
-
const checkCorrectConfiguration = () => {
|
|
518
|
-
if (instances.languageDetector) {
|
|
519
|
-
const availableLanguages = getAvailableLanguages();
|
|
520
|
-
if (!availableLanguages) {
|
|
521
|
-
throw new Error(missingOptionError('availableLanguages'));
|
|
522
|
-
}
|
|
523
|
-
}
|
|
546
|
+
defaultValue,
|
|
547
|
+
ns: getTranslationNs({ key, ns }),
|
|
548
|
+
translation: getTranslation({
|
|
549
|
+
key,
|
|
550
|
+
ns,
|
|
551
|
+
}),
|
|
552
|
+
};
|
|
553
|
+
});
|
|
554
|
+
(_a = instances.ui) === null || _a === void 0 ? void 0 : _a.handleElementClick(withNs, event);
|
|
524
555
|
};
|
|
525
556
|
const stop = () => {
|
|
526
557
|
var _a;
|
|
@@ -532,14 +563,17 @@
|
|
|
532
563
|
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() { } };
|
|
533
564
|
};
|
|
534
565
|
const translate = (props) => {
|
|
535
|
-
const translation = getTranslation(
|
|
566
|
+
const translation = getTranslation({
|
|
567
|
+
key: props.key,
|
|
568
|
+
ns: props.ns,
|
|
569
|
+
});
|
|
536
570
|
return formatTranslation(Object.assign(Object.assign({}, props), { translation, formatEnabled: true }));
|
|
537
571
|
};
|
|
538
572
|
const setObserver = (observer) => {
|
|
539
|
-
|
|
573
|
+
plugins.observer = observer;
|
|
540
574
|
};
|
|
541
|
-
const
|
|
542
|
-
return
|
|
575
|
+
const hasObserver = () => {
|
|
576
|
+
return Boolean(plugins.observer);
|
|
543
577
|
};
|
|
544
578
|
const addFormatter = (formatter) => {
|
|
545
579
|
if (formatter) {
|
|
@@ -550,14 +584,17 @@
|
|
|
550
584
|
instances.finalFormatter = formatter;
|
|
551
585
|
};
|
|
552
586
|
const setUi = (ui) => {
|
|
553
|
-
plugins.ui =
|
|
587
|
+
plugins.ui = ui;
|
|
554
588
|
};
|
|
555
|
-
const
|
|
556
|
-
return plugins.ui;
|
|
589
|
+
const hasUi = () => {
|
|
590
|
+
return Boolean(plugins.ui);
|
|
557
591
|
};
|
|
558
592
|
const setLanguageStorage = (storage) => {
|
|
559
593
|
instances.languageStorage = storage;
|
|
560
594
|
};
|
|
595
|
+
const getLanguageStorage = () => {
|
|
596
|
+
return instances.languageStorage;
|
|
597
|
+
};
|
|
561
598
|
const setStoredLanguage = (language) => {
|
|
562
599
|
var _a;
|
|
563
600
|
(_a = instances.languageStorage) === null || _a === void 0 ? void 0 : _a.setLanguage(language);
|
|
@@ -565,6 +602,9 @@
|
|
|
565
602
|
const setLanguageDetector = (detector) => {
|
|
566
603
|
instances.languageDetector = detector;
|
|
567
604
|
};
|
|
605
|
+
const getLanguageDetector = () => {
|
|
606
|
+
return instances.languageDetector;
|
|
607
|
+
};
|
|
568
608
|
const detectLanguage = () => {
|
|
569
609
|
if (!instances.languageDetector) {
|
|
570
610
|
return undefined;
|
|
@@ -594,14 +634,37 @@
|
|
|
594
634
|
const setDevBackend = (backend) => {
|
|
595
635
|
instances.devBackend = backend;
|
|
596
636
|
};
|
|
637
|
+
const run = () => {
|
|
638
|
+
var _a, _b, _c;
|
|
639
|
+
if (!instances.ui) {
|
|
640
|
+
const { apiKey, apiUrl, projectId } = getInitialOptions();
|
|
641
|
+
instances.ui = (_a = plugins.ui) === null || _a === void 0 ? void 0 : _a.call(plugins, {
|
|
642
|
+
apiKey: apiKey,
|
|
643
|
+
apiUrl: apiUrl,
|
|
644
|
+
projectId,
|
|
645
|
+
highlight,
|
|
646
|
+
changeTranslation,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
if (!instances.observer) {
|
|
650
|
+
instances.observer = (_b = plugins.observer) === null || _b === void 0 ? void 0 : _b.call(plugins, {
|
|
651
|
+
translate,
|
|
652
|
+
onClick,
|
|
653
|
+
options: getInitialOptions().observerOptions,
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
(_c = instances.observer) === null || _c === void 0 ? void 0 : _c.run({ mouseHighlight: true });
|
|
657
|
+
};
|
|
597
658
|
const getDevBackend = () => {
|
|
598
659
|
return instances.devBackend;
|
|
599
660
|
};
|
|
600
661
|
const getBackendDevRecord = ({ language, namespace }) => {
|
|
601
662
|
var _a;
|
|
663
|
+
const { apiKey, apiUrl, projectId } = getInitialOptions();
|
|
602
664
|
return (_a = instances.devBackend) === null || _a === void 0 ? void 0 : _a.getRecord({
|
|
603
|
-
apiKey
|
|
604
|
-
apiUrl
|
|
665
|
+
apiKey,
|
|
666
|
+
apiUrl,
|
|
667
|
+
projectId,
|
|
605
668
|
language,
|
|
606
669
|
namespace,
|
|
607
670
|
});
|
|
@@ -622,42 +685,97 @@
|
|
|
622
685
|
}
|
|
623
686
|
return undefined;
|
|
624
687
|
};
|
|
625
|
-
const
|
|
688
|
+
const unwrap = (text) => {
|
|
689
|
+
var _a;
|
|
690
|
+
if (instances.observer) {
|
|
691
|
+
return (_a = instances.observer) === null || _a === void 0 ? void 0 : _a.unwrap(text);
|
|
692
|
+
}
|
|
693
|
+
return { text, keys: [] };
|
|
694
|
+
};
|
|
695
|
+
const retranslate = () => {
|
|
626
696
|
var _a;
|
|
697
|
+
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.retranslate();
|
|
698
|
+
};
|
|
699
|
+
function addPlugin(tolgeeInstance, plugin) {
|
|
700
|
+
const pluginTools = Object.freeze({
|
|
701
|
+
setFinalFormatter,
|
|
702
|
+
addFormatter,
|
|
703
|
+
setObserver,
|
|
704
|
+
hasObserver,
|
|
705
|
+
setUi,
|
|
706
|
+
hasUi,
|
|
707
|
+
setDevBackend,
|
|
708
|
+
addBackend,
|
|
709
|
+
setLanguageDetector,
|
|
710
|
+
setLanguageStorage,
|
|
711
|
+
});
|
|
712
|
+
plugin(tolgeeInstance, pluginTools);
|
|
713
|
+
}
|
|
714
|
+
function formatTranslation(_a) {
|
|
715
|
+
var _b;
|
|
716
|
+
var { formatEnabled } = _a, props = __rest(_a, ["formatEnabled"]);
|
|
717
|
+
const { key, translation, defaultValue, noWrap, params, orEmpty, ns } = props;
|
|
627
718
|
const formattableTranslation = translation || defaultValue;
|
|
628
719
|
let result = formattableTranslation || (orEmpty ? '' : key);
|
|
629
|
-
if (instances.observer && !noWrap) {
|
|
630
|
-
result = instances.observer.wrap({
|
|
631
|
-
key,
|
|
632
|
-
translation: result,
|
|
633
|
-
defaultValue,
|
|
634
|
-
params,
|
|
635
|
-
ns,
|
|
636
|
-
});
|
|
637
|
-
}
|
|
638
720
|
const language = getLanguage();
|
|
639
|
-
const isFormatEnabled = formatEnabled || !((
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
721
|
+
const isFormatEnabled = formatEnabled || !((_b = instances.observer) === null || _b === void 0 ? void 0 : _b.outputNotFormattable);
|
|
722
|
+
const wrap = (result) => {
|
|
723
|
+
if (instances.observer && !noWrap) {
|
|
724
|
+
return instances.observer.wrap({
|
|
725
|
+
key,
|
|
726
|
+
translation: result,
|
|
727
|
+
defaultValue,
|
|
728
|
+
params,
|
|
729
|
+
ns,
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
return result;
|
|
733
|
+
};
|
|
734
|
+
result = wrap(result);
|
|
735
|
+
try {
|
|
736
|
+
if (formattableTranslation && language && isFormatEnabled) {
|
|
737
|
+
for (const formatter of instances.formatters) {
|
|
738
|
+
result = formatter.format({
|
|
739
|
+
translation: result,
|
|
740
|
+
language,
|
|
741
|
+
params,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if (instances.finalFormatter &&
|
|
746
|
+
formattableTranslation &&
|
|
747
|
+
language &&
|
|
748
|
+
isFormatEnabled) {
|
|
749
|
+
result = instances.finalFormatter.format({
|
|
643
750
|
translation: result,
|
|
644
751
|
language,
|
|
645
752
|
params,
|
|
646
753
|
});
|
|
647
754
|
}
|
|
648
755
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
756
|
+
catch (e) {
|
|
757
|
+
// eslint-disable-next-line no-console
|
|
758
|
+
console.error(e);
|
|
759
|
+
const errorMessage = getErrorMessage(e) || DEFAULT_FORMAT_ERROR;
|
|
760
|
+
const onFormatError = getInitialOptions().onFormatError;
|
|
761
|
+
const formatErrorType = typeof onFormatError;
|
|
762
|
+
if (formatErrorType === 'string') {
|
|
763
|
+
result = onFormatError;
|
|
764
|
+
}
|
|
765
|
+
else if (formatErrorType === 'function') {
|
|
766
|
+
result = onFormatError(errorMessage, props);
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
result = DEFAULT_FORMAT_ERROR;
|
|
770
|
+
}
|
|
771
|
+
// wrap error message, so it's detectable
|
|
772
|
+
result = wrap(result);
|
|
658
773
|
}
|
|
659
774
|
return result;
|
|
660
|
-
}
|
|
775
|
+
}
|
|
776
|
+
function hasDevBackend() {
|
|
777
|
+
return Boolean(getDevBackend());
|
|
778
|
+
}
|
|
661
779
|
const wrap = (params) => {
|
|
662
780
|
var _a;
|
|
663
781
|
if (instances.observer) {
|
|
@@ -665,40 +783,23 @@
|
|
|
665
783
|
}
|
|
666
784
|
return params.translation;
|
|
667
785
|
};
|
|
668
|
-
const unwrap = (text) => {
|
|
669
|
-
var _a;
|
|
670
|
-
if (instances.observer) {
|
|
671
|
-
return (_a = instances.observer) === null || _a === void 0 ? void 0 : _a.unwrap(text);
|
|
672
|
-
}
|
|
673
|
-
return { text, keys: [] };
|
|
674
|
-
};
|
|
675
|
-
const retranslate = () => {
|
|
676
|
-
var _a;
|
|
677
|
-
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.retranslate();
|
|
678
|
-
};
|
|
679
786
|
return Object.freeze({
|
|
680
|
-
|
|
681
|
-
addFormatter,
|
|
787
|
+
addPlugin,
|
|
682
788
|
formatTranslation,
|
|
683
|
-
setObserver,
|
|
684
|
-
getObserver,
|
|
685
|
-
setUi,
|
|
686
|
-
getUi,
|
|
687
|
-
addBackend,
|
|
688
|
-
setDevBackend,
|
|
689
789
|
getDevBackend,
|
|
690
790
|
getBackendRecord,
|
|
691
791
|
getBackendDevRecord,
|
|
692
|
-
|
|
693
|
-
|
|
792
|
+
getLanguageDetector,
|
|
793
|
+
getLanguageStorage,
|
|
694
794
|
getInitialLanguage,
|
|
695
795
|
setStoredLanguage,
|
|
696
796
|
run,
|
|
697
797
|
stop,
|
|
698
798
|
retranslate,
|
|
699
799
|
highlight,
|
|
700
|
-
wrap,
|
|
701
800
|
unwrap,
|
|
801
|
+
wrap,
|
|
802
|
+
hasDevBackend,
|
|
702
803
|
});
|
|
703
804
|
};
|
|
704
805
|
|
|
@@ -720,28 +821,9 @@
|
|
|
720
821
|
});
|
|
721
822
|
};
|
|
722
823
|
|
|
723
|
-
const defaultValues = {
|
|
724
|
-
enableLanguageStore: true,
|
|
725
|
-
defaultNs: '',
|
|
726
|
-
filesUrlPrefix: 'i18n/',
|
|
727
|
-
};
|
|
728
|
-
const initState = (options, previousState) => {
|
|
729
|
-
const initialOptions = Object.assign(Object.assign(Object.assign({}, defaultValues), previousState === null || previousState === void 0 ? void 0 : previousState.initialOptions), options);
|
|
730
|
-
// remove extra '/' from url end
|
|
731
|
-
const apiUrl = initialOptions.apiUrl;
|
|
732
|
-
initialOptions.apiUrl = apiUrl ? apiUrl.replace(/\/+$/, '') : apiUrl;
|
|
733
|
-
return {
|
|
734
|
-
initialOptions,
|
|
735
|
-
activeNamespaces: (previousState === null || previousState === void 0 ? void 0 : previousState.activeNamespaces) || new Map(),
|
|
736
|
-
language: previousState === null || previousState === void 0 ? void 0 : previousState.language,
|
|
737
|
-
pendingLanguage: previousState === null || previousState === void 0 ? void 0 : previousState.language,
|
|
738
|
-
isInitialLoading: false,
|
|
739
|
-
isRunning: false,
|
|
740
|
-
};
|
|
741
|
-
};
|
|
742
|
-
|
|
743
824
|
const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
744
825
|
let state = initState();
|
|
826
|
+
let devCredentials = undefined;
|
|
745
827
|
function init(options) {
|
|
746
828
|
state = initState(options, state);
|
|
747
829
|
}
|
|
@@ -763,13 +845,6 @@
|
|
|
763
845
|
function getLanguage() {
|
|
764
846
|
return state.language || state.initialOptions.language;
|
|
765
847
|
}
|
|
766
|
-
function getLanguageOrFail() {
|
|
767
|
-
const language = state.language || state.initialOptions.language;
|
|
768
|
-
if (!language) {
|
|
769
|
-
throw new Error(`No language set`);
|
|
770
|
-
}
|
|
771
|
-
return language;
|
|
772
|
-
}
|
|
773
848
|
function setLanguage(language) {
|
|
774
849
|
if (state.language !== language) {
|
|
775
850
|
state.language = language;
|
|
@@ -786,7 +861,7 @@
|
|
|
786
861
|
}
|
|
787
862
|
}
|
|
788
863
|
function getInitialOptions() {
|
|
789
|
-
return state.initialOptions;
|
|
864
|
+
return Object.assign(Object.assign({}, state.initialOptions), devCredentials);
|
|
790
865
|
}
|
|
791
866
|
function addActiveNs(ns) {
|
|
792
867
|
const namespaces = getFallbackArray(ns);
|
|
@@ -815,6 +890,7 @@
|
|
|
815
890
|
function getRequiredNamespaces() {
|
|
816
891
|
return unique([
|
|
817
892
|
...(state.initialOptions.ns || [state.initialOptions.defaultNs]),
|
|
893
|
+
...getFallbackArray(state.initialOptions.fallbackNs),
|
|
818
894
|
...state.activeNamespaces.keys(),
|
|
819
895
|
]);
|
|
820
896
|
}
|
|
@@ -828,11 +904,11 @@
|
|
|
828
904
|
...getFallbackFromStruct(language, state.initialOptions.fallbackLanguage),
|
|
829
905
|
]);
|
|
830
906
|
}
|
|
831
|
-
function
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
return
|
|
907
|
+
function getFallbackNs() {
|
|
908
|
+
return getFallbackArray(state.initialOptions.fallbackNs);
|
|
909
|
+
}
|
|
910
|
+
function getDefaultNs(ns) {
|
|
911
|
+
return ns === undefined ? state.initialOptions.defaultNs : ns;
|
|
836
912
|
}
|
|
837
913
|
function getAvailableLanguages() {
|
|
838
914
|
if (state.initialOptions.availableLanguages) {
|
|
@@ -851,6 +927,14 @@
|
|
|
851
927
|
language: descriptor.language,
|
|
852
928
|
};
|
|
853
929
|
}
|
|
930
|
+
function overrideCredentials(credentials) {
|
|
931
|
+
if (credentials) {
|
|
932
|
+
devCredentials = Object.assign(Object.assign({}, credentials), { apiUrl: sanitizeUrl(credentials.apiUrl) });
|
|
933
|
+
}
|
|
934
|
+
else {
|
|
935
|
+
devCredentials = undefined;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
854
938
|
return Object.freeze({
|
|
855
939
|
init,
|
|
856
940
|
isRunning,
|
|
@@ -858,7 +942,6 @@
|
|
|
858
942
|
isInitialLoading,
|
|
859
943
|
setInitialLoading,
|
|
860
944
|
getLanguage,
|
|
861
|
-
getLanguageOrFail,
|
|
862
945
|
setLanguage,
|
|
863
946
|
getPendingLanguage,
|
|
864
947
|
setPendingLanguage,
|
|
@@ -867,50 +950,24 @@
|
|
|
867
950
|
removeActiveNs,
|
|
868
951
|
getRequiredNamespaces,
|
|
869
952
|
getFallbackLangs,
|
|
870
|
-
|
|
953
|
+
getFallbackNs,
|
|
954
|
+
getDefaultNs,
|
|
871
955
|
getAvailableLanguages,
|
|
872
956
|
withDefaultNs,
|
|
957
|
+
overrideCredentials,
|
|
873
958
|
});
|
|
874
959
|
};
|
|
875
960
|
|
|
876
|
-
/******************************************************************************
|
|
877
|
-
Copyright (c) Microsoft Corporation.
|
|
878
|
-
|
|
879
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
880
|
-
purpose with or without fee is hereby granted.
|
|
881
|
-
|
|
882
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
883
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
884
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
885
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
886
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
887
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
888
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
889
|
-
***************************************************************************** */
|
|
890
|
-
|
|
891
|
-
function __rest(s, e) {
|
|
892
|
-
var t = {};
|
|
893
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
894
|
-
t[p] = s[p];
|
|
895
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
896
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
897
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
898
|
-
t[p[i]] = s[p[i]];
|
|
899
|
-
}
|
|
900
|
-
return t;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
961
|
function parseCombinedOptions(_a) {
|
|
904
962
|
var { ns, noWrap, orEmpty, params } = _a, rest = __rest(_a, ["ns", "noWrap", "orEmpty", "params"]);
|
|
905
963
|
const options = {
|
|
906
964
|
ns: ns,
|
|
907
965
|
noWrap: noWrap,
|
|
908
966
|
orEmpty: orEmpty,
|
|
909
|
-
params: Object.assign(Object.assign({}, rest), params),
|
|
910
967
|
};
|
|
911
|
-
return options;
|
|
968
|
+
return Object.assign(Object.assign({}, options), { params: Object.assign({}, rest) });
|
|
912
969
|
}
|
|
913
|
-
const
|
|
970
|
+
const getTranslateProps = (keyOrProps, ...params) => {
|
|
914
971
|
let result = {};
|
|
915
972
|
let options;
|
|
916
973
|
if (typeof keyOrProps === 'object') {
|
|
@@ -932,28 +989,40 @@
|
|
|
932
989
|
return result;
|
|
933
990
|
};
|
|
934
991
|
|
|
935
|
-
const Controller = ({
|
|
992
|
+
const Controller = ({ options }) => {
|
|
993
|
+
const events = Events(getFallbackNs, getDefaultNs);
|
|
936
994
|
const fetchingObserver = ValueObserver(false, () => cache.isFetching(), events.onFetchingChange.emit);
|
|
937
995
|
const loadingObserver = ValueObserver(false, () => isLoading(), events.onLoadingChange.emit);
|
|
938
996
|
const state = State(events.onLanguageChange, events.onPendingLanguageChange, events.onRunningChange);
|
|
939
|
-
const pluginService =
|
|
997
|
+
const pluginService = Plugins(state.getLanguage, state.getInitialOptions, state.getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation);
|
|
940
998
|
const cache = Cache(events.onCacheChange, pluginService.getBackendRecord, pluginService.getBackendDevRecord, state.withDefaultNs, state.isInitialLoading, fetchingObserver, loadingObserver);
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
if (isDev()) {
|
|
944
|
-
cache.invalidate();
|
|
999
|
+
if (options) {
|
|
1000
|
+
init(options);
|
|
945
1001
|
}
|
|
946
|
-
events.
|
|
1002
|
+
events.onUpdate.listen(() => {
|
|
947
1003
|
if (state.isRunning()) {
|
|
948
1004
|
pluginService.retranslate();
|
|
949
1005
|
}
|
|
950
1006
|
});
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
return
|
|
956
|
-
}
|
|
1007
|
+
function getFallbackNs() {
|
|
1008
|
+
return state.getFallbackNs();
|
|
1009
|
+
}
|
|
1010
|
+
function getDefaultNs(ns) {
|
|
1011
|
+
return state.getDefaultNs(ns);
|
|
1012
|
+
}
|
|
1013
|
+
// gets all namespaces where translation could be located
|
|
1014
|
+
// takes (ns|default, fallback ns)
|
|
1015
|
+
function getDefaultAndFallbackNs(ns) {
|
|
1016
|
+
return [...getFallbackArray(getDefaultNs(ns)), ...getFallbackNs()];
|
|
1017
|
+
}
|
|
1018
|
+
// gets all namespaces which need to be loaded
|
|
1019
|
+
// takes (ns|default, initial ns, fallback ns, active ns)
|
|
1020
|
+
function getRequiredNamespaces(ns) {
|
|
1021
|
+
return [
|
|
1022
|
+
...getFallbackArray(ns || getDefaultNs()),
|
|
1023
|
+
...state.getRequiredNamespaces(),
|
|
1024
|
+
];
|
|
1025
|
+
}
|
|
957
1026
|
function changeTranslation(descriptor, key, value) {
|
|
958
1027
|
const keyObject = state.withDefaultNs(descriptor);
|
|
959
1028
|
const previousValue = cache.getTranslation(keyObject, key);
|
|
@@ -972,7 +1041,7 @@
|
|
|
972
1041
|
return cache.isLoading(state.getLanguage(), ns);
|
|
973
1042
|
}
|
|
974
1043
|
function isDev() {
|
|
975
|
-
return Boolean(state.getInitialOptions().apiKey &&
|
|
1044
|
+
return Boolean(state.getInitialOptions().apiKey && state.getInitialOptions().apiUrl);
|
|
976
1045
|
}
|
|
977
1046
|
async function addActiveNs(ns, forget) {
|
|
978
1047
|
if (!forget) {
|
|
@@ -984,7 +1053,7 @@
|
|
|
984
1053
|
}
|
|
985
1054
|
function getRequiredRecords(lang, ns) {
|
|
986
1055
|
const languages = state.getFallbackLangs(lang);
|
|
987
|
-
const namespaces =
|
|
1056
|
+
const namespaces = getRequiredNamespaces(ns);
|
|
988
1057
|
const result = [];
|
|
989
1058
|
languages.forEach((language) => {
|
|
990
1059
|
namespaces.forEach((namespace) => {
|
|
@@ -1001,7 +1070,7 @@
|
|
|
1001
1070
|
return false;
|
|
1002
1071
|
}
|
|
1003
1072
|
const languages = state.getFallbackLangs(language);
|
|
1004
|
-
const namespaces =
|
|
1073
|
+
const namespaces = getRequiredNamespaces(ns);
|
|
1005
1074
|
const result = [];
|
|
1006
1075
|
languages.forEach((language) => {
|
|
1007
1076
|
namespaces.forEach((namespace) => {
|
|
@@ -1034,24 +1103,19 @@
|
|
|
1034
1103
|
pluginService.setStoredLanguage(language);
|
|
1035
1104
|
}
|
|
1036
1105
|
}
|
|
1037
|
-
function getTranslationNs({ key, ns
|
|
1038
|
-
const namespaces = ns
|
|
1039
|
-
? getFallbackArray(ns)
|
|
1040
|
-
: state.getFallbackNamespaces();
|
|
1106
|
+
function getTranslationNs({ key, ns }) {
|
|
1041
1107
|
const languages = state.getFallbackLangs();
|
|
1108
|
+
const namespaces = getDefaultAndFallbackNs(ns);
|
|
1042
1109
|
return cache.getTranslationNs(namespaces, languages, key);
|
|
1043
1110
|
}
|
|
1044
|
-
function getTranslation({ key, ns
|
|
1045
|
-
const namespaces = ns
|
|
1046
|
-
? getFallbackArray(ns)
|
|
1047
|
-
: state.getFallbackNamespaces();
|
|
1111
|
+
function getTranslation({ key, ns }) {
|
|
1112
|
+
const namespaces = getDefaultAndFallbackNs(ns);
|
|
1048
1113
|
const languages = state.getFallbackLangs();
|
|
1049
1114
|
return cache.getTranslationFallback(namespaces, languages, key);
|
|
1050
1115
|
}
|
|
1051
1116
|
function loadInitial() {
|
|
1052
1117
|
const data = valueOrPromise(initializeLanguage(), () => {
|
|
1053
1118
|
// fail if there is no language
|
|
1054
|
-
state.getLanguageOrFail();
|
|
1055
1119
|
return loadRequiredRecords();
|
|
1056
1120
|
});
|
|
1057
1121
|
if (isPromise(data)) {
|
|
@@ -1090,8 +1154,26 @@
|
|
|
1090
1154
|
function loadRecords(descriptors) {
|
|
1091
1155
|
return cache.loadRecords(descriptors, isDev());
|
|
1092
1156
|
}
|
|
1157
|
+
const checkCorrectConfiguration = () => {
|
|
1158
|
+
const languageComputable = pluginService.getLanguageDetector() || pluginService.getLanguageStorage();
|
|
1159
|
+
if (languageComputable) {
|
|
1160
|
+
const availableLanguages = state.getAvailableLanguages();
|
|
1161
|
+
if (!availableLanguages) {
|
|
1162
|
+
throw new Error(missingOptionError('availableLanguages'));
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
if (!state.getLanguage() && !state.getInitialOptions().defaultLanguage) {
|
|
1166
|
+
if (languageComputable) {
|
|
1167
|
+
throw new Error(missingOptionError('defaultLanguage'));
|
|
1168
|
+
}
|
|
1169
|
+
else {
|
|
1170
|
+
throw new Error(missingOptionError('language'));
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1093
1174
|
function run() {
|
|
1094
1175
|
let result = undefined;
|
|
1176
|
+
checkCorrectConfiguration();
|
|
1095
1177
|
if (!state.isRunning()) {
|
|
1096
1178
|
if (isDev()) {
|
|
1097
1179
|
cache.invalidate();
|
|
@@ -1108,12 +1190,17 @@
|
|
|
1108
1190
|
state.setRunning(false);
|
|
1109
1191
|
}
|
|
1110
1192
|
}
|
|
1111
|
-
|
|
1193
|
+
const t = (...args) => {
|
|
1194
|
+
// @ts-ignore
|
|
1195
|
+
const params = getTranslateProps(...args);
|
|
1196
|
+
const translation = getTranslation(params);
|
|
1197
|
+
return pluginService.formatTranslation(Object.assign(Object.assign({}, params), { translation }));
|
|
1198
|
+
};
|
|
1199
|
+
return Object.freeze(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, events), state), pluginService), cache), { init,
|
|
1112
1200
|
changeLanguage,
|
|
1113
1201
|
getTranslation,
|
|
1114
1202
|
changeTranslation,
|
|
1115
1203
|
addActiveNs,
|
|
1116
|
-
loadRequiredRecords,
|
|
1117
1204
|
loadRecords,
|
|
1118
1205
|
loadRecord,
|
|
1119
1206
|
isLoading,
|
|
@@ -1124,24 +1211,11 @@
|
|
|
1124
1211
|
stop }));
|
|
1125
1212
|
};
|
|
1126
1213
|
|
|
1127
|
-
const
|
|
1128
|
-
const events = Events();
|
|
1214
|
+
const createTolgee = (options) => {
|
|
1129
1215
|
const controller = Controller({
|
|
1130
|
-
events,
|
|
1131
1216
|
options,
|
|
1132
1217
|
});
|
|
1133
|
-
|
|
1134
|
-
setFinalFormatter: controller.setFinalFormatter,
|
|
1135
|
-
addFormatter: controller.addFormatter,
|
|
1136
|
-
setObserver: controller.setObserver,
|
|
1137
|
-
getObserver: controller.getObserver,
|
|
1138
|
-
setUi: controller.setUi,
|
|
1139
|
-
getUi: controller.getUi,
|
|
1140
|
-
setDevBackend: controller.setDevBackend,
|
|
1141
|
-
addBackend: controller.addBackend,
|
|
1142
|
-
setLanguageDetector: controller.setLanguageDetector,
|
|
1143
|
-
setLanguageStorage: controller.setLanguageStorage,
|
|
1144
|
-
});
|
|
1218
|
+
// restarts tolgee while applying callback
|
|
1145
1219
|
const withRestart = (callback) => {
|
|
1146
1220
|
const wasRunning = controller.isRunning();
|
|
1147
1221
|
wasRunning && controller.stop();
|
|
@@ -1149,65 +1223,363 @@
|
|
|
1149
1223
|
wasRunning && controller.run();
|
|
1150
1224
|
};
|
|
1151
1225
|
const tolgee = Object.freeze({
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1226
|
+
/**
|
|
1227
|
+
* Listen to tolgee events.
|
|
1228
|
+
*/
|
|
1229
|
+
on: controller.on,
|
|
1230
|
+
/**
|
|
1231
|
+
* Listen for specific namespaces changes.
|
|
1232
|
+
*
|
|
1233
|
+
* ```
|
|
1234
|
+
* const sub = tolgee.onUpdate(handler)
|
|
1235
|
+
*
|
|
1236
|
+
* // subscribe to selected namespace
|
|
1237
|
+
* sub.subscribeNs(['common'])
|
|
1238
|
+
*
|
|
1239
|
+
* // unsubscribe
|
|
1240
|
+
* sub.unsubscribe()
|
|
1241
|
+
* ```
|
|
1242
|
+
*/
|
|
1243
|
+
onNsUpdate: controller.onUpdate.listenSome,
|
|
1244
|
+
/**
|
|
1245
|
+
* Turn off/on events emitting. Is on by default.
|
|
1246
|
+
*/
|
|
1247
|
+
setEmmiterActive: controller.setEmmiterActive,
|
|
1248
|
+
/**
|
|
1249
|
+
* @return current language if set.
|
|
1250
|
+
*/
|
|
1156
1251
|
getLanguage: controller.getLanguage,
|
|
1252
|
+
/**
|
|
1253
|
+
* `pendingLanguage` represents language which is currently being loaded.
|
|
1254
|
+
* @return current `pendingLanguage` if set.
|
|
1255
|
+
*/
|
|
1157
1256
|
getPendingLanguage: controller.getPendingLanguage,
|
|
1257
|
+
/**
|
|
1258
|
+
* Change current language.
|
|
1259
|
+
* - if not running sets `pendingLanguage`, `language` to the new value
|
|
1260
|
+
* - if running sets `pendingLanguage` to the value, fetches necessary data and then changes `language`
|
|
1261
|
+
*
|
|
1262
|
+
* @return Promise which is resolved when `language` is changed.
|
|
1263
|
+
*/
|
|
1158
1264
|
changeLanguage: controller.changeLanguage,
|
|
1265
|
+
/**
|
|
1266
|
+
* Temporarily change translation in cache.
|
|
1267
|
+
* @return object with revert method.
|
|
1268
|
+
*/
|
|
1159
1269
|
changeTranslation: controller.changeTranslation,
|
|
1270
|
+
/**
|
|
1271
|
+
* Adds namespace(s) list of active namespaces. And if tolgee is running, loads required data.
|
|
1272
|
+
*/
|
|
1160
1273
|
addActiveNs: controller.addActiveNs,
|
|
1274
|
+
/**
|
|
1275
|
+
* Remove namespace(s) from active namespaces.
|
|
1276
|
+
*
|
|
1277
|
+
* Tolgee internally counts how many times was each active namespace added,
|
|
1278
|
+
* so this method will remove namespace only if the counter goes down to 0.
|
|
1279
|
+
*/
|
|
1161
1280
|
removeActiveNs: controller.removeActiveNs,
|
|
1281
|
+
/**
|
|
1282
|
+
* Manually load multiple records from `Backend` (or `DevBackend` when in dev mode)
|
|
1283
|
+
*
|
|
1284
|
+
* It loads data together and adds them to cache in one operation, to prevent partly loaded state.
|
|
1285
|
+
*/
|
|
1162
1286
|
loadRecords: controller.loadRecords,
|
|
1287
|
+
/**
|
|
1288
|
+
* Manually load record from `Backend` (or `DevBackend` when in dev mode)
|
|
1289
|
+
*/
|
|
1163
1290
|
loadRecord: controller.loadRecord,
|
|
1291
|
+
/**
|
|
1292
|
+
*
|
|
1293
|
+
*/
|
|
1164
1294
|
addStaticData: controller.addStaticData,
|
|
1295
|
+
/**
|
|
1296
|
+
* Get record from cache.
|
|
1297
|
+
*/
|
|
1165
1298
|
getRecord: controller.getRecord,
|
|
1299
|
+
/**
|
|
1300
|
+
* Get all records from cache.
|
|
1301
|
+
*/
|
|
1166
1302
|
getAllRecords: controller.getAllRecords,
|
|
1303
|
+
/**
|
|
1304
|
+
* @param ns optional list of namespaces that you are interested in
|
|
1305
|
+
* @return `true` if there are data that need to be fetched.
|
|
1306
|
+
*/
|
|
1167
1307
|
isLoaded: controller.isLoaded,
|
|
1308
|
+
/**
|
|
1309
|
+
* @return `true` if tolgee is loading initial data (triggered by `run`).
|
|
1310
|
+
*/
|
|
1168
1311
|
isInitialLoading: controller.isInitialLoading,
|
|
1312
|
+
/**
|
|
1313
|
+
* @param ns optional list of namespaces that you are interested in
|
|
1314
|
+
* @return `true` if tolgee is loading some translations for the first time.
|
|
1315
|
+
*/
|
|
1169
1316
|
isLoading: controller.isLoading,
|
|
1317
|
+
/**
|
|
1318
|
+
* @param ns optional list of namespaces that you are interested in
|
|
1319
|
+
* @return `true` if tolgee is fetching some translations.
|
|
1320
|
+
*/
|
|
1170
1321
|
isFetching: controller.isFetching,
|
|
1322
|
+
/**
|
|
1323
|
+
* @return `true` if tolgee is running.
|
|
1324
|
+
*/
|
|
1171
1325
|
isRunning: controller.isRunning,
|
|
1326
|
+
/**
|
|
1327
|
+
* Changes internal state to running: true and loads initial files.
|
|
1328
|
+
* Runs runnable plugins mainly Observer if present.
|
|
1329
|
+
*/
|
|
1172
1330
|
run: controller.run,
|
|
1331
|
+
/**
|
|
1332
|
+
* Changes internal state to running: false and stops runnable plugins.
|
|
1333
|
+
*/
|
|
1173
1334
|
stop: controller.stop,
|
|
1335
|
+
/**
|
|
1336
|
+
* Returns translated and formatted key.
|
|
1337
|
+
* If Observer is present and tolgee is running, wraps result to be identifiable in the DOM.
|
|
1338
|
+
*/
|
|
1174
1339
|
t: controller.t,
|
|
1340
|
+
/**
|
|
1341
|
+
* Highlight keys that match selection.
|
|
1342
|
+
*/
|
|
1175
1343
|
highlight: controller.highlight,
|
|
1344
|
+
/**
|
|
1345
|
+
* @return current Tolgee options.
|
|
1346
|
+
*/
|
|
1176
1347
|
getInitialOptions: controller.getInitialOptions,
|
|
1348
|
+
/**
|
|
1349
|
+
* Tolgee is in dev mode if `DevTools` plugin is used and `apiKey` + `apiUrl` are specified.
|
|
1350
|
+
* @return `true` if tolgee is in dev mode.
|
|
1351
|
+
*/
|
|
1177
1352
|
isDev: controller.isDev,
|
|
1353
|
+
/**
|
|
1354
|
+
* Wraps translation if there is `Observer` plugin
|
|
1355
|
+
*/
|
|
1178
1356
|
wrap: controller.wrap,
|
|
1357
|
+
/**
|
|
1358
|
+
* Unwrap translation
|
|
1359
|
+
*/
|
|
1179
1360
|
unwrap: controller.unwrap,
|
|
1180
|
-
|
|
1181
|
-
|
|
1361
|
+
/**
|
|
1362
|
+
* Override creadentials passed on initialization.
|
|
1363
|
+
*
|
|
1364
|
+
* When called in running state, tolgee stops and runs again.
|
|
1365
|
+
*/
|
|
1366
|
+
overrideCredentials(credentials) {
|
|
1367
|
+
withRestart(() => controller.overrideCredentials(credentials));
|
|
1368
|
+
},
|
|
1369
|
+
/**
|
|
1370
|
+
* Add tolgee plugin after initialization.
|
|
1371
|
+
*
|
|
1372
|
+
* When called in running state, tolgee stops and runs again.
|
|
1373
|
+
*/
|
|
1374
|
+
addPlugin(plugin) {
|
|
1182
1375
|
if (plugin) {
|
|
1183
|
-
withRestart(() =>
|
|
1376
|
+
withRestart(() => controller.addPlugin(tolgee, plugin));
|
|
1184
1377
|
}
|
|
1185
|
-
return tolgee;
|
|
1186
1378
|
},
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1379
|
+
/**
|
|
1380
|
+
* Updates options after instance creation. Extends existing options,
|
|
1381
|
+
* so it only changes the fields, that are listed.
|
|
1382
|
+
*
|
|
1383
|
+
* When called in running state, tolgee stops and runs again.
|
|
1384
|
+
*/
|
|
1385
|
+
updateOptions(options) {
|
|
1386
|
+
if (options) {
|
|
1387
|
+
withRestart(() => controller.init(options));
|
|
1388
|
+
}
|
|
1190
1389
|
},
|
|
1191
1390
|
});
|
|
1192
1391
|
return tolgee;
|
|
1193
1392
|
};
|
|
1393
|
+
/**
|
|
1394
|
+
* Tolgee chainable constructor.
|
|
1395
|
+
*
|
|
1396
|
+
* Usage:
|
|
1397
|
+
* ```
|
|
1398
|
+
* const tolgee = Tolgee().use(...).init(...)
|
|
1399
|
+
* ```
|
|
1400
|
+
*/
|
|
1401
|
+
const TolgeeCore = () => {
|
|
1402
|
+
const state = {
|
|
1403
|
+
plugins: [],
|
|
1404
|
+
options: {},
|
|
1405
|
+
};
|
|
1406
|
+
const tolgeeChain = Object.freeze({
|
|
1407
|
+
use(plugin) {
|
|
1408
|
+
state.plugins.push(plugin);
|
|
1409
|
+
return tolgeeChain;
|
|
1410
|
+
},
|
|
1411
|
+
updateDefaults(options) {
|
|
1412
|
+
state.options = combineOptions(state.options, options);
|
|
1413
|
+
return tolgeeChain;
|
|
1414
|
+
},
|
|
1415
|
+
init(options) {
|
|
1416
|
+
const tolgee = createTolgee(combineOptions(state.options, options));
|
|
1417
|
+
state.plugins.forEach(tolgee.addPlugin);
|
|
1418
|
+
return tolgee;
|
|
1419
|
+
},
|
|
1420
|
+
});
|
|
1421
|
+
return tolgeeChain;
|
|
1422
|
+
};
|
|
1194
1423
|
|
|
1195
|
-
const
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1424
|
+
const ERROR_PARAM_EMPTY = 0, ERROR_UNEXPECTED_CHAR = 1, ERROR_UNEXPECTED_END = 2;
|
|
1425
|
+
class FormatError extends Error {
|
|
1426
|
+
constructor(code, index, text) {
|
|
1427
|
+
let error;
|
|
1428
|
+
if (code === ERROR_PARAM_EMPTY) {
|
|
1429
|
+
error = 'Empty parameter';
|
|
1430
|
+
}
|
|
1431
|
+
else if (code === ERROR_UNEXPECTED_CHAR) {
|
|
1432
|
+
error = 'Unexpected character';
|
|
1433
|
+
}
|
|
1434
|
+
else {
|
|
1435
|
+
error = 'Unexpected end';
|
|
1436
|
+
}
|
|
1437
|
+
super(`Tolgee parser: ${error} at ${index} in "${text}"`);
|
|
1438
|
+
this.code = code;
|
|
1439
|
+
this.index = index;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
function isWhitespace(ch) {
|
|
1444
|
+
return /\s/.test(ch);
|
|
1445
|
+
}
|
|
1446
|
+
const STATE_TEXT = 0, STATE_ESCAPE_MAYBE = 1, STATE_ESCAPE = 2, STATE_PARAM = 3, STATE_PARAM_AFTER = 4;
|
|
1447
|
+
const END_STATES = new Set([
|
|
1448
|
+
STATE_ESCAPE,
|
|
1449
|
+
STATE_ESCAPE_MAYBE,
|
|
1450
|
+
STATE_TEXT,
|
|
1451
|
+
]);
|
|
1452
|
+
const CHAR_ESCAPE = "'";
|
|
1453
|
+
const ESCAPABLE = new Set(['{', '}', CHAR_ESCAPE]);
|
|
1454
|
+
const isAllowedInParam = (char) => {
|
|
1455
|
+
return /[0-9a-zA-Z_]/.test(char);
|
|
1456
|
+
};
|
|
1457
|
+
function formatParser(translation) {
|
|
1458
|
+
let state = STATE_TEXT;
|
|
1459
|
+
let text = '';
|
|
1460
|
+
let param = '';
|
|
1461
|
+
let ch = '';
|
|
1462
|
+
const texts = [];
|
|
1463
|
+
const params = [];
|
|
1464
|
+
let i = 0;
|
|
1465
|
+
function parsingError(code) {
|
|
1466
|
+
throw new FormatError(code, i, translation);
|
|
1467
|
+
}
|
|
1468
|
+
const addText = () => {
|
|
1469
|
+
texts.push(text);
|
|
1470
|
+
text = '';
|
|
1471
|
+
};
|
|
1472
|
+
const addParamChar = () => {
|
|
1473
|
+
if (!isAllowedInParam(ch)) {
|
|
1474
|
+
parsingError(ERROR_UNEXPECTED_CHAR);
|
|
1475
|
+
}
|
|
1476
|
+
param += ch;
|
|
1477
|
+
};
|
|
1478
|
+
const addParam = () => {
|
|
1479
|
+
if (param === '') {
|
|
1480
|
+
parsingError(ERROR_PARAM_EMPTY);
|
|
1481
|
+
}
|
|
1482
|
+
params.push(param);
|
|
1483
|
+
param = '';
|
|
1484
|
+
};
|
|
1485
|
+
for (i = 0; i < translation.length; i++) {
|
|
1486
|
+
ch = translation[i];
|
|
1487
|
+
switch (state) {
|
|
1488
|
+
case STATE_TEXT:
|
|
1489
|
+
if (ch === CHAR_ESCAPE) {
|
|
1490
|
+
text += ch;
|
|
1491
|
+
state = STATE_ESCAPE_MAYBE;
|
|
1492
|
+
}
|
|
1493
|
+
else if (ch === '{') {
|
|
1494
|
+
addText();
|
|
1495
|
+
state = STATE_PARAM;
|
|
1496
|
+
}
|
|
1497
|
+
else {
|
|
1498
|
+
text += ch;
|
|
1499
|
+
state = STATE_TEXT;
|
|
1500
|
+
}
|
|
1501
|
+
break;
|
|
1502
|
+
case STATE_ESCAPE_MAYBE:
|
|
1503
|
+
if (ESCAPABLE.has(ch)) {
|
|
1504
|
+
text = text.slice(0, -1) + ch;
|
|
1505
|
+
state = STATE_ESCAPE;
|
|
1506
|
+
}
|
|
1507
|
+
else {
|
|
1508
|
+
text += ch;
|
|
1509
|
+
state = STATE_TEXT;
|
|
1510
|
+
}
|
|
1511
|
+
break;
|
|
1512
|
+
case STATE_ESCAPE:
|
|
1513
|
+
if (ch === CHAR_ESCAPE) {
|
|
1514
|
+
state = STATE_TEXT;
|
|
1515
|
+
}
|
|
1516
|
+
else {
|
|
1517
|
+
text += ch;
|
|
1518
|
+
state = STATE_ESCAPE;
|
|
1519
|
+
}
|
|
1520
|
+
break;
|
|
1521
|
+
case STATE_PARAM:
|
|
1522
|
+
if (ch === '}') {
|
|
1523
|
+
addParam();
|
|
1524
|
+
state = STATE_TEXT;
|
|
1525
|
+
}
|
|
1526
|
+
else if (!isWhitespace(ch)) {
|
|
1527
|
+
addParamChar();
|
|
1528
|
+
state = STATE_PARAM;
|
|
1529
|
+
}
|
|
1530
|
+
else if (param !== '') {
|
|
1531
|
+
addParam();
|
|
1532
|
+
state = STATE_PARAM_AFTER;
|
|
1533
|
+
}
|
|
1534
|
+
break;
|
|
1535
|
+
case STATE_PARAM_AFTER:
|
|
1536
|
+
if (ch == '}') {
|
|
1537
|
+
state = STATE_TEXT;
|
|
1538
|
+
}
|
|
1539
|
+
else if (isWhitespace(ch)) {
|
|
1540
|
+
state = STATE_PARAM_AFTER;
|
|
1541
|
+
}
|
|
1542
|
+
else {
|
|
1543
|
+
parsingError(ERROR_UNEXPECTED_CHAR);
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
if (!END_STATES.has(state)) {
|
|
1548
|
+
parsingError(ERROR_UNEXPECTED_END);
|
|
1549
|
+
}
|
|
1550
|
+
addText();
|
|
1551
|
+
return [texts, params];
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
function formatter(translation, params) {
|
|
1555
|
+
const [texts, pars] = formatParser(translation);
|
|
1556
|
+
const result = [texts[0]];
|
|
1557
|
+
for (let i = 1; i < texts.length; i++) {
|
|
1558
|
+
const parameter = params === null || params === void 0 ? void 0 : params[pars[i - 1]];
|
|
1559
|
+
if (parameter === undefined) {
|
|
1560
|
+
throw new Error(`Missing parameter "${pars[i - 1]}" in "${translation}"`);
|
|
1561
|
+
}
|
|
1562
|
+
result.push(String(parameter));
|
|
1563
|
+
result.push(texts[i]);
|
|
1564
|
+
}
|
|
1565
|
+
return result.join('');
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
function createFormatSimple() {
|
|
1569
|
+
return {
|
|
1570
|
+
format: ({ translation, params }) => formatter(translation, params),
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
const FormatSimple = () => (tolgee, tools) => {
|
|
1574
|
+
tools.setFinalFormatter(createFormatSimple());
|
|
1575
|
+
return tolgee;
|
|
1576
|
+
};
|
|
1201
1577
|
|
|
1202
|
-
exports.
|
|
1203
|
-
exports.
|
|
1204
|
-
exports.TOLGEE_ATTRIBUTE_NAME = TOLGEE_ATTRIBUTE_NAME;
|
|
1205
|
-
exports.TOLGEE_HIGHLIGHTER_CLASS = TOLGEE_HIGHLIGHTER_CLASS;
|
|
1206
|
-
exports.TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE = TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE;
|
|
1207
|
-
exports.Tolgee = Tolgee;
|
|
1578
|
+
exports.FormatSimple = FormatSimple;
|
|
1579
|
+
exports.TolgeeCore = TolgeeCore;
|
|
1208
1580
|
exports.getFallback = getFallback;
|
|
1209
1581
|
exports.getFallbackArray = getFallbackArray;
|
|
1210
|
-
exports.
|
|
1582
|
+
exports.getTranslateProps = getTranslateProps;
|
|
1211
1583
|
|
|
1212
1584
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1213
1585
|
|