feat: DSL 磁力聚合 — 搜索/解析/预览/投递 + cilisousuo 源 + 中英双语 + Docker 部署

This commit is contained in:
ice-a
2026-10-16 18:53:45 +08:00
commit d6999104bf
64 changed files with 16524 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
// 中文(源文) → 英文 映射。
// 站点模板以中文书写,默认显示英文;切换到中文时回退到源文(即中文)。
// 键已做空格归一化(连续空白合并为单个空格),便于整句匹配。
export const zh2en: Record<string, string> = {
// ===== 顶栏 / 布局 =====
'预览台 / 投递器': 'Preview / Handoff',
'搜索': 'Search',
'任务': 'Tasks',
'历史': 'History',
'设置': 'Settings',
'MONGO 未连接': 'MONGO disconnected',
'磁力解析就绪': 'Magnet parsing ready',
'磁力解析不可用': 'Magnet parsing unavailable',
'本地自托管 · 单进程 Nuxt 单体应用': 'Self-hosted · single-process Nuxt app',
'种子只做解析与预览,文件内容由你自己的下载器拉取': 'Torrents are only parsed and previewed; file contents are fetched by your own download client',
// ===== 种子详情页 [infohash] =====
'← 返回搜索': '← Back to search',
'来自 MongoDB 缓存': 'From MongoDB cache',
'来自链接参数': 'From link parameter',
'拿不到这个种子的信息': "Can't fetch info for this torrent",
'如果你是直接从外部链接进来的,请带上 magnet 参数,例如': 'If you came from an external link, include a magnet parameter, e.g.',
'回到搜索页': 'Back to search',
'加载中…': 'Loading…',
// ===== 首页 index =====
'SEARCH · PARSE · HANDOFF': 'SEARCH · PARSE · HANDOFF',
'搜种子、看清里面有什么,再丢给本机下载器': 'Search torrents, see what is inside, then hand off to your local downloader',
'qBittorrent / Transmission / aria2,由它们完成实际下载。': 'qBittorrent / Transmission / aria2, which do the actual downloading.',
'经代理访问': 'Via proxy',
'直连访问': 'Direct connection',
'请输入关键词': 'Please enter a keyword',
'没有搜到结果': 'No results found',
'可以换个关键词,或检查代理设置': 'Try another keyword or check proxy settings',
'没有结果。换个关键词,或在「设置」里配置代理后再试。': 'No results. Try another keyword, or configure a proxy in Settings.',
'上一页': 'Previous',
'下一页': 'Next',
'预览': 'Preview',
'输入关键词开始搜索': 'Enter a keyword to search',
'关键词搜索': 'Keyword search',
'上传 .torrent': 'Upload .torrent',
'磁力链': 'Magnet link',
'把 .torrent 文件拖到这里,或点击选择': 'Drag a .torrent file here, or click to choose',
'文件只在服务端解析出文件清单,不会上传到任何第三方': 'Files are parsed into a file list on the server only; nothing is uploaded to any third party',
'解析中…': 'Resolving…',
'磁力链需要联网从 DHT / tracker 拉取元数据,才能看到文件清单': 'A magnet link needs to fetch metadata from DHT / trackers to show the file list',
'解析磁力链': 'Resolve magnet',
'名称': 'Name',
'来源': 'Source',
'大小': 'Size',
'文件': 'Files',
'做种': 'Seeders',
'下载': 'Leechers',
'发布': 'Added',
'操作': 'Actions',
'搜索源': 'Search sources',
// ===== 下载任务 downloads =====
'实时下载状态': 'Live download status',
'直接从你配置的 qBittorrent / Transmission / aria2 客户端拉取的实时数据。': 'Real-time data pulled directly from your configured qBittorrent / Transmission / aria2 clients.',
'活跃任务总数': 'Total active tasks',
'在线下载器': 'Online clients',
'刷新频率': 'Refresh rate',
'每 5 秒自动同步': 'Auto-sync every 5s',
'手动刷新': 'Manual refresh',
'同步中…': 'Syncing…',
'任务名称': 'Task name',
'进度': 'Progress',
'下载速度': 'DL speed',
'剩余时间': 'ETA',
'状态': 'Status',
'暂无任务': 'No tasks',
'还没有配置任何下载器,或者所有下载器都已禁用。': 'No download clients configured, or all are disabled.',
'去设置': 'Go to settings',
'下载中': 'Downloading',
'做种中': 'Seeding',
'已暂停': 'Paused',
'错误': 'Error',
'排队中': 'Queued',
'校验中': 'Checking',
'已完成': 'Completed',
'未知': 'Unknown',
'在线': 'online',
'离线': 'offline',
// ===== 历史 history =====
'搜索历史与种子库': 'Search history & torrent library',
'每次搜索都会落到 MongoDB 的 searches 集合;搜到和解析过的种子按 infoHash 去重存在 torrents 集合。': "Every search is stored in MongoDB's searches collection; found and parsed torrents are deduplicated by infoHash in the torrents collection.",
'MongoDB 未连接,历史记录不可用。启动本地 MongoDB 后刷新本页即可。': 'MongoDB not connected, history unavailable. Start local MongoDB and refresh this page.',
'搜索总次数': 'Total searches',
'库中种子数': 'Torrents in library',
'高频关键词': 'Top keywords',
'未连接': 'Disconnected',
'正常': 'OK',
'点击直接再搜一次': 'Click to search again',
'刷新': 'Refresh',
'刷新中…': 'Refreshing…',
'清空': 'Clear all',
'关键词': 'Keyword',
'结果数': 'Results',
'耗时': 'Time',
'时间': 'Time',
'删除': 'Delete',
'还没有搜索记录': 'No search history yet',
'加载中…': 'Loading…',
'更新': 'Updated',
'打开': 'Open',
'库里还没有种子': 'No torrents in library yet',
'已删除该条记录': 'Record deleted',
'删除失败': 'Delete failed',
'确定清空全部搜索历史?': 'Clear all search history?',
'清空失败': 'Clear failed',
// ===== 种子详情 TorrentDetail =====
'未知来源': 'Unknown source',
'磁力搜索': 'Magnet Search',
'本地上传': 'Local upload',
'数据库': 'Database',
'文件清单已解析': 'File list resolved',
'磁力链已复制到剪贴板': 'Magnet link copied to clipboard',
'复制失败,请手动选中复制': 'Copy failed, please select and copy manually',
'解析失败': 'Resolve failed',
'总大小': 'Total size',
'文件数': 'File count',
'做种 / 下载': 'Seeders / Leechers',
'发布时间': 'Published',
'展开': 'Expand',
'收起': 'Collapse',
'备注': 'Comment',
'复制磁力链': 'Copy magnet',
'下载 .torrent': 'Download .torrent',
'打开来源页面': 'Open source page',
// ===== SendPanel =====
'SEND TO LOCAL CLIENT': 'SEND TO LOCAL CLIENT',
'探测中…': 'Probing…',
'重新探测': 'Re-probe',
'配置': 'Configure',
'还没有配置任何下载器。去「设置」里填 qBittorrent / Transmission / aria2 的地址和账号密码。': 'No download client configured. Go to Settings and provide qBittorrent / Transmission / aria2 address and credentials.',
'目标下载器': 'Target client',
'下载目录(留空用客户端默认)': 'Download dir (blank = client default)',
'该下载器当前不可用': 'This client is currently unavailable',
'投递到本机下载器': 'Send to local client',
'投递中…': 'Sending…',
'种子交给本机客户端下载,服务器不中转文件内容': 'The torrent is downloaded by your local client; the server does not proxy file contents',
'读取下载器配置失败': 'Failed to read client config',
'投递成功': 'Delivered',
'投递失败': 'Delivery failed',
// ===== FileTable =====
'正在通过 DHT / tracker 获取种子元数据,通常几秒到几十秒…': 'Fetching torrent metadata via DHT / tracker, usually takes seconds to tens of seconds…',
'这个种子只有 infoHash,还没有文件清单。可以点击下面的按钮在线拉取元数据(需要本机能连上 DHT / tracker)。': 'This torrent only has an infoHash and no file list yet. Click the button below to fetch metadata online (requires the server to reach DHT / trackers).',
'在线解析文件清单': 'Resolve file list online',
'FILE LIST': 'FILE LIST',
'过滤文件名…': 'Filter filenames…',
'按大小': 'By size',
'按名称': 'By name',
'路径': 'Path',
'占比': 'Ratio',
'过大': 'Too large',
'结果较多,表格只展示前 500 条,可用过滤框缩小范围': 'Too many results; table shows the first 500 rows. Use the filter to narrow down',
// ===== ImagePreview =====
'IMAGE': 'IMAGE',
'关闭': 'Close',
'正在从做种节点拉取这张图片,取决于对方的上传速度…': 'Fetching this image from seeding peers, depending on their upload speed…',
'重试': 'Retry',
'直接打开图片地址': 'Open image URL directly',
'上一张': 'Previous',
'下一张': 'Next',
// ===== 设置 settings =====
'搜索源与本机下载器': 'Search sources & local clients',
'所有配置写在 MongoDB 的 settings 集合里(没连库时回落到 .env)。下载器地址默认指向本机,如果服务部署在别的机器上,改成本机可访问的地址即可。': "All config is stored in MongoDB's settings collection (falls back to .env when the DB is down). Downloader addresses point to localhost by default; change them to whatever address is reachable.",
'保存中…': 'Saving…',
'保存全部配置': 'Save all settings',
'重新加载': 'Reload',
'MongoDB 未连接,配置只能在本次运行内生效': 'MongoDB not connected; config only takes effect for this session',
'启用的搜索源': 'Enabled search sources',
'HTTP 代理(搜索源用)': 'HTTP proxy (for search sources)',
'搜索超时(毫秒)': 'Search timeout (ms)',
'元数据解析超时(毫秒)': 'Metadata parse timeout (ms)',
'公开磁力站在部分网络环境下不可直连,配好代理后「设置 → 保存」再回搜索页重试即可。代理只作用于搜索源请求,不影响下载器通信。': 'Public magnet sites may be unreachable on some networks. After setting a proxy, Save in Settings then retry from the search page. The proxy only affects search requests, not downloader communication.',
'LOCAL BT CLIENTS': 'LOCAL BT CLIENTS',
'新增下载器': 'Add client',
'启用': 'Enable',
'测试连接': 'Test connection',
'类型': 'Type',
'主机': 'Host',
'端口': 'Port',
'RPC 路径(可空)': 'RPC path (optional)',
'默认': 'default',
'用户名': 'Username',
'(aria2 用不到)': '(not used by aria2)',
'RPC 密钥 --rpc-secret': 'RPC secret --rpc-secret',
'密码': 'Password',
'aria2 的 --rpc-secret 值': "aria2's --rpc-secret value",
'默认下载目录': 'Default download dir',
'留空用客户端默认': 'Blank = client default',
'使用 HTTPS': 'Use HTTPS',
'可达': 'Reachable',
'qBittorrent:开启「工具 → 选项 → Web UI」,默认端口 8080;首次访问会让客户端把本机 IP 加入白名单。': 'qBittorrent: enable "Tools → Options → Web UI", default port 8080; first visit whitelists your local IP in the client.',
'Transmission:开启远程控制,默认端口 9091,RPC 路径 /transmission/rpc;没设用户名密码就留空。': 'Transmission: enable remote control, default port 9091, RPC path /transmission/rpc; leave blank if no username/password.',
'aria2:启动时加 --enable-rpc --rpc-listen-all=true --rpc-secret=你的密钥,把密钥填到「RPC 密钥」框。': 'aria2: start with --enable-rpc --rpc-listen-all=true --rpc-secret=YOUR_SECRET, and put the secret in the RPC secret field.',
'还没有下载器,点右上角「新增下载器」': 'No downloaders yet. Click "Add client" at the top right.',
'HANDOFF LOG': 'HANDOFF LOG',
'最近 25 条投递记录': 'Last 25 handoff records',
'下载器': 'Client',
'目录': 'Dir',
'结果': 'Result',
'成功': 'Success',
'失败': 'Failed',
'还没有投递记录': 'No handoff records yet',
'RUNTIME': 'RUNTIME',
'已连接': 'Connected',
'磁力解析': 'Magnet parsing',
'webtorrent 可用,可通过 DHT/tracker 取文件清单': 'webtorrent available; can fetch file list via DHT/tracker',
'webtorrent 不可用,磁力链只能显示 infoHash': 'webtorrent unavailable; magnet links can only show infoHash',
// ===== 输入框占位符 =====
'输入片名 / 剧名 / 关键词,回车搜索': 'Movie / show / keyword, press Enter to search',
'http://127.0.0.1:7890 / 留空直连': 'http://127.0.0.1:7890 / blank for direct'
}
export const en2zh: Record<string, string> = Object.fromEntries(
Object.entries(zh2en).map(([zh, en]) => [en, zh])
)
/** 归一化:折叠所有连续空白为单个空格,并去掉首尾空白 */
export function normalizeWs(s: string): string {
return s.trim().replace(/\s+/g, ' ')
}