Telegram 自动翻译机器人部署完整教程(DeepL官方 + Telethon)

DeepLx已经被DeepL官方封了,无法再翻译。直接用官方的api,免费的一个月5w字符,够用,偶尔和老外用用

先到官网注册
https://www.deepl.com/ 需要信用卡验证,虚拟卡就ok
注册好后生成api key
https://www.deepl.com/en/your-account/keys
file

好,下面在vps上安装运行,推荐ubuntu,debian要用虚拟安装,不爽

✅ Telethon + DeepL 官方 API
✅ translate.py(自动翻译消息)
✅ systemd 后台运行

全部在全新 Ubuntu 完整搭建成功。

这份指南适用于:Ubuntu 18.04 / 20.04 / 22.04 / 24.04 /

🚀 Ubuntu 完整安装教程(从零到运行)
📌 第 1 步:更新系统

这是任何服务器安装的第一步:

sudo apt update && sudo apt upgrade -y

📌 第 2 步:安装 Python3 + pip

Ubuntu 默认带 Python3,但最好安装 pip:

sudo apt install -y python3 python3-pip

验证:

python3 --version
pip3 --version

📌 第 3 步:创建 Translator 目录

你的脚本放在 /home 下:

mkdir -p /home/translator
cd /home/translator

📌 第 4 步:安装 Python 库

pip3 install telethon aiohttp

📌 第 5 步:创建 config.json

创建文件:

nano /home/translator/config.json

粘贴你的配置(含 DeepL API、api_id、api_hash、翻译配置):

{
  "api_id": xxxxxxx,
  "api_hash": "983xxxxxxx05b",

  "deepl_api_key": "083333333333333333333333333333c:fx",

  "target_config": {
    "7448827479": {
      "source_lang": "ZH",
      "target_langs": [ "ZH", "EN" ]
    },
    "7448827479.2031692021": {
      "source_lang": "ZH",
      "target_langs": [ "EN" ]
    }
  },

  "glossary": { }
}

保存退出
Ctrl+O 回车 → Ctrl+X

📌 第 6 步:创建 translate.py(DeepL 官方 API 版)
nano /home/translator/translate.py

# -*- coding: utf-8 -*-
import asyncio
import json
import logging
import os
import time
import aiohttp
from itertools import cycle
from telethon import events
from telethon.sync import TelegramClient

# ===== 日志配置 =====
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# ===== 配置加载与保存 =====
def load_config():
    if not os.path.exists('config.json'):
        logging.error('config.json not found, please create one first.')
        exit()
    with open('config.json', 'r', encoding='utf-8') as f:
        return json.load(f)

def save_config():
    cfg['target_config'] = target_config
    with open('config.json', 'w', encoding='utf-8') as f:
        json.dump(cfg, f, indent=2, ensure_ascii=False)

# ===== 初始化配置 =====
cfg = load_config()
api_id = cfg['api_id']
api_hash = cfg['api_hash']

deepl_keys = cfg.get("deepl_api_keys", [])
deepl_pool = cycle(deepl_keys)

target_config = cfg.get('target_config', {})

# ===== 初始化 Telegram 客户端 =====
client = TelegramClient('chat_translator', api_id, api_hash)

# ===== DeepL API 地址 =====
# 如果你的 Key 以后换成了付费版(不带 :fx),请把 api-free 改为 api
DEEPL_URL = "https://api-free.deepl.com/v2/translate"

# ===== 获取一个轮换的 DeepL Key =====
def get_deepl_key():
    key = next(deepl_pool)
    logging.info(f"使用 DeepL Key: {key[:10]}***{key[-3:]}")
    return key

# ===== DeepL 翻译函数 =====
async def translate_single(text, source_lang, target_lang, session):
    if source_lang == target_lang:
        return target_lang, text

    key = get_deepl_key()

    # 修复 403 的关键:将 Key 放在 Headers 中
    headers = {
        "Authorization": f"DeepL-Auth-Key {key}"
    }

    payload = {
        "text": text,
        "target_lang": target_lang
    }

    start_time = time.time()
    try:
        # 增加超时限制,防止卡死
        async with session.post(DEEPL_URL, headers=headers, data=payload, timeout=10) as resp:
            if resp.status == 403:
                raise Exception("HTTP 403: Key可能失效或域名(api-free)不匹配")
            if resp.status != 200:
                err_text = await resp.text()
                raise Exception(f"DeepL 翻译失败: HTTP {resp.status} - {err_text}")

            js = await resp.json()
            translated = js["translations"][0]["text"]

            logging.info(f"翻译 {source_lang} → {target_lang} 成功, 耗时 {time.time() - start_time:.2f}s")
            return target_lang, translated
    except Exception as e:
        logging.error(f"翻译单个语种出错: {e}")
        raise e

