一、核心实现原理 & 整体架构
1.1 整体调用链路
沉浸式翻译插件(浏览器) → Lucky反代(HTTPS+密码+路径分流) → 中转服务(格式适配/秘钥转发/语言清洗) → LibreTranslate(CUDA GPU翻译核心) → 原路返回翻译结果
1.2 各组件核心作用
- LibreTranslate:latest-cuda:核心翻译服务,启用NVIDIA GPU硬件加速,加载指定语言模型,提供原生翻译API,开启密钥认证防无授权调用,性能拉满;
- Python中转服务(translate_proxy.py):本次部署的「核心适配层」,解决沉浸式翻译插件和LibreTranslate的格式不兼容+传参问题,核心能力:
- 解析沉浸式插件的text_list数组请求格式,转为LibreTranslate支持的q文本格式;
- 自动清洗插件的zh-CN/en-US带后缀语言码,转为zh/en纯语言码,避免400报错;
- 自动读取URL中的?token=秘钥参数,转发给LibreTranslate做认证;
- 文本自动截断至5000字符,适配Libre的字符限制,避免超限400报错;
- 全网跨域放行,解决浏览器插件跨域调用限制;
- Lucky反代:本次部署的「关键优化层」,核心价值是同域名+同端口+不同路径,指向不同后端服务,同时提供:
- HTTP转HTTPS加密访问,避免浏览器不安全提示;
- 可以自行给Web管理界面设置访问密码,彻底杜绝他人滥用;
- 路径分流:一个域名端口搞定「Web管理+翻译API」两个服务,无需记多个地址;
- 沉浸式翻译插件:浏览器端翻译载体,支持网页划词/整页翻译,缺点是原生不支持自定义传参,需要中转服务适配。
二、以下示例中,服务/端口/地址对照表
| 服务功能 |
端口号 |
访问/转发地址 |
用途说明 |
| LibreTranslate主服务 |
50116 |
http://172.17.0.1:50116 |
核心翻译服务+Web管理界面,加载语言模型、密钥管理 |
| Python中转服务 |
50106 |
http://172.17.0.1:50106 |
仅对接反代,做插件格式适配/密钥转发/语言码清洗,不直接访问 |
| Lucky反代对外访问 |
5151 |
https://fanyi.xxxx.com:5151 |
对外唯一访问地址,同域名同端口,不同路径分流2个后端服务 |
三、部署文件结构
libretranslate/
**── docker-compose.yml # 双服务核心配置文件,完整复制
**── translate_proxy.py # 中转适配脚本,完整复制
# 以下文件夹启动后自动生成,无需手动创建
**── db/ # 存放API密钥数据库,持久化保存密钥
**── data/ # 存放翻译语言模型,重启不重复下载
四、完整核心配置文件
4.1 docker-compose.yml GPU加速完整版
services:
libretranslate:
image: libretranslate/libretranslate:latest-cuda
container_name: libretranslate-cuda
runtime: nvidia # 启用NVIDIA GPU运行时
environment:
- LT_CORS_ALLOWED_ORIGINS=*
- NVIDIA_VISIBLE_DEVICES=all
- LT_LOAD_ONLY=en,zh # 只加载英中模型,显存占用极低,启动超快
- LT_API_KEYS_DB_PATH=/app/db/api_keys.db
- LT_API_KEYS=False # 是否开启TOKEN令牌校验,当前关闭
- LT_REQ_LIMIT=500 # 单IP请求限流:500次/分钟
- LT_UPDATE_MODELS=True # 是否自动更新语言模型
- LT_MAX_TEXT_LENGTH=5000 # 翻译文本最大长度限制
- LT_DISABLE_FILTERS=True # 是否关闭文本过滤机制:开启(true),纯数字/短文本/特殊符号也能正常返回,不返回空值
- LT_GPU_MEMORY_LIMIT=1024 # GPU显存限制1G,英中双模型足够用,防溢出
- LT_WORKERS=1 # 单进程运行,GPU无冲突,极致稳定
- LT_DEBUG=False # 关闭调试模式,减少日志冗余
# 数据卷挂载:持久化模型/数据库文件,重启容器不丢失模型,无需重新下载
volumes:
- ./db:/app/db:rw
- ./data:/root/.local:rw
ports:
- "50116:5000"
restart: always
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
# ========== 中转服务:沉浸式翻译插件适配代理 ==========
lt-proxy:
image: python:3.11-slim # Python运行环境镜像
container_name: libretranslate-proxy
working_dir: /app
environment:
- PYTHONUNBUFFERED=1 # 开启Python日志实时输出,方便排查问题
volumes:
- ./translate_proxy.py:/app/translate_proxy.py:rw
ports:
- "50106:5000"
restart: always
# 依赖关系:先启动LibreTranslate,再启动中转服务,防止连接失败
depends_on:
- libretranslate
command: >
bash -c "pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple flask requests flask-cors && python translate_proxy.py"
4.2 translate_proxy.py
新建一个文本文件(注意使用Unix格式的UTF-8编码),粘贴以下代码,修改文件名和扩展名即可
# -*- coding: utf-8 -*-
import requests
from flask import Flask, request, jsonify
from flask_cors import CORS
# ===================== 全局核心配置=====================
LIBRE_URL = "http://172.17.0.1:50116/translate" # 172.17.0.1 为飞牛docker内部网络IP可以不改,端口需要改为 libretranslate 容器的对外映射端口
PROXY_PORT = 5000
MAX_TEXT_LENGTH = 5000 # 文本长度上限
TOKEN_CHECK = False # True=强制验token False=忽略所有token检查
app = Flask(__name__)
CORS(app, resources=r'/*') # 全网跨域放行,浏览器插件必开
# 语言码清洗适配【仅英中专用】,精简高效
def clean_lang_code(lang):
if not lang:
return "auto"
lang = lang.strip().lower()
if lang in ["zh-cn", "zh-tw", "zh"]:
return "zh"
elif lang == "en":
return "en"
else:
return "auto"
# 核心翻译接口
@app.route('/translate', methods=['POST'])
def translate_proxy():
# 从请求参数中获取前端传入的token
client_api_key = request.args.get("token", "")
api_key_param = ""
# ===== TOKEN核心校验逻辑 =====
if TOKEN_CHECK:
if not client_api_key: # 空token直接拦截拒绝,返回401未授权+提示语
return jsonify({"translations": [{"text": "请配置正确的API Token"}],"detected_source_lang": "auto"}), 401
api_key_param = client_api_key # 有token则赋值,传给后端做二次校验
else:
api_key_param = "" # 关闭校验时,不传token给后端
# 获取插件请求数据
req_data = request.get_json()
if not req_data:
return jsonify({"translations": [{"text": ""}], "detected_source_lang": "auto"}), 200
# 解析参数+清洗语言码
text_list = req_data.get("text_list", [])
source_lang = clean_lang_code(req_data.get("source_lang", "auto"))
target_lang = clean_lang_code(req_data.get("target_lang", "zh"))
detected_source_lang = source_lang
translations = []
# 批量循环处理所有文本,解决部分内容不翻译问题
for single_text in text_list:
if not isinstance(single_text, str):
translations.append({"text": ""})
continue
final_text = single_text.strip()[:MAX_TEXT_LENGTH]
if not final_text:
translations.append({"text": single_text})
continue
# 构造请求体
libre_req_data = {
"q": final_text,
"source": source_lang,
"target": target_lang,
"format": "text",
"api_key": api_key_param # 传给Libre做后端二次校验的核心参数
}
# 请求翻译+异常处理
try:
headers = {"Content-Type": "application/json; charset=utf-8"}
libre_response = requests.post(LIBRE_URL,json=libre_req_data,headers=headers,timeout=20,verify=False)
libre_response.raise_for_status()
libre_result = libre_response.json()
trans_text = libre_result.get("translatedText", single_text)
if detected_source_lang == "auto" and "detectedLanguage" in libre_result:
detected_source_lang = libre_result["detectedLanguage"]["language"]
translations.append({"text": trans_text})
except Exception as e:
# TOKEN校验开启时,异常返回【Token无效】提示+401;关闭时返回原文+200
if TOKEN_CHECK:
return jsonify({"translations": [{"text": "Token Error"}], "detected_source_lang": source_lang}), 401
else:
translations.append({"text": single_text})
# 返回插件标准格式
return jsonify({
"translations": translations,
"detected_source_lang": detected_source_lang
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=PROXY_PORT, debug=False)
首次启动libretranslate需要下载翻译模型,请耐心等待
五、Lucky反代配置(以应用中心里面的Lucky为例)
✅ 核心实现:一个域名+一个端口https://fanyi.xxxx.com:5151,通过不同路径,转发到2个不同的后端服务,这是最核心的配置,缺一不可
✅ 飞牛NAS Docker内网IP固定为 172.17.0.1,所有反代目标地址均填这个,如果不对,可以直接使用飞牛宿主机的局域网地址
规则1:【 翻译WebUI 】 → 指向 LibreTranslate主服务 (http://172.17.0.1:50116)
- Lucky → Web服务 → Web服务规则 → 监听端口 5151,启用TLS → 新建子规则(如果你已经配置过Lucky实现https访问,请忽略这条,从你原来的规则创建子规则即可)
- 前端地址:fanyi.xxxx.com、后端地址:http://172.17.0.1:50116
- ✅ 可选:开启【基本认证】,设置账号+密码
- 此时,浏览器通过 https://fanyi.xxxx.com:5151 这个地址,就能打开翻译的Web-UI

规则2: 【 翻译API中转 】 → 指向 中转服务 (http://172.17.0.1:50106)
- 同样新建一条子规则
- 前端地址:fanyi.xxxx.com/pyapi、后端地址:http://172.17.0.1:50106,其中/pyapi 这个路径可以自定义用其他的,沉浸式翻译插件跟着修改即可
- ✅ 必须:关闭【基本认证】→ 插件调用不能设置密码,直接放行
- 此时,沉浸式翻译插件的API URL https://fanyi.xxxx.com:5151/pyapi/translate?token=你的API密钥 这个地址,就能调用API翻译
- 上述配置文件中,默认是关闭 API Key ,也就是不进行token校验,使用https://fanyi.xxxx.com:5151/pyapi/translate也可调用API翻译

最终效果示例

💡 Tip
如果没有设置反代,沉浸式翻译插件直接填写 http://fanyi.xxxx.com:5151/translate?token=你的API密钥 即可,也就是直接指向中转容器的端口。
六、沉浸式翻译插件配置
前置必做步骤(不然找不到自定义服务)
插件图标 → 设置 → 左侧下滑找到【开发者设置】→ 开启【启用 Beta 测试特性】→ 保存并刷新插件页面

插件配置步骤
-
左侧 翻译服务 → 点击【添加自定义翻译服务】→ 选择【自定义API】

-
名称随意(例如:本地Libre翻译)
-
✅API URL 填写格式:
https://fanyi.xxxx.com:5151/pyapi/translate?token=你的API密钥
或者
https://fanyi.xxxx.com:5151/pyapi/translate #无需密钥校验
-
插件的其余所有配置项保持默认即可,如果显卡性能优异,可以试着调高每秒最大请求数

-
保存后,选中该自定义服务为默认翻译服务,完成配置
✅ 为什么是pyapi/translate?
反代规则2的前端地址加了/pyapi,中转服务的翻译接口本身是/translate,路径叠加后就是/pyapi/translate,少一个直接报404 Not Found,这是部署最大的坑,记住即可。
七、如果想使用API Key
把 Compose 里的 LT_API_KEYS 和 Python 文件里的TOKEN_CHECK 都设置为 True,重构Docker即可
| 需求场景 |
Compose(LT_API_KEYS) |
Python(TOKEN_CHECK) |
效果 |
| 强制验token(防滥用) |
True |
True |
仅正确token可访问 |
| 免验token(自用便捷) |
False |
False |
空/错/正确token均可访问 |
关于LibreTranslate+Python中转 双开关组合解释
Compose
|
Python |
访问效果 |
是否合理 |
核心逻辑 |
| True |
True |
空/错token拒绝,正确token通过 |
✅ 合理 |
Python前置拦截+后端半校验,双重保障 |
| True |
False |
空/错/正确token均通过 |
⚠️ 现象正常(非预期) |
Python无拦截,后端宽松接口对空/错token直接放行 |
| False |
True |
空/错token拒绝,正确token通过 |
⚠️ 现象正常(非预期) |
Python前置绝对拦截,无视后端校验状态 |
| False |
False |
空/错/正确token均通过 |
✅ 合理 |
Python无拦截+后端无校验,全程放行 |
八、创建LibreTranslate的API密钥
-
在飞牛的 Docker 管理器中,找到 libretranslate-cuda 容器,运行其终端,连接 /bin/bash


-
添加新密钥
ltmanage keys add 3000 --char-limit 5000
# 以上表示创建一个新的以每分钟3000个请求,最多单次请求5000个字符的新秘钥,也就是每分钟能翻译3000*5000字(如果你显卡够牛的话)
-
删除密钥
ltmanage keys remove <api-key>
-
查看密钥
ltmanage keys
-
自己用,只保留1个密钥,删除其他密钥即可
九、纯CPU 的Compose方案
如果你没有 Nvidia 显卡,compose可以使用这个纯CPU方案,translate_proxy.py 内容不变,其他设置也均一样
services:
libretranslate:
image: libretranslate/libretranslate:latest # CPU核心修改:移除-cuda,纯CPU官方镜像
container_name: libretranslate-cuda
environment:
- LT_CORS_ALLOWED_ORIGINS=*
- LT_LOAD_ONLY=en,zh # 只加载英中模型,显存/内存占用极低,启动超快
- LT_API_KEYS_DB_PATH=/app/db/api_keys.db
- LT_API_KEYS=False # 是否开启TOKEN令牌校验
- LT_REQ_LIMIT=200 # 单IP请求限流:200次/分钟
- LT_UPDATE_MODELS=True # 是否自动更新语言模型
- LT_MAX_TEXT_LENGTH=5000 # 翻译文本最大长度限制
- LT_DISABLE_FILTERS=True # 是否关闭文本过滤机制:开启(true),纯数字/短文本/特殊符号也能正常返回,不返回空值
- LT_WORKERS=1 # 单进程运行,CPU无冲突,极致稳定
- LT_DEBUG=False # 关闭调试模式,减少日志冗余
# 数据卷挂载:持久化模型/数据库文件,重启容器不丢失模型,无需重新下载
volumes:
- ./db:/app/db:rw
- ./data:/root/.local:rw
ports:
- "50116:5000"
restart: always
# ========== 中转服务:沉浸式翻译插件适配代理 ==========
lt-proxy:
image: python:3.11-slim # Python运行环境镜像
container_name: libretranslate-proxy
working_dir: /app
environment:
- PYTHONUNBUFFERED=1 # 开启Python日志实时输出,方便排查问题
volumes:
- ./translate_proxy.py:/app/translate_proxy.py:rw
ports:
- "50106:5000"
restart: always
# 依赖关系:先启动LibreTranslate,再启动中转服务,防止连接失败
depends_on:
- libretranslate
command: >
bash -c "pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple flask requests flask-cors && python translate_proxy.py"