@@ -186,6 +210,7 @@ const Sicp: React.FC = () => {
>
+ {languageToggle}
{loading ? (
{loadingComponent}
) : section === 'index' ? (
diff --git a/src/pages/sicp/subcomponents/SicpLanguageProvider.tsx b/src/pages/sicp/subcomponents/SicpLanguageProvider.tsx
new file mode 100644
index 0000000000..ad72a3926e
--- /dev/null
+++ b/src/pages/sicp/subcomponents/SicpLanguageProvider.tsx
@@ -0,0 +1,45 @@
+import { createContext, useCallback, useContext, useState } from 'react';
+import {
+ getSicpLanguageFromLocalStorage,
+ SICP_DEFAULT_LANGUAGE,
+ type SicpSupportedLanguage
+} from 'src/features/sicp/utils/SicpUtils';
+
+type SicpLanguageContext = {
+ sicpLanguage: SicpSupportedLanguage;
+ setSicpLanguage: (lang: SicpSupportedLanguage) => void;
+};
+
+const sicpLanguageContext = createContext(undefined);
+
+export const useSicpLanguageContext = (): SicpLanguageContext => {
+ const context = useContext(sicpLanguageContext);
+ if (!context) {
+ throw new Error('useSicpLanguageContext must be used inside an SicpLanguageContextProvider');
+ }
+
+ return context;
+};
+
+export const SicpLanguageContextProvider: React.FC<{ children: React.ReactNode }> = ({
+ children
+}) => {
+ const [lang, setLang] = useState(
+ getSicpLanguageFromLocalStorage() ?? SICP_DEFAULT_LANGUAGE
+ );
+
+ const handleLangChange = useCallback((newLang: SicpSupportedLanguage) => {
+ setLang(newLang);
+ }, []);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/pages/sicp/subcomponents/SicpToc.tsx b/src/pages/sicp/subcomponents/SicpToc.tsx
index 84fbced81f..407e5ab15c 100644
--- a/src/pages/sicp/subcomponents/SicpToc.tsx
+++ b/src/pages/sicp/subcomponents/SicpToc.tsx
@@ -1,9 +1,11 @@
import { Tree, TreeNodeInfo } from '@blueprintjs/core';
import { cloneDeep } from 'lodash';
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router';
+import Constants from 'src/commons/utils/Constants';
-import toc from '../../../features/sicp/data/toc.json';
+import fallbackToc from '../../../features/sicp/data/toc.json';
+import { useSicpLanguageContext } from './SicpLanguageProvider';
type TocProps = OwnProps;
@@ -15,8 +17,17 @@ type OwnProps = {
* Table of contents of SICP.
*/
const SicpToc: React.FC = props => {
- const [sidebarContent, setSidebarContent] = useState(toc as TreeNodeInfo[]);
+ const [sidebarContent, setSidebarContent] = useState(fallbackToc as TreeNodeInfo[]);
const navigate = useNavigate();
+ const { sicpLanguage } = useSicpLanguageContext();
+
+ useEffect(() => {
+ const loadLocalizedToc = async () => {
+ const resp = await fetch(`${Constants.sicpBackendUrl}json/${sicpLanguage}/toc.json`);
+ return (await resp.json()) as TreeNodeInfo[];
+ };
+ loadLocalizedToc().then(setSidebarContent).catch(console.error);
+ }, [sicpLanguage]);
const handleNodeExpand = (_node: TreeNodeInfo, path: integer[]) => {
const newState = cloneDeep(sidebarContent);
diff --git a/src/pages/sicp/subcomponents/__tests__/SicpIndexPage.test.tsx b/src/pages/sicp/subcomponents/__tests__/SicpIndexPage.test.tsx
index ae300b4173..4f2fa6bff3 100644
--- a/src/pages/sicp/subcomponents/__tests__/SicpIndexPage.test.tsx
+++ b/src/pages/sicp/subcomponents/__tests__/SicpIndexPage.test.tsx
@@ -2,11 +2,14 @@ import { MemoryRouter } from 'react-router';
import { renderTreeJson } from 'src/commons/utils/TestUtils';
import SicpIndexPage from '../../subcomponents/SicpIndexPage';
+import { SicpLanguageContextProvider } from '../SicpLanguageProvider';
test('Sicp index page', async () => {
const tree = await renderTreeJson(
-
+
+
+
);
expect(tree).toMatchSnapshot();
diff --git a/src/pages/sicp/subcomponents/__tests__/SicpToc.test.tsx b/src/pages/sicp/subcomponents/__tests__/SicpToc.test.tsx
index 73c8bf41a9..791e9d2d6d 100644
--- a/src/pages/sicp/subcomponents/__tests__/SicpToc.test.tsx
+++ b/src/pages/sicp/subcomponents/__tests__/SicpToc.test.tsx
@@ -1,6 +1,7 @@
import { MemoryRouter } from 'react-router';
import { renderTreeJson } from 'src/commons/utils/TestUtils';
+import { SicpLanguageContextProvider } from '../SicpLanguageProvider';
import SicpToc from '../SicpToc';
test('Sicp toc renders correctly', async () => {
@@ -10,7 +11,9 @@ test('Sicp toc renders correctly', async () => {
const tree = await renderTreeJson(
-
+
+
+
);
expect(tree).toMatchSnapshot();