Skip to contentSkip to Braille Studio
ALB Wiki

albBRAILLE

albBRAILLE is the site's braille transcription engine — a two-engine transcriber written in AdaLogic BASIC and compiled to JavaScript by the ALBW backend. It turns literary text into real UEB contracted braille and math notation into real Nemeth code, and it runs the public API at /api/braille. The second engine, albNEMETH, handles mathematics — the part of braille that almost nothing on the open web can produce on demand.

Why it exists

The site was built eyes-free first — the Linux handbook is written for blind readers, the library publishes braille-ready editions, and the wiki carries the Braille, Nemeth Braille Code, and Eyes-Free Linux trail as flagship content. A library of braille needs a transcriber, so one was written — in ALB, which turned out to be the right tool for it: deterministic rules, bounded tables, no hidden state.

The public API answers a gap that is easy to miss. Braille translation does exist elsewhere — liblouis transcribes UEB text, and commercial services embed Nemeth inside document workflows. But a free, public endpoint that turns an arbitrary math string into Nemeth braille is a different thing, and there essentially isn't one. That gap has gotten sharper with AI: a tutoring agent can write the words "factor x squared plus three x minus ten," but it cannot produce the braille. POST /api/braille with {"sys":"nemeth","txt":"x^2+3x-10=0"} closes that last inch — the envelope it returns (brf, uni, cells) drives an embosser, a screen, or a refreshable display from one call.

The two engines

EngineInputOutput
UEB Grade 2literary textcontracted braille — the shortforms and groupsigns real braille readers expect (the, quick, brown all contract)
UEB Grade 1literary textuncontracted letter-for-cell — for learners and precise spellings
albNEMETHlatex-ish / asciimath mathNemeth code — linear and spatial: matrices, cases, binomials, stacked arithmetic, long division

The UEB pipeline

The literary engine runs text through five stages — a tokenizer, a shortform dictionary, a context-legality pass (a contraction is only legal in the positions UEB allows), a greedy longest-match selector, and finally a 6-bit cell stream. The legality stage is where real transcription happens — UEB is a context-sensitive code, not a lookup table, and whether st may contract depends on morpheme boundaries the engine has to reason about rather than memorize. Capitals get letter, word, and passage modes; numbers get the numeric indicator and numeric-space rules; errors land in a ledger rather than disappearing.

The Nemeth engine

albNEMETH takes the ascii/latex-ish grammar — x^2, sqrt(16), fractions, matrices — and emits Nemeth with proper indicators: the superscript and subscript marks, grouping symbols, the numeric indicator's level shifts. Beyond linear math it does spatial Nemeth: matrices laid out as braille tables, cases constructions, binomial coefficients, stacked arithmetic, and long division in its traditional carried layout. That matters because Nemeth is how blind STEM students actually read math — linear text is not a substitute.

Live Nemeth, inline: ⠰⠭⠘⠆⠐⠬⠼⠒⠰⠭⠤⠼⠂⠴⠀⠨⠅⠀⠼⠴x^2+3x-10=0 factors as ⠷⠰⠭⠬⠼⠢⠾⠷⠰⠭⠤⠼⠆⠾⠀⠨⠅⠀⠼⠴(x+5)(x-2)=0, and the quadratic formula sets as ⠰⠭⠀⠨⠅⠀⠷⠤⠰⠃⠬⠤⠎⠟⠗⠞⠷⠰⠃⠘⠆⠐⠤⠼⠲⠹⠁⠉⠾⠾⠌⠷⠼⠆⠰⠁⠾⠼x=(-b+-sqrt(b^2-4ac))/(2a). Those cells are not an image or a font trick — they are the engine's real output, transcribed server-side at render time, readable on a refreshable braille display or embossed straight from the page's own braille edition.

Validation

The UEB engine was checked the honest way — against liblouis, the reference open-source braille translator. On a 25,836-word corpus (a 13,747-word stratified sample, a 12,000-word a-initial slice, and 89 curated edge cases) the output matched en-ueb-g2.ctb cell-for-cell. That is the claim a transcription engine is entitled to make.

The API

EndpointPurpose
POST /api/braille{sys, txt} → the envelope — sys is ueb, ueb-g1, or nemeth
GET /api/brailleself-describing docs: systems, formats, limits, examples
GET /api/braille/statuscapability report
POST /api/braille/keysmint a free API key (raises the rate limit)

No key is needed to try it — anonymous callers get a per-IP budget; a free key raises it. Keys arrive via X-API-Key or Authorization: Bearer. Underneath, the same engine also speaks JSON-RPC tools (br_ueb, br_ueb_g1, br_nemeth, br_translate) — the REST surface mirrors them.

In the wiki and across the site

The same engine serves three reading surfaces on top of the API:

  • [[math:expr]] — wiki markup that transcribes expr to Nemeth inline, as used above. Spatial input (matrices, cases) renders as a braille cell block.
  • Braille editions — every public wiki article carries a ⠃ Braille tab next to Edit and History, linking /braille/wiki/<slug> — a UEB Grade 2 edition with Nemeth math — plus a .brf download paged for embossers. ?grade=1 switches to uncontracted. Static site pages have the same treatment under /braille/site/<path>.
  • The Braille Studio — a browser workbench: type text or math, get Unicode braille, the BRF stream, the raw cell masks, and a dot-grid — plus live curl examples for the API.

Editions are generated on demand and cached against the article's revision — an edit produces a new braille edition on the next read, not a stale one.

The honest gaps

No typeform, foreign-language, or italic markup; Nemeth arrays don't take colspecs and display environments aren't emitted; cells[] caps at 256 so long documents page per-paragraph. The Nemeth input is the engine's own ascii/latex-ish grammar, not full LaTeX \commands.

See also

This page was last edited 2026-10-27 04:58:57 UTC by ALB Team. What links here