← todas las entradas

Aún no disponible en Español — mostrando inglés.

SWORD, MySword and e-Sword module formats: what the docs get wrong

A zText index drawn as one bar with four segments in proportion: one module heading, one testament heading, 287 book and chapter headings, and 7,957 verses — 8,246 records of 10 bytes, 82,460 bytes. Caption: a zText index counts slots, not verses.

Short answer: If you are building a Bible module, three widely repeated things are wrong. e-Sword has no .bbl format. A New Testament module must keep whole-Bible book numbering. And a SWORD zText index counts slots, not verses. Each mistake produces a module that installs cleanly and reads wrong, which is the worst way to be wrong.

We wrote module builders for SWORD, MySword and e-Sword in pure Go, with no external toolchain, to ship the free Bible modules behind Tringine. Every schema and byte layout below was read off real published modules with a hex editor and sqlite3, not off a write-up. This is the whole of what we learned, including the one check we now run on every build because reading the code was not enough.

Why is there no .bbl file for e-Sword?

Because it does not exist. Searching for the e-Sword Bible module format turns up .bbl constantly, and .bbl is a LaTeX bibliography extension — which is why hunting for a specification comes back empty and confusing.

The real formats are .bblx for e-Sword 9 and 10, where verse text is RTF, and .bbli for version 11 and later, where verse text is HTML. Versions 11 through 13 read both, so shipping .bblx alone covers e-Sword 9 through 13. If you build one format, build that one.

