Skip to content

Commit

Permalink
合并:完成兼容性调整,合并至主分支 (#4)
Browse files Browse the repository at this point in the history
Merge pull request #4 from guobao2333/dev
  • Loading branch information
guobao2333 authored Aug 31, 2024
2 parents c9b72eb + 1354f51 commit 621f573
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 113 deletions.
93 changes: 47 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
# DeepLX Serverless

DeepLX 免费翻译API**函数部署版**[原项目DeepLX](https://github.com/OwO-Network/DeepLX)的区别在于**利用了云函数的请求IP不固定的特性,极大程度上避免了`429`请求太频繁报错**
DeepLX 免费翻译API**函数部署版**与原项目[DeepLX](https://github.com/OwO-Network/DeepLX)的区别在于**利用了无服务器函数(也叫边缘函数)的请求IP不固定的特性,极大程度上避免了`429`请求太频繁报错**

## Usage | 用法
**如果本项目对你有用的话,不妨点个`Star`❤️**
**Click `Star` if you like!! thanks❤️**

## Major Changes | 重大改变
> *vvvvery big changes🤣
如果您在这之前不使用本项目,此部分可以跳过。
1. 新增了docker部署支持
2. 请求参数变化: `alternative_number` -> `alt_count`

## Let's Go | 开始使用
### Prerequisites | 你需要准备什么

- 一双灵活的小手
- 一个聪明的脑袋瓜
- 安装nodejs
- 支持 `Nodejs ≥16.13``Serverless Function` 的服务器

### Deploy | 部署

使用任意支持云函数部署的服务器,比如可以使用vercel进行部署,又或者其他能够使用nodejs的服务器。(几乎大多数服务器提供商都提供函数计算服务器)
使用任意支持无服务器函数部署的服务器,比如可以使用 `Vercel` 或者 `Netlify` 进行部署,又或者其他能够使用nodejs的服务器。(大多数服务器提供商都提供函数计算服务器)

如果你拥有[Vercel](https://vercel.com)账号的话那就很简单了,因为你只需要点击下方按钮即可一键部署到Vercel:

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/guobao2333/DeepLX-Serverless)

如果你拥有[vercel](https://vercel.com)账号的话那就很简单了,因为你只需要点击下方按钮即可一键部署到Vercel:
<!-- 你也可以在[Netlify](https://netlify.com)上一键部署本项目:
(但目前正在测试中,多平台兼容好难啊……)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fguobao2333%2FDeepLX-Serverless%2Ftree%2Fmain)
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/guobao2333/DeepLX-Serverless) -->

项目当前没有任何需要填写的变量值,但在后续可能会添加。
因维护者我有多个仓库需要维护,短时间内将无法对多平台部署方案进行兼容,您可以选择**自托管**方案。
✨项目当前没有任何需要填写的变量值,你只需要直接部署就可以用了,但在后续可能会添加。

如果部署完成了,就可以开始使用啦!🎉
#### Docker

直接运行容器:
Expand All @@ -33,71 +49,55 @@ docker build -t deeplx-api .
docker run -d -p 9000:9000 deeplx-api
```

#### 自托管
#### Self hosting | 自托管

尽管本项目是专为 serverless 适配的方案,但是也能使用自己的服务器进行部署:
尽管本项目是专为 serverless 适配的方案,但是也能使用自己的服务器进行部署:
```bash
git clone https://github.com/guobao/DeepLX-Serverless
git clone https://github.com/guobao2333/DeepLX-Serverless
cd DeepLX-Serverless
npm i
npm run start
```

直接复制到命令行运行:
📋直接复制到命令行运行:
```bash
git clone https://github.com/guobao/DeepLX-Serverless && cd DeepLX-Serverless && npm i && npm run start
git clone https://github.com/guobao2333/DeepLX-Serverless && cd DeepLX-Serverless && npm i && npm run start
```

你可以运行`npm run test`用来测试翻译接口。
🚧你可以运行`npm run test`用来测试翻译接口。
⚠️注意!测试命令仅返回翻译内容,获取所有结果需要使用`POST`

### How To Use | 如何使用

使用post通过 `域名` + `/translate` + `json请求体` 这样的形式获取json响应。
使用post通过 `域名地址` + `/translate` + `json请求体` 这样的形式获取json响应。

请求示例:
```bash
curl --location --request POST 'https://YOUR-DOMAIN/translate' \
--header 'Content-Type: application/json' \
--data-raw '{
"text": "Hello, World!",
"source_lang": "en",
"target_lang": "zh",
"alternative_number": 3
}'
```
详细API文档,请查看本项目的wiki:
[English](https://github.com/guobao2333/DeepLX-Serverless/wiki/English-document) | [简体中文](https://github.com/guobao2333/DeepLX-Serverless/wiki/%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

直接复制到命令行运行本地测试:
📋你可以直接复制到命令行运行**本地测试:**
```bash
curl --location 'http://localhost:9000/translate' --header 'Content-Type: application/json' --data '{"text": "你好,世界!", "source_lang": "zh", "target_lang": "en", "alternative_number": 3}'
```

**请修改`YOUR-DOMAIN`为你部署服务的域名!!**

-----------------

响应示例:
```json
{
"code": 200,
"message": "success",
"data": "Hello, world.",
"source_lang": "en",
"target_lang": "zh",
"alternatives": ["Hello, World.", "Hello, world!", "Hi, world."]
}
curl --location --request POST 'http://localhost:9000/translate' --header 'Content-Type: application/json' --data '{"text": "你好,世界!", "source_lang": "zh", "target_lang": "en"}'
```

部署完成后,建议搭配浏览器插件「沉浸式翻译」一同使用。
部署完成后,建议搭配浏览器插件「沉浸式翻译」一同使用。

## 沉浸式翻译设置

1. 在浏览器上安装最新的 [沉浸式翻译](https://github.com/immersive-translate/immersive-translate/releases)
2. 点击左下角的 "开发者设置"。启用测试版实验功能。
3. 翻译服务选中 `DeepLX(beta)`
3. 设置 URL 为刚才获取的访问路径(需带translate)。
4. 设置 URL 为刚才获取的访问路径(需带translate)。

![沉浸式翻译](https://github.com/LegendLeo/deeplx-serverless/assets/25115173/d3affe2b-9e99-4d5c-bc8c-cd67e70d0368)

## Contribute | 贡献

> [!IMPORTANT]
> **在您做出贡献之前,请先切换到`dev`分支!!**
> 因为解决分支冲突真的很麻烦!
本人因时间(和各种各样的)原因,故无法及时对您的贡献进行测试,所以您需要**自行测试**

## Star History

<a href="https://star-history.com/#guobao2333/DeepLX-Serverless&Date">
Expand All @@ -108,7 +108,8 @@ curl --location 'http://localhost:9000/translate' --header 'Content-Type: applic
</picture>
</a>

## 鸣谢
## Acknowledgments | 鸣谢

1. [OwO-Network/DeepLX](https://github.com/OwO-Network/DeepLX)
2. [LegendLeo/deeplx-serverless](https://github.com/LegendLeo/deeplx-serverless)
3. [bropines/Deeplx-vercel](https://github.com/bropines/Deeplx-vercel)
67 changes: 9 additions & 58 deletions api/index.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,16 @@
const express = require('express');
const bodyParser = require('body-parser');
const { translate } = require('../translate');
import express from 'express';
import fetch from 'node-fetch';
import { post, get } from '../server.js';

const app = express();
const PORT = 9000;
const allowAlternative = true;

app.use(bodyParser.json());

app.post('/translate', async (req, res) => {
const startTime = Date.now(); // 记录开始时间

// 检查请求方法和请求体
if (req.method !== 'POST' || !req.body || !req.body.text) {
const duration = Date.now() - startTime;
console.log(`[LOG] ${new Date().toISOString()} | 404 | ${duration}ms | POST "translate"`);
return res.status(404).json({
"code": 404,
"message": "Path not found"
});
}

if (!allowAlternative) alternative_number = 0;
const { text, source_lang, target_lang, alternative_number } = req.body;

try {
const result = await translate(text, source_lang, target_lang, alternative_number);
const duration = Date.now() - startTime; // 计算处理时间
console.log(`[LOG] ${new Date().toISOString()} | 200 | ${duration}ms | POST "translate"`);
// 转发请求
const response = await post(req, res);

const responseData = {
code: 200,
data: result.text, // 取第一个翻译结果
id: Math.floor(Math.random() * 10000000000), // 生成一个随机 ID
method: 'Free',
source_lang,
target_lang,
alternatives: result.alternatives
};

res.json(responseData);
} catch (error) {
const duration = Date.now() - startTime;
console.error(`[ERROR] ${new Date().toISOString()} | 500 | ${duration}ms | POST "translate" | ${error.message}`);
res.status(500).json({
code: 500,
message: 'Translation failed',
error: error.message
});
}
});

//
app.get('/', (req, res) => {
res.json({
code: 200,
message: "Welcome to the DeepL Free API. Please POST to '/translate'. Visit 'https://github.com/OwO-Network/DeepLX' and 'https://github.com/guobao/DeepLX-Serverless' for more information."
});
// 返回响应
const data = await response.json();
res.status(response.status).json(data);
});

// 启动本地服务器
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
app.get('/', async (req, res) => await get(req, res));
2 changes: 2 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
command = "npm install"
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
"name": "deeplx-serverless",
"version": "1.0.0",
"description": "DeepLX Free API for serverless",
"type": "module",
"main": "translate.js",
"engines": {
"node": ">=16.13"
},
"scripts": {
"start": "node api/index.js",
"start": "node server.js",
"test": "node test.js"
},
"keywords": [
Expand All @@ -19,6 +23,7 @@
"body-parser": "^1.20.2",
"express": "^4.18.2",
"lodash": "^4.17.21",
"node-fetch": "^3.3.2",
"random-int": "^3.0.0"
}
}
70 changes: 70 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import express from 'express';
import bodyParser from 'body-parser';
import { translate } from './translate.js';

const app = express();
const PORT = 9000;
const allowAlternative = true;

app.use(bodyParser.json());
// 为了方便兼容多平台才这样写
app.post('/translate', async (req, res) => await post(req, res));
app.get('/', async (req, res) => await get(req, res));

async function post(req, res) {
const startTime = Date.now(); // 记录开始时间

// 检查请求方法和请求体
if (req.method !== 'POST' || !req.body || !req.body.text) {
const duration = Date.now() - startTime;
console.log(`[LOG] ${new Date().toISOString()} | 404 | ${duration}ms | POST "translate"`);
return res.status(404).json({
"code": 404,
"message": "Path not found"
});
}

// 判断是否备选翻译
if (!allowAlternative) alt_count = 0;
const { text, source_lang, target_lang, alt_count } = req.body;

try {
const result = await translate(text, source_lang, target_lang, alt_count);
const duration = Date.now() - startTime; // 计算处理时间
console.log(`[LOG] ${new Date().toISOString()} | 200 | ${duration}ms | POST "translate"`);

const responseData = {
code: 200,
data: result.text, // 取第一个翻译结果
id: Math.floor(Math.random() * 10000000000), // 生成一个随机 ID
method: 'Free',
source_lang,
target_lang,
alternatives: result.alternatives
};

res.json(responseData);
} catch (error) {
const duration = Date.now() - startTime;
console.error(`[ERROR] ${new Date().toISOString()} | 500 | ${duration}ms | POST "translate" | ${error.message}`);
res.status(500).json({
code: 500,
message: 'Translation failed',
error: error.message
});
}
};

async function get(req, res) {
res.json({
code: 200,
message: "Welcome to the DeepL Free API. Please POST to '/translate'. Visit 'https://github.com/OwO-Network/DeepLX' and 'https://github.com/guobao2333/DeepLX-Serverless' for more information."
});
};

// 启动本地服务器
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

export { post, get };
3 changes: 1 addition & 2 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const { translate } = require('./translate');
import { translate } from './translate.js';

(async () => {
// Example Call
await translate('各位评委好,我是练习时长两年半的个人练习生,蔡徐坤', 'ZH', 'EN', 3, true);
console.log('\n');
await translate('鸡你太美,baby,鸡你实在是太美,baby', 'ZH', 'EN', 0, true)
})()
13 changes: 7 additions & 6 deletions translate.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const axios = require('axios').default;
const { random } = require('lodash');
import axios from 'axios';
import lodash from 'lodash';

const { random } = lodash;
const DEEPL_BASE_URL = 'https://www2.deepl.com/jsonrpc';
const headers = {
'Content-Type': 'application/json',
Expand Down Expand Up @@ -37,20 +38,20 @@ async function translate(
text,
sourceLang = 'AUTO',
targetLang = 'ZH',
alternativeNumber = 0,
alternativeCount = 0,
printResult = false,
) {
const iCount = getICount(text);
const id = getRandomNumber();

alternativeNumber = Math.max(Math.min(3, alternativeNumber), 0);
alternativeCount = Math.max(Math.min(3, alternativeCount), 0);

const postData = {
jsonrpc: '2.0',
method: 'LMT_handle_texts',
id: id,
params: {
texts: [{ text: text, requestAlternatives: alternativeNumber }],
texts: [{ text: text, requestAlternatives: alternativeCount }],
splitting: 'newlines',
lang: {
source_lang_user_selected: sourceLang.toUpperCase(),
Expand Down Expand Up @@ -97,4 +98,4 @@ async function translate(
}
}

exports.translate = translate;
export { translate };

0 comments on commit 621f573

Please sign in to comment.