qBittorrent 手册页工程实践:Markdown 源稿编写、Pandoc 转换与多语言(en/ru)构建流程
【免费下载链接】qBittorrentqBittorrent BitTorrent client项目地址: https://gitcode.com/GitHub_Trending/qb/qBittorrent
导读
qBittorrent 的手册页(man pages)并非直接以 roff 语法编写,而是采用Markdown 源稿 + Pandoc 自动转换的维护流程,源稿与产物同时入库、随构建系统统一安装。本文以仓库中的 doc/README.md 为骨架,完整梳理其写作约定、构建命令、内容章节结构与多语言翻译发布全链路,并结合 src/app/cmdoptions.cpp、dist/unix/CMakeLists.txt 等源码给出底层实现印证。读完本文,你可以熟练地在 qBittorrent 源码仓库中增改手册页、复现转换命令,并为新语言添加手册翻译。
一、为什么手册页要先写成 Markdown
传统 Unix 手册页直接使用 roff/troff 排版指令(.TH、.SH、.TP等),书写与维护成本高、可读性差。qBittorrent 的解决方案是:先在doc/<语言>/目录下维护可读的 Markdown 源稿(.md),再借助 Pandoc 将其转换为 roff 格式的最终手册文件(无扩展名的.1文件)。
仓库中当前同时存在两种文件,且均被纳入版本管理:
- 源稿:如 doc/en/qbittorrent-nox.1.md、doc/en/qbittorrent.1.md 及 doc/ru/ 下的俄语对应文件;
- 产物:doc/en/qbittorrent.1、doc/en/qbittorrent-nox.1 等 roff 文件。
这一"写 Markdown、出 roff"的模式让贡献者无需掌握 roff 语法即可维护高质量手册,也使文档正文能够被普通 Markdown 渲染工具预览、diff 与检索。
二、Pandoc 转换命令与构建步骤
构建手册页需要 Pandoc 支持 Markdown 到man格式的转换。doc/README.md给出的两条标准命令是:
pandoc -s -f markdown -t man qbittorrent.1.md -o qbittorrent.1 pandoc -s -f markdown -t man qbittorrent-nox.1.md -o qbittorrent-nox.1命令要点拆解:
| 参数 | 含义 |
|---|---|
-s | standalone(独立文档)模式,生成带完整 roff 头/尾结构的完整 man 文件,而不是 fragment |
-f markdown | 输入格式为 Pandoc's Markdown(其扩展语法与通用 GFM 略有差异) |
-t man | 输出格式为 roff man page |
-o | 指定输出文件名 |
转换时需要注意:由于使用了 Pandoc 特定的 Markdown 方言,源稿中的标题层级、列表、加粗等写法需遵循Pandoc 的 Markdown 规范才能被正确映射为 roff 排版指令,仓库在 README 中也明确要求编辑者先了解该格式约定。
2.1 没有本地 Pandoc 时的备选路径
若本机安装 Pandoc 有困难,可使用 Pandoc 官方提供的在线转换器(to=man、standalone=true的预置参数链接)。但官方在线转换器的输出存在一个已知陷阱:复制结果到本地文件时部分头部信息会丢失,因此必须小心——既不要覆盖文件已有的开头头部,也不要截掉结尾的尾部头部。稳妥起见,仍建议以本地pandoc命令生成的产物为准。
2.2 产物必须随源稿一并提交
doc/README.md明确要求:编辑完成后,Markdown 源稿(*.md)与生成的 man 产物(*.1)都要提交,二者是同步维护的一对文件,缺一不可——源稿保证可维护性,产物保证用户安装即用。
三、手册正文的标准章节结构
观察 doc/en/qbittorrent-nox.1.md(91 行)与 doc/en/qbittorrent.1.md(82 行)两个英文源稿,可总结出 qBittorrent 手册统一的 roff 命名与章节模板:
% QBITTORRENT-NOX(1) <一行描述> % <空作者行> % <月份年份> # NAME # SYNOPSIS # DESCRIPTION # OPTIONS ## Options when adding new torrents # ENVIRONMENT # BUGS # AUTHORS头部三行%是 Pandoc man 输出所需的标题块(对应 roff 的.TH),紧随其后是手册标准小节:
- NAME / SYNOPSIS:程序名与调用形式。无头模式为
qbittorrent-nox [options] [(<filename> | <url>)...],GUI 版为qbittorrent,均支持--help、--version; - DESCRIPTION:介绍程序定位——基于 C++/Qt、使用 libtorrent-rasterbar 实现、支持 Unicode、UPnP/NAT-PMP 端口映射、加密、FAST extension 与 PeX 等特性。
qbittorrent-nox一节还会说明其默认由 Web UI(http://localhost:8080,默认用户名admin,未设密码时每次启动在控制台打印临时随机密码)控制; - OPTIONS:全部命令行参数(详见下一节);
- ENVIRONMENT:环境变量等价写法(详见第五节);
- BUGS / AUTHORS:指向官方 bug 跟踪系统,作者署名。
四、手册收录的命令行参数清单
两个手册源稿中 OPTIONS 部分的参数高度一致,其中 GUI 版独有的--no-splash与--skip-dialog(GUI 版添加种子时是否弹窗),正是两类二进制的功能差异体现:
| 选项 | 适用 | 说明 |
|---|---|---|
-h | --help | 全部 | 显示帮助并退出 |
-v | --version | 全部 | 显示版本并退出 |
--confirm-legal-notice | 全部 | 确认法律声明(配合无人值守启动) |
--webui-port=<port> | 全部 | 修改 WebUI 端口 |
--torrenting-port=<port> | 全部 | 修改 BT 传输端口 |
--no-splash | GUI | 禁用启动闪屏 |
-d | --daemon | nox | 以守护进程方式后台运行 |
--profile=<dir> | 全部 | 将配置文件存放于指定目录 |
--configuration=<name> | 全部 | 使用qBittorrent_<name>形式的独立配置目录 |
--relative-fastresume | 全部 | 改写 libtorrent fastresume 文件,使文件路径相对于 profile 目录 |
(<filename> | <url>)... | 全部 | 直接下载传入的种子文件或链接 |
4.1 添加新种子时的附加参数
两个源稿还用三级小节"Options when adding new torrents"单独归纳了添加种子场景的选项:
--save-path=<path>:种子保存路径;--add-stopped=<true|false>:以运行还是停止状态添加;--seed-mode:种子模式(只做种不上传数据);--category=<name>:分配给指定分类,分类不存在时自动创建;--sequential:按顺序下载文件;--first-and-last:优先下载首尾分片;--skip-dialog=<true|false>:添加种子时是否弹出"Add New Torrent"对话框。
4.2 源码侧的参数定义印证
上述参数并非文档凭空撰写,均可在命令行解析实现中逐一定位。参数解析集中在 src/app/cmdoptions.cpp:
- 布尔开关、整型参数分别由
BoolOption、IntOption等选项类封装,例如第 316~319 行就声明了NO_SPLASH_OPTION {"no-splash"}、WEBUI_PORT_OPTION {"webui-port"}、TORRENTING_PORT_OPTION {"torrenting-port"}; - 布尔值的取值判定
isTrue()(cmdoptions.cpp 第 62~65 行)只接受字面量1或大小写不敏感的true,这与手册 ENVIRONMENT 一节的约定一致。
五、环境变量等价写法(源码级印证)
两个手册的 ENVIRONMENT 小节都记载了一条通用映射规则:对名为parameter-name的选项,环境变量名为QBT_PARAMETER_NAME(全大写,-替换为_);标志类参数置为1或TRUE即表示开启。
这一规则的实现位于 src/app/cmdoptions.cpp 第 97~101 行的envVarName():
return u"QBT_" + m_name.toString().toUpper().replace(u'-', u'_');即选项名webui-port→QBT_WEBUI_PORT,no-splash→QBT_NO_SPLASH,与文档描述完全一致。手册中给出的两个可直接执行的示例:
QBT_WEBUI_PORT=8081 qbittorrent-nox # nox:用环境变量改 WebUI 端口 QBT_NO_SPLASH=1 qbittorrent # GUI:用环境变量禁用闪屏手册同时强调了一条优先级规则:命令行参数优先于环境变量。也就是说--webui-port=8082与QBT_WEBUI_PORT=8081同时出现时,以命令行取值 8082 为准。
六、多语言翻译流程与 CMake 安装规则
将手册页翻译为新语言是doc/README.md着力说明的第二条主线。参考 doc/ru/(已含俄语版两对源稿/产物)可归纳出标准步骤:
- 在
doc/下创建以语言代码命名的新子目录,如doc/fr/; - 将翻译好的文件放入该目录,命名必须与英文版保持一致:
qbittorrent.1.md+qbittorrent.1、qbittorrent-nox.1.md+qbittorrent-nox.1; - 把该语言代码追加到 dist/unix/CMakeLists.txt 的
manPageLanguages列表中。
6.1 CMake 中的实际安装逻辑
dist/unix/CMakeLists.txt 第 21~33 行展示了语言清单与安装细节:
set(manPageLanguages en ru ) foreach(manPageLanguage ${manPageLanguages}) install(FILES ${PROJECT_SOURCE_DIR}/doc/${manPageLanguage}/$<IF:$<BOOL:${GUI}>,qbittorrent.1,qbittorrent-nox.1> DESTINATION ${CMAKE_INSTALL_MANDIR}/$<$<NOT:$<STREQUAL:${manPageLanguage},en>>:${manPageLanguage}/>man1 COMPONENT doc ) endforeach()几点可从中读出的工程约束:
- 当前官方维护的语言是en 与 ru,新增翻译需同步修改此清单,否则不会进入安装产物;
- 安装哪个手册文件由构建目标决定:构建GUI版时装
qbittorrent.1,构建nox(无头)版时装qbittorrent-nox.1; - 安装目录遵循 man 惯例:英文版装入
<mandir>/man1,其他语言版装入<mandir>/<语言>/man1(如ru/man1),对应第 29~30 行注释中"English man pages are installed into man1, while other languages into /man1"的说明。
七、维护自查清单
结合全文,给出手册维护者的最终检查要点:
- 格式:源稿用 Pandoc's Markdown 撰写,保留首部
%标题块与 NAME/SYNOPSIS/…/AUTHORS 标准小节; - 转换:用
pandoc -s -f markdown -t man生成产物;若走在线转换器,复制输出时注意补齐丢失的头部、勿截断头尾; - 提交:
*.md源稿与生成的*.1产物必须成对提交; - 翻译:新增语言需同时完成
doc/<lang>/下的全部四个文件,并在 dist/unix/CMakeLists.txt 的manPageLanguages注册语言代码; - 一致性:手册中的参数与 ENVIRONMENT 规则改动时,同步核对 src/app/cmdoptions.cpp 中选项定义及
envVarName()的命名映射,确保文档、实现与安装三处不脱节。
【免费下载链接】qBittorrentqBittorrent BitTorrent client项目地址: https://gitcode.com/GitHub_Trending/qb/qBittorrent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考