async def translate_text(text, source_lang, target_langs):
    result = {}
    # 使用统一的 Session
    async with aiohttp.ClientSession() as session:
        tasks = [translate_single(text, source_lang, lang, session) for lang in target_langs]
        # 使用 return_exceptions 防止一个语种失败导致全部失败
        responses = await asyncio.gather(*tasks, return_exceptions=True)
        for res in responses:
            if isinstance(res, tuple):
                lang, translated = res
                result[lang] = translated
    return result

# ===== 命令模式 =====
async def command_mode(event, target_key, text) -> bool:
    if text == '.tt-off':
        await event.delete()
        if target_key in target_config:
            del target_config[target_key]
            save_config()
            logging.info(f"已关闭翻译: {target_key}")
        return False

    if text.startswith('.tt-on,'):
        await event.delete()
        try:
            parts = text.split(',')
            if len(parts) < 3:
                raise ValueError
            src = parts[1].strip()
            targets = parts[2].strip()
        except ValueError:
            logging.error("命令格式错误,应为:.tt-on,ZH,EN|RU")
            return False

        target_config[target_key] = {
            "source_lang": src.upper(),
            "target_langs": [x.upper() for x in targets.split('|')]
        }
        save_config()
        logging.info(f"已启用翻译: {target_config[target_key]}")
        return False

    return True

# ===== 监听消息并翻译 =====
@client.on(events.NewMessage(outgoing=True))
async def handle_message(event):
    # 这里的 target_key 逻辑保留你原有的设置
    target_key = f"{event.chat_id}.{event.sender_id}"

    try:
        if not event.message.text:
            return

        text = event.message.text.strip()
        if not text:
            return

        # 处理指令
        if text.startswith('.tt-') and not await command_mode(event, target_key, text):
            return

        # 检查是否在该聊天开启了翻译
        if target_key not in target_config:
            return

        conf = target_config[target_key]
        translated_texts = await translate_text(text, conf['source_lang'], conf['target_langs'])

        if not translated_texts:
            return

        main_texts = []
        code_texts = []

        # 这里的排版逻辑保留你原有的:EN放在正文,其他放在代码块
        for lang in conf["target_langs"]:
            if lang in translated_texts:
                if lang == "EN":
                    main_texts.append(translated_texts[lang])
                else:
                    code_texts.append(translated_texts[lang])

        if main_texts:
            output = '\n'.join(main_texts)
        elif code_texts:
            # 如果没有EN,取第一个翻译作为主文本
            output = code_texts.pop(0)
        else:
            return

        if code_texts:
            output += "\n``<code>\n" + "\n".join(code_texts) + "\n</code>``"

        await event.message.edit(output)
        logging.info(f"消息翻译完成: {output[:30]}...")

    except Exception as e:
        logging.error(f"处理异常: {e}")

# ===== 启动 =====
try:
    client.start()
    logging.info("🤖 Telegram 翻译机器人已启动(DeepL 多 Key 轮换版)")
    client.run_until_disconnected()
finally:
    if client.is_connected():
        client.disconnect()
    logging.info("⚠️ 机器人已断开连接")

📌 第 7 步:第一次启动(建立 Telegram session)

必须进入目录:

cd /home/translator
python3 translate.py

你会看到:

Please enter your phone (or bot token):

因为你使用 outgoing=True(个人账号翻译自己消息)
所以必须输入你的手机号:

+8613812345678

输入验证码:

Please enter the code you received: 12345

登录成功后看到:

Signed in successfully as XXX
🤖 Telegram 翻译机器人已启动(DeepL 官方 API)

成功!

此时会生成:

/home/translator/chat_translator.session

以后无需再登录。

📌 第 8 步:测试翻译功能

进入 Telegram 任意聊天框输入:

.tt-on,zh,zh|en

再发:

你好

你的消息会被自动翻译成:

Hello

你好

此功能已确认正常。

📌 第 9 步:创建 Systemd 服务(后台运行)

创建服务文件:

sudo nano /etc/systemd/system/translator.service

粘贴:

[Unit]
Description=Telegram DeepL Translator Service
After=network.target

[Service]
User=root
WorkingDirectory=/home/translator
ExecStart=/usr/bin/python3 /home/translator/translate.py
Restart=always
RestartSec=5

StandardOutput=append:/home/translator/translator.log
StandardError=append:/home/translator/translator.log

[Install]
WantedBy=multi-user.target

保存退出。

📌 第 10 步:启动 systemd 服务

让 systemd 识别新服务:

sudo systemctl daemon-reload

设置开机自启:

sudo systemctl enable translator

启动:

sudo systemctl start translator

查看是否运行中:

sudo systemctl status translator

看到:

Active: active (running)

即可。