@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.
Files changed (273) hide show
  1. package/dist/tolgee.cjs.js +1069 -7029
  2. package/dist/tolgee.cjs.js.map +1 -1
  3. package/dist/tolgee.cjs.min.js +1 -1
  4. package/dist/tolgee.cjs.min.js.map +1 -1
  5. package/dist/tolgee.esm.min.mjs +1 -1
  6. package/dist/tolgee.esm.min.mjs.map +1 -1
  7. package/dist/tolgee.esm.mjs +1067 -7024
  8. package/dist/tolgee.esm.mjs.map +1 -1
  9. package/dist/tolgee.umd.js +1069 -7029
  10. package/dist/tolgee.umd.js.map +1 -1
  11. package/dist/tolgee.umd.min.js +1 -1
  12. package/dist/tolgee.umd.min.js.map +1 -1
  13. package/lib/Controller/Cache/Cache.d.ts +23 -0
  14. package/lib/Controller/Cache/helpers.d.ts +4 -0
  15. package/lib/Controller/Controller.d.ts +93 -0
  16. package/lib/Controller/Plugins/Plugins.d.ts +41 -0
  17. package/lib/Controller/State/State.d.ts +22 -0
  18. package/lib/Controller/State/helpers.d.ts +6 -0
  19. package/lib/Controller/State/initState.d.ts +55 -0
  20. package/lib/Controller/ValueObserver.d.ts +5 -0
  21. package/lib/Events/EventEmitter.d.ts +6 -0
  22. package/lib/Events/EventEmitterSelective.d.ts +15 -0
  23. package/lib/Events/Events.d.ts +50 -0
  24. package/lib/Tolgee.d.ts +2 -68
  25. package/lib/TranslateParams.d.ts +2 -0
  26. package/lib/{Constants/Global.d.ts → constants.d.ts} +1 -2
  27. package/lib/helpers.d.ts +3 -0
  28. package/lib/index.d.ts +3 -8
  29. package/lib/types.d.ts +235 -84
  30. package/package.json +20 -29
  31. package/src/Controller/Cache/Cache.ts +295 -0
  32. package/src/Controller/Cache/helpers.ts +39 -0
  33. package/src/Controller/Controller.ts +289 -0
  34. package/src/Controller/Plugins/Plugins.ts +305 -0
  35. package/src/Controller/State/State.ts +165 -0
  36. package/src/Controller/State/helpers.ts +41 -0
  37. package/src/Controller/State/initState.ts +90 -0
  38. package/src/Controller/ValueObserver.ts +23 -0
  39. package/src/Events/EventEmitter.ts +27 -0
  40. package/src/Events/EventEmitterSelective.test.ts +108 -0
  41. package/src/Events/EventEmitterSelective.ts +160 -0
  42. package/src/Events/Events.ts +66 -0
  43. package/src/Tolgee.ts +75 -333
  44. package/src/TranslateParams.test.ts +41 -0
  45. package/src/TranslateParams.ts +51 -0
  46. package/src/__test/backend.test.ts +48 -0
  47. package/src/__test/client.test.ts +48 -0
  48. package/src/__test/events.test.ts +33 -0
  49. package/src/__test/initialization.test.ts +73 -0
  50. package/src/__test/jest-setup.ts +2 -0
  51. package/src/__test/languageDetection.test.ts +123 -0
  52. package/src/__test/languageStorage.test.ts +145 -0
  53. package/src/__test/languages.test.ts +106 -0
  54. package/src/__test/loading.test.ts +39 -0
  55. package/src/__test/namespaces.test.ts +99 -0
  56. package/src/__test/namespacesFallback.test.ts +73 -0
  57. package/src/__test/plugins.test.ts +98 -0
  58. package/src/__test/testTools.ts +7 -0
  59. package/src/{Constants/Global.ts → constants.ts} +1 -3
  60. package/src/helpers.ts +17 -0
  61. package/src/index.ts +9 -8
  62. package/src/types.ts +324 -90
  63. package/README.md +0 -45
  64. package/dist/Constants/Global.d.ts +0 -6
  65. package/dist/Constants/ModifierKey.d.ts +0 -6
  66. package/dist/Errors/ApiHttpError.d.ts +0 -5
  67. package/dist/Observer.d.ts +0 -14
  68. package/dist/Observer.test.d.ts +0 -2
  69. package/dist/Properties.d.ts +0 -17
  70. package/dist/Properties.test.d.ts +0 -1
  71. package/dist/Tolgee.d.ts +0 -68
  72. package/dist/Tolgee.test.d.ts +0 -1
  73. package/dist/TolgeeConfig.d.ts +0 -69
  74. package/dist/TolgeeConfig.test.d.ts +0 -1
  75. package/dist/__integration/FormatterIcu.test.d.ts +0 -1
  76. package/dist/__integration/FormatterMissing.d.ts +0 -1
  77. package/dist/__integration/Tolgee.test.d.ts +0 -1
  78. package/dist/__integration/TolgeeInvisible.test.d.ts +0 -1
  79. package/dist/__integration/mockTranslations.d.ts +0 -7
  80. package/dist/__integration/testConfig.d.ts +0 -9
  81. package/dist/__testFixtures/classMock.d.ts +0 -3
  82. package/dist/__testFixtures/createElement.d.ts +0 -2
  83. package/dist/__testFixtures/createTestDom.d.ts +0 -9
  84. package/dist/__testFixtures/mocked.d.ts +0 -20
  85. package/dist/__testFixtures/setupAfterEnv.d.ts +0 -8
  86. package/dist/helpers/NodeHelper.d.ts +0 -14
  87. package/dist/helpers/TextHelper.d.ts +0 -5
  88. package/dist/helpers/TextHelper.test.d.ts +0 -1
  89. package/dist/helpers/commonTypes.d.ts +0 -2
  90. package/dist/helpers/encoderPolyfill.d.ts +0 -8
  91. package/dist/helpers/secret.d.ts +0 -6
  92. package/dist/helpers/secret.test.d.ts +0 -1
  93. package/dist/helpers/sleep.d.ts +0 -1
  94. package/dist/highlighter/HighlightFunctionsInitializer.d.ts +0 -10
  95. package/dist/highlighter/HighlightFunctionsInitializer.test.d.ts +0 -1
  96. package/dist/highlighter/MouseEventHandler.d.ts +0 -29
  97. package/dist/highlighter/MouseEventHandler.test.d.ts +0 -1
  98. package/dist/highlighter/TranslationHighlighter.d.ts +0 -14
  99. package/dist/highlighter/TranslationHighlighter.test.d.ts +0 -1
  100. package/dist/index.d.ts +0 -10
  101. package/dist/internal.d.ts +0 -2
  102. package/dist/modules/IcuFormatter.d.ts +0 -2
  103. package/dist/modules/IcuFormatter.test.d.ts +0 -1
  104. package/dist/modules/index.d.ts +0 -1
  105. package/dist/services/ApiHttpService.d.ts +0 -15
  106. package/dist/services/CoreService.d.ts +0 -18
  107. package/dist/services/CoreService.test.d.ts +0 -1
  108. package/dist/services/DependencyService.d.ts +0 -39
  109. package/dist/services/DependencyService.test.d.ts +0 -1
  110. package/dist/services/ElementRegistrar.d.ts +0 -19
  111. package/dist/services/ElementRegistrar.test.d.ts +0 -1
  112. package/dist/services/EventEmitter.d.ts +0 -13
  113. package/dist/services/EventService.d.ts +0 -9
  114. package/dist/services/ModuleService.d.ts +0 -5
  115. package/dist/services/ScreenshotService.d.ts +0 -15
  116. package/dist/services/Subscription.d.ts +0 -5
  117. package/dist/services/TextService.d.ts +0 -14
  118. package/dist/services/TextService.test.d.ts +0 -1
  119. package/dist/services/TranslationService.d.ts +0 -75
  120. package/dist/services/TranslationService.test.d.ts +0 -1
  121. package/dist/services/__mocks__/CoreService.d.ts +0 -2
  122. package/dist/toolsManager/Messages.d.ts +0 -8
  123. package/dist/toolsManager/Messages.test.d.ts +0 -1
  124. package/dist/toolsManager/PluginManager.d.ts +0 -21
  125. package/dist/toolsManager/PluginManager.test.d.ts +0 -1
  126. package/dist/types/DTOs.d.ts +0 -20
  127. package/dist/types/apiSchema.generated.d.ts +0 -6185
  128. package/dist/types.d.ts +0 -123
  129. package/dist/wrappers/AbstractWrapper.d.ts +0 -8
  130. package/dist/wrappers/NodeHandler.d.ts +0 -18
  131. package/dist/wrappers/WrappedHandler.d.ts +0 -8
  132. package/dist/wrappers/invisible/AttributeHandler.d.ts +0 -8
  133. package/dist/wrappers/invisible/Coder.d.ts +0 -7
  134. package/dist/wrappers/invisible/ContentHandler.d.ts +0 -6
  135. package/dist/wrappers/invisible/CoreHandler.d.ts +0 -10
  136. package/dist/wrappers/invisible/InvisibleWrapper.d.ts +0 -18
  137. package/dist/wrappers/invisible/ValueMemory.d.ts +0 -5
  138. package/dist/wrappers/invisible/ValueMemory.test.d.ts +0 -1
  139. package/dist/wrappers/text/AttributeHandler.d.ts +0 -8
  140. package/dist/wrappers/text/AttributeHandler.test.d.ts +0 -1
  141. package/dist/wrappers/text/Coder.d.ts +0 -15
  142. package/dist/wrappers/text/Coder.test.d.ts +0 -1
  143. package/dist/wrappers/text/ContentHandler.d.ts +0 -8
  144. package/dist/wrappers/text/ContentHandler.test.d.ts +0 -1
  145. package/dist/wrappers/text/CoreHandler.d.ts +0 -17
  146. package/dist/wrappers/text/CoreHandler.test.d.ts +0 -1
  147. package/dist/wrappers/text/TextWrapper.d.ts +0 -20
  148. package/index.js +0 -7
  149. package/lib/Constants/ModifierKey.d.ts +0 -6
  150. package/lib/Errors/ApiHttpError.d.ts +0 -5
  151. package/lib/Observer.d.ts +0 -14
  152. package/lib/Properties.d.ts +0 -17
  153. package/lib/TolgeeConfig.d.ts +0 -69
  154. package/lib/helpers/NodeHelper.d.ts +0 -14
  155. package/lib/helpers/TextHelper.d.ts +0 -5
  156. package/lib/helpers/commonTypes.d.ts +0 -2
  157. package/lib/helpers/encoderPolyfill.d.ts +0 -8
  158. package/lib/helpers/secret.d.ts +0 -6
  159. package/lib/helpers/sleep.d.ts +0 -1
  160. package/lib/highlighter/HighlightFunctionsInitializer.d.ts +0 -10
  161. package/lib/highlighter/MouseEventHandler.d.ts +0 -29
  162. package/lib/highlighter/TranslationHighlighter.d.ts +0 -14
  163. package/lib/modules/IcuFormatter.d.ts +0 -2
  164. package/lib/modules/index.d.ts +0 -1
  165. package/lib/services/ApiHttpService.d.ts +0 -15
  166. package/lib/services/CoreService.d.ts +0 -18
  167. package/lib/services/DependencyService.d.ts +0 -39
  168. package/lib/services/ElementRegistrar.d.ts +0 -19
  169. package/lib/services/EventEmitter.d.ts +0 -13
  170. package/lib/services/EventService.d.ts +0 -9
  171. package/lib/services/ModuleService.d.ts +0 -5
  172. package/lib/services/ScreenshotService.d.ts +0 -15
  173. package/lib/services/Subscription.d.ts +0 -5
  174. package/lib/services/TextService.d.ts +0 -14
  175. package/lib/services/TranslationService.d.ts +0 -75
  176. package/lib/toolsManager/Messages.d.ts +0 -8
  177. package/lib/toolsManager/PluginManager.d.ts +0 -21
  178. package/lib/types/DTOs.d.ts +0 -20
  179. package/lib/types/apiSchema.generated.d.ts +0 -6185
  180. package/lib/wrappers/AbstractWrapper.d.ts +0 -8
  181. package/lib/wrappers/NodeHandler.d.ts +0 -18
  182. package/lib/wrappers/WrappedHandler.d.ts +0 -8
  183. package/lib/wrappers/invisible/AttributeHandler.d.ts +0 -8
  184. package/lib/wrappers/invisible/Coder.d.ts +0 -7
  185. package/lib/wrappers/invisible/ContentHandler.d.ts +0 -6
  186. package/lib/wrappers/invisible/CoreHandler.d.ts +0 -10
  187. package/lib/wrappers/invisible/InvisibleWrapper.d.ts +0 -18
  188. package/lib/wrappers/invisible/ValueMemory.d.ts +0 -5
  189. package/lib/wrappers/text/AttributeHandler.d.ts +0 -8
  190. package/lib/wrappers/text/Coder.d.ts +0 -15
  191. package/lib/wrappers/text/ContentHandler.d.ts +0 -8
  192. package/lib/wrappers/text/CoreHandler.d.ts +0 -17
  193. package/lib/wrappers/text/TextWrapper.d.ts +0 -20
  194. package/src/Constants/ModifierKey.ts +0 -6
  195. package/src/Errors/ApiHttpError.ts +0 -8
  196. package/src/Observer.test.ts +0 -119
  197. package/src/Observer.ts +0 -68
  198. package/src/Properties.test.ts +0 -150
  199. package/src/Properties.ts +0 -112
  200. package/src/Tolgee.test.ts +0 -473
  201. package/src/TolgeeConfig.test.ts +0 -21
  202. package/src/TolgeeConfig.ts +0 -134
  203. package/src/__integration/FormatterIcu.test.ts +0 -80
  204. package/src/__integration/FormatterMissing.ts +0 -54
  205. package/src/__integration/Tolgee.test.ts +0 -90
  206. package/src/__integration/TolgeeInvisible.test.ts +0 -145
  207. package/src/__integration/mockTranslations.ts +0 -6
  208. package/src/__integration/testConfig.ts +0 -16
  209. package/src/__testFixtures/classMock.ts +0 -11
  210. package/src/__testFixtures/createElement.ts +0 -43
  211. package/src/__testFixtures/createTestDom.ts +0 -26
  212. package/src/__testFixtures/mocked.ts +0 -25
  213. package/src/__testFixtures/setupAfterEnv.ts +0 -34
  214. package/src/helpers/NodeHelper.ts +0 -90
  215. package/src/helpers/TextHelper.test.ts +0 -62
  216. package/src/helpers/TextHelper.ts +0 -58
  217. package/src/helpers/commonTypes.ts +0 -8
  218. package/src/helpers/encoderPolyfill.ts +0 -96
  219. package/src/helpers/secret.test.ts +0 -61
  220. package/src/helpers/secret.ts +0 -68
  221. package/src/helpers/sleep.ts +0 -2
  222. package/src/highlighter/HighlightFunctionsInitializer.test.ts +0 -40
  223. package/src/highlighter/HighlightFunctionsInitializer.ts +0 -61
  224. package/src/highlighter/MouseEventHandler.test.ts +0 -151
  225. package/src/highlighter/MouseEventHandler.ts +0 -191
  226. package/src/highlighter/TranslationHighlighter.test.ts +0 -177
  227. package/src/highlighter/TranslationHighlighter.ts +0 -113
  228. package/src/internal.ts +0 -2
  229. package/src/modules/IcuFormatter.test.ts +0 -21
  230. package/src/modules/IcuFormatter.ts +0 -39
  231. package/src/modules/index.ts +0 -1
  232. package/src/services/ApiHttpService.ts +0 -85
  233. package/src/services/CoreService.test.ts +0 -141
  234. package/src/services/CoreService.ts +0 -76
  235. package/src/services/DependencyService.test.ts +0 -51
  236. package/src/services/DependencyService.ts +0 -116
  237. package/src/services/ElementRegistrar.test.ts +0 -131
  238. package/src/services/ElementRegistrar.ts +0 -108
  239. package/src/services/EventEmitter.ts +0 -52
  240. package/src/services/EventService.ts +0 -14
  241. package/src/services/ModuleService.ts +0 -14
  242. package/src/services/ScreenshotService.ts +0 -31
  243. package/src/services/Subscription.ts +0 -7
  244. package/src/services/TextService.test.ts +0 -88
  245. package/src/services/TextService.ts +0 -82
  246. package/src/services/TranslationService.test.ts +0 -358
  247. package/src/services/TranslationService.ts +0 -417
  248. package/src/services/__mocks__/CoreService.ts +0 -17
  249. package/src/toolsManager/Messages.test.ts +0 -79
  250. package/src/toolsManager/Messages.ts +0 -60
  251. package/src/toolsManager/PluginManager.test.ts +0 -108
  252. package/src/toolsManager/PluginManager.ts +0 -129
  253. package/src/types/DTOs.ts +0 -25
  254. package/src/types/apiSchema.generated.ts +0 -6208
  255. package/src/wrappers/AbstractWrapper.ts +0 -14
  256. package/src/wrappers/NodeHandler.ts +0 -143
  257. package/src/wrappers/WrappedHandler.ts +0 -28
  258. package/src/wrappers/invisible/AttributeHandler.ts +0 -23
  259. package/src/wrappers/invisible/Coder.ts +0 -65
  260. package/src/wrappers/invisible/ContentHandler.ts +0 -15
  261. package/src/wrappers/invisible/CoreHandler.ts +0 -17
  262. package/src/wrappers/invisible/InvisibleWrapper.ts +0 -59
  263. package/src/wrappers/invisible/ValueMemory.test.ts +0 -25
  264. package/src/wrappers/invisible/ValueMemory.ts +0 -16
  265. package/src/wrappers/text/AttributeHandler.test.ts +0 -118
  266. package/src/wrappers/text/AttributeHandler.ts +0 -25
  267. package/src/wrappers/text/Coder.test.ts +0 -298
  268. package/src/wrappers/text/Coder.ts +0 -202
  269. package/src/wrappers/text/ContentHandler.test.ts +0 -185
  270. package/src/wrappers/text/ContentHandler.ts +0 -21
  271. package/src/wrappers/text/CoreHandler.test.ts +0 -106
  272. package/src/wrappers/text/CoreHandler.ts +0 -45
  273. 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>>;