Skip to content

Commit 1ee33de

Browse files
committed
add translation
1 parent 2198240 commit 1ee33de

File tree

9 files changed

+134
-144
lines changed

9 files changed

+134
-144
lines changed

xinference/web/ui/src/App.js

+13-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { CssBaseline, ThemeProvider } from "@mui/material";
22
import { HashRouter, Route, Routes } from "react-router-dom";
3-
import { ApiContextProvider } from "./components/apiContext";
4-
import { useMode } from "./theme";
3+
import { useMode, ApiContextProvider, LanguageContextProvider } from "./theme";
54
import Layout from "./scenes/_layout";
65

76
import RunningModels from "./scenes/running_models";
@@ -14,16 +13,18 @@ function App() {
1413
<div className="app">
1514
<HashRouter>
1615
<ThemeProvider theme={theme}>
17-
<ApiContextProvider>
18-
<CssBaseline />
19-
<Routes>
20-
<Route element={<Layout />}>
21-
<Route path="/" element={<LaunchModel />} />
22-
<Route path="/running_models" element={<RunningModels />} />
23-
<Route path="/register_model" element={<RegisterModel />} />
24-
</Route>
25-
</Routes>
26-
</ApiContextProvider>
16+
<LanguageContextProvider>
17+
<ApiContextProvider>
18+
<CssBaseline />
19+
<Routes>
20+
<Route element={<Layout />}>
21+
<Route path="/" element={<LaunchModel />} />
22+
<Route path="/running_models" element={<RunningModels />} />
23+
<Route path="/register_model" element={<RegisterModel />} />
24+
</Route>
25+
</Routes>
26+
</ApiContextProvider>
27+
</LanguageContextProvider>
2728
</ThemeProvider>
2829
</HashRouter>
2930
</div>

xinference/web/ui/src/components/MenuSide.js

+84-31
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useState, useContext } from "react";
22
import {
33
Box,
44
Drawer,
@@ -7,47 +7,56 @@ import {
77
ListItemButton,
88
ListItemIcon,
99
ListItemText,
10+
Select,
11+
MenuItem,
1012
Typography,
1113
useTheme,
1214
} from "@mui/material";
1315
import {
1416
ChevronRightOutlined,
1517
RocketLaunchOutlined,
1618
SmartToyOutlined,
19+
TranslateOutlined,
1720
AddBoxOutlined,
1821
GitHub,
1922
} from "@mui/icons-material";
2023
import icon from "../media/icon.webp";
2124
import { useLocation, useNavigate } from "react-router-dom";
22-
23-
const navItems = [
24-
{
25-
text: "Launch Model",
26-
icon: <RocketLaunchOutlined />,
27-
},
28-
{
29-
text: "Running Models",
30-
icon: <SmartToyOutlined />,
31-
},
32-
{
33-
text: "Register Model",
34-
icon: <AddBoxOutlined />,
35-
},
36-
{
37-
text: "Contact Us",
38-
icon: <GitHub />,
39-
},
40-
];
25+
import { LanguageContext } from "../theme";
4126

4227
const MenuSide = () => {
4328
const theme = useTheme();
29+
const { translation, translation_dict, language, setLanguage } =
30+
useContext(LanguageContext);
31+
4432
const { pathname } = useLocation();
4533
const [active, setActive] = useState("");
4634
const navigate = useNavigate();
4735
const [drawerWidth, setDrawerWidth] = useState(
48-
`${Math.min(Math.max(window.innerWidth * 0.2, 287), 320)}px`,
36+
`${Math.min(Math.max(window.innerWidth * 0.2, 287), 320)}px`
4937
);
5038

39+
const navItems = [
40+
{
41+
link: "launch_model",
42+
icon: <RocketLaunchOutlined />,
43+
},
44+
{
45+
link: "running_models",
46+
icon: <SmartToyOutlined />,
47+
},
48+
{
49+
link: "register_model",
50+
icon: <AddBoxOutlined />,
51+
},
52+
{
53+
link: "contact_us",
54+
icon: <GitHub />,
55+
},
56+
];
57+
58+
console.log(translation);
59+
5160
useEffect(() => {
5261
setActive(pathname.substring(1));
5362
}, [pathname]);
@@ -62,7 +71,7 @@ const MenuSide = () => {
6271
const newScreenWidth = window.innerWidth;
6372
const newMaxDrawerWidth = Math.min(
6473
Math.max(newScreenWidth * 0.2, 287),
65-
320,
74+
320
6675
);
6776
setDrawerWidth(`${newMaxDrawerWidth}px`);
6877
};
@@ -118,31 +127,32 @@ const MenuSide = () => {
118127
</Box>
119128
</Box>
120129

130+
{/* Pages or Screens */}
121131
<Box>
122132
<Box width="100%">
123133
<Box m="1.5rem 2rem 2rem 3rem"></Box>
124134
<List>
125-
{navItems.map(({ text, icon }) => {
135+
{navItems.map(({ link, icon }) => {
126136
if (!icon) {
127137
return (
128-
<Typography key={text} sx={{ m: "2.25rem 0 1rem 3rem" }}>
129-
{text}
138+
<Typography
139+
key={translation.page_title[link]}
140+
sx={{ m: "2.25rem 0 1rem 3rem" }}
141+
>
142+
{translation.page_title[link]}
130143
</Typography>
131144
);
132145
}
133146

134-
const link = text.toLowerCase().replace(" ", "_");
135-
console.log(link);
136-
137147
return (
138-
<ListItem key={text}>
148+
<ListItem key={translation.page_title[link]}>
139149
<ListItemButton
140150
onClick={() => {
141151
if (link === "contact_us") {
142152
window.open(
143153
"https://github.com/xorbitsai/inference",
144154
"_blank",
145-
"noreferrer",
155+
"noreferrer"
146156
);
147157
} else if (link === "launch_model") {
148158
navigate(`/`);
@@ -162,12 +172,55 @@ const MenuSide = () => {
162172
>
163173
{icon}
164174
</ListItemIcon>
165-
<ListItemText primary={text} />
175+
<ListItemText primary={translation.page_title[link]} />
166176
<ChevronRightOutlined sx={{ ml: "auto" }} />
167177
</ListItemButton>
168178
</ListItem>
169179
);
170180
})}
181+
182+
{/* Translation */}
183+
<ListItem key="translation">
184+
<ListItemButton
185+
onClick={() => {}}
186+
disableRipple={true}
187+
sx={{
188+
"&:hover": {
189+
backgroundColor: "transparent",
190+
},
191+
}}
192+
>
193+
<ListItemIcon
194+
sx={{
195+
ml: "2rem",
196+
mr: "-0.4rem",
197+
}}
198+
>
199+
<TranslateOutlined />
200+
</ListItemIcon>
201+
<Select
202+
value={language}
203+
onChange={(event) => setLanguage(event.target.value)}
204+
variant="outlined"
205+
displayEmpty
206+
sx={{
207+
"& .MuiOutlinedInput-input": {
208+
padding: "10px 0px 10px 14px",
209+
height: "fit-content",
210+
},
211+
"& .MuiOutlinedInput-root": {
212+
marginLeft: "-14px",
213+
},
214+
}}
215+
>
216+
{Object.keys(translation_dict).map((lang) => (
217+
<MenuItem key={lang} value={lang}>
218+
{lang}
219+
</MenuItem>
220+
))}
221+
</Select>
222+
</ListItemButton>
223+
</ListItem>
171224
</List>
172225
</Box>
173226
</Box>

xinference/web/ui/src/components/Title.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import { useContext } from "react";
12
import { Typography, Box } from "@mui/material";
3+
import { LanguageContext } from "../theme";
24

35
const Title = ({ title, subtitle }) => {
6+
const { translation } = useContext(LanguageContext);
47
return (
58
<Box mb="30px">
69
<Typography
@@ -9,7 +12,7 @@ const Title = ({ title, subtitle }) => {
912
fontWeight="bold"
1013
sx={{ m: "0 0 5px 0" }}
1114
>
12-
{title}
15+
{translation.page_title[title.toLowerCase().replace(" ", "_")]}
1316
</Typography>
1417
<Typography variant="h5" color="#3d3d3d">
1518
{subtitle}

xinference/web/ui/src/components/apiContext.js

-29
This file was deleted.

xinference/web/ui/src/scenes/launch_model/index.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ import React, { useContext, useState, useEffect } from "react";
22
import ModelCard from "./modelCard";
33
import Title from "../../components/Title";
44
import { Box, TextField, FormControl } from "@mui/material";
5-
import { ApiContext } from "../../components/apiContext";
5+
import { ApiContext } from "../../theme";
66

77
const LaunchModel = () => {
8-
let endPoint = useContext(ApiContext).endPoint;
9-
const [registrationData, setRegistrationData] = useState([]);
10-
const { isCallingApi, setIsCallingApi } = useContext(ApiContext);
11-
const { isUpdatingModel } = useContext(ApiContext);
8+
const { endPoint, isCallingApi, setIsCallingApi, isUpdatingModel } =
9+
useContext(ApiContext);
1210

13-
// States used for filtering
11+
const [registrationData, setRegistrationData] = useState([]);
1412
const [searchTerm, setSearchTerm] = useState("");
1513

1614
const handleChange = (event) => {
@@ -53,14 +51,14 @@ const LaunchModel = () => {
5351
`${endPoint}/v1/model_registrations/LLM/${registration.model_name}`,
5452
{
5553
method: "GET",
56-
},
54+
}
5755
);
5856

5957
return {
6058
...(await desc.json()),
6159
is_builtin: registration.is_builtin,
6260
};
63-
}),
61+
})
6462
);
6563

6664
setRegistrationData(newRegistrationData);

xinference/web/ui/src/scenes/launch_model/modelCard.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useContext, useEffect } from "react";
22
import { v1 as uuidv1 } from "uuid";
3-
import { ApiContext } from "../../components/apiContext";
3+
import { ApiContext } from "../../theme";
44
import { FormControl, InputLabel, Select, MenuItem, Box } from "@mui/material";
55
import { CircularProgress } from "@mui/material";
66
import {
@@ -15,10 +15,11 @@ const CARD_HEIGHT = 350;
1515
const CARD_WIDTH = 270;
1616

1717
const ModelCard = ({ url, modelData }) => {
18+
const { isCallingApi, setIsCallingApi, isUpdatingModel } =
19+
useContext(ApiContext);
20+
1821
const [hover, setHover] = useState(false);
1922
const [selected, setSelected] = useState(false);
20-
const { isCallingApi, setIsCallingApi } = useContext(ApiContext);
21-
const { isUpdatingModel } = useContext(ApiContext);
2223

2324
// Model parameter selections
2425
const [modelFormat, setModelFormat] = useState("");
@@ -47,7 +48,7 @@ const ModelCard = ({ url, modelData }) => {
4748
...new Set(
4849
modelFamily
4950
.filter((spec) => spec.model_format === modelFormat)
50-
.map((spec) => spec.model_size_in_billions),
51+
.map((spec) => spec.model_size_in_billions)
5152
),
5253
];
5354
setSizeOptions(sizes);
@@ -63,9 +64,9 @@ const ModelCard = ({ url, modelData }) => {
6364
.filter(
6465
(spec) =>
6566
spec.model_format === modelFormat &&
66-
spec.model_size_in_billions === parseFloat(modelSize),
67+
spec.model_size_in_billions === parseFloat(modelSize)
6768
)
68-
.flatMap((spec) => spec.quantizations),
69+
.flatMap((spec) => spec.quantizations)
6970
),
7071
];
7172
setQuantizationOptions(quants);

0 commit comments

Comments
 (0)