@tolgee/core 4.9.2 → 4.9.3-rc.128edeb.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tolgee.cjs.js +1275 -7024
- package/dist/tolgee.cjs.js.map +1 -1
- package/dist/tolgee.cjs.min.js +1 -1
- package/dist/tolgee.cjs.min.js.map +1 -1
- package/dist/tolgee.esm.js +1404 -0
- 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 +1275 -7024
- 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 +22 -0
- package/lib/Controller/Cache/helpers.d.ts +4 -0
- package/lib/Controller/Controller.d.ts +110 -0
- 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 +36 -0
- package/lib/Controller/State/State.d.ts +39 -0
- package/lib/Controller/State/helpers.d.ts +6 -0
- package/lib/Controller/State/initObserverOptions.d.ts +13 -0
- package/lib/Controller/State/initState.d.ts +47 -0
- package/lib/Controller/ValueObserver.d.ts +5 -0
- package/lib/FormatSimple/FormatError.d.ts +7 -0
- package/lib/FormatSimple/FormatSimple.d.ts +3 -0
- package/lib/FormatSimple/formatParser.d.ts +1 -0
- package/lib/FormatSimple/formatter.d.ts +2 -0
- package/lib/Tolgee.d.ts +2 -68
- package/lib/TranslateParams.d.ts +2 -0
- package/lib/{Constants/Global.d.ts → constants.d.ts} +1 -3
- package/lib/helpers.d.ts +3 -0
- package/lib/index.d.ts +4 -8
- package/lib/types.d.ts +244 -84
- package/package.json +21 -29
- package/src/Controller/Cache/Cache.ts +293 -0
- package/src/Controller/Cache/helpers.ts +37 -0
- package/src/Controller/Controller.ts +310 -0
- package/src/Controller/Events/EventEmitter.ts +30 -0
- package/src/Controller/Events/EventEmitterSelective.test.ts +125 -0
- package/src/Controller/Events/EventEmitterSelective.ts +188 -0
- package/src/Controller/Events/Events.ts +66 -0
- package/src/Controller/Plugins/Plugins.ts +315 -0
- package/src/Controller/State/State.ts +175 -0
- package/src/Controller/State/helpers.ts +41 -0
- package/src/Controller/State/initObserverOptions.ts +38 -0
- package/src/Controller/State/initState.ts +81 -0
- package/src/Controller/ValueObserver.ts +26 -0
- package/src/FormatSimple/FormatError.ts +26 -0
- package/src/FormatSimple/FormatSimple.ts +13 -0
- package/src/FormatSimple/formatParser.ts +133 -0
- package/src/FormatSimple/formatter.test.ts +190 -0
- package/src/FormatSimple/formatter.ts +19 -0
- package/src/Tolgee.ts +79 -330
- package/src/TranslateParams.test.ts +41 -0
- package/src/TranslateParams.ts +51 -0
- package/src/__test/backend.test.ts +48 -0
- package/src/__test/cache.test.ts +148 -0
- package/src/__test/client.test.ts +48 -0
- package/src/__test/events.test.ts +33 -0
- package/src/__test/format.simple.test.ts +26 -0
- package/src/__test/initialization.test.ts +85 -0
- package/src/__test/jest-setup.ts +2 -0
- package/src/__test/languageDetection.test.ts +129 -0
- package/src/__test/languageStorage.test.ts +145 -0
- package/src/__test/languages.test.ts +112 -0
- package/src/__test/loading.test.ts +39 -0
- package/src/__test/namespaces.test.ts +99 -0
- package/src/__test/namespacesFallback.test.ts +74 -0
- package/src/__test/plugins.test.ts +136 -0
- package/src/__test/testTools.ts +7 -0
- package/src/{Constants/Global.ts → constants.ts} +1 -6
- package/src/helpers.ts +17 -0
- package/src/index.ts +9 -8
- package/src/types.ts +338 -90
- package/README.md +0 -45
- package/dist/Constants/Global.d.ts +0 -6
- package/dist/Constants/ModifierKey.d.ts +0 -6
- package/dist/Errors/ApiHttpError.d.ts +0 -5
- package/dist/Observer.d.ts +0 -14
- package/dist/Observer.test.d.ts +0 -2
- package/dist/Properties.d.ts +0 -17
- package/dist/Properties.test.d.ts +0 -1
- package/dist/Tolgee.d.ts +0 -68
- package/dist/Tolgee.test.d.ts +0 -1
- package/dist/TolgeeConfig.d.ts +0 -69
- package/dist/TolgeeConfig.test.d.ts +0 -1
- package/dist/__integration/FormatterIcu.test.d.ts +0 -1
- package/dist/__integration/FormatterMissing.d.ts +0 -1
- package/dist/__integration/Tolgee.test.d.ts +0 -1
- package/dist/__integration/TolgeeInvisible.test.d.ts +0 -1
- package/dist/__integration/mockTranslations.d.ts +0 -7
- package/dist/__integration/testConfig.d.ts +0 -9
- package/dist/__testFixtures/classMock.d.ts +0 -3
- package/dist/__testFixtures/createElement.d.ts +0 -2
- package/dist/__testFixtures/createTestDom.d.ts +0 -9
- package/dist/__testFixtures/mocked.d.ts +0 -20
- package/dist/__testFixtures/setupAfterEnv.d.ts +0 -8
- package/dist/helpers/NodeHelper.d.ts +0 -14
- package/dist/helpers/TextHelper.d.ts +0 -5
- package/dist/helpers/TextHelper.test.d.ts +0 -1
- package/dist/helpers/commonTypes.d.ts +0 -2
- package/dist/helpers/encoderPolyfill.d.ts +0 -8
- package/dist/helpers/secret.d.ts +0 -6
- package/dist/helpers/secret.test.d.ts +0 -1
- package/dist/helpers/sleep.d.ts +0 -1
- package/dist/highlighter/HighlightFunctionsInitializer.d.ts +0 -10
- package/dist/highlighter/HighlightFunctionsInitializer.test.d.ts +0 -1
- package/dist/highlighter/MouseEventHandler.d.ts +0 -29
- package/dist/highlighter/MouseEventHandler.test.d.ts +0 -1
- package/dist/highlighter/TranslationHighlighter.d.ts +0 -14
- package/dist/highlighter/TranslationHighlighter.test.d.ts +0 -1
- package/dist/index.d.ts +0 -10
- package/dist/internal.d.ts +0 -2
- package/dist/modules/IcuFormatter.d.ts +0 -2
- package/dist/modules/IcuFormatter.test.d.ts +0 -1
- package/dist/modules/index.d.ts +0 -1
- package/dist/services/ApiHttpService.d.ts +0 -15
- package/dist/services/CoreService.d.ts +0 -18
- package/dist/services/CoreService.test.d.ts +0 -1
- package/dist/services/DependencyService.d.ts +0 -39
- package/dist/services/DependencyService.test.d.ts +0 -1
- package/dist/services/ElementRegistrar.d.ts +0 -19
- package/dist/services/ElementRegistrar.test.d.ts +0 -1
- package/dist/services/EventEmitter.d.ts +0 -13
- package/dist/services/EventService.d.ts +0 -9
- package/dist/services/ModuleService.d.ts +0 -5
- package/dist/services/ScreenshotService.d.ts +0 -15
- package/dist/services/Subscription.d.ts +0 -5
- package/dist/services/TextService.d.ts +0 -14
- package/dist/services/TextService.test.d.ts +0 -1
- package/dist/services/TranslationService.d.ts +0 -75
- package/dist/services/TranslationService.test.d.ts +0 -1
- package/dist/services/__mocks__/CoreService.d.ts +0 -2
- package/dist/tolgee.esm.mjs +0 -7150
- package/dist/tolgee.esm.mjs.map +0 -1
- package/dist/toolsManager/Messages.d.ts +0 -8
- package/dist/toolsManager/Messages.test.d.ts +0 -1
- package/dist/toolsManager/PluginManager.d.ts +0 -21
- package/dist/toolsManager/PluginManager.test.d.ts +0 -1
- package/dist/types/DTOs.d.ts +0 -20
- package/dist/types/apiSchema.generated.d.ts +0 -6185
- package/dist/types.d.ts +0 -123
- package/dist/wrappers/AbstractWrapper.d.ts +0 -8
- package/dist/wrappers/NodeHandler.d.ts +0 -18
- package/dist/wrappers/WrappedHandler.d.ts +0 -8
- package/dist/wrappers/invisible/AttributeHandler.d.ts +0 -8
- package/dist/wrappers/invisible/Coder.d.ts +0 -7
- package/dist/wrappers/invisible/ContentHandler.d.ts +0 -6
- package/dist/wrappers/invisible/CoreHandler.d.ts +0 -10
- package/dist/wrappers/invisible/InvisibleWrapper.d.ts +0 -18
- package/dist/wrappers/invisible/ValueMemory.d.ts +0 -5
- package/dist/wrappers/invisible/ValueMemory.test.d.ts +0 -1
- package/dist/wrappers/text/AttributeHandler.d.ts +0 -8
- package/dist/wrappers/text/AttributeHandler.test.d.ts +0 -1
- package/dist/wrappers/text/Coder.d.ts +0 -15
- package/dist/wrappers/text/Coder.test.d.ts +0 -1
- package/dist/wrappers/text/ContentHandler.d.ts +0 -8
- package/dist/wrappers/text/ContentHandler.test.d.ts +0 -1
- package/dist/wrappers/text/CoreHandler.d.ts +0 -17
- package/dist/wrappers/text/CoreHandler.test.d.ts +0 -1
- package/dist/wrappers/text/TextWrapper.d.ts +0 -20
- package/index.js +0 -7
- package/lib/Constants/ModifierKey.d.ts +0 -6
- package/lib/Errors/ApiHttpError.d.ts +0 -5
- package/lib/Observer.d.ts +0 -14
- package/lib/Properties.d.ts +0 -17
- package/lib/TolgeeConfig.d.ts +0 -69
- package/lib/helpers/NodeHelper.d.ts +0 -14
- package/lib/helpers/TextHelper.d.ts +0 -5
- package/lib/helpers/commonTypes.d.ts +0 -2
- package/lib/helpers/encoderPolyfill.d.ts +0 -8
- package/lib/helpers/secret.d.ts +0 -6
- package/lib/helpers/sleep.d.ts +0 -1
- package/lib/highlighter/HighlightFunctionsInitializer.d.ts +0 -10
- package/lib/highlighter/MouseEventHandler.d.ts +0 -29
- package/lib/highlighter/TranslationHighlighter.d.ts +0 -14
- package/lib/modules/IcuFormatter.d.ts +0 -2
- package/lib/modules/index.d.ts +0 -1
- package/lib/services/ApiHttpService.d.ts +0 -15
- package/lib/services/CoreService.d.ts +0 -18
- package/lib/services/DependencyService.d.ts +0 -39
- package/lib/services/ElementRegistrar.d.ts +0 -19
- package/lib/services/EventEmitter.d.ts +0 -13
- package/lib/services/EventService.d.ts +0 -9
- package/lib/services/ModuleService.d.ts +0 -5
- package/lib/services/ScreenshotService.d.ts +0 -15
- package/lib/services/Subscription.d.ts +0 -5
- package/lib/services/TextService.d.ts +0 -14
- package/lib/services/TranslationService.d.ts +0 -75
- package/lib/toolsManager/Messages.d.ts +0 -8
- package/lib/toolsManager/PluginManager.d.ts +0 -21
- package/lib/types/DTOs.d.ts +0 -20
- package/lib/types/apiSchema.generated.d.ts +0 -6185
- package/lib/wrappers/AbstractWrapper.d.ts +0 -8
- package/lib/wrappers/NodeHandler.d.ts +0 -18
- package/lib/wrappers/WrappedHandler.d.ts +0 -8
- package/lib/wrappers/invisible/AttributeHandler.d.ts +0 -8
- package/lib/wrappers/invisible/Coder.d.ts +0 -7
- package/lib/wrappers/invisible/ContentHandler.d.ts +0 -6
- package/lib/wrappers/invisible/CoreHandler.d.ts +0 -10
- package/lib/wrappers/invisible/InvisibleWrapper.d.ts +0 -18
- package/lib/wrappers/invisible/ValueMemory.d.ts +0 -5
- package/lib/wrappers/text/AttributeHandler.d.ts +0 -8
- package/lib/wrappers/text/Coder.d.ts +0 -15
- package/lib/wrappers/text/ContentHandler.d.ts +0 -8
- package/lib/wrappers/text/CoreHandler.d.ts +0 -17
- package/lib/wrappers/text/TextWrapper.d.ts +0 -20
- package/src/Constants/ModifierKey.ts +0 -6
- package/src/Errors/ApiHttpError.ts +0 -8
- package/src/Observer.test.ts +0 -119
- package/src/Observer.ts +0 -68
- package/src/Properties.test.ts +0 -150
- package/src/Properties.ts +0 -112
- package/src/Tolgee.test.ts +0 -473
- package/src/TolgeeConfig.test.ts +0 -21
- package/src/TolgeeConfig.ts +0 -134
- package/src/__integration/FormatterIcu.test.ts +0 -80
- package/src/__integration/FormatterMissing.ts +0 -54
- package/src/__integration/Tolgee.test.ts +0 -90
- package/src/__integration/TolgeeInvisible.test.ts +0 -145
- package/src/__integration/mockTranslations.ts +0 -6
- package/src/__integration/testConfig.ts +0 -16
- package/src/__testFixtures/classMock.ts +0 -11
- package/src/__testFixtures/createElement.ts +0 -43
- package/src/__testFixtures/createTestDom.ts +0 -26
- package/src/__testFixtures/mocked.ts +0 -25
- package/src/__testFixtures/setupAfterEnv.ts +0 -34
- package/src/helpers/NodeHelper.ts +0 -90
- package/src/helpers/TextHelper.test.ts +0 -62
- package/src/helpers/TextHelper.ts +0 -58
- package/src/helpers/commonTypes.ts +0 -8
- package/src/helpers/encoderPolyfill.ts +0 -96
- package/src/helpers/secret.test.ts +0 -61
- package/src/helpers/secret.ts +0 -68
- package/src/helpers/sleep.ts +0 -2
- package/src/highlighter/HighlightFunctionsInitializer.test.ts +0 -40
- package/src/highlighter/HighlightFunctionsInitializer.ts +0 -61
- package/src/highlighter/MouseEventHandler.test.ts +0 -151
- package/src/highlighter/MouseEventHandler.ts +0 -191
- package/src/highlighter/TranslationHighlighter.test.ts +0 -177
- package/src/highlighter/TranslationHighlighter.ts +0 -113
- package/src/internal.ts +0 -2
- package/src/modules/IcuFormatter.test.ts +0 -21
- package/src/modules/IcuFormatter.ts +0 -39
- package/src/modules/index.ts +0 -1
- package/src/services/ApiHttpService.ts +0 -85
- package/src/services/CoreService.test.ts +0 -141
- package/src/services/CoreService.ts +0 -76
- package/src/services/DependencyService.test.ts +0 -51
- package/src/services/DependencyService.ts +0 -116
- package/src/services/ElementRegistrar.test.ts +0 -131
- package/src/services/ElementRegistrar.ts +0 -108
- package/src/services/EventEmitter.ts +0 -52
- package/src/services/EventService.ts +0 -14
- package/src/services/ModuleService.ts +0 -14
- package/src/services/ScreenshotService.ts +0 -31
- package/src/services/Subscription.ts +0 -7
- package/src/services/TextService.test.ts +0 -88
- package/src/services/TextService.ts +0 -82
- package/src/services/TranslationService.test.ts +0 -358
- package/src/services/TranslationService.ts +0 -417
- package/src/services/__mocks__/CoreService.ts +0 -17
- package/src/toolsManager/Messages.test.ts +0 -79
- package/src/toolsManager/Messages.ts +0 -60
- package/src/toolsManager/PluginManager.test.ts +0 -108
- package/src/toolsManager/PluginManager.ts +0 -129
- package/src/types/DTOs.ts +0 -25
- package/src/types/apiSchema.generated.ts +0 -6208
- package/src/wrappers/AbstractWrapper.ts +0 -14
- package/src/wrappers/NodeHandler.ts +0 -143
- package/src/wrappers/WrappedHandler.ts +0 -28
- package/src/wrappers/invisible/AttributeHandler.ts +0 -23
- package/src/wrappers/invisible/Coder.ts +0 -65
- package/src/wrappers/invisible/ContentHandler.ts +0 -15
- package/src/wrappers/invisible/CoreHandler.ts +0 -17
- package/src/wrappers/invisible/InvisibleWrapper.ts +0 -59
- package/src/wrappers/invisible/ValueMemory.test.ts +0 -25
- package/src/wrappers/invisible/ValueMemory.ts +0 -16
- package/src/wrappers/text/AttributeHandler.test.ts +0 -118
- package/src/wrappers/text/AttributeHandler.ts +0 -25
- package/src/wrappers/text/Coder.test.ts +0 -298
- package/src/wrappers/text/Coder.ts +0 -202
- package/src/wrappers/text/ContentHandler.test.ts +0 -185
- package/src/wrappers/text/ContentHandler.ts +0 -21
- package/src/wrappers/text/CoreHandler.test.ts +0 -106
- package/src/wrappers/text/CoreHandler.ts +0 -45
- package/src/wrappers/text/TextWrapper.ts +0 -69
|
@@ -0,0 +1,1404 @@
|
|
|
1
|
+
const EventEmitter = () => {
|
|
2
|
+
let handlers = [];
|
|
3
|
+
const listen = (handler) => {
|
|
4
|
+
const handlerWrapper = (e) => {
|
|
5
|
+
handler(e);
|
|
6
|
+
};
|
|
7
|
+
handlers.push(handlerWrapper);
|
|
8
|
+
return {
|
|
9
|
+
unsubscribe: () => {
|
|
10
|
+
handlers = handlers.filter((i) => handlerWrapper !== i);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const emit = (data) => {
|
|
15
|
+
handlers.forEach((handler) => handler({ value: data }));
|
|
16
|
+
};
|
|
17
|
+
return Object.freeze({ listen, emit });
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function isObject(item) {
|
|
21
|
+
return typeof item === 'object' && !Array.isArray(item) && item !== null;
|
|
22
|
+
}
|
|
23
|
+
function getFallback(value) {
|
|
24
|
+
if (typeof value === 'string') {
|
|
25
|
+
return [value];
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
function getFallbackArray(value) {
|
|
33
|
+
return getFallback(value) || [];
|
|
34
|
+
}
|
|
35
|
+
function getFallbackFromStruct(language, fallbackLanguage) {
|
|
36
|
+
if (isObject(fallbackLanguage)) {
|
|
37
|
+
return getFallbackArray(fallbackLanguage === null || fallbackLanguage === void 0 ? void 0 : fallbackLanguage[language]);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return getFallbackArray(fallbackLanguage);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function unique(arr) {
|
|
44
|
+
return Array.from(new Set(arr));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function incrementInMap(map, value) {
|
|
48
|
+
const currNum = map.get(value) || 0;
|
|
49
|
+
map.set(value, currNum + 1);
|
|
50
|
+
}
|
|
51
|
+
function decrementInMap(map, value) {
|
|
52
|
+
let currNum = map.get(value) || 1;
|
|
53
|
+
currNum -= 1;
|
|
54
|
+
if (currNum <= 0) {
|
|
55
|
+
map.delete(value);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
map.set(value, currNum);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const EventEmitterSelective = (getFallbackNamespaces) => {
|
|
62
|
+
const listeners = new Set();
|
|
63
|
+
const partialListeners = new Set();
|
|
64
|
+
const listen = (handler) => {
|
|
65
|
+
listeners.add(handler);
|
|
66
|
+
const result = {
|
|
67
|
+
unsubscribe: () => {
|
|
68
|
+
listeners.delete(handler);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
return result;
|
|
72
|
+
};
|
|
73
|
+
const listenSome = (handler) => {
|
|
74
|
+
const handlerWrapper = {
|
|
75
|
+
fn: (e) => {
|
|
76
|
+
handler(e);
|
|
77
|
+
},
|
|
78
|
+
keys: new Map(),
|
|
79
|
+
namespaces: new Map(),
|
|
80
|
+
};
|
|
81
|
+
partialListeners.add(handlerWrapper);
|
|
82
|
+
const result = {
|
|
83
|
+
unsubscribe: () => {
|
|
84
|
+
partialListeners.delete(handlerWrapper);
|
|
85
|
+
},
|
|
86
|
+
subscribeNs: (ns) => {
|
|
87
|
+
getFallbackArray(ns).forEach((val) => incrementInMap(handlerWrapper.namespaces, val));
|
|
88
|
+
return result;
|
|
89
|
+
},
|
|
90
|
+
unsubscribeNs: (ns) => {
|
|
91
|
+
getFallbackArray(ns).forEach((val) => decrementInMap(handlerWrapper.namespaces, val));
|
|
92
|
+
return result;
|
|
93
|
+
},
|
|
94
|
+
subscribeKey: (descriptor) => {
|
|
95
|
+
const { key, ns } = descriptor;
|
|
96
|
+
incrementInMap(handlerWrapper.keys, key);
|
|
97
|
+
getFallbackArray(ns).forEach((val) => incrementInMap(handlerWrapper.namespaces, val));
|
|
98
|
+
if (ns === undefined) {
|
|
99
|
+
// subscribing to all namespaces
|
|
100
|
+
incrementInMap(handlerWrapper.namespaces, undefined);
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
},
|
|
104
|
+
unsubscribeKey: (descriptor) => {
|
|
105
|
+
const { key, ns } = descriptor;
|
|
106
|
+
decrementInMap(handlerWrapper.keys, key);
|
|
107
|
+
getFallbackArray(ns).forEach((val) => decrementInMap(handlerWrapper.namespaces, val));
|
|
108
|
+
if (ns === undefined) {
|
|
109
|
+
// subscribing to all namespaces
|
|
110
|
+
decrementInMap(handlerWrapper.namespaces, undefined);
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
return result;
|
|
116
|
+
};
|
|
117
|
+
const namespacesWithFallbacks = (namespaces) => {
|
|
118
|
+
if (namespaces.has(undefined)) {
|
|
119
|
+
const result = new Set(namespaces.keys());
|
|
120
|
+
result.delete(undefined);
|
|
121
|
+
getFallbackNamespaces().forEach((ns) => result.add(ns));
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
return namespaces;
|
|
125
|
+
};
|
|
126
|
+
const callHandlers = (key, ns) => {
|
|
127
|
+
partialListeners.forEach((handler) => {
|
|
128
|
+
const handlerNamespaces = namespacesWithFallbacks(handler.namespaces);
|
|
129
|
+
const nsMatches = ns === undefined ||
|
|
130
|
+
(ns === null || ns === void 0 ? void 0 : ns.findIndex((ns) => handlerNamespaces.has(ns))) !== -1;
|
|
131
|
+
const keyMatches = key === undefined || handler.keys.has(key) || handler.keys.size === 0;
|
|
132
|
+
if (nsMatches && keyMatches) {
|
|
133
|
+
handler.fn({ value: undefined });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
let queue = [];
|
|
138
|
+
// merge events in queue into one event
|
|
139
|
+
const solveQueue = () => {
|
|
140
|
+
if (queue.length === 0) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
listeners.forEach((handler) => {
|
|
144
|
+
handler({ value: undefined });
|
|
145
|
+
});
|
|
146
|
+
const namespaces = new Set();
|
|
147
|
+
let keys = new Set();
|
|
148
|
+
queue.forEach((descriptor) => {
|
|
149
|
+
if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.ns) === undefined) {
|
|
150
|
+
// when no ns specified, it affets all fallback namespaces
|
|
151
|
+
namespaces.add(undefined);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
descriptor.ns.forEach((ns) => namespaces.add(ns));
|
|
155
|
+
}
|
|
156
|
+
if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.key) === undefined) {
|
|
157
|
+
// when no key specified, it affects all keys
|
|
158
|
+
keys = undefined;
|
|
159
|
+
}
|
|
160
|
+
else if (keys !== undefined) {
|
|
161
|
+
keys.add(descriptor.key);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const namespacesArray = Array.from(namespacesWithFallbacks(namespaces).keys());
|
|
165
|
+
(keys || [undefined]).forEach((key) => {
|
|
166
|
+
callHandlers(key, namespacesArray);
|
|
167
|
+
});
|
|
168
|
+
queue = [];
|
|
169
|
+
};
|
|
170
|
+
const emit = (descriptor, delayed) => {
|
|
171
|
+
queue.push(descriptor);
|
|
172
|
+
if (!delayed) {
|
|
173
|
+
solveQueue();
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
Promise.resolve().then(() => {
|
|
177
|
+
solveQueue();
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
return Object.freeze({ listenSome, listen, emit });
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const Events = (getFallbackNamespaces) => {
|
|
185
|
+
const onPendingLanguageChange = EventEmitter();
|
|
186
|
+
const onLanguageChange = EventEmitter();
|
|
187
|
+
const onKeyChange = EventEmitter();
|
|
188
|
+
const onLoadingChange = EventEmitter();
|
|
189
|
+
const onFetchingChange = EventEmitter();
|
|
190
|
+
const onInitialLoaded = EventEmitter();
|
|
191
|
+
const onKeyUpdate = EventEmitterSelective(getFallbackNamespaces);
|
|
192
|
+
const onCacheChange = EventEmitter();
|
|
193
|
+
const onRunningChange = EventEmitter();
|
|
194
|
+
onInitialLoaded.listen(() => onKeyUpdate.emit());
|
|
195
|
+
onLanguageChange.listen(() => onKeyUpdate.emit());
|
|
196
|
+
onCacheChange.listen(({ value }) => {
|
|
197
|
+
onKeyUpdate.emit({ ns: [value.namespace], key: value.key }, true);
|
|
198
|
+
});
|
|
199
|
+
const on = (event, handler) => {
|
|
200
|
+
switch (event) {
|
|
201
|
+
case 'pendingLanguage':
|
|
202
|
+
return onPendingLanguageChange.listen(handler);
|
|
203
|
+
case 'language':
|
|
204
|
+
return onLanguageChange.listen(handler);
|
|
205
|
+
case 'loading':
|
|
206
|
+
return onLoadingChange.listen(handler);
|
|
207
|
+
case 'fetching':
|
|
208
|
+
return onFetchingChange.listen(handler);
|
|
209
|
+
case 'initialLoad':
|
|
210
|
+
return onInitialLoaded.listen(handler);
|
|
211
|
+
case 'running':
|
|
212
|
+
return onRunningChange.listen(handler);
|
|
213
|
+
case 'cache':
|
|
214
|
+
return onCacheChange.listen(handler);
|
|
215
|
+
case 'keyUpdate':
|
|
216
|
+
return onKeyUpdate.listen(handler);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
return Object.freeze({
|
|
220
|
+
onPendingLanguageChange,
|
|
221
|
+
onLanguageChange,
|
|
222
|
+
onKeyChange,
|
|
223
|
+
onKeyUpdate,
|
|
224
|
+
onLoadingChange,
|
|
225
|
+
onFetchingChange,
|
|
226
|
+
onInitialLoaded,
|
|
227
|
+
onRunningChange,
|
|
228
|
+
onCacheChange,
|
|
229
|
+
on,
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const flattenTranslations = (data) => {
|
|
234
|
+
const result = new Map();
|
|
235
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
236
|
+
// ignore empty values
|
|
237
|
+
if (value === undefined || value === null) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (typeof value === 'object') {
|
|
241
|
+
flattenTranslations(value).forEach((flatValue, flatKey) => {
|
|
242
|
+
result.set(key + '.' + flatKey, flatValue);
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
result.set(key, value);
|
|
247
|
+
});
|
|
248
|
+
return result;
|
|
249
|
+
};
|
|
250
|
+
const decodeCacheKey = (key) => {
|
|
251
|
+
const [firstPart, secondPart] = key.split(':');
|
|
252
|
+
return { language: firstPart, namespace: secondPart || '' };
|
|
253
|
+
};
|
|
254
|
+
const encodeCacheKey = ({ language, namespace, }) => {
|
|
255
|
+
if (namespace) {
|
|
256
|
+
return `${language}:${namespace}`;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
return language;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const Cache = (onCacheChange, backendGetRecord, backendGetDevRecord, withDefaultNs, isInitialLoading, fetchingObserver, loadingObserver) => {
|
|
264
|
+
const asyncRequests = new Map();
|
|
265
|
+
const cache = new Map();
|
|
266
|
+
let staticData = {};
|
|
267
|
+
let version = 0;
|
|
268
|
+
function addStaticData(data) {
|
|
269
|
+
if (data) {
|
|
270
|
+
staticData = Object.assign(Object.assign({}, staticData), data);
|
|
271
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
272
|
+
if (typeof value !== 'function') {
|
|
273
|
+
const descriptor = decodeCacheKey(key);
|
|
274
|
+
const existing = cache.get(key);
|
|
275
|
+
if (!existing || existing.version === 0) {
|
|
276
|
+
addRecordInternal(descriptor, value, 0);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function invalidate() {
|
|
283
|
+
asyncRequests.clear();
|
|
284
|
+
version += 1;
|
|
285
|
+
}
|
|
286
|
+
function addRecordInternal(descriptor, data, recordVersion) {
|
|
287
|
+
const cacheKey = encodeCacheKey(descriptor);
|
|
288
|
+
cache.set(cacheKey, {
|
|
289
|
+
data: flattenTranslations(data),
|
|
290
|
+
version: recordVersion,
|
|
291
|
+
});
|
|
292
|
+
onCacheChange.emit(descriptor);
|
|
293
|
+
}
|
|
294
|
+
function addRecord(descriptor, data) {
|
|
295
|
+
addRecordInternal(descriptor, data, version);
|
|
296
|
+
}
|
|
297
|
+
function exists(descriptor, strict = false) {
|
|
298
|
+
const record = cache.get(encodeCacheKey(descriptor));
|
|
299
|
+
if (record && strict) {
|
|
300
|
+
return record.version === version;
|
|
301
|
+
}
|
|
302
|
+
return Boolean(record);
|
|
303
|
+
}
|
|
304
|
+
function getRecord(descriptor) {
|
|
305
|
+
var _a;
|
|
306
|
+
return (_a = cache.get(encodeCacheKey(withDefaultNs(descriptor)))) === null || _a === void 0 ? void 0 : _a.data;
|
|
307
|
+
}
|
|
308
|
+
function getTranslation(descriptor, key) {
|
|
309
|
+
var _a;
|
|
310
|
+
return (_a = cache.get(encodeCacheKey(descriptor))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
311
|
+
}
|
|
312
|
+
function getTranslationNs(namespaces, languages, key) {
|
|
313
|
+
var _a;
|
|
314
|
+
for (const namespace of namespaces) {
|
|
315
|
+
for (const language of languages) {
|
|
316
|
+
const value = (_a = cache
|
|
317
|
+
.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
318
|
+
if (value !== undefined && value !== null) {
|
|
319
|
+
return namespace;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return Array.from(new Set(namespaces));
|
|
324
|
+
}
|
|
325
|
+
function getTranslationFallback(namespaces, languages, key) {
|
|
326
|
+
var _a;
|
|
327
|
+
for (const namespace of namespaces) {
|
|
328
|
+
for (const language of languages) {
|
|
329
|
+
const value = (_a = cache
|
|
330
|
+
.get(encodeCacheKey({ language, namespace }))) === null || _a === void 0 ? void 0 : _a.data.get(key);
|
|
331
|
+
if (value !== undefined && value !== null) {
|
|
332
|
+
return value;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
function changeTranslation(descriptor, key, value) {
|
|
339
|
+
var _a;
|
|
340
|
+
const record = (_a = cache.get(encodeCacheKey(descriptor))) === null || _a === void 0 ? void 0 : _a.data;
|
|
341
|
+
record === null || record === void 0 ? void 0 : record.set(key, value);
|
|
342
|
+
onCacheChange.emit(Object.assign(Object.assign({}, descriptor), { key }));
|
|
343
|
+
}
|
|
344
|
+
function isFetching(ns) {
|
|
345
|
+
if (isInitialLoading()) {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
if (ns === undefined) {
|
|
349
|
+
return asyncRequests.size > 0;
|
|
350
|
+
}
|
|
351
|
+
const namespaces = getFallbackArray(ns);
|
|
352
|
+
return Boolean(Array.from(asyncRequests.keys()).find((key) => namespaces.includes(decodeCacheKey(key).namespace)));
|
|
353
|
+
}
|
|
354
|
+
function isLoading(language, ns) {
|
|
355
|
+
const namespaces = getFallbackArray(ns);
|
|
356
|
+
return Boolean(isInitialLoading() ||
|
|
357
|
+
Array.from(asyncRequests.keys()).find((key) => {
|
|
358
|
+
const descriptor = decodeCacheKey(key);
|
|
359
|
+
return ((!namespaces.length || namespaces.includes(descriptor.namespace)) &&
|
|
360
|
+
!exists({
|
|
361
|
+
namespace: descriptor.namespace,
|
|
362
|
+
language: language,
|
|
363
|
+
}));
|
|
364
|
+
}));
|
|
365
|
+
}
|
|
366
|
+
function fetchNormal(keyObject) {
|
|
367
|
+
let dataPromise = undefined;
|
|
368
|
+
if (!dataPromise) {
|
|
369
|
+
const staticDataValue = staticData[encodeCacheKey(keyObject)];
|
|
370
|
+
if (typeof staticDataValue === 'function') {
|
|
371
|
+
dataPromise = staticDataValue();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (!dataPromise) {
|
|
375
|
+
dataPromise = backendGetRecord(keyObject);
|
|
376
|
+
}
|
|
377
|
+
if (!dataPromise) {
|
|
378
|
+
// return current data or empty object
|
|
379
|
+
dataPromise = Promise.resolve(cache.get(encodeCacheKey(keyObject)) || {});
|
|
380
|
+
}
|
|
381
|
+
return dataPromise;
|
|
382
|
+
}
|
|
383
|
+
function fetchData(keyObject, isDev) {
|
|
384
|
+
var _a;
|
|
385
|
+
let dataPromise = undefined;
|
|
386
|
+
if (isDev) {
|
|
387
|
+
dataPromise = (_a = backendGetDevRecord(keyObject)) === null || _a === void 0 ? void 0 : _a.catch(() => {
|
|
388
|
+
// eslint-disable-next-line no-console
|
|
389
|
+
console.warn(`Tolgee: Failed to fetch data from dev backend`);
|
|
390
|
+
// fallback to normal fetch if dev fails
|
|
391
|
+
return fetchNormal(keyObject);
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
if (!dataPromise) {
|
|
395
|
+
dataPromise = fetchNormal(keyObject);
|
|
396
|
+
}
|
|
397
|
+
return dataPromise;
|
|
398
|
+
}
|
|
399
|
+
async function loadRecords(descriptors, isDev) {
|
|
400
|
+
const withPromises = descriptors.map((descriptor) => {
|
|
401
|
+
const keyObject = withDefaultNs(descriptor);
|
|
402
|
+
const cacheKey = encodeCacheKey(keyObject);
|
|
403
|
+
const existingPromise = asyncRequests.get(cacheKey);
|
|
404
|
+
if (existingPromise) {
|
|
405
|
+
return {
|
|
406
|
+
new: false,
|
|
407
|
+
promise: existingPromise,
|
|
408
|
+
keyObject,
|
|
409
|
+
cacheKey,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
const dataPromise = fetchData(keyObject, isDev);
|
|
413
|
+
asyncRequests.set(cacheKey, dataPromise);
|
|
414
|
+
return {
|
|
415
|
+
new: true,
|
|
416
|
+
promise: dataPromise,
|
|
417
|
+
keyObject,
|
|
418
|
+
cacheKey,
|
|
419
|
+
};
|
|
420
|
+
});
|
|
421
|
+
fetchingObserver.notify();
|
|
422
|
+
loadingObserver.notify();
|
|
423
|
+
const results = await Promise.all(withPromises.map((val) => val.promise));
|
|
424
|
+
withPromises.forEach((value, i) => {
|
|
425
|
+
const promiseChanged = asyncRequests.get(value.cacheKey) !== value.promise;
|
|
426
|
+
// if promise has changed in between, it means cache been invalidated or
|
|
427
|
+
// new data are being fetched
|
|
428
|
+
if (value.new && !promiseChanged) {
|
|
429
|
+
asyncRequests.delete(value.cacheKey);
|
|
430
|
+
const data = results[i];
|
|
431
|
+
if (data) {
|
|
432
|
+
addRecord(value.keyObject, data);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
fetchingObserver.notify();
|
|
437
|
+
loadingObserver.notify();
|
|
438
|
+
return withPromises.map((val) => getRecord(val.keyObject));
|
|
439
|
+
}
|
|
440
|
+
function getAllRecords() {
|
|
441
|
+
const entries = Array.from(cache.entries());
|
|
442
|
+
return entries.map(([key, entry]) => {
|
|
443
|
+
return Object.assign(Object.assign({}, decodeCacheKey(key)), { data: entry.data });
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
return Object.freeze({
|
|
447
|
+
addStaticData,
|
|
448
|
+
invalidate,
|
|
449
|
+
addRecord,
|
|
450
|
+
exists,
|
|
451
|
+
getRecord,
|
|
452
|
+
getTranslation,
|
|
453
|
+
getTranslationNs,
|
|
454
|
+
getTranslationFallback,
|
|
455
|
+
changeTranslation,
|
|
456
|
+
isFetching,
|
|
457
|
+
isLoading,
|
|
458
|
+
loadRecords,
|
|
459
|
+
getAllRecords,
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
function isPromise(value) {
|
|
464
|
+
return Boolean(value && typeof value.then === 'function');
|
|
465
|
+
}
|
|
466
|
+
const valueOrPromise = (value, callback) => {
|
|
467
|
+
if (isPromise(value)) {
|
|
468
|
+
return Promise.resolve(value).then(callback);
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
return callback(value);
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
const missingOptionError = (option) => `Tolgee: You need to specify '${option}' option`;
|
|
475
|
+
|
|
476
|
+
const PluginService = (getLanguage, getInitialOptions, getObserverOptions, getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation) => {
|
|
477
|
+
const plugins = {
|
|
478
|
+
ui: undefined,
|
|
479
|
+
observer: undefined,
|
|
480
|
+
};
|
|
481
|
+
const instances = {
|
|
482
|
+
formatters: [],
|
|
483
|
+
finalFormatter: undefined,
|
|
484
|
+
observer: undefined,
|
|
485
|
+
devBackend: undefined,
|
|
486
|
+
backends: [],
|
|
487
|
+
ui: undefined,
|
|
488
|
+
languageDetector: undefined,
|
|
489
|
+
languageStorage: undefined,
|
|
490
|
+
};
|
|
491
|
+
const onClick = async (event, { keysAndDefaults }) => {
|
|
492
|
+
var _a;
|
|
493
|
+
const withNs = keysAndDefaults.map(({ key, ns, defaultValue }) => ({
|
|
494
|
+
key,
|
|
495
|
+
defaultValue,
|
|
496
|
+
ns: getFallbackArray(getTranslationNs({ key, ns, defaultValue })),
|
|
497
|
+
translation: getTranslation({
|
|
498
|
+
key,
|
|
499
|
+
ns,
|
|
500
|
+
}),
|
|
501
|
+
}));
|
|
502
|
+
(_a = instances.ui) === null || _a === void 0 ? void 0 : _a.handleElementClick(event, withNs);
|
|
503
|
+
};
|
|
504
|
+
const run = (isDev) => {
|
|
505
|
+
var _a, _b;
|
|
506
|
+
if (!instances.ui && plugins.ui) {
|
|
507
|
+
instances.ui = new plugins.ui({
|
|
508
|
+
apiKey: getInitialOptions().apiKey,
|
|
509
|
+
apiUrl: getInitialOptions().apiUrl,
|
|
510
|
+
highlight,
|
|
511
|
+
changeTranslation,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
if (!instances.observer) {
|
|
515
|
+
instances.observer = (_a = plugins.observer) === null || _a === void 0 ? void 0 : _a.call(plugins, {
|
|
516
|
+
translate,
|
|
517
|
+
onClick,
|
|
518
|
+
options: getObserverOptions(),
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
(_b = instances.observer) === null || _b === void 0 ? void 0 : _b.run({ mouseHighlight: isDev });
|
|
522
|
+
};
|
|
523
|
+
const stop = () => {
|
|
524
|
+
var _a;
|
|
525
|
+
instances.ui = undefined;
|
|
526
|
+
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.stop();
|
|
527
|
+
};
|
|
528
|
+
const highlight = (key, ns) => {
|
|
529
|
+
var _a, _b;
|
|
530
|
+
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
|
+
};
|
|
532
|
+
const translate = (props) => {
|
|
533
|
+
const translation = getTranslation(props);
|
|
534
|
+
return formatTranslation(Object.assign(Object.assign({}, props), { translation, formatEnabled: true }));
|
|
535
|
+
};
|
|
536
|
+
const setObserver = (observer) => {
|
|
537
|
+
plugins.observer = observer;
|
|
538
|
+
};
|
|
539
|
+
const hasObserver = () => {
|
|
540
|
+
return Boolean(plugins.observer);
|
|
541
|
+
};
|
|
542
|
+
const addFormatter = (formatter) => {
|
|
543
|
+
if (formatter) {
|
|
544
|
+
instances.formatters.push(formatter);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
const setFinalFormatter = (formatter) => {
|
|
548
|
+
instances.finalFormatter = formatter;
|
|
549
|
+
};
|
|
550
|
+
const setUi = (ui) => {
|
|
551
|
+
plugins.ui = (ui === null || ui === void 0 ? void 0 : ui.UI) || ui;
|
|
552
|
+
};
|
|
553
|
+
const hasUi = () => {
|
|
554
|
+
return Boolean(plugins.ui);
|
|
555
|
+
};
|
|
556
|
+
const setLanguageStorage = (storage) => {
|
|
557
|
+
instances.languageStorage = storage;
|
|
558
|
+
};
|
|
559
|
+
const getLanguageStorage = () => {
|
|
560
|
+
return instances.languageStorage;
|
|
561
|
+
};
|
|
562
|
+
const setStoredLanguage = (language) => {
|
|
563
|
+
var _a;
|
|
564
|
+
(_a = instances.languageStorage) === null || _a === void 0 ? void 0 : _a.setLanguage(language);
|
|
565
|
+
};
|
|
566
|
+
const setLanguageDetector = (detector) => {
|
|
567
|
+
instances.languageDetector = detector;
|
|
568
|
+
};
|
|
569
|
+
const getLanguageDetector = () => {
|
|
570
|
+
return instances.languageDetector;
|
|
571
|
+
};
|
|
572
|
+
const detectLanguage = () => {
|
|
573
|
+
if (!instances.languageDetector) {
|
|
574
|
+
return undefined;
|
|
575
|
+
}
|
|
576
|
+
const availableLanguages = getAvailableLanguages();
|
|
577
|
+
return instances.languageDetector.getLanguage({
|
|
578
|
+
availableLanguages,
|
|
579
|
+
});
|
|
580
|
+
};
|
|
581
|
+
const getInitialLanguage = () => {
|
|
582
|
+
var _a;
|
|
583
|
+
const availableLanguages = getAvailableLanguages();
|
|
584
|
+
const languageOrPromise = (_a = instances.languageStorage) === null || _a === void 0 ? void 0 : _a.getLanguage();
|
|
585
|
+
return valueOrPromise(languageOrPromise, (language) => {
|
|
586
|
+
if ((!availableLanguages || availableLanguages.includes(language)) &&
|
|
587
|
+
language) {
|
|
588
|
+
return language;
|
|
589
|
+
}
|
|
590
|
+
return detectLanguage();
|
|
591
|
+
});
|
|
592
|
+
};
|
|
593
|
+
const addBackend = (backend) => {
|
|
594
|
+
if (backend) {
|
|
595
|
+
instances.backends.push(backend);
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
const setDevBackend = (backend) => {
|
|
599
|
+
instances.devBackend = backend;
|
|
600
|
+
};
|
|
601
|
+
const getDevBackend = () => {
|
|
602
|
+
return instances.devBackend;
|
|
603
|
+
};
|
|
604
|
+
const getBackendDevRecord = ({ language, namespace }) => {
|
|
605
|
+
var _a;
|
|
606
|
+
return (_a = instances.devBackend) === null || _a === void 0 ? void 0 : _a.getRecord({
|
|
607
|
+
apiKey: getInitialOptions().apiKey,
|
|
608
|
+
apiUrl: getInitialOptions().apiUrl,
|
|
609
|
+
language,
|
|
610
|
+
namespace,
|
|
611
|
+
});
|
|
612
|
+
};
|
|
613
|
+
const getBackendRecord = ({ language, namespace }) => {
|
|
614
|
+
for (const backend of instances.backends) {
|
|
615
|
+
const data = backend.getRecord({ language, namespace });
|
|
616
|
+
if (isPromise(data)) {
|
|
617
|
+
return data === null || data === void 0 ? void 0 : data.catch((e) => {
|
|
618
|
+
// eslint-disable-next-line no-console
|
|
619
|
+
console.error(e);
|
|
620
|
+
return {};
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
if (data !== undefined) {
|
|
624
|
+
return data;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return undefined;
|
|
628
|
+
};
|
|
629
|
+
const formatTranslation = ({ key, translation, defaultValue, noWrap, params, orEmpty, ns, formatEnabled, }) => {
|
|
630
|
+
var _a;
|
|
631
|
+
const formattableTranslation = translation || defaultValue;
|
|
632
|
+
let result = formattableTranslation || (orEmpty ? '' : key);
|
|
633
|
+
if (instances.observer && !noWrap) {
|
|
634
|
+
result = instances.observer.wrap({
|
|
635
|
+
key,
|
|
636
|
+
translation: result,
|
|
637
|
+
defaultValue,
|
|
638
|
+
params,
|
|
639
|
+
ns,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
const language = getLanguage();
|
|
643
|
+
const isFormatEnabled = formatEnabled || !((_a = instances.observer) === null || _a === void 0 ? void 0 : _a.outputNotFormattable);
|
|
644
|
+
if (formattableTranslation && language && isFormatEnabled) {
|
|
645
|
+
for (const formatter of instances.formatters) {
|
|
646
|
+
result = formatter.format({
|
|
647
|
+
translation: result,
|
|
648
|
+
language,
|
|
649
|
+
params,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if (instances.finalFormatter &&
|
|
654
|
+
formattableTranslation &&
|
|
655
|
+
language &&
|
|
656
|
+
isFormatEnabled) {
|
|
657
|
+
result = instances.finalFormatter.format({
|
|
658
|
+
translation: result,
|
|
659
|
+
language,
|
|
660
|
+
params,
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
return result;
|
|
664
|
+
};
|
|
665
|
+
const wrap = (params) => {
|
|
666
|
+
var _a;
|
|
667
|
+
if (instances.observer) {
|
|
668
|
+
return (_a = instances.observer) === null || _a === void 0 ? void 0 : _a.wrap(params);
|
|
669
|
+
}
|
|
670
|
+
return params.translation;
|
|
671
|
+
};
|
|
672
|
+
const unwrap = (text) => {
|
|
673
|
+
var _a;
|
|
674
|
+
if (instances.observer) {
|
|
675
|
+
return (_a = instances.observer) === null || _a === void 0 ? void 0 : _a.unwrap(text);
|
|
676
|
+
}
|
|
677
|
+
return { text, keys: [] };
|
|
678
|
+
};
|
|
679
|
+
const retranslate = () => {
|
|
680
|
+
var _a;
|
|
681
|
+
(_a = instances.observer) === null || _a === void 0 ? void 0 : _a.retranslate();
|
|
682
|
+
};
|
|
683
|
+
return Object.freeze({
|
|
684
|
+
setFinalFormatter,
|
|
685
|
+
addFormatter,
|
|
686
|
+
formatTranslation,
|
|
687
|
+
setObserver,
|
|
688
|
+
hasObserver,
|
|
689
|
+
setUi,
|
|
690
|
+
hasUi,
|
|
691
|
+
addBackend,
|
|
692
|
+
setDevBackend,
|
|
693
|
+
getDevBackend,
|
|
694
|
+
getBackendRecord,
|
|
695
|
+
getBackendDevRecord,
|
|
696
|
+
setLanguageDetector,
|
|
697
|
+
getLanguageDetector,
|
|
698
|
+
setLanguageStorage,
|
|
699
|
+
getLanguageStorage,
|
|
700
|
+
getInitialLanguage,
|
|
701
|
+
setStoredLanguage,
|
|
702
|
+
run,
|
|
703
|
+
stop,
|
|
704
|
+
retranslate,
|
|
705
|
+
highlight,
|
|
706
|
+
wrap,
|
|
707
|
+
unwrap,
|
|
708
|
+
});
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
const ValueObserver = (initialValue, valueGetter, handler) => {
|
|
712
|
+
let previousValue = initialValue;
|
|
713
|
+
function init(value) {
|
|
714
|
+
previousValue = value;
|
|
715
|
+
}
|
|
716
|
+
function notify() {
|
|
717
|
+
const value = valueGetter();
|
|
718
|
+
if (previousValue !== value) {
|
|
719
|
+
handler(value);
|
|
720
|
+
}
|
|
721
|
+
previousValue = value;
|
|
722
|
+
}
|
|
723
|
+
return Object.freeze({
|
|
724
|
+
init,
|
|
725
|
+
notify,
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
const defaultValues$1 = {
|
|
730
|
+
tagAttributes: {
|
|
731
|
+
textarea: ['placeholder'],
|
|
732
|
+
input: ['value', 'placeholder'],
|
|
733
|
+
img: ['alt'],
|
|
734
|
+
'*': ['aria-label', 'title'],
|
|
735
|
+
},
|
|
736
|
+
restrictedElements: ['script', 'style'],
|
|
737
|
+
highlightKeys: ['Alt'],
|
|
738
|
+
highlightColor: 'rgb(255, 0, 0)',
|
|
739
|
+
highlightWidth: 5,
|
|
740
|
+
inputPrefix: '%-%tolgee:',
|
|
741
|
+
inputSuffix: '%-%',
|
|
742
|
+
passToParent: ['option', 'optgroup'],
|
|
743
|
+
};
|
|
744
|
+
const initObserverOptions = (options) => {
|
|
745
|
+
return Object.assign(Object.assign({}, defaultValues$1), options);
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
const defaultValues = {
|
|
749
|
+
defaultNs: '',
|
|
750
|
+
};
|
|
751
|
+
const initState = (options, previousState) => {
|
|
752
|
+
const initialOptions = Object.assign(Object.assign(Object.assign({}, defaultValues), previousState === null || previousState === void 0 ? void 0 : previousState.initialOptions), options);
|
|
753
|
+
// remove extra '/' from url end
|
|
754
|
+
const apiUrl = initialOptions.apiUrl;
|
|
755
|
+
initialOptions.apiUrl = apiUrl ? apiUrl.replace(/\/+$/, '') : apiUrl;
|
|
756
|
+
return {
|
|
757
|
+
initialOptions,
|
|
758
|
+
activeNamespaces: (previousState === null || previousState === void 0 ? void 0 : previousState.activeNamespaces) || new Map(),
|
|
759
|
+
language: previousState === null || previousState === void 0 ? void 0 : previousState.language,
|
|
760
|
+
pendingLanguage: previousState === null || previousState === void 0 ? void 0 : previousState.language,
|
|
761
|
+
isInitialLoading: false,
|
|
762
|
+
isRunning: false,
|
|
763
|
+
};
|
|
764
|
+
};
|
|
765
|
+
|
|
766
|
+
const State = (onLanguageChange, onPendingLanguageChange, onRunningChange) => {
|
|
767
|
+
let state = initState();
|
|
768
|
+
let observerOptions = initObserverOptions();
|
|
769
|
+
let devCredentials = undefined;
|
|
770
|
+
function init(options) {
|
|
771
|
+
state = initState(options, state);
|
|
772
|
+
}
|
|
773
|
+
function isRunning() {
|
|
774
|
+
return state.isRunning;
|
|
775
|
+
}
|
|
776
|
+
function setRunning(value) {
|
|
777
|
+
if (state.isRunning !== value) {
|
|
778
|
+
state.isRunning = value;
|
|
779
|
+
onRunningChange.emit(value);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
function isInitialLoading() {
|
|
783
|
+
return state.isInitialLoading;
|
|
784
|
+
}
|
|
785
|
+
function setInitialLoading(value) {
|
|
786
|
+
state.isInitialLoading = value;
|
|
787
|
+
}
|
|
788
|
+
function getLanguage() {
|
|
789
|
+
return state.language || state.initialOptions.language;
|
|
790
|
+
}
|
|
791
|
+
function setLanguage(language) {
|
|
792
|
+
if (state.language !== language) {
|
|
793
|
+
state.language = language;
|
|
794
|
+
onLanguageChange.emit(language);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
function getPendingLanguage() {
|
|
798
|
+
return state.pendingLanguage || getLanguage();
|
|
799
|
+
}
|
|
800
|
+
function setPendingLanguage(language) {
|
|
801
|
+
if (state.pendingLanguage !== language) {
|
|
802
|
+
state.pendingLanguage = language;
|
|
803
|
+
onPendingLanguageChange.emit(language);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function getInitialOptions() {
|
|
807
|
+
return Object.assign(Object.assign({}, state.initialOptions), devCredentials);
|
|
808
|
+
}
|
|
809
|
+
function addActiveNs(ns) {
|
|
810
|
+
const namespaces = getFallbackArray(ns);
|
|
811
|
+
namespaces.forEach((namespace) => {
|
|
812
|
+
const value = state.activeNamespaces.get(namespace);
|
|
813
|
+
if (value !== undefined) {
|
|
814
|
+
state.activeNamespaces.set(namespace, value + 1);
|
|
815
|
+
}
|
|
816
|
+
else {
|
|
817
|
+
state.activeNamespaces.set(namespace, 1);
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
function removeActiveNs(ns) {
|
|
822
|
+
const namespaces = getFallbackArray(ns);
|
|
823
|
+
namespaces.forEach((namespace) => {
|
|
824
|
+
const value = state.activeNamespaces.get(namespace);
|
|
825
|
+
if (value !== undefined && value > 1) {
|
|
826
|
+
state.activeNamespaces.set(namespace, value - 1);
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
state.activeNamespaces.delete(namespace);
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
function getRequiredNamespaces() {
|
|
834
|
+
return unique([
|
|
835
|
+
...(state.initialOptions.ns || [state.initialOptions.defaultNs]),
|
|
836
|
+
...state.activeNamespaces.keys(),
|
|
837
|
+
]);
|
|
838
|
+
}
|
|
839
|
+
function getFallbackLangs(lang) {
|
|
840
|
+
const language = lang || getLanguage();
|
|
841
|
+
if (!language) {
|
|
842
|
+
return [];
|
|
843
|
+
}
|
|
844
|
+
return unique([
|
|
845
|
+
language,
|
|
846
|
+
...getFallbackFromStruct(language, state.initialOptions.fallbackLanguage),
|
|
847
|
+
]);
|
|
848
|
+
}
|
|
849
|
+
function getFallbackNamespaces() {
|
|
850
|
+
const defaultNs = state.initialOptions.defaultNs;
|
|
851
|
+
const fallbackNs = state.initialOptions.fallbackNs;
|
|
852
|
+
const fallbackNamespaces = typeof defaultNs === 'string' ? [defaultNs] : [];
|
|
853
|
+
return unique([...fallbackNamespaces, ...getFallbackArray(fallbackNs)]);
|
|
854
|
+
}
|
|
855
|
+
function getAvailableLanguages() {
|
|
856
|
+
if (state.initialOptions.availableLanguages) {
|
|
857
|
+
return state.initialOptions.availableLanguages;
|
|
858
|
+
}
|
|
859
|
+
else if (state.initialOptions.staticData) {
|
|
860
|
+
const languagesFromStaticData = Object.keys(state.initialOptions.staticData).map((key) => decodeCacheKey(key).language);
|
|
861
|
+
return Array.from(new Set(languagesFromStaticData));
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
function withDefaultNs(descriptor) {
|
|
865
|
+
return {
|
|
866
|
+
namespace: descriptor.namespace === undefined
|
|
867
|
+
? getInitialOptions().defaultNs
|
|
868
|
+
: descriptor.namespace,
|
|
869
|
+
language: descriptor.language,
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
function overrideCredentials(credentials) {
|
|
873
|
+
devCredentials = credentials;
|
|
874
|
+
}
|
|
875
|
+
function setObserverOptions(options) {
|
|
876
|
+
observerOptions = initObserverOptions(options);
|
|
877
|
+
}
|
|
878
|
+
function getObserverOptions() {
|
|
879
|
+
return observerOptions;
|
|
880
|
+
}
|
|
881
|
+
return Object.freeze({
|
|
882
|
+
init,
|
|
883
|
+
isRunning,
|
|
884
|
+
setRunning,
|
|
885
|
+
isInitialLoading,
|
|
886
|
+
setInitialLoading,
|
|
887
|
+
getLanguage,
|
|
888
|
+
setLanguage,
|
|
889
|
+
getPendingLanguage,
|
|
890
|
+
setPendingLanguage,
|
|
891
|
+
getInitialOptions,
|
|
892
|
+
addActiveNs,
|
|
893
|
+
removeActiveNs,
|
|
894
|
+
getRequiredNamespaces,
|
|
895
|
+
getFallbackLangs,
|
|
896
|
+
getFallbackNamespaces,
|
|
897
|
+
getAvailableLanguages,
|
|
898
|
+
withDefaultNs,
|
|
899
|
+
overrideCredentials,
|
|
900
|
+
setObserverOptions,
|
|
901
|
+
getObserverOptions,
|
|
902
|
+
});
|
|
903
|
+
};
|
|
904
|
+
|
|
905
|
+
/******************************************************************************
|
|
906
|
+
Copyright (c) Microsoft Corporation.
|
|
907
|
+
|
|
908
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
909
|
+
purpose with or without fee is hereby granted.
|
|
910
|
+
|
|
911
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
912
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
913
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
914
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
915
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
916
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
917
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
918
|
+
***************************************************************************** */
|
|
919
|
+
|
|
920
|
+
function __rest(s, e) {
|
|
921
|
+
var t = {};
|
|
922
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
923
|
+
t[p] = s[p];
|
|
924
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
925
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
926
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
927
|
+
t[p[i]] = s[p[i]];
|
|
928
|
+
}
|
|
929
|
+
return t;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
function parseCombinedOptions(_a) {
|
|
933
|
+
var { ns, noWrap, orEmpty, params } = _a, rest = __rest(_a, ["ns", "noWrap", "orEmpty", "params"]);
|
|
934
|
+
const options = {
|
|
935
|
+
ns: ns,
|
|
936
|
+
noWrap: noWrap,
|
|
937
|
+
orEmpty: orEmpty,
|
|
938
|
+
params: Object.assign(Object.assign({}, rest), params),
|
|
939
|
+
};
|
|
940
|
+
return options;
|
|
941
|
+
}
|
|
942
|
+
const getTranslateParams = (keyOrProps, ...params) => {
|
|
943
|
+
let result = {};
|
|
944
|
+
let options;
|
|
945
|
+
if (typeof keyOrProps === 'object') {
|
|
946
|
+
result = keyOrProps;
|
|
947
|
+
}
|
|
948
|
+
else {
|
|
949
|
+
result.key = keyOrProps;
|
|
950
|
+
if (typeof params[0] === 'string') {
|
|
951
|
+
result.defaultValue = params[0];
|
|
952
|
+
options = params[1];
|
|
953
|
+
}
|
|
954
|
+
else if (typeof params[0] === 'object') {
|
|
955
|
+
options = params[0];
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
if (options) {
|
|
959
|
+
result = Object.assign(Object.assign({}, parseCombinedOptions(options)), result);
|
|
960
|
+
}
|
|
961
|
+
return result;
|
|
962
|
+
};
|
|
963
|
+
|
|
964
|
+
const Controller = ({ options }) => {
|
|
965
|
+
const events = Events(getFallbackNamespaces);
|
|
966
|
+
const fetchingObserver = ValueObserver(false, () => cache.isFetching(), events.onFetchingChange.emit);
|
|
967
|
+
const loadingObserver = ValueObserver(false, () => isLoading(), events.onLoadingChange.emit);
|
|
968
|
+
const state = State(events.onLanguageChange, events.onPendingLanguageChange, events.onRunningChange);
|
|
969
|
+
const pluginService = PluginService(state.getLanguage, state.getInitialOptions, state.getObserverOptions, state.getAvailableLanguages, getTranslationNs, getTranslation, changeTranslation);
|
|
970
|
+
const cache = Cache(events.onCacheChange, pluginService.getBackendRecord, pluginService.getBackendDevRecord, state.withDefaultNs, state.isInitialLoading, fetchingObserver, loadingObserver);
|
|
971
|
+
if (options) {
|
|
972
|
+
init(options);
|
|
973
|
+
}
|
|
974
|
+
events.onKeyUpdate.listen(() => {
|
|
975
|
+
if (state.isRunning()) {
|
|
976
|
+
pluginService.retranslate();
|
|
977
|
+
}
|
|
978
|
+
});
|
|
979
|
+
function changeTranslation(descriptor, key, value) {
|
|
980
|
+
const keyObject = state.withDefaultNs(descriptor);
|
|
981
|
+
const previousValue = cache.getTranslation(keyObject, key);
|
|
982
|
+
cache.changeTranslation(keyObject, key, value);
|
|
983
|
+
return {
|
|
984
|
+
revert: () => {
|
|
985
|
+
cache.changeTranslation(keyObject, key, previousValue);
|
|
986
|
+
},
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
function getFallbackNamespaces() {
|
|
990
|
+
return state.getFallbackNamespaces();
|
|
991
|
+
}
|
|
992
|
+
function init(options) {
|
|
993
|
+
state.init(options);
|
|
994
|
+
cache.addStaticData(state.getInitialOptions().staticData);
|
|
995
|
+
}
|
|
996
|
+
function isLoading(ns) {
|
|
997
|
+
return cache.isLoading(state.getLanguage(), ns);
|
|
998
|
+
}
|
|
999
|
+
function isDev() {
|
|
1000
|
+
return Boolean(state.getInitialOptions().apiKey &&
|
|
1001
|
+
state.getInitialOptions().apiUrl &&
|
|
1002
|
+
pluginService.getDevBackend());
|
|
1003
|
+
}
|
|
1004
|
+
async function addActiveNs(ns, forget) {
|
|
1005
|
+
if (!forget) {
|
|
1006
|
+
state.addActiveNs(ns);
|
|
1007
|
+
}
|
|
1008
|
+
if (state.isRunning()) {
|
|
1009
|
+
await loadRequiredRecords(undefined, ns);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
function getRequiredRecords(lang, ns) {
|
|
1013
|
+
const languages = state.getFallbackLangs(lang);
|
|
1014
|
+
const namespaces = ns !== undefined ? getFallbackArray(ns) : state.getRequiredNamespaces();
|
|
1015
|
+
const result = [];
|
|
1016
|
+
languages.forEach((language) => {
|
|
1017
|
+
namespaces.forEach((namespace) => {
|
|
1018
|
+
if (!cache.exists({ language, namespace }, true)) {
|
|
1019
|
+
result.push({ language, namespace });
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
return result;
|
|
1024
|
+
}
|
|
1025
|
+
function isLoaded(ns) {
|
|
1026
|
+
const language = state.getLanguage();
|
|
1027
|
+
if (!language) {
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
const languages = state.getFallbackLangs(language);
|
|
1031
|
+
const namespaces = ns !== undefined ? getFallbackArray(ns) : state.getRequiredNamespaces();
|
|
1032
|
+
const result = [];
|
|
1033
|
+
languages.forEach((language) => {
|
|
1034
|
+
namespaces.forEach((namespace) => {
|
|
1035
|
+
if (!cache.exists({ language, namespace })) {
|
|
1036
|
+
result.push({ language, namespace });
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
});
|
|
1040
|
+
return result.length === 0;
|
|
1041
|
+
}
|
|
1042
|
+
function loadRequiredRecords(lang, ns) {
|
|
1043
|
+
const descriptors = getRequiredRecords(lang, ns);
|
|
1044
|
+
if (descriptors.length) {
|
|
1045
|
+
return valueOrPromise(loadRecords(descriptors), () => { });
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
async function changeLanguage(language) {
|
|
1049
|
+
if (state.getPendingLanguage() === language &&
|
|
1050
|
+
state.getLanguage() === language) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
state.setPendingLanguage(language);
|
|
1054
|
+
if (state.isRunning()) {
|
|
1055
|
+
await loadRequiredRecords(language);
|
|
1056
|
+
}
|
|
1057
|
+
if (language === state.getPendingLanguage()) {
|
|
1058
|
+
// there might be parallel language change
|
|
1059
|
+
// we only want to apply latest
|
|
1060
|
+
state.setLanguage(language);
|
|
1061
|
+
pluginService.setStoredLanguage(language);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
function getTranslationNs({ key, ns, }) {
|
|
1065
|
+
const namespaces = ns !== undefined ? getFallbackArray(ns) : state.getFallbackNamespaces();
|
|
1066
|
+
const languages = state.getFallbackLangs();
|
|
1067
|
+
return cache.getTranslationNs(namespaces, languages, key);
|
|
1068
|
+
}
|
|
1069
|
+
function getTranslation({ key, ns, }) {
|
|
1070
|
+
const namespaces = ns !== undefined ? getFallbackArray(ns) : state.getFallbackNamespaces();
|
|
1071
|
+
const languages = state.getFallbackLangs();
|
|
1072
|
+
return cache.getTranslationFallback(namespaces, languages, key);
|
|
1073
|
+
}
|
|
1074
|
+
function loadInitial() {
|
|
1075
|
+
const data = valueOrPromise(initializeLanguage(), () => {
|
|
1076
|
+
// fail if there is no language
|
|
1077
|
+
return loadRequiredRecords();
|
|
1078
|
+
});
|
|
1079
|
+
if (isPromise(data)) {
|
|
1080
|
+
state.setInitialLoading(true);
|
|
1081
|
+
fetchingObserver.notify();
|
|
1082
|
+
loadingObserver.notify();
|
|
1083
|
+
return Promise.resolve(data).then(() => {
|
|
1084
|
+
state.setInitialLoading(false);
|
|
1085
|
+
fetchingObserver.notify();
|
|
1086
|
+
loadingObserver.notify();
|
|
1087
|
+
events.onInitialLoaded.emit();
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
else {
|
|
1091
|
+
events.onInitialLoaded.emit();
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
function initializeLanguage() {
|
|
1095
|
+
const existingLanguage = state.getLanguage();
|
|
1096
|
+
if (existingLanguage) {
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
if (!state.getInitialOptions().defaultLanguage) {
|
|
1100
|
+
throw new Error(missingOptionError('defaultLanguage'));
|
|
1101
|
+
}
|
|
1102
|
+
const languageOrPromise = pluginService.getInitialLanguage();
|
|
1103
|
+
return valueOrPromise(languageOrPromise, (lang) => {
|
|
1104
|
+
const language = lang ||
|
|
1105
|
+
state.getInitialOptions().defaultLanguage;
|
|
1106
|
+
language && state.setLanguage(language);
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
async function loadRecord(descriptor) {
|
|
1110
|
+
return (await loadRecords([descriptor]))[0];
|
|
1111
|
+
}
|
|
1112
|
+
function loadRecords(descriptors) {
|
|
1113
|
+
return cache.loadRecords(descriptors, isDev());
|
|
1114
|
+
}
|
|
1115
|
+
const checkCorrectConfiguration = () => {
|
|
1116
|
+
const languageDetector = pluginService.getLanguageDetector();
|
|
1117
|
+
if (languageDetector) {
|
|
1118
|
+
const availableLanguages = state.getAvailableLanguages();
|
|
1119
|
+
if (!availableLanguages) {
|
|
1120
|
+
throw new Error(missingOptionError('availableLanguages'));
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
if (!state.getLanguage() && !state.getInitialOptions().defaultLanguage) {
|
|
1124
|
+
if (languageDetector) {
|
|
1125
|
+
throw new Error(missingOptionError('defaultLanguage'));
|
|
1126
|
+
}
|
|
1127
|
+
else {
|
|
1128
|
+
throw new Error(missingOptionError('language'));
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
};
|
|
1132
|
+
function run() {
|
|
1133
|
+
let result = undefined;
|
|
1134
|
+
checkCorrectConfiguration();
|
|
1135
|
+
if (!state.isRunning()) {
|
|
1136
|
+
if (isDev()) {
|
|
1137
|
+
cache.invalidate();
|
|
1138
|
+
}
|
|
1139
|
+
state.setRunning(true);
|
|
1140
|
+
pluginService.run(isDev());
|
|
1141
|
+
result = loadInitial();
|
|
1142
|
+
}
|
|
1143
|
+
return Promise.resolve(result);
|
|
1144
|
+
}
|
|
1145
|
+
function stop() {
|
|
1146
|
+
if (state.isRunning()) {
|
|
1147
|
+
pluginService.stop();
|
|
1148
|
+
state.setRunning(false);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
const t = (...args) => {
|
|
1152
|
+
// @ts-ignore
|
|
1153
|
+
const params = getTranslateParams(...args);
|
|
1154
|
+
const translation = getTranslation(params);
|
|
1155
|
+
return pluginService.formatTranslation(Object.assign(Object.assign({}, params), { translation }));
|
|
1156
|
+
};
|
|
1157
|
+
return Object.freeze(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, events), state), pluginService), cache), { init,
|
|
1158
|
+
changeLanguage,
|
|
1159
|
+
getTranslation,
|
|
1160
|
+
changeTranslation,
|
|
1161
|
+
addActiveNs,
|
|
1162
|
+
loadRequiredRecords,
|
|
1163
|
+
loadRecords,
|
|
1164
|
+
loadRecord,
|
|
1165
|
+
isLoading,
|
|
1166
|
+
isLoaded,
|
|
1167
|
+
t,
|
|
1168
|
+
isDev,
|
|
1169
|
+
run,
|
|
1170
|
+
stop }));
|
|
1171
|
+
};
|
|
1172
|
+
|
|
1173
|
+
const Tolgee = (options) => {
|
|
1174
|
+
const controller = Controller({
|
|
1175
|
+
options,
|
|
1176
|
+
});
|
|
1177
|
+
const pluginTools = Object.freeze({
|
|
1178
|
+
setFinalFormatter: controller.setFinalFormatter,
|
|
1179
|
+
addFormatter: controller.addFormatter,
|
|
1180
|
+
setObserver: controller.setObserver,
|
|
1181
|
+
hasObserver: controller.hasObserver,
|
|
1182
|
+
setUi: controller.setUi,
|
|
1183
|
+
hasUi: controller.hasUi,
|
|
1184
|
+
setDevBackend: controller.setDevBackend,
|
|
1185
|
+
addBackend: controller.addBackend,
|
|
1186
|
+
setLanguageDetector: controller.setLanguageDetector,
|
|
1187
|
+
setLanguageStorage: controller.setLanguageStorage,
|
|
1188
|
+
overrideCredentials: controller.overrideCredentials,
|
|
1189
|
+
});
|
|
1190
|
+
const withRestart = (callback) => {
|
|
1191
|
+
const wasRunning = controller.isRunning();
|
|
1192
|
+
wasRunning && controller.stop();
|
|
1193
|
+
callback();
|
|
1194
|
+
wasRunning && controller.run();
|
|
1195
|
+
};
|
|
1196
|
+
const tolgee = Object.freeze({
|
|
1197
|
+
// event listeners
|
|
1198
|
+
on: controller.on,
|
|
1199
|
+
onKeyUpdate: controller.onKeyUpdate.listenSome,
|
|
1200
|
+
// state
|
|
1201
|
+
getLanguage: controller.getLanguage,
|
|
1202
|
+
getPendingLanguage: controller.getPendingLanguage,
|
|
1203
|
+
changeLanguage: controller.changeLanguage,
|
|
1204
|
+
changeTranslation: controller.changeTranslation,
|
|
1205
|
+
addActiveNs: controller.addActiveNs,
|
|
1206
|
+
removeActiveNs: controller.removeActiveNs,
|
|
1207
|
+
loadRecords: controller.loadRecords,
|
|
1208
|
+
loadRecord: controller.loadRecord,
|
|
1209
|
+
addStaticData: controller.addStaticData,
|
|
1210
|
+
getRecord: controller.getRecord,
|
|
1211
|
+
getAllRecords: controller.getAllRecords,
|
|
1212
|
+
isLoaded: controller.isLoaded,
|
|
1213
|
+
isInitialLoading: controller.isInitialLoading,
|
|
1214
|
+
isLoading: controller.isLoading,
|
|
1215
|
+
isFetching: controller.isFetching,
|
|
1216
|
+
isRunning: controller.isRunning,
|
|
1217
|
+
run: controller.run,
|
|
1218
|
+
stop: controller.stop,
|
|
1219
|
+
t: controller.t,
|
|
1220
|
+
highlight: controller.highlight,
|
|
1221
|
+
getInitialOptions: controller.getInitialOptions,
|
|
1222
|
+
isDev: controller.isDev,
|
|
1223
|
+
wrap: controller.wrap,
|
|
1224
|
+
unwrap: controller.unwrap,
|
|
1225
|
+
// plugins
|
|
1226
|
+
setObserverOptions: (options) => {
|
|
1227
|
+
controller.setObserverOptions(options);
|
|
1228
|
+
return tolgee;
|
|
1229
|
+
},
|
|
1230
|
+
use: (plugin) => {
|
|
1231
|
+
if (plugin) {
|
|
1232
|
+
withRestart(() => plugin(tolgee, pluginTools));
|
|
1233
|
+
}
|
|
1234
|
+
return tolgee;
|
|
1235
|
+
},
|
|
1236
|
+
init: (options) => {
|
|
1237
|
+
withRestart(() => controller.init(options));
|
|
1238
|
+
return tolgee;
|
|
1239
|
+
},
|
|
1240
|
+
});
|
|
1241
|
+
return tolgee;
|
|
1242
|
+
};
|
|
1243
|
+
|
|
1244
|
+
const RESTRICTED_ASCENDANT_ATTRIBUTE = 'data-tolgee-restricted';
|
|
1245
|
+
const TOLGEE_ATTRIBUTE_NAME = '_tolgee';
|
|
1246
|
+
const TOLGEE_HIGHLIGHTER_CLASS = '_tolgee-highlighter';
|
|
1247
|
+
const TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE = 'data-tolgee-key-only';
|
|
1248
|
+
|
|
1249
|
+
const ERROR_PARAM_EMPTY = 0, ERROR_UNEXPECTED_CHAR = 1, ERROR_UNEXPECTED_END = 2;
|
|
1250
|
+
class FormatError extends Error {
|
|
1251
|
+
constructor(code, index, text) {
|
|
1252
|
+
let error;
|
|
1253
|
+
if (code === ERROR_PARAM_EMPTY) {
|
|
1254
|
+
error = 'Empty parameter';
|
|
1255
|
+
}
|
|
1256
|
+
else if (code === ERROR_UNEXPECTED_CHAR) {
|
|
1257
|
+
error = 'Unexpected character';
|
|
1258
|
+
}
|
|
1259
|
+
else {
|
|
1260
|
+
error = 'Unexpected end';
|
|
1261
|
+
}
|
|
1262
|
+
super(`Tolgee parser: ${error} at ${index} in "${text}"`);
|
|
1263
|
+
this.code = code;
|
|
1264
|
+
this.index = index;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
function isWhitespace(ch) {
|
|
1269
|
+
return /\s/.test(ch);
|
|
1270
|
+
}
|
|
1271
|
+
const STATE_TEXT = 0, STATE_ESCAPE_MAYBE = 1, STATE_ESCAPE = 2, STATE_PARAM = 3, STATE_PARAM_AFTER = 4;
|
|
1272
|
+
const END_STATES = new Set([
|
|
1273
|
+
STATE_ESCAPE,
|
|
1274
|
+
STATE_ESCAPE_MAYBE,
|
|
1275
|
+
STATE_TEXT,
|
|
1276
|
+
]);
|
|
1277
|
+
const CHAR_ESCAPE = "'";
|
|
1278
|
+
const ESCAPABLE = new Set(['{', '}', CHAR_ESCAPE]);
|
|
1279
|
+
const isAllowedInParam = (char) => {
|
|
1280
|
+
return /[0-9a-zA-Z_]/.test(char);
|
|
1281
|
+
};
|
|
1282
|
+
function formatParser(translation) {
|
|
1283
|
+
let state = STATE_TEXT;
|
|
1284
|
+
let text = '';
|
|
1285
|
+
let param = '';
|
|
1286
|
+
let ch = '';
|
|
1287
|
+
const texts = [];
|
|
1288
|
+
const params = [];
|
|
1289
|
+
let i = 0;
|
|
1290
|
+
function parsingError(code) {
|
|
1291
|
+
throw new FormatError(code, i, translation);
|
|
1292
|
+
}
|
|
1293
|
+
const addText = () => {
|
|
1294
|
+
texts.push(text);
|
|
1295
|
+
text = '';
|
|
1296
|
+
};
|
|
1297
|
+
const addParamChar = () => {
|
|
1298
|
+
if (!isAllowedInParam(ch)) {
|
|
1299
|
+
parsingError(ERROR_UNEXPECTED_CHAR);
|
|
1300
|
+
}
|
|
1301
|
+
param += ch;
|
|
1302
|
+
};
|
|
1303
|
+
const addParam = () => {
|
|
1304
|
+
if (param === '') {
|
|
1305
|
+
parsingError(ERROR_PARAM_EMPTY);
|
|
1306
|
+
}
|
|
1307
|
+
params.push(param);
|
|
1308
|
+
param = '';
|
|
1309
|
+
};
|
|
1310
|
+
for (i = 0; i < translation.length; i++) {
|
|
1311
|
+
ch = translation[i];
|
|
1312
|
+
switch (state) {
|
|
1313
|
+
case STATE_TEXT:
|
|
1314
|
+
if (ch === CHAR_ESCAPE) {
|
|
1315
|
+
text += ch;
|
|
1316
|
+
state = STATE_ESCAPE_MAYBE;
|
|
1317
|
+
}
|
|
1318
|
+
else if (ch === '{') {
|
|
1319
|
+
addText();
|
|
1320
|
+
state = STATE_PARAM;
|
|
1321
|
+
}
|
|
1322
|
+
else {
|
|
1323
|
+
text += ch;
|
|
1324
|
+
state = STATE_TEXT;
|
|
1325
|
+
}
|
|
1326
|
+
break;
|
|
1327
|
+
case STATE_ESCAPE_MAYBE:
|
|
1328
|
+
if (ESCAPABLE.has(ch)) {
|
|
1329
|
+
text = text.slice(0, -1) + ch;
|
|
1330
|
+
state = STATE_ESCAPE;
|
|
1331
|
+
}
|
|
1332
|
+
else {
|
|
1333
|
+
text += ch;
|
|
1334
|
+
state = STATE_TEXT;
|
|
1335
|
+
}
|
|
1336
|
+
break;
|
|
1337
|
+
case STATE_ESCAPE:
|
|
1338
|
+
if (ch === CHAR_ESCAPE) {
|
|
1339
|
+
state = STATE_TEXT;
|
|
1340
|
+
}
|
|
1341
|
+
else {
|
|
1342
|
+
text += ch;
|
|
1343
|
+
state = STATE_ESCAPE;
|
|
1344
|
+
}
|
|
1345
|
+
break;
|
|
1346
|
+
case STATE_PARAM:
|
|
1347
|
+
if (ch === '}') {
|
|
1348
|
+
addParam();
|
|
1349
|
+
state = STATE_TEXT;
|
|
1350
|
+
}
|
|
1351
|
+
else if (!isWhitespace(ch)) {
|
|
1352
|
+
addParamChar();
|
|
1353
|
+
state = STATE_PARAM;
|
|
1354
|
+
}
|
|
1355
|
+
else if (param !== '') {
|
|
1356
|
+
addParam();
|
|
1357
|
+
state = STATE_PARAM_AFTER;
|
|
1358
|
+
}
|
|
1359
|
+
break;
|
|
1360
|
+
case STATE_PARAM_AFTER:
|
|
1361
|
+
if (ch == '}') {
|
|
1362
|
+
state = STATE_TEXT;
|
|
1363
|
+
}
|
|
1364
|
+
else if (isWhitespace(ch)) {
|
|
1365
|
+
state = STATE_PARAM_AFTER;
|
|
1366
|
+
}
|
|
1367
|
+
else {
|
|
1368
|
+
parsingError(ERROR_UNEXPECTED_CHAR);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
if (!END_STATES.has(state)) {
|
|
1373
|
+
parsingError(ERROR_UNEXPECTED_END);
|
|
1374
|
+
}
|
|
1375
|
+
addText();
|
|
1376
|
+
return [texts, params];
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
function formatter(translation, params) {
|
|
1380
|
+
const [texts, pars] = formatParser(translation);
|
|
1381
|
+
const result = [texts[0]];
|
|
1382
|
+
for (let i = 1; i < texts.length; i++) {
|
|
1383
|
+
const parameter = params === null || params === void 0 ? void 0 : params[pars[i - 1]];
|
|
1384
|
+
if (parameter === undefined) {
|
|
1385
|
+
throw new Error(`Missing parameter "${pars[i - 1]}" in "${translation}"`);
|
|
1386
|
+
}
|
|
1387
|
+
result.push(String(parameter));
|
|
1388
|
+
result.push(texts[i]);
|
|
1389
|
+
}
|
|
1390
|
+
return result.join('');
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
function FormatSimpleCreator() {
|
|
1394
|
+
return {
|
|
1395
|
+
format: ({ translation, params }) => formatter(translation, params),
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
const FormatSimple = () => (tolgee, tools) => {
|
|
1399
|
+
tools.setFinalFormatter(FormatSimpleCreator());
|
|
1400
|
+
return tolgee;
|
|
1401
|
+
};
|
|
1402
|
+
|
|
1403
|
+
export { FormatSimple, RESTRICTED_ASCENDANT_ATTRIBUTE, TOLGEE_ATTRIBUTE_NAME, TOLGEE_HIGHLIGHTER_CLASS, TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE, Tolgee, getFallback, getFallbackArray, getTranslateParams };
|
|
1404
|
+
//# sourceMappingURL=tolgee.esm.js.map
|