Files
kiss-translator/src/views/Selection/Tranbox.js

282 lines
7.6 KiB
JavaScript
Raw Normal View History

2023-10-23 18:02:42 +08:00
import { SettingProvider } from "../../hooks/Setting";
import ThemeProvider from "../../hooks/Theme";
import DraggableResizable from "./DraggableResizable";
import Header from "../Popup/Header";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
import Grid from "@mui/material/Grid";
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
2023-10-24 17:58:37 +08:00
import Alert from "@mui/material/Alert";
import CircularProgress from "@mui/material/CircularProgress";
2023-10-23 18:02:42 +08:00
import { useI18n } from "../../hooks/I18n";
2023-10-24 17:58:37 +08:00
import {
OPT_TRANS_ALL,
OPT_LANGS_FROM,
OPT_LANGS_TO,
DEFAULT_TRANS_APIS,
OPT_TRANS_BAIDU,
} from "../../config";
import { useEffect, useState, useRef } from "react";
import { apiTranslate } from "../../apis";
import { isValidWord } from "../../libs/utils";
2023-10-23 18:02:42 +08:00
2023-10-24 17:58:37 +08:00
const exchangeMap = {
word_third: "第三人称单数",
word_ing: "现在分词",
word_done: "过去式",
word_past: "过去分词",
word_pl: "复数",
word_proto: "原词",
};
function DictCont({ dictResult }) {
if (!dictResult) {
return;
}
return (
<Box>
<h4>{dictResult.simple_means?.word_name}</h4>
<p>
{Object.entries(dictResult.simple_means?.exchange || {}).map(
([key, val]) => (
<span key={key}>{`${exchangeMap[key] || key}: ${val.join(
","
)}; `}</span>
)
)}
</p>
<p>
{Object.values(dictResult.simple_means?.tags || {})
.map((vals) => vals.join(", "))
.join(", ")}
</p>
{dictResult.simple_means?.symbols?.map(({ ph_en, ph_am, parts }, idx) => (
<div key={idx}>
<p>{`英: [${ph_en}] 美: [${ph_am}]`}</p>
{parts.map(({ part, means }, idx) => (
<p key={idx}>{`[${part}]: ${means.join("; ")}`}</p>
))}
</div>
))}
</Box>
);
}
function TranCont({ text, translator, fromLang, toLang, transApis }) {
const i18n = useI18n();
const [trText, setTrText] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [dictResult, setDictResult] = useState(null);
useEffect(() => {
(async () => {
try {
setLoading(true);
setTrText("");
setError("");
setDictResult(null);
const apis = { ...transApis, ...DEFAULT_TRANS_APIS };
const apiSetting = apis[translator];
const tranRes = await apiTranslate({
text,
translator,
fromLang,
toLang,
apiSetting,
});
setTrText(tranRes[0]);
// 词典
if (isValidWord(text) && toLang.startsWith("zh")) {
if (fromLang === "en" && translator === OPT_TRANS_BAIDU) {
setDictResult(tranRes[2]);
} else {
const dictRes = await apiTranslate({
text,
translator: OPT_TRANS_BAIDU,
fromLang: "en",
toLang: "zh-CN",
apiSetting: apis[OPT_TRANS_BAIDU],
});
setDictResult(dictRes[2].dict_result);
}
}
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
})();
}, [text, translator, fromLang, toLang, transApis]);
return (
<>
<Box>
<TextField
label={i18n("translated_text")}
fullWidth
multiline
value={trText}
/>
</Box>
{loading && <CircularProgress size={24} />}
{error && <Alert severity="error">{error}</Alert>}
{dictResult && <DictCont dictResult={dictResult} />}
</>
);
}
function TranForm({ text, setText, tranboxSetting, transApis }) {
2023-10-23 18:02:42 +08:00
const i18n = useI18n();
2023-10-24 17:58:37 +08:00
const [editMode, setEditMode] = useState(false);
const [editText, setEditText] = useState("");
const [translator, setTranslator] = useState(tranboxSetting.translator);
const [fromLang, setFromLang] = useState(tranboxSetting.fromLang);
const [toLang, setToLang] = useState(tranboxSetting.toLang);
const inputRef = useRef(null);
2023-10-23 18:02:42 +08:00
return (
<Stack sx={{ p: 2 }} spacing={2}>
<Box>
<Grid container spacing={2} columns={12}>
<Grid item xs={4} sm={4} md={4} lg={4}>
<TextField
select
SelectProps={{ MenuProps: { disablePortal: true } }}
fullWidth
size="small"
name="fromLang"
value={fromLang}
label={i18n("from_lang")}
2023-10-24 17:58:37 +08:00
onChange={(e) => {
setFromLang(e.target.value);
}}
2023-10-23 18:02:42 +08:00
>
{OPT_LANGS_FROM.map(([lang, name]) => (
<MenuItem key={lang} value={lang}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={4} sm={4} md={4} lg={4}>
<TextField
select
SelectProps={{ MenuProps: { disablePortal: true } }}
fullWidth
size="small"
name="toLang"
value={toLang}
label={i18n("to_lang")}
2023-10-24 17:58:37 +08:00
onChange={(e) => {
setToLang(e.target.value);
}}
2023-10-23 18:02:42 +08:00
>
{OPT_LANGS_TO.map(([lang, name]) => (
<MenuItem key={lang} value={lang}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={4} sm={4} md={4} lg={4}>
<TextField
select
SelectProps={{ MenuProps: { disablePortal: true } }}
fullWidth
size="small"
value={translator}
name="translator"
label={i18n("translate_service")}
2023-10-24 17:58:37 +08:00
onChange={(e) => {
setTranslator(e.target.value);
}}
2023-10-23 18:02:42 +08:00
>
{OPT_TRANS_ALL.map((item) => (
<MenuItem key={item} value={item}>
{item}
</MenuItem>
))}
</TextField>
</Grid>
</Grid>
</Box>
2023-10-24 17:58:37 +08:00
<Box>
<TextField
label={i18n("original_text")}
inputRef={inputRef}
fullWidth
multiline
value={editMode ? editText : text}
disabled={!editMode}
onChange={(e) => {
setEditText(e.target.value);
}}
onClick={() => {
setEditMode(true);
setEditText(text);
const timer = setTimeout(() => {
clearTimeout(timer);
inputRef.current?.focus();
}, 100);
}}
onBlur={() => {
setEditMode(false);
setText(editText.trim());
}}
/>
</Box>
<TranCont
text={text}
translator={translator}
fromLang={fromLang}
toLang={toLang}
transApis={transApis}
/>
2023-10-23 18:02:42 +08:00
</Stack>
);
}
2023-10-24 17:58:37 +08:00
export default function TranBox({
text,
setText,
setShowBox,
tranboxSetting,
transApis,
boxSize,
setBoxSize,
boxPosition,
setBoxPosition,
}) {
2023-10-23 18:02:42 +08:00
return (
<SettingProvider>
<ThemeProvider>
<DraggableResizable
2023-10-24 17:58:37 +08:00
defaultPosition={boxPosition}
defaultSize={boxSize}
2023-10-23 18:02:42 +08:00
header={<Header setShowPopup={setShowBox} />}
2023-10-24 17:58:37 +08:00
onChangeSize={setBoxSize}
onChangePosition={setBoxPosition}
2023-10-23 18:02:42 +08:00
>
<Divider />
2023-10-24 17:58:37 +08:00
<TranForm
text={text}
setText={setText}
tranboxSetting={tranboxSetting}
transApis={transApis}
/>
2023-10-23 18:02:42 +08:00
</DraggableResizable>
</ThemeProvider>
</SettingProvider>
);
}