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