@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
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { getFallbackArray } from '../../helpers';
|
|
2
|
+
import {
|
|
3
|
+
NsFallback,
|
|
4
|
+
Subscription,
|
|
5
|
+
Listener,
|
|
6
|
+
ListenerEvent,
|
|
7
|
+
SubscriptionSelective,
|
|
8
|
+
NsType,
|
|
9
|
+
} from '../../types';
|
|
10
|
+
|
|
11
|
+
type NsListType = string;
|
|
12
|
+
|
|
13
|
+
type HandlerWrapperType = {
|
|
14
|
+
fn: Listener<undefined>;
|
|
15
|
+
namespaces: Set<string>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const EventEmitterSelective = (
|
|
19
|
+
isActive: () => boolean,
|
|
20
|
+
getFallbackNs: () => string[],
|
|
21
|
+
getDefaultNs: () => string
|
|
22
|
+
): EventEmitterSelectiveInstance => {
|
|
23
|
+
const listeners: Set<Listener<undefined>> = new Set();
|
|
24
|
+
const partialListeners: Set<HandlerWrapperType> = new Set();
|
|
25
|
+
|
|
26
|
+
const listen = (handler: Listener<undefined>) => {
|
|
27
|
+
listeners.add(handler);
|
|
28
|
+
const result = {
|
|
29
|
+
unsubscribe: () => {
|
|
30
|
+
listeners.delete(handler);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const listenSome = (handler: Listener<undefined>) => {
|
|
37
|
+
const handlerWrapper = {
|
|
38
|
+
fn: (e: ListenerEvent<undefined>) => {
|
|
39
|
+
handler(e);
|
|
40
|
+
},
|
|
41
|
+
namespaces: new Set<NsListType>(),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
partialListeners.add(handlerWrapper);
|
|
45
|
+
|
|
46
|
+
const result = {
|
|
47
|
+
unsubscribe: () => {
|
|
48
|
+
partialListeners.delete(handlerWrapper);
|
|
49
|
+
},
|
|
50
|
+
subscribeNs: (ns: NsFallback) => {
|
|
51
|
+
getFallbackArray(ns).forEach((val) =>
|
|
52
|
+
handlerWrapper.namespaces.add(val)
|
|
53
|
+
);
|
|
54
|
+
if (ns === undefined) {
|
|
55
|
+
// subscribing to default ns
|
|
56
|
+
handlerWrapper.namespaces.add(getDefaultNs());
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const callHandlers = (ns: Array<string> | undefined) => {
|
|
66
|
+
// everything is implicitly subscribed to fallbacks
|
|
67
|
+
// as it can always fall through to it
|
|
68
|
+
const fallbackNamespaces = new Set(getFallbackNs());
|
|
69
|
+
|
|
70
|
+
partialListeners.forEach((handler) => {
|
|
71
|
+
const nsMatches =
|
|
72
|
+
ns === undefined ||
|
|
73
|
+
ns?.findIndex(
|
|
74
|
+
(ns) => fallbackNamespaces.has(ns) || handler.namespaces.has(ns!)
|
|
75
|
+
) !== -1;
|
|
76
|
+
|
|
77
|
+
if (nsMatches) {
|
|
78
|
+
handler.fn({ value: undefined as any });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
let queue: (string[] | undefined)[] = [];
|
|
84
|
+
// merge events in queue into one event
|
|
85
|
+
const solveQueue = () => {
|
|
86
|
+
if (queue.length === 0) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const queueCopy = queue;
|
|
90
|
+
queue = [];
|
|
91
|
+
|
|
92
|
+
listeners.forEach((handler) => {
|
|
93
|
+
handler({ value: undefined as any });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
let namespaces: Set<NsType> | undefined = new Set<NsType>();
|
|
97
|
+
|
|
98
|
+
queueCopy.forEach((ns) => {
|
|
99
|
+
if (ns === undefined) {
|
|
100
|
+
// when no ns specified, it affects all namespaces
|
|
101
|
+
namespaces = undefined;
|
|
102
|
+
} else if (namespaces !== undefined) {
|
|
103
|
+
ns.forEach((ns) => namespaces!.add(ns));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const namespacesArray = namespaces
|
|
108
|
+
? Array.from(namespaces.keys())
|
|
109
|
+
: undefined;
|
|
110
|
+
|
|
111
|
+
callHandlers(namespacesArray);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const emit = (ns?: string[], delayed?: boolean) => {
|
|
115
|
+
if (isActive()) {
|
|
116
|
+
queue.push(ns);
|
|
117
|
+
if (!delayed) {
|
|
118
|
+
solveQueue();
|
|
119
|
+
} else {
|
|
120
|
+
setTimeout(solveQueue, 0);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return Object.freeze({ listenSome, listen, emit });
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export type EventEmitterSelectiveInstance = {
|
|
129
|
+
readonly listenSome: (handler: Listener<undefined>) => SubscriptionSelective;
|
|
130
|
+
readonly listen: (handler: Listener<undefined>) => Subscription;
|
|
131
|
+
readonly emit: (ns?: string[], delayed?: boolean) => void;
|
|
132
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { EventEmitter } from './EventEmitter';
|
|
2
|
+
import { EventEmitterSelective } from './EventEmitterSelective';
|
|
3
|
+
import { CacheDescriptorWithKey, TolgeeOn } from '../../types';
|
|
4
|
+
|
|
5
|
+
export const Events = (
|
|
6
|
+
getFallbackNs: () => string[],
|
|
7
|
+
getDefaultNs: () => string
|
|
8
|
+
) => {
|
|
9
|
+
let emitterActive = true;
|
|
10
|
+
|
|
11
|
+
function isActive() {
|
|
12
|
+
return emitterActive;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const onPendingLanguageChange = EventEmitter<string>(isActive);
|
|
16
|
+
const onLanguageChange = EventEmitter<string>(isActive);
|
|
17
|
+
const onLoadingChange = EventEmitter<boolean>(isActive);
|
|
18
|
+
const onFetchingChange = EventEmitter<boolean>(isActive);
|
|
19
|
+
const onInitialLoaded = EventEmitter<void>(isActive);
|
|
20
|
+
const onRunningChange = EventEmitter<boolean>(isActive);
|
|
21
|
+
const onCacheChange = EventEmitter<CacheDescriptorWithKey>(isActive);
|
|
22
|
+
const onUpdate = EventEmitterSelective(isActive, getFallbackNs, getDefaultNs);
|
|
23
|
+
|
|
24
|
+
onInitialLoaded.listen(() => onUpdate.emit());
|
|
25
|
+
onLanguageChange.listen(() => onUpdate.emit());
|
|
26
|
+
onCacheChange.listen(({ value }) => {
|
|
27
|
+
onUpdate.emit([value.namespace], true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const on: TolgeeOn = (event, handler): any => {
|
|
31
|
+
switch (event) {
|
|
32
|
+
case 'pendingLanguage':
|
|
33
|
+
return onPendingLanguageChange.listen(handler as any);
|
|
34
|
+
case 'language':
|
|
35
|
+
return onLanguageChange.listen(handler as any);
|
|
36
|
+
case 'loading':
|
|
37
|
+
return onLoadingChange.listen(handler as any);
|
|
38
|
+
case 'fetching':
|
|
39
|
+
return onFetchingChange.listen(handler as any);
|
|
40
|
+
case 'initialLoad':
|
|
41
|
+
return onInitialLoaded.listen(handler as any);
|
|
42
|
+
case 'running':
|
|
43
|
+
return onRunningChange.listen(handler as any);
|
|
44
|
+
case 'cache':
|
|
45
|
+
return onCacheChange.listen(handler as any);
|
|
46
|
+
case 'update':
|
|
47
|
+
return onUpdate.listen(handler as any);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function setEmmiterActive(active: boolean) {
|
|
52
|
+
emitterActive = active;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return Object.freeze({
|
|
56
|
+
onPendingLanguageChange,
|
|
57
|
+
onLanguageChange,
|
|
58
|
+
onLoadingChange,
|
|
59
|
+
onFetchingChange,
|
|
60
|
+
onInitialLoaded,
|
|
61
|
+
onRunningChange,
|
|
62
|
+
onCacheChange,
|
|
63
|
+
onUpdate,
|
|
64
|
+
setEmmiterActive,
|
|
65
|
+
on,
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type EventsInstance = ReturnType<typeof Events>;
|
|
@@ -1,86 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getErrorMessage, isPromise, valueOrPromise } from '../../helpers';
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
BackendDevMiddleware,
|
|
4
4
|
BackendGetRecord,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
BackendMiddleware,
|
|
6
|
+
FormatterMiddleware,
|
|
7
|
+
ObserverMiddleware,
|
|
8
8
|
TranslatePropsInternal,
|
|
9
9
|
TranslationOnClick,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
UiType,
|
|
13
|
-
FinalFormatterInterface,
|
|
10
|
+
UiMiddleware,
|
|
11
|
+
FinalFormatterMiddleware,
|
|
14
12
|
HighlightInterface,
|
|
15
|
-
UiConstructor,
|
|
16
13
|
UiKeyOption,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Options,
|
|
14
|
+
LanguageDetectorMiddleware,
|
|
15
|
+
LanguageStorageMiddleware,
|
|
20
16
|
ChangeTranslationInterface,
|
|
21
17
|
WrapperWrapProps,
|
|
22
18
|
Unwrapped,
|
|
19
|
+
KeyAndNamespacesInternal,
|
|
20
|
+
TolgeePlugin,
|
|
21
|
+
TolgeeInstance,
|
|
22
|
+
TolgeeOptionsInternal,
|
|
23
|
+
FormatErrorHandler,
|
|
23
24
|
} from '../../types';
|
|
24
|
-
import {
|
|
25
|
+
import { DEFAULT_FORMAT_ERROR } from '../State/initState';
|
|
25
26
|
|
|
26
|
-
export const
|
|
27
|
+
export const Plugins = (
|
|
27
28
|
getLanguage: () => string | undefined,
|
|
28
|
-
getInitialOptions: () =>
|
|
29
|
+
getInitialOptions: () => TolgeeOptionsInternal,
|
|
29
30
|
getAvailableLanguages: () => string[] | undefined,
|
|
30
|
-
getTranslationNs: (props:
|
|
31
|
-
getTranslation: (props:
|
|
31
|
+
getTranslationNs: (props: KeyAndNamespacesInternal) => string[],
|
|
32
|
+
getTranslation: (props: KeyAndNamespacesInternal) => string | undefined,
|
|
32
33
|
changeTranslation: ChangeTranslationInterface
|
|
33
34
|
) => {
|
|
34
35
|
const plugins = {
|
|
35
|
-
ui: undefined as
|
|
36
|
+
ui: undefined as UiMiddleware | undefined,
|
|
37
|
+
observer: undefined as ObserverMiddleware | undefined,
|
|
36
38
|
};
|
|
37
39
|
|
|
38
40
|
const instances = {
|
|
39
|
-
formatters: [] as
|
|
40
|
-
finalFormatter: undefined as
|
|
41
|
-
observer: undefined as ReturnType<
|
|
42
|
-
devBackend: undefined as
|
|
43
|
-
backends: [] as
|
|
44
|
-
ui: undefined as
|
|
45
|
-
languageDetector: undefined as
|
|
46
|
-
languageStorage: undefined as
|
|
41
|
+
formatters: [] as FormatterMiddleware[],
|
|
42
|
+
finalFormatter: undefined as FinalFormatterMiddleware | undefined,
|
|
43
|
+
observer: undefined as ReturnType<ObserverMiddleware> | undefined,
|
|
44
|
+
devBackend: undefined as BackendDevMiddleware | undefined,
|
|
45
|
+
backends: [] as BackendMiddleware[],
|
|
46
|
+
ui: undefined as ReturnType<UiMiddleware> | undefined,
|
|
47
|
+
languageDetector: undefined as LanguageDetectorMiddleware | undefined,
|
|
48
|
+
languageStorage: undefined as LanguageStorageMiddleware | undefined,
|
|
47
49
|
};
|
|
48
50
|
|
|
49
|
-
const onClick: TranslationOnClick = async (
|
|
51
|
+
const onClick: TranslationOnClick = async ({ keysAndDefaults, event }) => {
|
|
50
52
|
const withNs: UiKeyOption[] = keysAndDefaults.map(
|
|
51
|
-
({ key, ns, defaultValue }) =>
|
|
52
|
-
|
|
53
|
-
defaultValue,
|
|
54
|
-
ns: getFallbackArray(getTranslationNs({ key, ns, defaultValue })),
|
|
55
|
-
translation: getTranslation({
|
|
53
|
+
({ key, ns, defaultValue }) => {
|
|
54
|
+
return {
|
|
56
55
|
key,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const run = () => {
|
|
65
|
-
instances.ui =
|
|
66
|
-
plugins.ui &&
|
|
67
|
-
new plugins.ui({
|
|
68
|
-
apiKey: getInitialOptions().apiKey!,
|
|
69
|
-
apiUrl: getInitialOptions().apiUrl!,
|
|
70
|
-
highlight,
|
|
71
|
-
changeTranslation,
|
|
72
|
-
});
|
|
73
|
-
instances.observer?.run({ mouseHighlight: Boolean(instances.ui) });
|
|
74
|
-
checkCorrectConfiguration();
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const checkCorrectConfiguration = () => {
|
|
78
|
-
if (instances.languageDetector) {
|
|
79
|
-
const availableLanguages = getAvailableLanguages();
|
|
80
|
-
if (!availableLanguages) {
|
|
81
|
-
throw new Error(missingOptionError('availableLanguages'));
|
|
56
|
+
defaultValue,
|
|
57
|
+
ns: getTranslationNs({ key, ns }),
|
|
58
|
+
translation: getTranslation({
|
|
59
|
+
key,
|
|
60
|
+
ns,
|
|
61
|
+
}),
|
|
62
|
+
};
|
|
82
63
|
}
|
|
83
|
-
|
|
64
|
+
);
|
|
65
|
+
instances.ui?.handleElementClick(withNs, event);
|
|
84
66
|
};
|
|
85
67
|
|
|
86
68
|
const stop = () => {
|
|
@@ -93,54 +75,65 @@ export const PluginService = (
|
|
|
93
75
|
};
|
|
94
76
|
|
|
95
77
|
const translate = (props: TranslatePropsInternal) => {
|
|
96
|
-
const translation = getTranslation(
|
|
78
|
+
const translation = getTranslation({
|
|
79
|
+
key: props.key,
|
|
80
|
+
ns: props.ns,
|
|
81
|
+
});
|
|
97
82
|
return formatTranslation({ ...props, translation, formatEnabled: true });
|
|
98
83
|
};
|
|
99
84
|
|
|
100
|
-
const setObserver = (observer:
|
|
101
|
-
|
|
85
|
+
const setObserver = (observer: ObserverMiddleware | undefined) => {
|
|
86
|
+
plugins.observer = observer;
|
|
102
87
|
};
|
|
103
88
|
|
|
104
|
-
const
|
|
105
|
-
return
|
|
89
|
+
const hasObserver = () => {
|
|
90
|
+
return Boolean(plugins.observer);
|
|
106
91
|
};
|
|
107
92
|
|
|
108
|
-
const addFormatter = (formatter:
|
|
93
|
+
const addFormatter = (formatter: FormatterMiddleware | undefined) => {
|
|
109
94
|
if (formatter) {
|
|
110
95
|
instances.formatters.push(formatter);
|
|
111
96
|
}
|
|
112
97
|
};
|
|
113
98
|
|
|
114
99
|
const setFinalFormatter = (
|
|
115
|
-
formatter:
|
|
100
|
+
formatter: FinalFormatterMiddleware | undefined
|
|
116
101
|
) => {
|
|
117
102
|
instances.finalFormatter = formatter;
|
|
118
103
|
};
|
|
119
104
|
|
|
120
|
-
const setUi = (ui:
|
|
121
|
-
plugins.ui =
|
|
105
|
+
const setUi = (ui: UiMiddleware | undefined) => {
|
|
106
|
+
plugins.ui = ui as UiMiddleware;
|
|
122
107
|
};
|
|
123
108
|
|
|
124
|
-
const
|
|
125
|
-
return plugins.ui;
|
|
109
|
+
const hasUi = () => {
|
|
110
|
+
return Boolean(plugins.ui);
|
|
126
111
|
};
|
|
127
112
|
|
|
128
113
|
const setLanguageStorage = (
|
|
129
|
-
storage:
|
|
114
|
+
storage: LanguageStorageMiddleware | undefined
|
|
130
115
|
) => {
|
|
131
116
|
instances.languageStorage = storage;
|
|
132
117
|
};
|
|
133
118
|
|
|
119
|
+
const getLanguageStorage = () => {
|
|
120
|
+
return instances.languageStorage;
|
|
121
|
+
};
|
|
122
|
+
|
|
134
123
|
const setStoredLanguage = (language: string) => {
|
|
135
124
|
instances.languageStorage?.setLanguage(language);
|
|
136
125
|
};
|
|
137
126
|
|
|
138
127
|
const setLanguageDetector = (
|
|
139
|
-
detector:
|
|
128
|
+
detector: LanguageDetectorMiddleware | undefined
|
|
140
129
|
) => {
|
|
141
130
|
instances.languageDetector = detector;
|
|
142
131
|
};
|
|
143
132
|
|
|
133
|
+
const getLanguageDetector = () => {
|
|
134
|
+
return instances.languageDetector;
|
|
135
|
+
};
|
|
136
|
+
|
|
144
137
|
const detectLanguage = () => {
|
|
145
138
|
if (!instances.languageDetector) {
|
|
146
139
|
return undefined;
|
|
@@ -168,24 +161,47 @@ export const PluginService = (
|
|
|
168
161
|
});
|
|
169
162
|
};
|
|
170
163
|
|
|
171
|
-
const addBackend = (backend:
|
|
164
|
+
const addBackend = (backend: BackendMiddleware | undefined) => {
|
|
172
165
|
if (backend) {
|
|
173
166
|
instances.backends.push(backend);
|
|
174
167
|
}
|
|
175
168
|
};
|
|
176
169
|
|
|
177
|
-
const setDevBackend = (backend:
|
|
170
|
+
const setDevBackend = (backend: BackendDevMiddleware | undefined) => {
|
|
178
171
|
instances.devBackend = backend;
|
|
179
172
|
};
|
|
180
173
|
|
|
174
|
+
const run = () => {
|
|
175
|
+
if (!instances.ui) {
|
|
176
|
+
const { apiKey, apiUrl, projectId } = getInitialOptions();
|
|
177
|
+
instances.ui = plugins.ui?.({
|
|
178
|
+
apiKey: apiKey!,
|
|
179
|
+
apiUrl: apiUrl!,
|
|
180
|
+
projectId,
|
|
181
|
+
highlight,
|
|
182
|
+
changeTranslation,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (!instances.observer) {
|
|
186
|
+
instances.observer = plugins.observer?.({
|
|
187
|
+
translate,
|
|
188
|
+
onClick,
|
|
189
|
+
options: getInitialOptions().observerOptions,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
instances.observer?.run({ mouseHighlight: true });
|
|
193
|
+
};
|
|
194
|
+
|
|
181
195
|
const getDevBackend = () => {
|
|
182
196
|
return instances.devBackend;
|
|
183
197
|
};
|
|
184
198
|
|
|
185
199
|
const getBackendDevRecord: BackendGetRecord = ({ language, namespace }) => {
|
|
200
|
+
const { apiKey, apiUrl, projectId } = getInitialOptions();
|
|
186
201
|
return instances.devBackend?.getRecord({
|
|
187
|
-
apiKey
|
|
188
|
-
apiUrl
|
|
202
|
+
apiKey,
|
|
203
|
+
apiUrl,
|
|
204
|
+
projectId,
|
|
189
205
|
language,
|
|
190
206
|
namespace,
|
|
191
207
|
});
|
|
@@ -208,55 +224,105 @@ export const PluginService = (
|
|
|
208
224
|
return undefined;
|
|
209
225
|
};
|
|
210
226
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
227
|
+
const unwrap = (text: string): Unwrapped => {
|
|
228
|
+
if (instances.observer) {
|
|
229
|
+
return instances.observer?.unwrap(text);
|
|
230
|
+
}
|
|
231
|
+
return { text, keys: [] };
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const retranslate = () => {
|
|
235
|
+
instances.observer?.retranslate();
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
function addPlugin(tolgeeInstance: TolgeeInstance, plugin: TolgeePlugin) {
|
|
239
|
+
const pluginTools = Object.freeze({
|
|
240
|
+
setFinalFormatter,
|
|
241
|
+
addFormatter,
|
|
242
|
+
setObserver,
|
|
243
|
+
hasObserver,
|
|
244
|
+
setUi,
|
|
245
|
+
hasUi,
|
|
246
|
+
setDevBackend,
|
|
247
|
+
addBackend,
|
|
248
|
+
setLanguageDetector,
|
|
249
|
+
setLanguageStorage,
|
|
250
|
+
});
|
|
251
|
+
plugin(tolgeeInstance, pluginTools);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function formatTranslation({
|
|
219
255
|
formatEnabled,
|
|
220
|
-
|
|
256
|
+
...props
|
|
257
|
+
}: TranslatePropsInternal & { formatEnabled?: boolean }) {
|
|
258
|
+
const { key, translation, defaultValue, noWrap, params, orEmpty, ns } =
|
|
259
|
+
props;
|
|
221
260
|
const formattableTranslation = translation || defaultValue;
|
|
222
261
|
let result = formattableTranslation || (orEmpty ? '' : key);
|
|
223
|
-
if (instances.observer && !noWrap) {
|
|
224
|
-
result = instances.observer.wrap({
|
|
225
|
-
key,
|
|
226
|
-
translation: result,
|
|
227
|
-
defaultValue,
|
|
228
|
-
params,
|
|
229
|
-
ns,
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
262
|
|
|
233
263
|
const language = getLanguage();
|
|
234
264
|
const isFormatEnabled =
|
|
235
265
|
formatEnabled || !instances.observer?.outputNotFormattable;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
266
|
+
|
|
267
|
+
const wrap = (result: string) => {
|
|
268
|
+
if (instances.observer && !noWrap) {
|
|
269
|
+
return instances.observer.wrap({
|
|
270
|
+
key,
|
|
271
|
+
translation: result,
|
|
272
|
+
defaultValue,
|
|
273
|
+
params,
|
|
274
|
+
ns,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
result = wrap(result);
|
|
281
|
+
try {
|
|
282
|
+
if (formattableTranslation && language && isFormatEnabled) {
|
|
283
|
+
for (const formatter of instances.formatters) {
|
|
284
|
+
result = formatter.format({
|
|
285
|
+
translation: result,
|
|
286
|
+
language,
|
|
287
|
+
params,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (
|
|
292
|
+
instances.finalFormatter &&
|
|
293
|
+
formattableTranslation &&
|
|
294
|
+
language &&
|
|
295
|
+
isFormatEnabled
|
|
296
|
+
) {
|
|
297
|
+
result = instances.finalFormatter.format({
|
|
239
298
|
translation: result,
|
|
240
299
|
language,
|
|
241
300
|
params,
|
|
242
301
|
});
|
|
243
302
|
}
|
|
303
|
+
} catch (e: any) {
|
|
304
|
+
// eslint-disable-next-line no-console
|
|
305
|
+
console.error(e);
|
|
306
|
+
const errorMessage = getErrorMessage(e) || DEFAULT_FORMAT_ERROR;
|
|
307
|
+
const onFormatError = getInitialOptions().onFormatError;
|
|
308
|
+
const formatErrorType = typeof onFormatError;
|
|
309
|
+
if (formatErrorType === 'string') {
|
|
310
|
+
result = onFormatError as string;
|
|
311
|
+
} else if (formatErrorType === 'function') {
|
|
312
|
+
result = (onFormatError as FormatErrorHandler)(errorMessage, props);
|
|
313
|
+
} else {
|
|
314
|
+
result = DEFAULT_FORMAT_ERROR;
|
|
315
|
+
}
|
|
316
|
+
// wrap error message, so it's detectable
|
|
317
|
+
result = wrap(result);
|
|
244
318
|
}
|
|
245
319
|
|
|
246
|
-
if (
|
|
247
|
-
instances.finalFormatter &&
|
|
248
|
-
formattableTranslation &&
|
|
249
|
-
language &&
|
|
250
|
-
isFormatEnabled
|
|
251
|
-
) {
|
|
252
|
-
result = instances.finalFormatter.format({
|
|
253
|
-
translation: result,
|
|
254
|
-
language,
|
|
255
|
-
params,
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
320
|
return result;
|
|
259
|
-
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function hasDevBackend() {
|
|
324
|
+
return Boolean(getDevBackend());
|
|
325
|
+
}
|
|
260
326
|
|
|
261
327
|
const wrap = (params: WrapperWrapProps) => {
|
|
262
328
|
if (instances.observer) {
|
|
@@ -265,41 +331,24 @@ export const PluginService = (
|
|
|
265
331
|
return params.translation;
|
|
266
332
|
};
|
|
267
333
|
|
|
268
|
-
const unwrap = (text: string): Unwrapped => {
|
|
269
|
-
if (instances.observer) {
|
|
270
|
-
return instances.observer?.unwrap(text);
|
|
271
|
-
}
|
|
272
|
-
return { text, keys: [] };
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const retranslate = () => {
|
|
276
|
-
instances.observer?.retranslate();
|
|
277
|
-
};
|
|
278
|
-
|
|
279
334
|
return Object.freeze({
|
|
280
|
-
|
|
281
|
-
addFormatter,
|
|
335
|
+
addPlugin,
|
|
282
336
|
formatTranslation,
|
|
283
|
-
setObserver,
|
|
284
|
-
getObserver,
|
|
285
|
-
setUi,
|
|
286
|
-
getUi,
|
|
287
|
-
addBackend,
|
|
288
|
-
setDevBackend,
|
|
289
337
|
getDevBackend,
|
|
290
338
|
getBackendRecord,
|
|
291
339
|
getBackendDevRecord,
|
|
292
|
-
|
|
293
|
-
|
|
340
|
+
getLanguageDetector,
|
|
341
|
+
getLanguageStorage,
|
|
294
342
|
getInitialLanguage,
|
|
295
343
|
setStoredLanguage,
|
|
296
344
|
run,
|
|
297
345
|
stop,
|
|
298
346
|
retranslate,
|
|
299
347
|
highlight,
|
|
300
|
-
wrap,
|
|
301
348
|
unwrap,
|
|
349
|
+
wrap,
|
|
350
|
+
hasDevBackend,
|
|
302
351
|
});
|
|
303
352
|
};
|
|
304
353
|
|
|
305
|
-
export type
|
|
354
|
+
export type PluginsInstance = ReturnType<typeof Plugins>;
|