feat: support builtin AI

This commit is contained in:
Gabe
2025-10-04 21:25:54 +08:00
parent c353c88db8
commit 7b2b48f0d1
23 changed files with 558 additions and 243 deletions

View File

@@ -30,6 +30,7 @@ import {
OPT_TRANS_OLLAMA,
OPT_TRANS_CUSTOMIZE,
OPT_TRANS_NIUTRANS,
OPT_TRANS_BUILTINAI,
DEFAULT_FETCH_LIMIT,
DEFAULT_FETCH_INTERVAL,
DEFAULT_HTTP_TIMEOUT,
@@ -253,32 +254,33 @@ function ApiFields({ apiSlug, isUserApi, deleteApi }) {
onChange={handleChange}
/>
{!API_SPE_TYPES.machine.has(apiType) && (
<>
<TextField
size="small"
label={"URL"}
name="url"
value={url}
onChange={handleChange}
multiline={apiType === OPT_TRANS_DEEPLX}
maxRows={10}
helperText={
apiType === OPT_TRANS_DEEPLX ? i18n("mulkeys_help") : ""
}
/>
<TextField
size="small"
label={"KEY"}
name="key"
value={key}
onChange={handleChange}
multiline={API_SPE_TYPES.mulkeys.has(apiType)}
maxRows={10}
helperText={keyHelper}
/>
</>
)}
{!API_SPE_TYPES.machine.has(apiType) &&
apiType !== OPT_TRANS_BUILTINAI && (
<>
<TextField
size="small"
label={"URL"}
name="url"
value={url}
onChange={handleChange}
multiline={apiType === OPT_TRANS_DEEPLX}
maxRows={10}
helperText={
apiType === OPT_TRANS_DEEPLX ? i18n("mulkeys_help") : ""
}
/>
<TextField
size="small"
label={"KEY"}
name="key"
value={key}
onChange={handleChange}
multiline={API_SPE_TYPES.mulkeys.has(apiType)}
maxRows={10}
helperText={keyHelper}
/>
</>
)}
{API_SPE_TYPES.ai.has(apiType) && (
<>
@@ -606,65 +608,71 @@ function ApiFields({ apiSlug, isUserApi, deleteApi }) {
</Grid>
</Box>
<TextField
size="small"
label={i18n("custom_header")}
name="customHeader"
value={customHeader}
onChange={handleChange}
multiline
maxRows={10}
helperText={i18n("custom_header_help")}
/>
<TextField
size="small"
label={i18n("custom_body")}
name="customBody"
value={customBody}
onChange={handleChange}
multiline
maxRows={10}
helperText={i18n("custom_body_help")}
/>
{apiType !== OPT_TRANS_CUSTOMIZE && (
{apiType !== OPT_TRANS_BUILTINAI && (
<>
{" "}
<TextField
size="small"
label={"Request Hook"}
name="reqHook"
value={reqHook}
label={i18n("custom_header")}
name="customHeader"
value={customHeader}
onChange={handleChange}
multiline
maxRows={10}
FormHelperTextProps={{
component: "div",
}}
helperText={
<Box component="pre" sx={{ overflowX: "auto" }}>
{i18n("request_hook_helper")}
</Box>
}
helperText={i18n("custom_header_help")}
/>
<TextField
size="small"
label={"Response Hook"}
name="resHook"
value={resHook}
label={i18n("custom_body")}
name="customBody"
value={customBody}
onChange={handleChange}
multiline
maxRows={10}
FormHelperTextProps={{
component: "div",
}}
helperText={
<Box component="pre" sx={{ overflowX: "auto" }}>
{i18n("response_hook_helper")}
</Box>
}
helperText={i18n("custom_body_help")}
/>
</>
)}
{apiType !== OPT_TRANS_CUSTOMIZE &&
apiType !== OPT_TRANS_BUILTINAI && (
<>
<TextField
size="small"
label={"Request Hook"}
name="reqHook"
value={reqHook}
onChange={handleChange}
multiline
maxRows={10}
FormHelperTextProps={{
component: "div",
}}
helperText={
<Box component="pre" sx={{ overflowX: "auto" }}>
{i18n("request_hook_helper")}
</Box>
}
/>
<TextField
size="small"
label={"Response Hook"}
name="resHook"
value={resHook}
onChange={handleChange}
multiline
maxRows={10}
FormHelperTextProps={{
component: "div",
}}
helperText={
<Box component="pre" sx={{ overflowX: "auto" }}>
{i18n("response_hook_helper")}
</Box>
}
/>
</>
)}
</>
)}
@@ -782,7 +790,11 @@ export default function Apis() {
return (
<Box>
<Stack spacing={3}>
<Alert severity="info">{i18n("about_api")}</Alert>
<Alert severity="info">
{i18n("about_api")}
<br />
{i18n("about_api_2")}
</Alert>
<Box>
<Button

View File

@@ -5,7 +5,6 @@ import Accordion from "@mui/material/Accordion";
import AccordionSummary from "@mui/material/AccordionSummary";
import AccordionDetails from "@mui/material/AccordionDetails";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
// import CircularProgress from "@mui/material/CircularProgress";
import { useI18n } from "../../hooks/I18n";
import Box from "@mui/material/Box";
import { useFavWords } from "../../hooks/FavWords";
@@ -18,11 +17,9 @@ import ClearAllIcon from "@mui/icons-material/ClearAll";
import Alert from "@mui/material/Alert";
import { isValidWord } from "../../libs/utils";
import { kissLog } from "../../libs/log";
import { apiTranslate } from "../../apis";
import { OPT_TRANS_BAIDU, PHONIC_MAP } from "../../config";
import { useConfirm } from "../../hooks/Confirm";
import { useSetting } from "../../hooks/Setting";
import { DICT_MAP } from "../Selection/DictMap";
import { dictHandlers } from "../Selection/DictHandler";
function FavAccordion({ word, index }) {
const [expanded, setExpanded] = useState(false);
@@ -83,17 +80,20 @@ export default function FavWords() {
const handleTranslation = async () => {
const { enDict } = setting?.tranboxSetting;
const dict = DICT_MAP[enDict];
const dict = dictHandlers[enDict];
if (!dict) return "";
const tranList = [];
for (const word of wordList) {
try {
const data = await dict.apiFn(word);
const tran = dict.toText(data);
tranList.push([word, tran].join("\n"));
const tran = dict
.toText(data)
.map((line) => `- ${line}`)
.join("\n");
tranList.push([`## ${word}`, tran].join("\n"));
} catch (err) {
// skip
kissLog("export translation", err);
}
}

View File

@@ -289,6 +289,64 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
<MenuItem value={"false"}>{i18n("default_disabled")}</MenuItem>
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="apiSlug"
value={apiSlug}
label={i18n("translate_service")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
{enabledApis.map((api) => (
<MenuItem key={api.apiSlug} value={api.apiSlug}>
{api.apiName}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="fromLang"
value={fromLang}
label={i18n("from_lang")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
{OPT_LANGS_FROM.map(([lang, name]) => (
<MenuItem key={lang} value={lang}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="toLang"
value={toLang}
label={i18n("to_lang")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
{OPT_LANGS_TO.map(([lang, name]) => (
<MenuItem key={lang} value={lang}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
@@ -354,22 +412,7 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
<MenuItem value={"true"}>{i18n("enable")}</MenuItem>
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="transTag"
value={transTag}
label={i18n("translation_element_tag")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
<MenuItem value={"span"}>{`<span>`}</MenuItem>
<MenuItem value={"font"}>{`<font>`}</MenuItem>
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
@@ -386,64 +429,23 @@ function RuleFields({ rule, rules, setShow, setKeyword }) {
<MenuItem value={"true"}>{i18n("enable")}</MenuItem>
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="transTag"
value={transTag}
label={i18n("translation_element_tag")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
<MenuItem value={"span"}>{`<span>`}</MenuItem>
<MenuItem value={"font"}>{`<font>`}</MenuItem>
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="apiSlug"
value={apiSlug}
label={i18n("translate_service")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
{enabledApis.map((api) => (
<MenuItem key={api.apiSlug} value={api.apiSlug}>
{api.apiName}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="fromLang"
value={fromLang}
label={i18n("from_lang")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
{OPT_LANGS_FROM.map(([lang, name]) => (
<MenuItem key={lang} value={lang}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select
size="small"
fullWidth
name="toLang"
value={toLang}
label={i18n("to_lang")}
disabled={disabled}
onChange={handleChange}
>
{GlobalItem}
{OPT_LANGS_TO.map(([lang, name]) => (
<MenuItem key={lang} value={lang}>
{name}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={12} md={6} lg={3}>
<TextField
select

View File

@@ -340,7 +340,7 @@ export default function Settings() {
size="small"
name="langDetector"
value={langDetector}
label={i18n("detect_lang_remote")}
label={i18n("detected_lang")}
onChange={handleChange}
>
<MenuItem value={"-"}>{i18n("disable")}</MenuItem>

View File

@@ -9,10 +9,10 @@ import {
OPT_LANGS_TO,
OPT_TRANBOX_TRIGGER_CLICK,
OPT_TRANBOX_TRIGGER_ALL,
OPT_DICT_BAIDU,
OPT_DICT_BING,
OPT_DICT_ALL,
OPT_SUG_ALL,
OPT_SUG_BAIDU,
OPT_SUG_YOUDAO,
} from "../../config";
import ShortcutInput from "./ShortcutInput";
import FormControlLabel from "@mui/material/FormControlLabel";
@@ -69,8 +69,8 @@ export default function Tranbox() {
followSelection = false,
triggerMode = OPT_TRANBOX_TRIGGER_CLICK,
// extStyles = "",
enDict = OPT_DICT_BAIDU,
enSug = OPT_SUG_BAIDU,
enDict = OPT_DICT_BING,
enSug = OPT_SUG_YOUDAO,
} = tranboxSetting;
return (