← 所有文章

SWORD、MySword 与 e-Sword 模块格式:官方文档搞错的地方

绘制为一个按比例分为四段的长条的 zText 索引:1 个模块标题、1 个约标题、287 个书卷与章节标题,以及 7,957 节经文——共 8,246 条记录,每条 10 字节,计 82,460 字节。说明文字:zText 索引统计的是槽位,而不是经文节数。

简短回答: 如果你正在构建圣经模块,有三件被广泛流传的说法是错误的。e-Sword 根本没有 .bbl 格式。新约模块必须保持整本圣经的书卷编号。SWORD 的 zText 索引统计的是槽位(slots),而不是经文节数。每个错误都会导致构建出的模块能够顺利安装,但读取出来全是错的——这是出错最糟糕的一种形式。

我们用纯 Go 编写了适用于 SWORD、MySword 和 e-Sword 的模块构建器,没有引入任何外部工具链,用于发布 Tringine 背后的免费圣经模块。下文提到的每一种架构和字节布局,都是使用十六进制编辑器和 sqlite3 从已发布的真实模块中实测读出的,而不是出自任何二手文章。这就是我们学到的全部内容,其中包括一项我们现在在每次构建时都会运行的检查,因为光看代码是远远不够的。

为什么 e-Sword 没有 .bbl 文件?

因为它根本不存在。搜索 e-Sword 圣经模块格式时,.bbl 会频繁出现,但 .bbl 实际上是 LaTeX 参考文献文件的扩展名——这正是为什么去搜寻其规范时总是一无所获且令人困惑的原因。

真正的格式是用于 e-Sword 9 和 10 的 .bblx(其中经文文本为 RTF 格式),以及用于版本 11 及更新版本的 .bbli(其中经文文本为 HTML 格式)。版本 11 到 13 对这两者都能读取,因此只分发 .bblx 就能覆盖 e-Sword 9 到 13。如果你只打算构建一种格式,那就构建这一种。

