feat: i18n supports
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import i18next from "i18next";
|
||||
import useSWR, { SWRConfig, useSWRConfig } from "swr";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import { alpha, createTheme, List, Paper, ThemeProvider } from "@mui/material";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
@@ -16,6 +18,7 @@ import UpdateButton from "../components/layout/update-button";
|
||||
const isMacos = navigator.userAgent.includes("Mac OS X");
|
||||
|
||||
const Layout = () => {
|
||||
const { t } = useTranslation();
|
||||
const { mutate } = useSWRConfig();
|
||||
const { data } = useSWR("getVergeConfig", getVergeConfig);
|
||||
|
||||
@@ -37,6 +40,12 @@ const Layout = () => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.language) {
|
||||
i18next.changeLanguage(data.language);
|
||||
}
|
||||
}, [data?.language]);
|
||||
|
||||
const theme = useMemo(() => {
|
||||
// const background = mode === "light" ? "#f5f5f5" : "#000";
|
||||
const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
|
||||
@@ -87,7 +96,7 @@ const Layout = () => {
|
||||
<List className="the-menu" data-windrag>
|
||||
{routers.map((router) => (
|
||||
<LayoutItem key={router.label} to={router.link}>
|
||||
{router.label}
|
||||
{t(router.label)}
|
||||
</LayoutItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
@@ -6,27 +6,27 @@ import ConnectionsPage from "./connections";
|
||||
|
||||
export const routers = [
|
||||
{
|
||||
label: "Proxies",
|
||||
label: "Label-Proxies",
|
||||
link: "/",
|
||||
ele: ProxiesPage,
|
||||
},
|
||||
{
|
||||
label: "Profiles",
|
||||
label: "Label-Profiles",
|
||||
link: "/profile",
|
||||
ele: ProfilesPage,
|
||||
},
|
||||
{
|
||||
label: "Connections",
|
||||
label: "Label-Connections",
|
||||
link: "/connections",
|
||||
ele: ConnectionsPage,
|
||||
},
|
||||
{
|
||||
label: "Logs",
|
||||
label: "Label-Logs",
|
||||
link: "/logs",
|
||||
ele: LogsPage,
|
||||
},
|
||||
{
|
||||
label: "Settings",
|
||||
label: "Label-Settings",
|
||||
link: "/settings",
|
||||
ele: SettingsPage,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Paper } from "@mui/material";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ApiType } from "../services/types";
|
||||
import { getInfomation } from "../services/api";
|
||||
import BasePage from "../components/base/base-page";
|
||||
@@ -8,6 +9,8 @@ import ConnectionItem from "../components/connection/connection-item";
|
||||
|
||||
const ConnectionsPage = () => {
|
||||
const initConn = { uploadTotal: 0, downloadTotal: 0, connections: [] };
|
||||
|
||||
const { t } = useTranslation();
|
||||
const [conn, setConn] = useState<ApiType.Connections>(initConn);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -27,7 +30,7 @@ const ConnectionsPage = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<BasePage title="Connections" contentStyle={{ height: "100%" }}>
|
||||
<BasePage title={t("Connections")} contentStyle={{ height: "100%" }}>
|
||||
<Paper sx={{ boxShadow: 2, height: "100%" }}>
|
||||
<Virtuoso
|
||||
data={conn.connections}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { useRecoilState } from "recoil";
|
||||
import { Button, Paper } from "@mui/material";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { atomLogData } from "../services/states";
|
||||
import BasePage from "../components/base/base-page";
|
||||
import LogItem from "../components/log/log-item";
|
||||
|
||||
const LogPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const [logData, setLogData] = useRecoilState(atomLogData);
|
||||
|
||||
return (
|
||||
<BasePage
|
||||
title="Logs"
|
||||
title={t("Logs")}
|
||||
contentStyle={{ height: "100%" }}
|
||||
header={
|
||||
<Button
|
||||
@@ -19,7 +21,7 @@ const LogPage = () => {
|
||||
variant="contained"
|
||||
onClick={() => setLogData([])}
|
||||
>
|
||||
Clear
|
||||
{t("Clear")}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -2,6 +2,7 @@ import useSWR, { useSWRConfig } from "swr";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Box, Button, Grid, TextField } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
getProfiles,
|
||||
patchProfile,
|
||||
@@ -19,6 +20,7 @@ import ProfileItem from "../components/profile/profile-item";
|
||||
import ProfileMore from "../components/profile/profile-more";
|
||||
|
||||
const ProfilePage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { mutate } = useSWRConfig();
|
||||
|
||||
const [url, setUrl] = useState("");
|
||||
@@ -175,12 +177,12 @@ const ProfilePage = () => {
|
||||
});
|
||||
|
||||
return (
|
||||
<BasePage title="Profiles">
|
||||
<BasePage title={t("Profiles")}>
|
||||
<Box sx={{ display: "flex", mb: 2.5 }}>
|
||||
<TextField
|
||||
id="clas_verge_profile_url"
|
||||
name="profile_url"
|
||||
label="Profile URL"
|
||||
label={t("Profile URL")}
|
||||
size="small"
|
||||
fullWidth
|
||||
value={url}
|
||||
@@ -193,10 +195,10 @@ const ProfilePage = () => {
|
||||
onClick={onImport}
|
||||
sx={{ mr: 1 }}
|
||||
>
|
||||
Import
|
||||
{t("Import")}
|
||||
</Button>
|
||||
<Button variant="contained" onClick={() => setDialogOpen(true)}>
|
||||
New
|
||||
{t("New")}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import useSWR, { useSWRConfig } from "swr";
|
||||
import { useEffect } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, ButtonGroup, List, Paper } from "@mui/material";
|
||||
import { getClashConfig, updateConfigs } from "../services/api";
|
||||
import { patchClashConfig } from "../services/cmds";
|
||||
@@ -10,6 +11,7 @@ import ProxyGroup from "../components/proxy/proxy-group";
|
||||
import ProxyGlobal from "../components/proxy/proxy-global";
|
||||
|
||||
const ProxyPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { mutate } = useSWRConfig();
|
||||
const { data: proxiesData } = useSWR("getProxies", getProxies);
|
||||
const { data: clashConfig } = useSWR("getClashConfig", getClashConfig);
|
||||
@@ -45,7 +47,7 @@ const ProxyPage = () => {
|
||||
return (
|
||||
<BasePage
|
||||
contentStyle={pageStyle}
|
||||
title={showGroup ? "Proxy Groups" : "Proxies"}
|
||||
title={showGroup ? t("Proxy Groups") : t("Proxies")}
|
||||
header={
|
||||
<ButtonGroup size="small">
|
||||
{modeList.map((mode) => (
|
||||
@@ -55,7 +57,7 @@ const ProxyPage = () => {
|
||||
onClick={() => onChangeMode(mode)}
|
||||
sx={{ textTransform: "capitalize" }}
|
||||
>
|
||||
{mode}
|
||||
{t(mode)}
|
||||
</Button>
|
||||
))}
|
||||
</ButtonGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Paper } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Notice from "../components/base/base-notice";
|
||||
import BasePage from "../components/base/base-page";
|
||||
import SettingVerge from "../components/setting/setting-verge";
|
||||
@@ -6,12 +7,14 @@ import SettingClash from "../components/setting/setting-clash";
|
||||
import SettingSystem from "../components/setting/setting-system";
|
||||
|
||||
const SettingPage = () => {
|
||||
const onError = (error: any) => {
|
||||
error && Notice.error(error.toString());
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onError = (err: any) => {
|
||||
Notice.error(err?.message || err.toString());
|
||||
};
|
||||
|
||||
return (
|
||||
<BasePage title="Settings">
|
||||
<BasePage title={t("Settings")}>
|
||||
<Paper sx={{ borderRadius: 1, boxShadow: 2, mb: 3 }}>
|
||||
<SettingClash onError={onError} />
|
||||
</Paper>
|
||||
|
||||
Reference in New Issue
Block a user