-
Notifications
You must be signed in to change notification settings - Fork 88
/
translationContext.tsx
105 lines (86 loc) · 3.92 KB
/
translationContext.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import React, { useCallback, useContext, useEffect, useState } from "react";
import { mergeObjects } from "../utils";
import { getCurrentLanguageFromCookie } from "./translationHelpers";
import type {
TranslationContextType,
TranslationControlEventSource,
TranslationEventHandler,
TranslationFunc,
TranslationStore,
} from "./translationHelpers";
import type { PropsWithChildren } from "react";
const errCB = () => {
throw new Error("Cannot use translation func outside TranslationContext provider.");
};
export const TranslationContext = React.createContext<TranslationContextType>({
translate: errCB,
});
export const useTranslation = (): TranslationFunc => {
return useContext(TranslationContext).translate;
};
export const TranslationContextProvider: React.FC<
PropsWithChildren<{
defaultLanguage: string;
defaultStore: TranslationStore;
userTranslationFunc?: TranslationFunc;
translationControlEventSource: TranslationControlEventSource;
}>
> = ({ children, defaultLanguage, userTranslationFunc, defaultStore, translationControlEventSource }) => {
const [translationStore, setTranslationStore] = useState<TranslationStore>(defaultStore);
const [currentLanguage, setCurrentLanguage] = useState<string | undefined>(undefined);
useEffect(() => {
async function loadLanguageFromCookies() {
const cookieLang = await getCurrentLanguageFromCookie();
const cookieLangTemp = cookieLang === null ? defaultLanguage : cookieLang;
/**
* If current is not undefined, it means that something else has set the language.
* For example if the user calls SuperTokens.changeLanguage before this
*
* We want to use the language preference from cookies only if something else has
* not set language before this
*/
setCurrentLanguage((current) => (current !== undefined ? current : cookieLangTemp));
}
void loadLanguageFromCookies();
}, [defaultLanguage, setCurrentLanguage]);
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const changeHandler: TranslationEventHandler<"LanguageChange"> = (_eventName, detail) => {
setCurrentLanguage(detail);
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const loadHandler: TranslationEventHandler<"TranslationLoaded"> = (_eventName, detail) => {
setTranslationStore((os) => mergeObjects(os, detail));
};
translationControlEventSource.on("LanguageChange", changeHandler);
translationControlEventSource.on("TranslationLoaded", loadHandler);
return () => {
translationControlEventSource.off("LanguageChange", changeHandler);
translationControlEventSource.off("TranslationLoaded", loadHandler);
};
});
const translateFunc = useCallback<TranslationFunc>(
(key: string) => {
if (userTranslationFunc !== undefined) {
return userTranslationFunc(key);
}
if (currentLanguage !== undefined) {
const res = translationStore[currentLanguage] && translationStore[currentLanguage][key];
const fallback = translationStore[defaultLanguage] && translationStore[defaultLanguage][key];
if (res === undefined) {
if (fallback !== undefined) {
return fallback;
}
return key;
}
return res;
}
throw new Error("Should never come here");
},
[translationStore, currentLanguage, defaultLanguage, userTranslationFunc]
);
if (currentLanguage === undefined) {
return null;
}
return <TranslationContext.Provider value={{ translate: translateFunc }}>{children}</TranslationContext.Provider>;
};