阅读器 文件 经文文本 支持读取的软件
SWORD (AndBible, Xiphos, BibleTime) mods.d/*.conf + zText 文件 源自 OSIS,zlib 块 所有 libsword 前端
MySword .bbl.mybible (SQLite) theWord 风格标签 MySword for Android
e-Sword 9–13 .bblx (SQLite) RTF e-Sword 9, 10, 11, 12, 13
e-Sword 11+ .bbli (SQLite) HTML 仅限 e-Sword 11 及更高版本

为什么新约模块的书卷编号仍然是 40 到 66?

因为这三种格式寻址经文时,都是基于一套固定的章节编排体系(versification)——即阅读器用来定位经文的规范化书卷、章节和节数列表(默认采用 KJV)——而且这种编号是绝对的,并不取决于你的版本具体包含了哪些内容。把新约重新编号为 1 到 27,会把马太福音直接放到创世记的位置上,其后的所有内容都会发生错位。

我们没有单纯依赖理论推导,而是在两个真实的新约单行本模块上进行了验证:它们都从第 40 卷开始,并且都设置了 OT=0。同样的原则在一个约的内部也生效——如果你的版本不包含某一卷书,它仍然要占用对应的槽位,只是内容为空。为了节省空间而跳过它,阅读器就会在空缺之后的所有书卷中,默默地在马太福音的引用下显示马可福音的经文。

zText 索引中应该有多少条记录?

这个问题很容易在不知不觉中损坏模块,因为长度错误的索引仍然能够被正常解析。

SWORD 的一个约包含三个文件。根据对 CrossWire 的 ASV 和 Byzantine 模块的实测,全文均为小端序:

文件 记录大小 内容
nt.bzv 10 字节 uint32 块编号、在解压后块内的 uint32 偏移量、uint16 长度
nt.bzs 12 字节 .bzz 中的 uint32 偏移量、uint32 压缩后大小、uint32 解压后大小
nt.bzz 数据块本身,每个块都是独立的 zlib 流,每卷书一个块,外加用于标题的 0 号块

问题出在计数枚举上。槽位的排列规则是:槽位 0 为模块标题,槽位 1 为约标题,然后每卷书有一个书卷标题,每章有一个章节标题,接着是每节经文各占一个槽位。因此记录总数是 2 + books + chapters + verses——而不是经文的节数。

在 KJV 章节体系下,新约的计算方式是 2 + 27 + 260 + 7,957 = 8,246 条记录,所以 nt.bzv 的大小恰好是 82,460 字节。对于旧约,则是 2 + 39 + 929 + 23,145 = 24,115 条记录,即 241,150 字节

这可以通过一条命令直接检查,这正是将其记录下来的意义所在:官方发布的 ASV 和 Byzantine 模块的 nt.bzv 大小都恰好是 82,460 字节。如果你的文件大小不同,说明枚举出错了,并且你只能在阅读器错乱时才发现,而不会收到任何崩溃报错。

还有一个值得照搬的做法:纯新约模块仍然会附带一个 ot.bzv——完整大小,全为零——同时配有长度为零的 ot.bzsot.bzz。这与官方发布的 Byzantine 模块在字节级别完全一致。

SQLite 格式到底有什么要求?

MySword (.bbl.mybible):page_size=32768,UTF-8 编码,圣经索引必须是 UNIQUE。经文文本是 theWord 风格的成对标签,不是 HTML——例如脚注是 <RF>…<Rf>Details.Language 采用三字母代码,但具体是哪三个字母并不明显:ISO 639-2 为大约二十种语言各提供了书目代码和术语代码,已发布的模块对两者的使用并不一致(德语和捷克语模块使用 deuces;法语、阿尔巴尼亚语和希腊语模块使用 frealbgre;约有三分之一的模块直接省略了该列)。我们是通过打开真实模块而不是死抠标准来确定的——两个已发布的挪威语模块都使用 nor,所以我们的模块也采用它。对于无法确切映射的语言,我们宁可写入 NULL 也不去猜测,因为错误的语言标签比缺失更糟糕。

e-Sword (.bblx):page_size=1024,单引号包裹标识符,且索引不是唯一的。这里有两个陷阱。Details.Version 是一个表示格式版本的 INT——.bblx 为 2,.bbli 为 4——而不是你的版本号,你的版本号应该写在 Comments 中。此外,我们检查的三个真实模块在数据库本身的编码上各不相同:一个使用 UTF-16LE,两个使用 UTF-8。因此,不能指望数据库列的编码能够正确承载泰米尔文或泰卢固文字符。

解决办法是将每个非 ASCII 字符都写成 RTF 的 \uN? 转义符,在 BMP 之上使用带符号的 16 位代理对。这种方式与编码无关,也是真实模块的做法。如果你要向 e-Sword 发布非拉丁字母语言的模块,正是这一细节决定了用户究竟能不能正常阅读。

在两种 SQLite 格式中,布尔值均为 1/0。(.bbli 使用 Delphi 风格的 -1,这也是不建议随意生成 .bbli 的一个好理由。)

检查渲染出的 .conf,而不是代码中的结构体

元数据是模块中会被目录抓取、也可能在法庭上被审视的部分,但它往往是测试套件最少关注的地方。我们的测试最初也没有覆盖到:Go 结构体中完全正确的许可证字段,在渲染到 .conf 时变成了别的内容,我们是通过肉眼检查生成的文件发现的,而不是靠跑测试。我们在当天就修复并重新构建了所有模块;如今我们存放在服务器上的文件明确将 1868 年泰米尔语和 1880 年泰卢固语文本标为 Copyright=Public Domain,不列出任何版权所有者,并在 TextSource 中仅将 Publifye 注明为该版本的整理者。

在这个文件中,有两项声明必须严格区分。文本本身的许可证是关于该翻译版本的既定事实,不是你能自由决定的:公有领域的圣经在你的模块里同样是公有领域,任何 DistributionNotes 都无权限制它。分发服务的条款(如注册、日志记录等)只约束你的服务器,别无其他。混淆这两者,要么限制了原本免费的内容,要么擅自放开了受限的内容。

现在用来守护这部分的测试会直接针对渲染出的 .conf 文件进行断言。一旦公有领域文本被赋予版权所有者或限制性声明,或者我们自己的译本被悄悄降级为公有领域,测试就会立刻失败。双向检查都不可或缺,因为过度放任的错误同样是错误。任何分发圣经模块的人,都应该仔细检查自己最终发布的文件,而不仅仅是检查生成文件的代码。

我们是如何验证的

绝不是靠把规范抄一遍来自己糊弄自己:

  • 在 Debian 容器中使用 libsword 自带的 diatheke 构建并读取了一个完整体量的新约模块(7,957 节)。它正常出现在 modulelist 中,能够在正确的地址解析太 1:1、约 3:16、林前 13:13 和启 22:21,对于创 1:1 则像正规新约单行本一样不返回任何内容,并且搜索功能运行正常。
  • 对包含两约共 31,102 节的完整圣经模块进行了同样的检查:创 1:1 和诗 119:176 能用泰米尔语正确读出,启 22:21 能用泰卢固语读出,各自对应正确的地址,且包含一个真实的、恰好为 241,150 字节的 ot.bzv,并列着 82,460 字节的 nt.bzv
  • xmllint 验证了 OSIS 格式良好,权利声明完整存在。
  • sqlite3 打开 SQLite 文件,行数与计划完全一致——新约模块在第 40 至 66 卷间正好有 7,957 行,完整圣经在第 1 至 66 卷间正好有 31,102 行。

我们自己的两个 Bug 正是通过这种实机检查发现的,而不是靠单元测试。这种比例很正常,也证明了针对真实阅读器进行测试、而非仅凭自己对规范的理解进行测试是多么必要。

常见问题

为 e-Sword 构建模块时我应该优先构建哪种格式?

.bblx。版本 11 到 13 在支持较新的 .bbli 的同时依然能够读取它,因此一份文件就能覆盖 e-Sword 9 到 13。

为什么我的模块显示的经文书卷错位了?

几乎总是枚举问题导致的。要么是新约的书卷被重新编号成了 1 到 27,要么是版本中缺失的书卷被直接跳过,而没有保留为空槽位。首先检查你的 nt.bzv 字节大小是否为 82,460。

新约模块中需要包含 ot 文件吗?

是的。需要一个全尺寸、全为零的 ot.bzv,以及长度为零的 ot.bzsot.bzz

如何在 .bblx 中支持泰米尔语、泰卢固语或其他非拉丁文本?

将每个非 ASCII 字符都写成 RTF 的 \uN? 转义符,而不要依赖数据库列的编码,后者在各类真实模块中并不一致。

我可以使用你们的模块吗?

可以。属于公有领域的模块我们不加任何限制——排版制作是我们的工作,文字属于所有人。我们自己的译本 Bibelen Anno 2026 可供免费用于非商业分发。


只想要模块而不是格式细节? 阅读如何在 AndBible、MySword 和 e-Sword 中安装免费圣经模块,其中详细介绍了每个应用的操作步骤。tringine.publifye.com/modules 上的每个模块都附带其 OSIS 源码,以便你重新构建或审查我们的工作。下载需要注册一个免费账户,这是我们的服务条款,并不是对经文文本的主张——许可证页面对此写得很清楚。

作者:Jørn André Halseth,Publifye AS 创始人——从事圣经出版及排版印刷引擎开发十载,Tringine、Darash、Junifye 和 Lexifye 的作者。关于 · 联系方式

我们发布新内容时给您发邮件。 订阅新闻通讯