Reader File Verse text Read by
SWORD (AndBible, Xiphos, BibleTime) mods.d/*.conf + zText files OSIS-derived, zlib blocks every libsword front end
MySword .bbl.mybible (SQLite) theWord-style tags 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 and later only

Why does a New Testament module still number books 40 to 66?

Because all three formats address verses against a fixed versification — the canonical list of books, chapters and verse counts a reader uses to find a verse, KJV by default — and the numbering is absolute rather than relative to what your edition contains. Renumbering a New Testament 1 to 27 puts Matthew exactly where Genesis belongs, and everything after it shifts.

We confirmed this against two real NT-only modules rather than trusting the reasoning: both start at book 40 and both set OT=0. The same principle bites inside a testament — a book your edition does not carry still occupies its slots, empty. Skip it to save space and the reader will show Mark's text under Matthew's references, silently, for every book after the gap.

How many records belong in a zText index?

This is the one that quietly corrupts a module, because an index of the wrong length still parses.

A SWORD testament is three files. Little-endian throughout, measured from the CrossWire ASV and Byzantine modules:

File Record size Contents
nt.bzv 10 bytes uint32 block, uint32 offset within the decompressed block, uint16 length
nt.bzs 12 bytes uint32 offset into .bzz, uint32 compressed size, uint32 decompressed size
nt.bzz The blocks themselves, each an independent zlib stream, one per book plus block 0 for headings

The enumeration is where it goes wrong. Slots run: slot 0 is the module heading, slot 1 the testament heading, then per book one book heading, then per chapter one chapter heading, then one slot per verse. So the record count is 2 + books + chapters + verses — not the verse count.

For the New Testament under KJV versification that is 2 + 27 + 260 + 7,957 = 8,246 records, so nt.bzv is exactly 82,460 bytes. For the Old Testament, 2 + 39 + 929 + 23,145 = 24,115 records, or 241,150 bytes.

That is checkable in one command, which is the point of writing it down: the shipped ASV and Byzantine modules both have an nt.bzv of exactly 82,460 bytes. If yours differs, your enumeration is wrong, and you will find out from a confused reader rather than from a crash.

One more shape worth copying: an NT-only module still ships an ot.bzv — full-size, all zeroes — with ot.bzs and ot.bzz of length zero. That is byte-for-byte what the shipped Byzantine module does.

What do the SQLite formats actually require?

MySword (.bbl.mybible): page_size=32768, UTF-8, and the Bible index is UNIQUE. Verse text is theWord-style tag pairs, not HTML — footnotes are <RF>…<Rf>. Details.Language takes a three-letter code, and which three letters is not obvious: ISO 639-2 has a bibliographic and a terminological code for about twenty languages, and published modules follow neither consistently (German and Czech modules use deu and ces; French, Albanian and Greek ones use fre, alb and gre; roughly a third omit the column). We settled ours by opening real modules rather than reading the standard — both published Norwegian modules carry nor, so ours does too. Where we could not map a language confidently we still write NULL rather than guess, because a wrong language tag is worse than an absent one.

e-Sword (.bblx): page_size=1024, single-quoted identifiers, and the index is not unique. Two traps here. Details.Version is an INT naming the format generation — 2 for .bblx, 4 for .bbli — and not your edition version, which belongs in Comments. And three real modules we examined disagree about the database's own encoding: one UTF-16LE, two UTF-8. So the column encoding cannot be trusted to carry a Tamil or Telugu codepoint.

The fix is to write every non-ASCII rune as an RTF \uN? escape, signed 16-bit with surrogate pairs above the BMP. It is encoding-independent, and it is what the real modules do. If you are shipping a non-Latin script to e-Sword, this is the single detail that decides whether anyone can read it.

Booleans are 1/0 in both SQLite formats. (.bbli uses Delphi's -1, which is a good reason not to emit .bbli casually.)

Check the rendered .conf, not the struct

The metadata is the part of a module that a catalogue reads and a court could, and it is the part a test suite is least likely to look at. Ours did not, at first: a licence field that was correct in the Go struct rendered as something else in the .conf, and we caught it by reading the file, not by running the tests. It was fixed and every module rebuilt the same day; the files on our shelf today say Copyright=Public Domain for the 1868 Tamil and 1880 Telugu texts, name no copyright holder, and credit Publifye only as the edition's preparer in TextSource.

Two claims have to stay apart in that file. The licence of the text is a fact about the translation and not yours to choose: a public-domain Bible is public domain in your module too, and no DistributionNotes line can restrict it. The terms of your distribution service — registration, logging — govern your servers and nothing else. Collapse the two and you either restrict what is free or free what is not.

The test that guards it now asserts on the rendered .conf file. It fails the moment a public-domain text is given a copyright holder or a restrictive note, and equally the moment our own translation is quietly demoted to public domain. Both directions, because a permissive error is still an error. Anyone shipping scripture modules should read the file they ship, not the code that wrote it.

How we verified it

Not by reading the specification back to ourselves:

  • A full-size New Testament module — 7,957 verses — was built and read back with libsword's own diatheke in a Debian container. It appears in modulelist, resolves Matt 1:1, John 3:16, 1 Cor 13:13 and Rev 22:21 at their correct addresses, returns nothing for Genesis 1:1 as an NT-only module should, and searches correctly.
  • The same check on a whole-Bible module, 31,102 verses across both testaments: Genesis 1:1 and Psalm 119:176 read back in Tamil and Revelation 22:21 in Telugu, each at its own address, with a real ot.bzv of exactly 241,150 bytes beside the 82,460-byte nt.bzv.
  • xmllint validates the OSIS as well-formed, with the rights statement present.
  • The SQLite files open with sqlite3 at exactly the row counts the plan reported — 7,957 rows over books 40 to 66 for the New Testament module, 31,102 over books 1 to 66 for the whole Bible.

Two of our own bugs were caught by that live checking rather than by the test suite. That ratio is normal, and it is an argument for testing against the real reader rather than against your own understanding of it.

Frequently asked

What format should I build first for e-Sword?

.bblx. Versions 11 through 13 read it alongside the newer .bbli, so one file covers e-Sword 9 through 13.

Why is my module showing the wrong book's text?

Almost always the enumeration. Either books were renumbered 1 to 27 for a New Testament, or a book the edition does not carry was skipped instead of left as empty slots. Check the byte length of your nt.bzv against 82,460 first.

Do I need an ot file in a New Testament module?

Yes. A full-size, all-zero ot.bzv, with ot.bzs and ot.bzz at zero length.

How do I get Tamil, Telugu or other non-Latin text into .bblx?

Write every non-ASCII rune as an RTF \uN? escape rather than relying on the column encoding, which is inconsistent across real modules.

Can I use your modules?

Yes. The public-domain ones carry no restriction from us whatsoever — the edition is our work, the words are everyone's. Our own translation, Bibelen Anno 2026, is free for non-commercial distribution.


Want the modules rather than the format? How to install free Bible modules in AndBible, MySword and e-Sword walks through each app. Every module on tringine.publifye.com/modules ships with its OSIS source so you can rebuild or check our work. Downloading needs a free account, which is a term of our service and not a claim on the texts — the licence page says so plainly.

Written by Jørn André Halseth, founder of Publifye AS — ten years publishing Bibles and building the presses they run on, and the author of Tringine, Darash, Junifye and Lexifye. About · Contact

Recibe un correo cuando lancemos algo nuevo. Suscríbete al boletín