Research
Ten bugs we found in the reference braille tables
liblouis is the implementation this entire site measures itself against. Writing Arabic, Spanish and Portuguese engines against it, then checking this site's published punctuation against it, turned up ten rows where it departed from its own stated rule, or from the standard it implements. The two Portuguese ones are fixed in liblouis 3.39.0, the current release; the five Arabic rows and three Spanish ones are not.
First, the part that matters more than the list: liblouis is very good, and this site depends on it. It is the free software behind most braille output in the world — screen readers, embossers, transcription tools — it covers scores of languages, and it is the yardstick every measurement on this site is taken against. Nothing below changes that. A project that ships tables for that many languages will have rows that are wrong, and the useful thing to do with one is to write down exactly which row and why.
None of these were found by reading the tables looking for trouble. Six fell out of building two new engines — Arabic grade 1 and Portuguese grade 1 — and comparing every word of a frequency corpus against the reference. Where the two disagreed, each disagreement had to be resolved one way or the other before the engine could ship, and those six resolved against the reference. The Arabic dash turned up on 14 September 2026, when this site's published punctuation was checked mark by mark against the reference; the three Spanish rows turned up on 17 September 2026, when its Spanish number handling was built against the rule book rather than against the table.
The method
- Question
- Where this engine and the reference disagree, which one departs from the published rule?
- Compared against
- liblouis 3.39.0, the current release, using its Arabic (ar-ar-g1) and Portuguese (pt-pt-g1) tables, and the table sources themselves rather than only their output. The defects were found against 3.29.0; the Arabic table is unchanged between the two releases, line for line.
- Over
- 5,000 Arabic words and 5,045 Portuguese texts by frequency, with every remaining disagreement resolved by hand against the table source or the national standard.
- Checked by
verify/verify-defects.js, which runs the reference on each case below, reads the cited table lines, and fails if either side has moved
Each defect below is asserted from both ends: that the reference still behaves the way this page describes, and that this engine does something different. The first half is the one that matters. The day liblouis fixes one of these, that assertion fails and this page is corrected instead of quietly becoming a lie about someone else's software.
Arabic — five rows in ar-ar-g1
Arabic grade 1 is letter-for-letter, so there is little room for interpretation: a divergence is either a rule or a slip. Four of these five are slips, three of them visible in the table source without running anything. The fifth is a rule, on line 240, that disagrees with the published reference the table names as its basis.
Measured over 5,000 words, this engine and the reference agree on 4,999 — the disagreements below are rare in running text, which is exactly why they survive.
The shadda after alif maqsura
- liblouis
- leaves the shadda where it stands, after the letter
- This site
- moves it before the letter, as it does for every other letter
- Evidence
- The table lists thirty-six rules that move the shadda before its letter, and its own comment says they cover every Arabic letter. Alif maqsura is the one letter missing from the list. That is an omission in an enumeration, not an orthographic rule — no published source treats alif maqsura differently.
- Source
ar-ar-g1-core.uti lines 96–132- Check it
$ echo "علىّ" | lou_translate --forward unicode.dis,ar-ar-g1.utbliblouis 3.39.0 answers ⠷⠇⠕⠠ · this site answers ⠷⠇⠠⠕.
The shadda does not survive a round trip
- liblouis
- leaves the shadda before the letter, producing Arabic that cannot be read
- This site
- puts the shadda back after the letter it doubles
- Evidence
- Every shadda rule in the table is marked noback, so it applies in one direction only. Back-translating ⠌⠠⠝ yields أّن instead of أنّ — a shadda before its letter, which is not a valid sequence in Arabic. Forward translation is correct; only the reverse is affected, which is why it survives a forward-only test suite.
- Source
ar-ar-g1-core.uti lines 97–132- Check it
$ echo "⠌⠠⠝" | lou_translate --backward unicode.dis,ar-ar-g1.utbliblouis 3.39.0 answers أّن · this site answers أنّ.
Tatweel is written as two sukun cells
- liblouis
- writes it as two cells of dots 2-5
- This site
- drops it
- Evidence
- Tatweel is a typographic stretch with no sound — it exists to justify a line, not to be pronounced. Dots 2-5 is the sukun, so a reader cannot tell a tatweel from two sukun, and back-translation resolves it as two sukun: مـم returns as مْْم. Dropping a mark that carries no sound loses nothing; writing it as a different mark loses the word.
- Source
ar-ar-g1-core.uti line 89- Check it
$ echo "مـم" | lou_translate --forward unicode.dis,ar-ar-g1.utbliblouis 3.39.0 answers ⠍⠒⠒⠍ · this site answers ⠍⠍.
No letter sign before fa after a digit
- liblouis
- omits it, so the letter is read as a digit
- This site
- writes it, as it does before the other six ambiguous letters
- Evidence
- Fa is dots 1-2-4, which is also the digit 6. So 1ف and 16 produce identical cells, and back-translation reads both as 16 — the letter is gone. The table writes the letter sign before alif, ba, jeem, dal, ha and ya for exactly this reason, and omits fa alone.
- Source
ar-ar-g1-core.uti lines 172 and 279- Check it
$ echo "1ف" | lou_translate --forward unicode.dis,ar-ar-g1.utbliblouis 3.39.0 answers ⠼⠁⠋ · this site answers ⠼⠁⠰⠋ — liblouis writes the same three cells for 16, so the two are indistinguishable.
The dash takes a comma cell in front
- liblouis
- writes the dash as three cells: dot 5, then dots 3-6, then dots 3-6
- This site
- writes it as dots 3-6, 3-6, as the published grade 1 reference does
- Evidence
- The table's header says it is based on the Unified Arabic Braille Project, and that project's grade 1 reference gives the dash (–) as 36-36. The table's rule for the dash puts a dot-5 cell in front. Dot 5 on its own is the Arabic comma, in the reference and in this table, and no mark in the grade 1 reference begins with dot 5 followed by 3-6 — so the extra cell reads as a comma the text never had. The same table writes the hyphen as 3-6, 3-6.
- Source
ar-ar-g1-core.uti line 240; Unified Arabic Braille Portal (Mada, Qatar), Braille Grade 1 Reference- Check it
$ echo "–" | lou_translate --forward unicode.dis,ar-ar-g1.utbliblouis 3.39.0 answers ⠐⠤⠤ · this site answers ⠤⠤.
Spanish — three rows in es-g1
Spanish has a published national standard too: the Documento técnico B 2 de la Comisión Braille Española, which gives the signs and the rules for using them, with worked examples. The three rows below are measured against that document: a rule the table does not implement, three characters it defines upside down, and two it does not define at all. They were found on 17 September 2026, while building this site's Spanish number handling against §8 of that document.
A letter after a digit takes no prefix
- liblouis
- writes the letter straight after the digits, so it reads as a digit
- This site
- writes the dot-5 prefix the standard gives it
- Evidence
- In Spanish braille the first ten letters are the digits, told apart by the number sign. §8.2 of the Documento técnico B 2 covers what happens when one of those letters follows a number with nothing between them: a dot-5 cell, the prefijo de latina minúscula, separates them. Its example is 8b — ⠼⠓⠐⠃. liblouis writes ⠼⠓⠃, which is what it writes for 82, and its own back-translation of those cells returns 82. The letter is gone. This is not an oversight the project makes everywhere: its Portuguese table declares the same separator and writes 8b as ⠼⠓⠐⠃.
- Source
es-g1.ctb line 33declares the number sign and no rule for the letter prefix;pt-pt-g1.utb line 928declares one- Check it
$ echo "8b" | lou_translate --forward unicode.dis,es-g1.ctbliblouis 3.39.0 answers ⠼⠓⠃ · this site answers ⠼⠓⠐⠃ — liblouis writes the same three cells for 82, so the two cannot be told apart.
The fractions have their halves the wrong way round
- liblouis
- lowers the numerator and leaves the denominator in the normal position
- This site
- lowers the denominator, as the standard says
- Evidence
- §8.4 is one sentence: the number sign, then the numerator in its normal position and the denominator in the lower one. Its examples are ¾ and ½. liblouis has all three of the common fractions the other way up: its ¾ is the number sign, a lowered 3 and a normal 4, so a reader following the standard meets a denominator where the numerator should be. Going the other way it is worse than a swap — the cells the standard gives ¾ are read by liblouis as 3÷, because it uses that cell for the division sign. The rows are visible in the table source without running anything.
- Source
es-chardefs.cti lines 154 to 156—3456-2-145,3456-2-12and3456-25-145for ¼, ½ and ¾- Check it
$ echo "¾" | lou_translate --forward unicode.dis,es-g1.ctbliblouis 3.39.0 answers ⠼⠒⠙ · this site answers ⠼⠉⠲.
The ordinal indicators are not in the table
- liblouis
- has no definition for º or ª and prints the character's code point instead
- This site
- writes the lowered number and the letter, as the standard gives it
- Evidence
- 1º and 2ª are ordinary Spanish writing — floors, dates, centuries, street numbers. §8.3 forms an ordinal from the lowered-number series followed by o or a: 1º is ⠼⠂⠕ and 2ª is ⠼⠆⠁. Neither character appears anywhere in the 206 lines of
es-chardefs.cti, so liblouis falls back to spelling out the code point: 1º comes out as ⠼⠁⠄⡳⠭⠚⠚⠃⠁⠄, which is the number 1 followed by the letters of\x00ba, one of them a cell with dot 7 that six-dot braille has no way to emboss. Translated back, it returns1.\12567/xjjba. - Source
es-chardefs.cti, 206 lines, no row for U+00BA or U+00AA- Check it
$ echo "1º" | lou_translate --forward unicode.dis,es-g1.ctbliblouis 3.39.0 answers ⠼⠁⠄⡳⠭⠚⠚⠃⠁⠄ · this site answers ⠼⠂⠕.
Portuguese — two marks in pt-pt-g1, fixed in 3.39.0
Portuguese has a published national standard, the Grafia Braille para a Língua Portuguesa, agreed jointly by Portugal and Brazil. In liblouis 3.29.0 the Portuguese table departed from it on two marks. liblouis 3.39.0, released on 1 September 2026, overhauled that table, and both now agree with the standard. They stay on this page, marked fixed, so that a link to them does not lead nowhere — and because anyone still running 3.29.0 still has them.
The apostrophe — fixed
- liblouis 3.29.0
- wrote dot 6, the prefix that opens angle quotes and closing brackets, where a mark belongs
- liblouis 3.39.0
- writes dot 3 between letters — d'água is ⠙⠄⠷⠛⠥⠁ — and reads a straight quote on its own as a single quotation mark, dots 5-6 then 2-3-6
- This site
- writes dot 3
- Evidence
- The Grafia gives the apostrophe dot 3, the cell of the full stop: “O sinal ⠄ (3) representa também o apóstrofo” (3rd edition, Brasília 2018, section 35). A lone straight quote can stand for a single quotation mark too, and the 2002 joint text gives “other variants of quotation marks” dots 5-6, 2-3-6 — so 3.39.0 reads that one character differently from this site, but defensibly, and it is no longer counted as a defect.
- Source
Grafia Braille para a Língua Portuguesa, 3.ª edição (MEC, 2018), §35; Alterações à Grafia Braille para a Língua Portuguesa (Comissão Brasileira do Braille e Comissão de Braille, 2002)- Check it
$ echo "d'água" | lou_translate --forward unicode.dis,pt-pt-g1.utbliblouis 3.39.0 answers ⠙⠄⠷⠛⠥⠁ · this site answers ⠙⠄⠷⠛⠥⠁ · liblouis 3.29.0 answered ⠙⠠⠷⠛⠥⠁.
The ellipsis — fixed
- liblouis 3.29.0
- wrote dots 3-5, 2-6, 3-5 for the single character “…”
- liblouis 3.39.0
- writes dot 3 three times, as three full stops
- This site
- writes dot 3 three times
- Evidence
- “As reticências, representadas pelo sinal composto ⠄⠄⠄ (3 3 3)” (Grafia Braille, 3rd edition, 2018, section 36). The older table got this right when the three stops were typed separately and failed only on the single character, a transcription slip in one rule.
- Source
Grafia Braille para a Língua Portuguesa, 3.ª edição (MEC, 2018), §36- Check it
$ echo "…" | lou_translate --forward unicode.dis,pt-pt-g1.utbliblouis 3.39.0 answers ⠄⠄⠄ · this site answers ⠄⠄⠄ · liblouis 3.29.0 answered ⠔⠢⠔.
What this page is not claiming
It is not claiming this site is more accurate than liblouis. On English it plainly is not: measured over the same kind of corpus, this site's Grade 2 output matches the reference on 99.98% of the 5,000 commonest words and differs from it on 1 of them — and every one of those failures is listed, with the reference's answer beside this engine's. There, on the one word left, the rulebook sides with this engine.
It is also not claiming these are the only defects. They are the ten that three specific exercises — two new engines against two frequency corpora, a mark-by-mark check of this site's punctuation, and a Spanish number engine built from the rule book — happened to surface. Another engine would probably find more.
Checking any of this yourself
Every defect above carries the command that shows it and the answer each side gives, so nothing here has to be taken on trust. All you need is liblouis 3.39.0; for the two fixed Portuguese rows, 3.29.0 still shows the old answers — unicode.dis in front of the table name is what makes it print braille characters rather than the ASCII form.
The table sources are in the liblouis repository under tables/, and the line numbers above are from the files as shipped in 3.39.0, and are the same lines in 3.29.0. This site's own answers come from the API, which publishes all five codes as JSON, and the divergences are carried in the coverage.divergesFromReference field of the Arabic and Portuguese documents so a consumer diffing against the reference learns why rather than concluding this site is broken.
Then this page is the thing that should change. These are claims about someone else's software, made from reading its tables and its output; if a rule below has a justification not visible from the source, say so and it comes off the list. The other measurements cover the reference tables, contraction positions and page counts.
The finding as an image
For a slide, an issue thread or a message.
