diff --git a/src/config/api.js b/src/config/api.js
index 1d30682..ad5dfdb 100644
--- a/src/config/api.js
+++ b/src/config/api.js
@@ -63,6 +63,9 @@ export const OPT_LANGDETECTOR_ALL = [
OPT_TRANS_TENCENT,
];
+export const OPT_DICT_ALL = [OPT_TRANS_BAIDU];
+export const OPT_DICT_MAP = new Set(OPT_DICT_ALL);
+
// 翻译引擎特殊集合
export const API_SPE_TYPES = {
// 内置翻译
diff --git a/src/config/i18n.js b/src/config/i18n.js
index 9447de1..f764c39 100644
--- a/src/config/i18n.js
+++ b/src/config/i18n.js
@@ -1513,4 +1513,14 @@ export const I18N = {
en: `Placeholder tags`,
zh_TW: `佔位標`,
},
+ detected_lang: {
+ zh: `语言检测`,
+ en: `Language detection`,
+ zh_TW: `語言偵測`,
+ },
+ detected_result: {
+ zh: `检测结果`,
+ en: `Detect result`,
+ zh_TW: `檢測結果`,
+ },
};
diff --git a/src/config/setting.js b/src/config/setting.js
index e4d52e0..bb04580 100644
--- a/src/config/setting.js
+++ b/src/config/setting.js
@@ -88,7 +88,7 @@ export const DEFAULT_TRANBOX_SETTING = {
simpleStyle: false, // 是否简洁界面
followSelection: false, // 翻译框是否跟随选中文本
triggerMode: OPT_TRANBOX_TRIGGER_CLICK, // 触发翻译方式
- extStyles: "", // 附加样式
+ // extStyles: "", // 附加样式
enDict: OPT_DICT_BAIDU, // 英文词典
};
diff --git a/src/views/Options/Navigator.js b/src/views/Options/Navigator.js
index bcdf36a..0e40946 100644
--- a/src/views/Options/Navigator.js
+++ b/src/views/Options/Navigator.js
@@ -14,7 +14,7 @@ import ApiIcon from "@mui/icons-material/Api";
import InputIcon from "@mui/icons-material/Input";
import SelectAllIcon from "@mui/icons-material/SelectAll";
import EventNoteIcon from "@mui/icons-material/EventNote";
-import MouseIcon from '@mui/icons-material/Mouse';
+import MouseIcon from "@mui/icons-material/Mouse";
function LinkItem({ label, url, icon }) {
const match = useMatch(url);
@@ -77,6 +77,12 @@ export default function Navigator(props) {
url: "/words",
icon: ,
},
+ {
+ id: "playground",
+ label: "Playground",
+ url: "/playground",
+ icon: ,
+ },
{ id: "about", label: i18n("about"), url: "/about", icon: },
];
return (
diff --git a/src/views/Options/Playground.js b/src/views/Options/Playground.js
new file mode 100644
index 0000000..90207bf
--- /dev/null
+++ b/src/views/Options/Playground.js
@@ -0,0 +1,28 @@
+import { useState } from "react";
+import TranForm from "../Selection/TranForm";
+import { DEFAULT_SETTING, DEFAULT_TRANBOX_SETTING } from "../../config";
+import { useSetting } from "../../hooks/Setting";
+
+export default function Playgound() {
+ const [text, setText] = useState("");
+ const { setting } = useSetting();
+ const { transApis, langDetector, tranboxSetting } =
+ setting || DEFAULT_SETTING;
+ const { apiSlugs, fromLang, toLang, toLang2, enDict } =
+ tranboxSetting || DEFAULT_TRANBOX_SETTING;
+ return (
+
+ );
+}
diff --git a/src/views/Options/Tranbox.js b/src/views/Options/Tranbox.js
index 1e2ddd6..6a322fa 100644
--- a/src/views/Options/Tranbox.js
+++ b/src/views/Options/Tranbox.js
@@ -10,6 +10,7 @@ import {
OPT_TRANBOX_TRIGGER_CLICK,
OPT_TRANBOX_TRIGGER_ALL,
OPT_DICT_BAIDU,
+ OPT_DICT_ALL,
} from "../../config";
import ShortcutInput from "./ShortcutInput";
import FormControlLabel from "@mui/material/FormControlLabel";
@@ -65,7 +66,7 @@ export default function Tranbox() {
simpleStyle = false,
followSelection = false,
triggerMode = OPT_TRANBOX_TRIGGER_CLICK,
- extStyles = "",
+ // extStyles = "",
enDict = OPT_DICT_BAIDU,
} = tranboxSetting;
@@ -153,7 +154,8 @@ export default function Tranbox() {
helperText={i18n("to_lang2_helper")}
onChange={handleChange}
>
- {[["none", "None"], ...OPT_LANGS_TO].map(([lang, name]) => (
+
+ {OPT_LANGS_TO.map(([lang, name]) => (
@@ -172,7 +174,11 @@ export default function Tranbox() {
onChange={handleChange}
>
-
+ {OPT_DICT_ALL.map((item) => (
+
+ ))}
@@ -305,7 +311,7 @@ export default function Tranbox() {
-
+ /> */}
);
diff --git a/src/views/Options/index.js b/src/views/Options/index.js
index a167713..02d5ba6 100644
--- a/src/views/Options/index.js
+++ b/src/views/Options/index.js
@@ -21,6 +21,7 @@ import Apis from "./Apis";
import InputSetting from "./InputSetting";
import Tranbox from "./Tranbox";
import FavWords from "./FavWords";
+import Playgound from "./Playground";
import MouseHoverSetting from "./MouseHover";
import Loading from "../../hooks/Loading";
@@ -111,6 +112,7 @@ export default function Options() {
} />
} />
} />
+ } />
} />
diff --git a/src/views/Popup/index.js b/src/views/Popup/index.js
index 9576a5c..3c8153e 100644
--- a/src/views/Popup/index.js
+++ b/src/views/Popup/index.js
@@ -312,20 +312,6 @@ export default function Popup({ setShowPopup, translator }) {
label={i18n("shadowroot_alt")}
/>
-
-
- }
- label={i18n("transonly_alt")}
- />
-
+
+
+ }
+ label={i18n("transonly_alt")}
+ />
+
{
+ useEffect(() => {
if (!dictResult) {
- return text;
+ return;
}
- return [
+ const copyText = [
dictResult.src,
dictResult.voice
?.map(Object.entries)
@@ -63,29 +63,22 @@ export default function DictCont({ text }) {
})
.join("\n"),
].join("\n");
- }, [text, dictResult]);
+
+ setCopyText(copyText);
+ }, [dictResult, setCopyText]);
if (loading) {
return ;
}
- return (
-
- {text && (
-
-
- {dictResult?.src || text}
-
-
-
-
-
-
- )}
+ if (error) {
+ return {error};
+ }
- {error && {error}}
+ return baidu: {text};
- {dictResult && (
+ {
+ /* {dictResult && (
{dictResult.voice
@@ -112,7 +105,32 @@ export default function DictCont({ text }) {
))}
+ )} */
+ }
+}
+
+export default function DictCont({ text, enDict }) {
+ const [copyText, setCopyText] = useState(text);
+
+ const dictMap = {
+ [OPT_TRANS_BAIDU]: ,
+ };
+
+ return (
+
+ {text && (
+
+
+ {text}
+
+
+
+
+
+
)}
+
+ {dictMap[enDict] || Dict not support}
);
}
diff --git a/src/views/Selection/SugCont.js b/src/views/Selection/SugCont.js
index b64ddd8..1afe01f 100644
--- a/src/views/Selection/SugCont.js
+++ b/src/views/Selection/SugCont.js
@@ -21,7 +21,7 @@ export default function SugCont({ text }) {
}
return (
-
+
{sugs.map(({ k, v }) => (
{k}
diff --git a/src/views/Selection/TranBox.js b/src/views/Selection/TranBox.js
index 28ac672..996fe4b 100644
--- a/src/views/Selection/TranBox.js
+++ b/src/views/Selection/TranBox.js
@@ -2,13 +2,9 @@ import { SettingProvider } from "../../hooks/Setting";
import ThemeProvider from "../../hooks/Theme";
import DraggableResizable from "./DraggableResizable";
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";
import IconButton from "@mui/material/IconButton";
-import DoneIcon from "@mui/icons-material/Done";
import DragIndicatorIcon from "@mui/icons-material/DragIndicator";
import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
@@ -19,14 +15,9 @@ import LockOpenIcon from "@mui/icons-material/LockOpen";
import CloseIcon from "@mui/icons-material/Close";
import Typography from "@mui/material/Typography";
import { useI18n } from "../../hooks/I18n";
-import { OPT_LANGS_FROM, OPT_LANGS_TO } from "../../config";
-import { useState, useRef, useMemo } from "react";
-import TranCont from "./TranCont";
-import DictCont from "./DictCont";
-import SugCont from "./SugCont";
-import CopyBtn from "./CopyBtn";
-import { isValidWord } from "../../libs/utils";
+import { useState } from "react";
import { isMobile } from "../../libs/mobile";
+import TranForm from "./TranForm.js";
function Header({
setShowPopup,
@@ -46,7 +37,6 @@ function Header({
return (
e.stopPropagation()}
onTouchEnd={(e) => e.stopPropagation()}
>
@@ -120,188 +110,11 @@ function Header({
);
}
-function TranForm({
- text,
- setText,
- tranboxSetting,
- transApis,
- simpleStyle,
- langDetector,
- enDict,
-}) {
- const i18n = useI18n();
-
- const [editMode, setEditMode] = useState(false);
- const [editText, setEditText] = useState("");
- const [apiSlug, setApiSlug] = useState(tranboxSetting.apiSlug);
- const [fromLang, setFromLang] = useState(tranboxSetting.fromLang);
- const [toLang, setToLang] = useState(tranboxSetting.toLang);
- const inputRef = useRef(null);
-
- const optApis = useMemo(
- () =>
- transApis
- .filter((api) => !api.isDisabled)
- .map((api) => ({
- key: api.apiSlug,
- name: api.apiName || api.apiSlug,
- })),
- [transApis]
- );
-
- return (
-
- {!simpleStyle && (
- <>
-
-
-
- {
- setFromLang(e.target.value);
- }}
- >
- {OPT_LANGS_FROM.map(([lang, name]) => (
-
- ))}
-
-
-
- {
- setToLang(e.target.value);
- }}
- >
- {OPT_LANGS_TO.map(([lang, name]) => (
-
- ))}
-
-
-
- {
- setApiSlug(e.target.value);
- }}
- >
- {optApis.map(({ key, name }) => (
-
- ))}
-
-
-
-
-
-
- {
- setEditText(e.target.value);
- }}
- onFocus={() => {
- setEditMode(true);
- setEditText(text);
- }}
- onBlur={() => {
- setEditMode(false);
- setText(editText.trim());
- }}
- InputProps={{
- endAdornment: (
-
- {editMode ? (
- {
- e.stopPropagation();
- }}
- >
-
-
- ) : (
-
- )}
-
- ),
- }}
- />
-
- >
- )}
-
- {(!simpleStyle ||
- !isValidWord(text) ||
- !toLang.startsWith("zh") ||
- enDict === "-") && (
-
- )}
-
- {enDict !== "-" && isValidWord(text) && (
- <>
-
-
- >
- )}
-
- );
-}
-
export default function TranBox({
text,
setText,
setShowBox,
- tranboxSetting,
+ tranboxSetting: { apiSlugs, fromLang, toLang, toLang2 },
transApis,
boxSize,
setBoxSize,
@@ -313,7 +126,7 @@ export default function TranBox({
setHideClickAway,
followSelection,
setFollowSelection,
- extStyles,
+ extStyles = "",
langDetector,
enDict,
}) {
@@ -343,15 +156,20 @@ export default function TranBox({
onMouseEnter={() => setMouseHover(true)}
onMouseLeave={() => setMouseHover(false)}
>
-
+
+
+
diff --git a/src/views/Selection/TranCont.js b/src/views/Selection/TranCont.js
index fef744c..c1ab854 100644
--- a/src/views/Selection/TranCont.js
+++ b/src/views/Selection/TranCont.js
@@ -3,31 +3,32 @@ import Box from "@mui/material/Box";
import CircularProgress from "@mui/material/CircularProgress";
import Stack from "@mui/material/Stack";
import { useI18n } from "../../hooks/I18n";
-import { DEFAULT_API_SETTING } from "../../config";
-import { useEffect, useState } from "react";
+import { useEffect, useState, useMemo } from "react";
import { apiTranslate } from "../../apis";
import CopyBtn from "./CopyBtn";
import Typography from "@mui/material/Typography";
import Alert from "@mui/material/Alert";
-import { tryDetectLang } from "../../libs/detect";
export default function TranCont({
text,
- apiSlug,
fromLang,
toLang,
- toLang2 = "en",
+ apiSlug,
transApis,
simpleStyle = false,
- langDetector,
}) {
const i18n = useI18n();
const [trText, setTrText] = useState("");
- const [loading, setLoading] = useState(true);
+ const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
+ const apiSetting = useMemo(
+ () => transApis.find((api) => api.apiSlug === apiSlug),
+ [transApis, apiSlug]
+ );
+
useEffect(() => {
- if (!text?.trim()) {
+ if (!text?.trim() || !apiSetting) {
return;
}
@@ -37,24 +38,13 @@ export default function TranCont({
setTrText("");
setError("");
- let to = toLang;
- if (fromLang === "auto" && toLang !== toLang2 && toLang2 !== "none") {
- const detectLang = await tryDetectLang(text, "true", langDetector);
- if (detectLang === toLang) {
- to = toLang2;
- }
- }
-
- const apiSetting =
- transApis.find((api) => api.apiSlug === apiSlug) ||
- DEFAULT_API_SETTING;
const [trText] = await apiTranslate({
text,
- apiSlug,
fromLang,
- toLang: to,
+ toLang,
apiSetting,
});
+
setTrText(trText);
} catch (err) {
setError(err.message);
@@ -62,11 +52,11 @@ export default function TranCont({
setLoading(false);
}
})();
- }, [text, apiSlug, fromLang, toLang, toLang2, transApis, langDetector]);
+ }, [text, fromLang, toLang, apiSetting]);
if (simpleStyle) {
return (
-
+
{error ? (
{error}
) : loading ? (
@@ -79,10 +69,10 @@ export default function TranCont({
}
return (
-
+
{
+ if (!text.trim()) {
+ setDeLang("");
+ return;
+ }
+
+ (async () => {
+ try {
+ setDeLoading(true);
+ const deLang = await tryDetectLang(text, langDetector);
+ if (deLang) {
+ setDeLang(deLang);
+ }
+ } catch (err) {
+ kissLog("tranbox: detect lang", err);
+ } finally {
+ setDeLoading(false);
+ }
+ })();
+ }, [text, langDetector, setDeLang, setDeLoading]);
+
+ // todo: 语言变化后,realToLang引发二次翻译请求
+ const realToLang = useMemo(() => {
+ if (
+ fromLang === "auto" &&
+ toLang !== toLang2 &&
+ toLang2 !== "-" &&
+ deLang === toLang
+ ) {
+ return toLang2;
+ }
+
+ return toLang;
+ }, [fromLang, toLang, toLang2, deLang]);
+
+ const optApis = useMemo(
+ () =>
+ transApis
+ .filter((api) => !api.isDisabled)
+ .map((api) => ({
+ key: api.apiSlug,
+ name: api.apiName || api.apiSlug,
+ })),
+ [transApis]
+ );
+
+ const isWord = useMemo(() => isValidWord(text), [text]);
+
+ return (
+
+ {!simpleStyle && (
+ <>
+
+
+
+ {
+ setApiSlugs(e.target.value);
+ }}
+ >
+ {optApis.map(({ key, name }) => (
+
+ ))}
+
+
+
+ {
+ setFromLang(e.target.value);
+ }}
+ >
+ {OPT_LANGS_FROM.map(([lang, name]) => (
+
+ ))}
+
+
+
+ {
+ setToLang(e.target.value);
+ }}
+ >
+ {OPT_LANGS_TO.map(([lang, name]) => (
+
+ ))}
+
+
+
+
+
+ {isPlaygound && (
+
+
+
+ {
+ setEnDict(e.target.value);
+ }}
+ >
+
+ {OPT_DICT_ALL.map((item) => (
+
+ ))}
+
+
+
+ {
+ setLangDetector(e.target.value);
+ }}
+ >
+
+ {OPT_LANGDETECTOR_ALL.map((item) => (
+
+ ))}
+
+
+
+
+ ) : null,
+ }}
+ />
+
+
+
+ )}
+
+
+ {
+ setEditText(e.target.value);
+ }}
+ onFocus={() => {
+ setEditMode(true);
+ }}
+ onBlur={() => {
+ setEditMode(false);
+ setText(editText.trim());
+ }}
+ InputProps={{
+ endAdornment: (
+
+ {editMode ? (
+ {
+ e.stopPropagation();
+ }}
+ >
+
+
+ ) : (
+
+ )}
+
+ ),
+ }}
+ />
+
+ >
+ )}
+
+ {apiSlugs.map((slug) => (
+
+ ))}
+
+ {isWord && OPT_DICT_MAP.has(enDict) && (
+ <>
+
+
+ >
+ )}
+
+ );
+}
diff --git a/src/views/Selection/index.js b/src/views/Selection/index.js
index b32feba..5eb6ee7 100644
--- a/src/views/Selection/index.js
+++ b/src/views/Selection/index.js
@@ -30,7 +30,7 @@ export default function Slection({
followSelection: initFollowMouse = false,
tranboxShortcut = DEFAULT_TRANBOX_SHORTCUT,
triggerMode = OPT_TRANBOX_TRIGGER_CLICK,
- extStyles,
+ // extStyles,
btnOffsetX,
btnOffsetY,
boxOffsetX = 0,
@@ -236,7 +236,7 @@ export default function Slection({
setHideClickAway={setHideClickAway}
followSelection={followSelection}
setFollowSelection={setFollowSelection}
- extStyles={extStyles}
+ // extStyles={extStyles}
langDetector={langDetector}
enDict={enDict}
/>