@tolgee/core 4.9.2 → 5.0.0-rc.0b3e627.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 +1069 -7029
- 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.min.mjs +1 -1
- package/dist/tolgee.esm.min.mjs.map +1 -1
- package/dist/tolgee.esm.mjs +1067 -7024
- package/dist/tolgee.esm.mjs.map +1 -1
- package/dist/tolgee.umd.js +1069 -7029
- 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 +23 -0
- package/lib/Controller/Cache/helpers.d.ts +4 -0
- package/lib/Controller/Controller.d.ts +93 -0
- package/lib/Controller/Plugins/Plugins.d.ts +41 -0
- package/lib/Controller/State/State.d.ts +22 -0
- package/lib/Controller/State/helpers.d.ts +6 -0
- package/lib/Controller/State/initState.d.ts +55 -0
- package/lib/Controller/ValueObserver.d.ts +5 -0
- package/lib/Events/EventEmitter.d.ts +6 -0
- package/lib/Events/EventEmitterSelective.d.ts +15 -0
- package/lib/Events/Events.d.ts +50 -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 -2
- package/lib/helpers.d.ts +3 -0
- package/lib/index.d.ts +3 -8
- package/lib/types.d.ts +235 -84
- package/package.json +20 -29
- package/src/Controller/Cache/Cache.ts +295 -0
- package/src/Controller/Cache/helpers.ts +39 -0
- package/src/Controller/Controller.ts +289 -0
- package/src/Controller/Plugins/Plugins.ts +305 -0
- package/src/Controller/State/State.ts +165 -0
- package/src/Controller/State/helpers.ts +41 -0
- package/src/Controller/State/initState.ts +90 -0
- package/src/Controller/ValueObserver.ts +23 -0
- package/src/Events/EventEmitter.ts +27 -0
- package/src/Events/EventEmitterSelective.test.ts +108 -0
- package/src/Events/EventEmitterSelective.ts +160 -0
- package/src/Events/Events.ts +66 -0
- package/src/Tolgee.ts +75 -333
- package/src/TranslateParams.test.ts +41 -0
- package/src/TranslateParams.ts +51 -0
- package/src/__test/backend.test.ts +48 -0
- package/src/__test/client.test.ts +48 -0
- package/src/__test/events.test.ts +33 -0
- package/src/__test/initialization.test.ts +73 -0
- package/src/__test/jest-setup.ts +2 -0
- package/src/__test/languageDetection.test.ts +123 -0
- package/src/__test/languageStorage.test.ts +145 -0
- package/src/__test/languages.test.ts +106 -0
- package/src/__test/loading.test.ts +39 -0
- package/src/__test/namespaces.test.ts +99 -0
- package/src/__test/namespacesFallback.test.ts +73 -0
- package/src/__test/plugins.test.ts +98 -0
- package/src/__test/testTools.ts +7 -0
- package/src/{Constants/Global.ts → constants.ts} +1 -3
- package/src/helpers.ts +17 -0
- package/src/index.ts +9 -8
- package/src/types.ts +324 -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/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,305 @@
|
|
|
1
|
+
import { isPromise, missingOptionError, valueOrPromise } from '../../helpers';
|
|
2
|
+
import {
|
|
3
|
+
BackendDevInterface,
|
|
4
|
+
BackendGetRecord,
|
|
5
|
+
BackendInterface,
|
|
6
|
+
FormatterInterface,
|
|
7
|
+
ObserverInterface,
|
|
8
|
+
TranslatePropsInternal,
|
|
9
|
+
TranslationOnClick,
|
|
10
|
+
UiInterface,
|
|
11
|
+
UiLibInterface,
|
|
12
|
+
UiType,
|
|
13
|
+
FinalFormatterInterface,
|
|
14
|
+
HighlightInterface,
|
|
15
|
+
UiConstructor,
|
|
16
|
+
UiKeyOption,
|
|
17
|
+
LanguageDetectorInterface,
|
|
18
|
+
LanguageStorageInterface,
|
|
19
|
+
Options,
|
|
20
|
+
ChangeTranslationInterface,
|
|
21
|
+
WrapperWrapProps,
|
|
22
|
+
Unwrapped,
|
|
23
|
+
} from '../../types';
|
|
24
|
+
import { getFallbackArray } from '../State/helpers';
|
|
25
|
+
|
|
26
|
+
export const PluginService = (
|
|
27
|
+
getLanguage: () => string | undefined,
|
|
28
|
+
getInitialOptions: () => Options,
|
|
29
|
+
getAvailableLanguages: () => string[] | undefined,
|
|
30
|
+
getTranslationNs: (props: TranslatePropsInternal) => string[] | string,
|
|
31
|
+
getTranslation: (props: TranslatePropsInternal) => string | undefined,
|
|
32
|
+
changeTranslation: ChangeTranslationInterface
|
|
33
|
+
) => {
|
|
34
|
+
const plugins = {
|
|
35
|
+
ui: undefined as UiConstructor | undefined,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const instances = {
|
|
39
|
+
formatters: [] as FormatterInterface[],
|
|
40
|
+
finalFormatter: undefined as FinalFormatterInterface | undefined,
|
|
41
|
+
observer: undefined as ReturnType<ObserverInterface> | undefined,
|
|
42
|
+
devBackend: undefined as BackendDevInterface | undefined,
|
|
43
|
+
backends: [] as BackendInterface[],
|
|
44
|
+
ui: undefined as UiInterface | undefined,
|
|
45
|
+
languageDetector: undefined as LanguageDetectorInterface | undefined,
|
|
46
|
+
languageStorage: undefined as LanguageStorageInterface | undefined,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const onClick: TranslationOnClick = async (event, { keysAndDefaults }) => {
|
|
50
|
+
const withNs: UiKeyOption[] = keysAndDefaults.map(
|
|
51
|
+
({ key, ns, defaultValue }) => ({
|
|
52
|
+
key,
|
|
53
|
+
defaultValue,
|
|
54
|
+
ns: getFallbackArray(getTranslationNs({ key, ns, defaultValue })),
|
|
55
|
+
translation: getTranslation({
|
|
56
|
+
key,
|
|
57
|
+
ns,
|
|
58
|
+
}),
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
instances.ui?.handleElementClick(event, withNs);
|
|
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'));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const stop = () => {
|
|
87
|
+
instances.ui = undefined;
|
|
88
|
+
instances.observer?.stop();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const highlight: HighlightInterface = (key, ns) => {
|
|
92
|
+
return instances.observer?.highlight?.(key, ns) || { unhighlight() {} };
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const translate = (props: TranslatePropsInternal) => {
|
|
96
|
+
const translation = getTranslation(props);
|
|
97
|
+
return formatTranslation({ ...props, translation, formatEnabled: true });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const setObserver = (observer: ObserverInterface | undefined) => {
|
|
101
|
+
instances.observer = observer?.({ translate, onClick });
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const getObserver = () => {
|
|
105
|
+
return instances.observer;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const addFormatter = (formatter: FormatterInterface | undefined) => {
|
|
109
|
+
if (formatter) {
|
|
110
|
+
instances.formatters.push(formatter);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const setFinalFormatter = (
|
|
115
|
+
formatter: FinalFormatterInterface | undefined
|
|
116
|
+
) => {
|
|
117
|
+
instances.finalFormatter = formatter;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const setUi = (ui: UiType | undefined) => {
|
|
121
|
+
plugins.ui = (ui as UiLibInterface)?.UI || ui;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const getUi = () => {
|
|
125
|
+
return plugins.ui;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const setLanguageStorage = (
|
|
129
|
+
storage: LanguageStorageInterface | undefined
|
|
130
|
+
) => {
|
|
131
|
+
instances.languageStorage = storage;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const setStoredLanguage = (language: string) => {
|
|
135
|
+
instances.languageStorage?.setLanguage(language);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const setLanguageDetector = (
|
|
139
|
+
detector: LanguageDetectorInterface | undefined
|
|
140
|
+
) => {
|
|
141
|
+
instances.languageDetector = detector;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const detectLanguage = () => {
|
|
145
|
+
if (!instances.languageDetector) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const availableLanguages = getAvailableLanguages()!;
|
|
150
|
+
|
|
151
|
+
return instances.languageDetector.getLanguage({
|
|
152
|
+
availableLanguages,
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const getInitialLanguage = () => {
|
|
157
|
+
const availableLanguages = getAvailableLanguages();
|
|
158
|
+
const languageOrPromise = instances.languageStorage?.getLanguage();
|
|
159
|
+
|
|
160
|
+
return valueOrPromise(languageOrPromise, (language) => {
|
|
161
|
+
if (
|
|
162
|
+
(!availableLanguages || availableLanguages.includes(language!)) &&
|
|
163
|
+
language
|
|
164
|
+
) {
|
|
165
|
+
return language;
|
|
166
|
+
}
|
|
167
|
+
return detectLanguage();
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const addBackend = (backend: BackendInterface | undefined) => {
|
|
172
|
+
if (backend) {
|
|
173
|
+
instances.backends.push(backend);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const setDevBackend = (backend: BackendDevInterface | undefined) => {
|
|
178
|
+
instances.devBackend = backend;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const getDevBackend = () => {
|
|
182
|
+
return instances.devBackend;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const getBackendDevRecord: BackendGetRecord = ({ language, namespace }) => {
|
|
186
|
+
return instances.devBackend?.getRecord({
|
|
187
|
+
apiKey: getInitialOptions().apiKey,
|
|
188
|
+
apiUrl: getInitialOptions().apiUrl,
|
|
189
|
+
language,
|
|
190
|
+
namespace,
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const getBackendRecord: BackendGetRecord = ({ language, namespace }) => {
|
|
195
|
+
for (const backend of instances.backends) {
|
|
196
|
+
const data = backend.getRecord({ language, namespace });
|
|
197
|
+
if (isPromise(data)) {
|
|
198
|
+
return data?.catch((e) => {
|
|
199
|
+
// eslint-disable-next-line no-console
|
|
200
|
+
console.error(e);
|
|
201
|
+
return {};
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
if (data !== undefined) {
|
|
205
|
+
return data;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return undefined;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const formatTranslation = ({
|
|
212
|
+
key,
|
|
213
|
+
translation,
|
|
214
|
+
defaultValue,
|
|
215
|
+
noWrap,
|
|
216
|
+
params,
|
|
217
|
+
orEmpty,
|
|
218
|
+
ns,
|
|
219
|
+
formatEnabled,
|
|
220
|
+
}: TranslatePropsInternal & { formatEnabled?: boolean }) => {
|
|
221
|
+
const formattableTranslation = translation || defaultValue;
|
|
222
|
+
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
|
+
|
|
233
|
+
const language = getLanguage();
|
|
234
|
+
const isFormatEnabled =
|
|
235
|
+
formatEnabled || !instances.observer?.outputNotFormattable;
|
|
236
|
+
if (formattableTranslation && language && isFormatEnabled) {
|
|
237
|
+
for (const formatter of instances.formatters) {
|
|
238
|
+
result = formatter.format({
|
|
239
|
+
translation: result,
|
|
240
|
+
language,
|
|
241
|
+
params,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
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
|
+
return result;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const wrap = (params: WrapperWrapProps) => {
|
|
262
|
+
if (instances.observer) {
|
|
263
|
+
return instances.observer?.wrap(params);
|
|
264
|
+
}
|
|
265
|
+
return params.translation;
|
|
266
|
+
};
|
|
267
|
+
|
|
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
|
+
return Object.freeze({
|
|
280
|
+
setFinalFormatter,
|
|
281
|
+
addFormatter,
|
|
282
|
+
formatTranslation,
|
|
283
|
+
setObserver,
|
|
284
|
+
getObserver,
|
|
285
|
+
setUi,
|
|
286
|
+
getUi,
|
|
287
|
+
addBackend,
|
|
288
|
+
setDevBackend,
|
|
289
|
+
getDevBackend,
|
|
290
|
+
getBackendRecord,
|
|
291
|
+
getBackendDevRecord,
|
|
292
|
+
setLanguageDetector,
|
|
293
|
+
setLanguageStorage,
|
|
294
|
+
getInitialLanguage,
|
|
295
|
+
setStoredLanguage,
|
|
296
|
+
run,
|
|
297
|
+
stop,
|
|
298
|
+
retranslate,
|
|
299
|
+
highlight,
|
|
300
|
+
wrap,
|
|
301
|
+
unwrap,
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
export type PluginServiceType = ReturnType<typeof PluginService>;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CacheDescriptor,
|
|
3
|
+
CacheDescriptorInternal,
|
|
4
|
+
EventEmitterType,
|
|
5
|
+
FallbackNSTranslation,
|
|
6
|
+
} from '../../types';
|
|
7
|
+
import { decodeCacheKey } from '../Cache/helpers';
|
|
8
|
+
import { getFallbackArray, getFallbackFromStruct, unique } from './helpers';
|
|
9
|
+
import { initState, Options } from './initState';
|
|
10
|
+
|
|
11
|
+
export const State = (
|
|
12
|
+
onLanguageChange: EventEmitterType<string>,
|
|
13
|
+
onPendingLanguageChange: EventEmitterType<string>,
|
|
14
|
+
onRunningChange: EventEmitterType<boolean>
|
|
15
|
+
) => {
|
|
16
|
+
let state = initState();
|
|
17
|
+
|
|
18
|
+
function init(options?: Partial<Options>) {
|
|
19
|
+
state = initState(options, state);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isRunning() {
|
|
23
|
+
return state.isRunning;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function setRunning(value: boolean) {
|
|
27
|
+
if (state.isRunning !== value) {
|
|
28
|
+
state.isRunning = value;
|
|
29
|
+
onRunningChange.emit(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isInitialLoading() {
|
|
34
|
+
return state.isInitialLoading;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function setInitialLoading(value: boolean) {
|
|
38
|
+
state.isInitialLoading = value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getLanguage() {
|
|
42
|
+
return state.language || state.initialOptions.language;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getLanguageOrFail() {
|
|
46
|
+
const language = state.language || state.initialOptions.language;
|
|
47
|
+
if (!language) {
|
|
48
|
+
throw new Error(`No language set`);
|
|
49
|
+
}
|
|
50
|
+
return language;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function setLanguage(language: string) {
|
|
54
|
+
if (state.language !== language) {
|
|
55
|
+
state.language = language;
|
|
56
|
+
onLanguageChange.emit(language);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getPendingLanguage() {
|
|
61
|
+
return state.pendingLanguage || getLanguage();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function setPendingLanguage(language: string) {
|
|
65
|
+
if (state.pendingLanguage !== language) {
|
|
66
|
+
state.pendingLanguage = language;
|
|
67
|
+
onPendingLanguageChange.emit(language);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getInitialOptions() {
|
|
72
|
+
return state.initialOptions;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function addActiveNs(ns: FallbackNSTranslation) {
|
|
76
|
+
const namespaces = getFallbackArray(ns);
|
|
77
|
+
namespaces.forEach((namespace) => {
|
|
78
|
+
const value = state.activeNamespaces.get(namespace);
|
|
79
|
+
if (value !== undefined) {
|
|
80
|
+
state.activeNamespaces.set(namespace, value + 1);
|
|
81
|
+
} else {
|
|
82
|
+
state.activeNamespaces.set(namespace, 1);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function removeActiveNs(ns: FallbackNSTranslation) {
|
|
88
|
+
const namespaces = getFallbackArray(ns);
|
|
89
|
+
namespaces.forEach((namespace) => {
|
|
90
|
+
const value = state.activeNamespaces.get(namespace);
|
|
91
|
+
if (value !== undefined && value > 1) {
|
|
92
|
+
state.activeNamespaces.set(namespace, value - 1);
|
|
93
|
+
} else {
|
|
94
|
+
state.activeNamespaces.delete(namespace);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function getRequiredNamespaces() {
|
|
100
|
+
return unique([
|
|
101
|
+
...(state.initialOptions.ns || [state.initialOptions.defaultNs]),
|
|
102
|
+
...state.activeNamespaces.keys(),
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getFallbackLangs(lang?: string) {
|
|
107
|
+
const language = lang || getLanguage();
|
|
108
|
+
if (!language) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
return unique([
|
|
112
|
+
language,
|
|
113
|
+
...getFallbackFromStruct(language, state.initialOptions.fallbackLanguage),
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function getFallbackNamespaces() {
|
|
118
|
+
const defaultNs = state.initialOptions.defaultNs;
|
|
119
|
+
const fallbackNs = state.initialOptions.fallbackNs;
|
|
120
|
+
const fallbackNamespaces = typeof defaultNs === 'string' ? [defaultNs] : [];
|
|
121
|
+
return unique([...fallbackNamespaces, ...getFallbackArray(fallbackNs)]);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getAvailableLanguages() {
|
|
125
|
+
if (state.initialOptions.availableLanguages) {
|
|
126
|
+
return state.initialOptions.availableLanguages;
|
|
127
|
+
} else if (state.initialOptions.staticData) {
|
|
128
|
+
const languagesFromStaticData = Object.keys(
|
|
129
|
+
state.initialOptions.staticData
|
|
130
|
+
).map((key) => decodeCacheKey(key).language);
|
|
131
|
+
return Array.from(new Set(languagesFromStaticData));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function withDefaultNs(descriptor: CacheDescriptor): CacheDescriptorInternal {
|
|
136
|
+
return {
|
|
137
|
+
namespace:
|
|
138
|
+
descriptor.namespace === undefined
|
|
139
|
+
? getInitialOptions().defaultNs
|
|
140
|
+
: descriptor.namespace,
|
|
141
|
+
language: descriptor.language,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return Object.freeze({
|
|
146
|
+
init,
|
|
147
|
+
isRunning,
|
|
148
|
+
setRunning,
|
|
149
|
+
isInitialLoading,
|
|
150
|
+
setInitialLoading,
|
|
151
|
+
getLanguage,
|
|
152
|
+
getLanguageOrFail,
|
|
153
|
+
setLanguage,
|
|
154
|
+
getPendingLanguage,
|
|
155
|
+
setPendingLanguage,
|
|
156
|
+
getInitialOptions,
|
|
157
|
+
addActiveNs,
|
|
158
|
+
removeActiveNs,
|
|
159
|
+
getRequiredNamespaces,
|
|
160
|
+
getFallbackLangs,
|
|
161
|
+
getFallbackNamespaces,
|
|
162
|
+
getAvailableLanguages,
|
|
163
|
+
withDefaultNs,
|
|
164
|
+
});
|
|
165
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FallbackGeneral,
|
|
3
|
+
FallbackLanguage,
|
|
4
|
+
FallbackLanguageObject,
|
|
5
|
+
FallbackLanguageOption,
|
|
6
|
+
} from '../../types';
|
|
7
|
+
|
|
8
|
+
export function isObject(item: any) {
|
|
9
|
+
return typeof item === 'object' && !Array.isArray(item) && item !== null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getFallback(value: FallbackGeneral): string[] | undefined {
|
|
13
|
+
if (typeof value === 'string') {
|
|
14
|
+
return [value];
|
|
15
|
+
}
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getFallbackArray(value: FallbackGeneral): string[] {
|
|
23
|
+
return getFallback(value) || [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getFallbackFromStruct(
|
|
27
|
+
language: string,
|
|
28
|
+
fallbackLanguage: FallbackLanguageOption
|
|
29
|
+
) {
|
|
30
|
+
if (isObject(fallbackLanguage)) {
|
|
31
|
+
return getFallbackArray(
|
|
32
|
+
(fallbackLanguage as FallbackLanguageObject)?.[language]
|
|
33
|
+
);
|
|
34
|
+
} else {
|
|
35
|
+
return getFallbackArray(fallbackLanguage as FallbackLanguage);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function unique<T>(arr: T[]) {
|
|
40
|
+
return Array.from(new Set(arr));
|
|
41
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FallbackLanguageOption,
|
|
3
|
+
FallbackNS,
|
|
4
|
+
TreeTranslationsData,
|
|
5
|
+
} from '../../types';
|
|
6
|
+
|
|
7
|
+
export type Options = {
|
|
8
|
+
/**
|
|
9
|
+
* Initial language
|
|
10
|
+
*/
|
|
11
|
+
language?: string;
|
|
12
|
+
apiUrl?: string;
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
projectId?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Used when auto detection is not available or is turned off
|
|
17
|
+
*/
|
|
18
|
+
defaultLanguage?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Languages which can be used for language detection
|
|
21
|
+
* and also limits which values can be stored
|
|
22
|
+
*/
|
|
23
|
+
availableLanguages?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Language which is used when no translation is available for current one
|
|
26
|
+
*/
|
|
27
|
+
fallbackLanguage?: FallbackLanguageOption;
|
|
28
|
+
/**
|
|
29
|
+
* Store user language in localStorage (default: true)
|
|
30
|
+
*/
|
|
31
|
+
enableLanguageStore?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Namespaces which should be always fetched
|
|
34
|
+
*/
|
|
35
|
+
ns?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Namespaces to be used to find translation when no explicit namespace set.
|
|
38
|
+
*/
|
|
39
|
+
fallbackNs?: FallbackNS;
|
|
40
|
+
/**
|
|
41
|
+
* Default namespace when no namespace defined (default: '')
|
|
42
|
+
*/
|
|
43
|
+
defaultNs: string;
|
|
44
|
+
/**
|
|
45
|
+
* Prefix used for fetching languages (default: 'i18n/')
|
|
46
|
+
*/
|
|
47
|
+
filesUrlPrefix: string;
|
|
48
|
+
staticData?: {
|
|
49
|
+
[key: string]: TreeTranslationsData | (() => Promise<TreeTranslationsData>);
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type State = {
|
|
54
|
+
initialOptions: Options;
|
|
55
|
+
activeNamespaces: Map<string, number>;
|
|
56
|
+
language: string | undefined;
|
|
57
|
+
pendingLanguage: string | undefined;
|
|
58
|
+
isInitialLoading: boolean;
|
|
59
|
+
isRunning: boolean;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const defaultValues: Options = {
|
|
63
|
+
enableLanguageStore: true,
|
|
64
|
+
defaultNs: '',
|
|
65
|
+
filesUrlPrefix: 'i18n/',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const initState = (
|
|
69
|
+
options?: Partial<Options>,
|
|
70
|
+
previousState?: State
|
|
71
|
+
): State => {
|
|
72
|
+
const initialOptions = {
|
|
73
|
+
...defaultValues,
|
|
74
|
+
...previousState?.initialOptions,
|
|
75
|
+
...options,
|
|
76
|
+
};
|
|
77
|
+
// remove extra '/' from url end
|
|
78
|
+
const apiUrl = initialOptions.apiUrl;
|
|
79
|
+
initialOptions.apiUrl = apiUrl ? apiUrl.replace(/\/+$/, '') : apiUrl;
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
initialOptions,
|
|
83
|
+
activeNamespaces:
|
|
84
|
+
previousState?.activeNamespaces || new Map<string, number>(),
|
|
85
|
+
language: previousState?.language,
|
|
86
|
+
pendingLanguage: previousState?.language,
|
|
87
|
+
isInitialLoading: false,
|
|
88
|
+
isRunning: false,
|
|
89
|
+
};
|
|
90
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const ValueObserver = <T = any>(
|
|
2
|
+
initialValue: T,
|
|
3
|
+
valueGetter: () => T,
|
|
4
|
+
handler: (value: T) => void
|
|
5
|
+
) => {
|
|
6
|
+
let previousValue: T = initialValue;
|
|
7
|
+
function init(value: T) {
|
|
8
|
+
previousValue = value;
|
|
9
|
+
}
|
|
10
|
+
function notify() {
|
|
11
|
+
const value = valueGetter();
|
|
12
|
+
if (previousValue !== value) {
|
|
13
|
+
handler(value);
|
|
14
|
+
}
|
|
15
|
+
previousValue = value;
|
|
16
|
+
}
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
init,
|
|
19
|
+
notify,
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type ValueObserverInstance<T> = ReturnType<typeof ValueObserver<T>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Listener, ListenerHandler } from '../types';
|
|
2
|
+
|
|
3
|
+
export const EventEmitter = <T>() => {
|
|
4
|
+
let handlers: ListenerHandler<T>[] = [];
|
|
5
|
+
|
|
6
|
+
const listen = (handler: ListenerHandler<T>): Listener => {
|
|
7
|
+
const handlerWrapper: ListenerHandler<T> = (e) => {
|
|
8
|
+
handler(e);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
handlers.push(handlerWrapper);
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
unsubscribe: () => {
|
|
15
|
+
handlers = handlers.filter((i) => handlerWrapper !== i);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const emit = (data: T) => {
|
|
21
|
+
handlers.forEach((handler) => handler({ value: data }));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return Object.freeze({ listen, emit });
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type EventEmitterType<T> = ReturnType<typeof EventEmitter<T>>;
|