feat: custom request
This commit is contained in:
@@ -264,6 +264,25 @@ export const apiTranslate = async ({
|
|||||||
case OPT_TRANS_CUSTOMIZE_5:
|
case OPT_TRANS_CUSTOMIZE_5:
|
||||||
trText = res.text;
|
trText = res.text;
|
||||||
isSame = to === res.from;
|
isSame = to === res.from;
|
||||||
|
|
||||||
|
const { customOption } = apiSetting;
|
||||||
|
if (customOption.trim()) {
|
||||||
|
try {
|
||||||
|
const opt = JSON.parse(customOption);
|
||||||
|
const textPattern = opt.resPattern?.text;
|
||||||
|
const fromPattern = opt.resPattern?.from;
|
||||||
|
if (textPattern) {
|
||||||
|
trText = textPattern.split(".").reduce((pre, cur) => pre[cur], res);
|
||||||
|
}
|
||||||
|
if (fromPattern) {
|
||||||
|
isSame =
|
||||||
|
to === fromPattern.split(".").reduce((pre, cur) => pre[cur], res);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`custom option parse err: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,24 +42,28 @@ const customApiLangs = `["en", "English - English"],
|
|||||||
["vi", "Vietnamese - Tiếng Việt"],
|
["vi", "Vietnamese - Tiếng Việt"],
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const customApiHelpZH = `/// 自定义翻译源接口说明
|
const customDefaultOption = `{
|
||||||
|
"url": "{{url}}",
|
||||||
// 请求(Request)数据将按下面规范发送
|
"method": "POST",
|
||||||
{
|
"headers": {
|
||||||
url: {{YOUR_URL}},
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-type": "application/json",
|
"Content-type": "application/json",
|
||||||
"Authorization": "Bearer {{YOUR_KEY}}",
|
"Authorization": "Bearer {{key}}"
|
||||||
},
|
},
|
||||||
body: {
|
"body": {
|
||||||
text: "", // 需要翻译的文字
|
"text": "{{text}}",
|
||||||
from: "", // 源语言,可能为空,表示需要接口自动识别语言
|
"from": "{{from}}",
|
||||||
to: "", // 目标语言
|
"to": "{{to}}"
|
||||||
|
},
|
||||||
|
"resPattern": {
|
||||||
|
"text": "text",
|
||||||
|
"from": "from"
|
||||||
}
|
}
|
||||||
}
|
}`;
|
||||||
|
|
||||||
// 返回(Response)数据需符合下面的JSON规范
|
const customApiHelpZH = `// 自定义选项范例
|
||||||
|
${customDefaultOption}
|
||||||
|
|
||||||
|
// 返回数据默认格式
|
||||||
{
|
{
|
||||||
text: "", // 翻译后的文字
|
text: "", // 翻译后的文字
|
||||||
from: "", // 识别的源语言
|
from: "", // 识别的源语言
|
||||||
@@ -70,24 +74,10 @@ const customApiHelpZH = `/// 自定义翻译源接口说明
|
|||||||
${customApiLangs}
|
${customApiLangs}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const customApiHelpEN = `/// Custom translation source interface description
|
const customApiHelpEN = `// Example of custom options
|
||||||
|
${customDefaultOption}
|
||||||
|
|
||||||
// Request data will be sent according to the following specifications
|
// Return data default format
|
||||||
{
|
|
||||||
url: {{YOUR_URL}},
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-type": "application/json",
|
|
||||||
"Authorization": "Bearer {{YOUR_KEY}}",
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
text: "", // text to be translated
|
|
||||||
from: "", // Source language, may be empty
|
|
||||||
to: "", // Target language
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The returned data must conform to the following JSON specification
|
|
||||||
{
|
{
|
||||||
text: "", // translated text
|
text: "", // translated text
|
||||||
from: "", // Recognized source language
|
from: "", // Recognized source language
|
||||||
@@ -851,4 +841,8 @@ export const I18N = {
|
|||||||
zh: `附加样式`,
|
zh: `附加样式`,
|
||||||
en: `Extend Styles`,
|
en: `Extend Styles`,
|
||||||
},
|
},
|
||||||
|
custom_option: {
|
||||||
|
zh: `自定义选项`,
|
||||||
|
en: `Custom Option`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -458,7 +458,7 @@ export const DEFAULT_SUBRULES_LIST = [
|
|||||||
const defaultCustomApi = {
|
const defaultCustomApi = {
|
||||||
url: "",
|
url: "",
|
||||||
key: "",
|
key: "",
|
||||||
customRequest: "",
|
customOption: "",
|
||||||
fetchLimit: DEFAULT_FETCH_LIMIT,
|
fetchLimit: DEFAULT_FETCH_LIMIT,
|
||||||
fetchInterval: DEFAULT_FETCH_INTERVAL,
|
fetchInterval: DEFAULT_FETCH_INTERVAL,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import {
|
|||||||
import { msAuth } from "./auth";
|
import { msAuth } from "./auth";
|
||||||
import { genDeeplFree } from "../apis/deepl";
|
import { genDeeplFree } from "../apis/deepl";
|
||||||
import { genBaidu } from "../apis/baidu";
|
import { genBaidu } from "../apis/baidu";
|
||||||
import { kissLog } from "./log";
|
|
||||||
|
|
||||||
const keyMap = new Map();
|
const keyMap = new Map();
|
||||||
|
|
||||||
@@ -279,7 +278,7 @@ const genCloudflareAI = ({ text, from, to, url, key }) => {
|
|||||||
return [url, init];
|
return [url, init];
|
||||||
};
|
};
|
||||||
|
|
||||||
const genCustom = ({ text, from, to, url, key, customRequest = "" }) => {
|
const genCustom = ({ text, from, to, url, key, customOption = "" }) => {
|
||||||
const replaceInput = (str) =>
|
const replaceInput = (str) =>
|
||||||
str
|
str
|
||||||
.replaceAll(INPUT_PLACE_URL, url)
|
.replaceAll(INPUT_PLACE_URL, url)
|
||||||
@@ -304,19 +303,19 @@ const genCustom = ({ text, from, to, url, key, customRequest = "" }) => {
|
|||||||
}
|
}
|
||||||
url = replaceInput(url);
|
url = replaceInput(url);
|
||||||
|
|
||||||
if (customRequest.trim()) {
|
if (customOption.trim()) {
|
||||||
try {
|
try {
|
||||||
const req = JSON.parse(replaceInput(customRequest));
|
const opt = JSON.parse(replaceInput(customOption));
|
||||||
req.url && (url = req.url);
|
opt.url && (url = opt.url);
|
||||||
req.headers && (init.headers = req.headers);
|
opt.headers && (init.headers = opt.headers);
|
||||||
req.method && (init.method = req.method);
|
opt.method && (init.method = opt.method);
|
||||||
if (init.method === "GET") {
|
if (init.method === "GET") {
|
||||||
delete init.body;
|
delete init.body;
|
||||||
} else {
|
} else {
|
||||||
req.body && (init.body = JSON.stringify(req.body));
|
opt.body && (init.body = JSON.stringify(opt.body));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
kissLog(err, "parse custom request");
|
throw new Error(`custom option parse err: ${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ function ApiFields({ translator }) {
|
|||||||
fetchInterval = DEFAULT_FETCH_INTERVAL,
|
fetchInterval = DEFAULT_FETCH_INTERVAL,
|
||||||
dictNo = "",
|
dictNo = "",
|
||||||
memoryNo = "",
|
memoryNo = "",
|
||||||
customRequest = "",
|
customOption = "",
|
||||||
} = api;
|
} = api;
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
@@ -226,9 +226,9 @@ function ApiFields({ translator }) {
|
|||||||
{translator.startsWith(OPT_TRANS_CUSTOMIZE) && (
|
{translator.startsWith(OPT_TRANS_CUSTOMIZE) && (
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
label={"CUSTOM REQUEST"}
|
label={i18n("custom_option")}
|
||||||
name="customRequest"
|
name="customOption"
|
||||||
value={customRequest}
|
value={customOption}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
multiline
|
multiline
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user