diff --git a/deploy/baidu-translate/Dockerfile b/deploy/baidu-translate/Dockerfile new file mode 100644 index 0000000..8c20813 --- /dev/null +++ b/deploy/baidu-translate/Dockerfile @@ -0,0 +1,21 @@ +# 使用官方 Python 3.8.2 slim 镜像(精简版) +FROM python:3.8.2-slim + +# 设置工作目录 +WORKDIR /app + +# 安装依赖前先复制 requirements(利用 Docker 缓存) +COPY requirements.txt . + +# 升级 pip 并安装依赖(使用国内源加速,可选) +RUN pip install --no-cache-dir --upgrade pip \ + && pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ + +# 复制应用代码 +COPY . . + +# 暴露端口 +EXPOSE 5000 + +# 启动命令(使用 gunicorn 提升生产性能) +CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "2", "--timeout", "60", "main:app"] \ No newline at end of file diff --git a/deploy/baidu-translate/main.py b/deploy/baidu-translate/main.py new file mode 100644 index 0000000..ccaf2fc --- /dev/null +++ b/deploy/baidu-translate/main.py @@ -0,0 +1,57 @@ +# main.py + +from flask import Flask, request, jsonify +from translate import translate_text + +app = Flask(__name__) + + +@app.route('/translate', methods=['POST']) +def translate_api(): + """ + 多语言翻译接口 + 请求体示例: + { + "text": "Hello world", + "source_lang": "en", // 可选,默认 auto + "target_lang": "zh" // 可选,默认 zh + } + """ + data = request.get_json() + if not data or 'text' not in data: + return jsonify({"error": "缺少参数 'text'"}), 400 + + text = data['text'] + source_lang = data.get('source_lang', 'auto') + target_lang = data.get('target_lang', 'zh') + + result = translate_text(text, source_lang, target_lang) + + if result['success']: + return jsonify({ + "translated_text": result['translated_text'], + "source_lang": source_lang, + "target_lang": target_lang + }) + else: + return jsonify({"error": result['error']}), 400 + + +@app.route('/health', methods=['GET']) +def health_check(): + return jsonify({"status": "ok", "service": "baidu-translate"}) + + +@app.route('/', methods=['GET']) +def index(): + return jsonify({ + "message": "Baidu Translate API Service", + "endpoints": { + "translate": "POST /translate", + "health": "GET /health" + } + }) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000, debug=False) diff --git a/deploy/baidu-translate/requirements.txt b/deploy/baidu-translate/requirements.txt new file mode 100644 index 0000000..aead026 --- /dev/null +++ b/deploy/baidu-translate/requirements.txt @@ -0,0 +1,3 @@ +Flask==2.3.3 +requests==2.31.0 +gunicorn==21.2.0 \ No newline at end of file diff --git a/deploy/baidu-translate/run.sh b/deploy/baidu-translate/run.sh new file mode 100644 index 0000000..13409fc --- /dev/null +++ b/deploy/baidu-translate/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# 构建镜像 +echo "正在构建 Docker 镜像..." +docker build -t baidu-translate-api:latest . + +# 停止并删除旧容器(如果存在) +if [ "$(docker ps -q -f name=baidu-translate)" ]; then + echo "停止旧容器..." + docker stop baidu-translate +fi + +if [ "$(docker ps -aq -f status=exited -f name=baidu-translate)" ]; then + echo "删除旧容器..." + docker rm baidu-translate +fi + +# 启动新容器 +echo "启动容器..." +docker run -d \ + --name baidu-translate \ + -p 28081:5000 \ + --restart unless-stopped \ + baidu-translate-api:latest + +echo "服务已启动!访问 http://<服务器IP>:5000/health" \ No newline at end of file diff --git a/deploy/baidu-translate/settings.py b/deploy/baidu-translate/settings.py new file mode 100644 index 0000000..87d9451 --- /dev/null +++ b/deploy/baidu-translate/settings.py @@ -0,0 +1,26 @@ +# settings.py + +# 百度翻译 API 配置 +BAIDU_APP_ID = "20200811000539778" +BAIDU_SECRET_KEY = "uK9IyUhuEWX3PIqN75iC" + +TIMEOUT = 10 +MAX_TEXT_LENGTH = 100 + +# 百度语言代码映射(ISO 639-1 → Baidu Code) +BAIDU_LANG_MAP = { + 'zh': 'zh', + 'en': 'en', + 'ko': 'kor', + 'ja': 'jp', + 'fr': 'fra', + 'es': 'spa', + 'ru': 'ru', + 'de': 'de', + 'pt': 'pt', + 'it': 'it', + 'ar': 'ara', + 'th': 'th', + 'vi': 'vie', + # 可继续扩展 +} diff --git a/deploy/baidu-translate/translate.py b/deploy/baidu-translate/translate.py new file mode 100644 index 0000000..b6ba5d7 --- /dev/null +++ b/deploy/baidu-translate/translate.py @@ -0,0 +1,71 @@ +# translate.py + +import hashlib +import random +import requests +import settings + + +def iso_to_baidu_lang(iso_code: str) -> str: + """将 ISO 639-1 语言代码转换为百度翻译所需代码""" + code = settings.BAIDU_LANG_MAP.get(iso_code.lower()) + if code is None: + raise ValueError(f"不支持的语言代码: {iso_code}") + return code + + +def translate_text(text: str, source_lang: str = "auto", target_lang: str = "zh") -> dict: + """ + 使用百度翻译 API 进行多语言翻译 + :param text: 原文 + :param source_lang: 源语言 ISO 代码(如 'ko', 'en'),默认 'auto' 自动检测 + :param target_lang: 目标语言 ISO 代码,默认 'zh' + :return: {'success': bool, 'translated_text': str, 'error': str (optional)} + """ + if not text or not text.strip(): + return {"success": False, "error": "输入文本为空"} + + try: + from_lang = "auto" if source_lang == "auto" else iso_to_baidu_lang(source_lang) + to_lang = iso_to_baidu_lang(target_lang) + except ValueError as e: + return {"success": False, "error": str(e)} + + q = text[:settings.MAX_TEXT_LENGTH] + + try: + salt = random.randint(32768, 65536) + sign_str = settings.BAIDU_APP_ID + q + str(salt) + settings.BAIDU_SECRET_KEY + sign = hashlib.md5(sign_str.encode()).hexdigest() + + payload = { + 'q': q, + 'from': from_lang, + 'to': to_lang, + 'appid': settings.BAIDU_APP_ID, + 'salt': salt, + 'sign': sign + } + + response = requests.post( + "https://fanyi-api.baidu.com/api/trans/vip/translate", + data=payload, + timeout=settings.TIMEOUT + ) + response.raise_for_status() + result = response.json() + + if 'error_code' in result: + error_msg = f"百度API错误 {result.get('error_code')}: {result.get('error_msg', '')}" + return {"success": False, "error": error_msg} + + if 'trans_result' not in result or not result['trans_result']: + return {"success": False, "error": "翻译结果为空"} + + translated = result['trans_result'][0]['dst'] + return {"success": True, "translated_text": translated} + + except requests.exceptions.RequestException as e: + return {"success": False, "error": f"网络请求失败: {str(e)}"} + except Exception as e: + return {"success": False, "error": f"未知错误: {str(e)}"}