Guide
Arabic PDF accessibility: what breaks and why
Arabic adds contextual letter shaping and ligatures on top of every right-to-left problem Hebrew has. What that does to extracted text, and how to check it.
About 14 minutes · involved
Everything in the Hebrew case, plus shaping
If you have read the Hebrew guide, you already know the three failures that matter, and all three apply to Arabic without modification:
- Text stored in visual order — the run is pre-reversed, the page looks perfect, the extracted text is mirrored. TG-RTL-001.
- No language declaration — Arabic paragraphs inheriting
en-USare read by a synthesiser with no Arabic phonemes. TG-RTL-002. - Left-to-right column order — auto-tagging walks the page the wrong way, so a two-column layout reads as two interleaved halves. TG-RTL-004.
Arabic then adds a fourth problem that Hebrew does not have, and it is the one that catches people who have solved the first three.
Contextual shaping and presentation forms
Arabic letters change shape depending on their position in a word. The letter ع has four forms — isolated ع, initial عـ, medial ـعـ, final ـع — and a correct rendering pipeline selects among them at draw time from a single stored character, U+0639.
Some producers do not work that way. They store the shaped form: a character from Unicode’s Arabic Presentation Forms blocks, U+FB50–U+FDFF and U+FE70–U+FEFF. These blocks exist for round-tripping legacy encodings and Unicode’s own documentation discourages their use in new text.
The result renders identically and is broken in every other respect:
- Search fails. Searching for a word in its normal spelling does not match the presentation-form spelling.
- Copy-paste produces unusable text. It pastes as a string of compatibility characters that most systems will not re-shape.
- Screen readers stumble. Behaviour varies by engine; some read presentation forms correctly, some read letter names, some fall silent.
- Ligatures collapse words. The lam-alef ligature ﻻ is a single character in presentation form and two characters — ل + ا — in correctly stored text. A word containing it has the wrong length and the wrong letters.
How to check for it
Copy a paragraph out of the PDF and inspect the code points:
python3 -c "
import sys
s = sys.stdin.read()
pf = [c for c in s if 0xFB50 <= ord(c) <= 0xFDFF or 0xFE70 <= ord(c) <= 0xFEFF]
print(f'{len(pf)} presentation-form characters out of {len(s)}')
"
Any non-zero count in body text is a defect. A handful may be legitimate — some documents use presentation forms deliberately for typographic reasons — but a paragraph made of them is a producer problem.
How to fix it
Unicode normalisation form NFKC maps presentation forms back to their base characters:
import unicodedata
logical = unicodedata.normalize('NFKC', extracted_text)
The normalised string goes into /ActualText on the structure element. The glyphs on the page are untouched, so the document still looks exactly as it did — which is the whole reason /ActualText is the right mechanism here rather than rewriting the content stream.
Note the order of operations: normalise after repairing visual order, not before. NFKC decomposition changes string length, and a reversal applied to a normalised string does not map cleanly back onto the original glyph runs.
The tatweel problem
The tatweel or kashida ـ (U+0640) is a stretching character used to justify Arabic text. It carries no phonetic value.
Justification engines insert them freely, and they end up in the stored text. A screen reader may announce them as a pause, may extend the preceding sound, or may say nothing — but the word is no longer the word, so searching for it fails and any downstream text processing sees a different string.
Strip them for the logical text, keep them on the page:
logical = extracted_text.replace('ـ', '')
Again: /ActualText, not the content stream. The justification stays; the extracted text becomes the word.
Diacritics
Arabic diacritics — fatha, damma, kasra, sukun, shadda (U+064B–U+0652) — are usually absent from ordinary text and present in Qur’anic, liturgical, pedagogical and poetic material, where they are not optional.
If the document has them, keep them. Stripping vowel marks from a text where they carry meaning changes the text. If the document does not have them, do not add them; a synthesiser handles unvocalised Modern Standard Arabic perfectly well, which is what readers expect.
The one thing to check is that they have not been separated from their base letters by a reversal. A diacritic is a combining character and must follow its base in the stored string. In a reversed run it precedes it, which some engines announce as a stray mark before every letter.
A checking sequence that works
Five minutes, no licence required:
- Select all, copy, paste into a plain-text editor that does not reapply bidi.
- Is anything there? No → it is a scan; see the scanned-PDF guide.
- Count presentation forms with the snippet above. Non-zero in body text → shaping problem.
- Check word order against the rendered page for one sentence you can verify. Mirrored → visual order.
- Check digits. A number you can read off the page coming out with its digits reversed confirms a character-level reversal.
- Check
/Lang.File → Properties → Advanced → Languagein any Acrobat, free Reader included.en-USon an Arabic document is a blocker.
Steps 3 and 5 are the ones no mainstream checker performs, which is why an Arabic PDF can pass PAC and veraPDF cleanly and still be unreadable.
What Taggart does with it
In short, and with what it does not do yet: Arabic PDF accessibility with Taggart. In detail:
The right-to-left analysis runs on Arabic exactly as it runs on Hebrew: paint order is compared against page geometry, line by line, and a line whose two orders disagree for its script is reported as stored in visual order. The second, independent signal uses Arabic’s own position-locked forms where Hebrew uses its final letters: taa marbuta ة and alif maqsura ى only ever end a word, and the definite article ال only ever begins one — reversed, it turns up as لا at the end.
The repair is /ActualText only. The logical order is reconstructed and attached with the line’s language, and every output is re-rendered and compared against the original at structural similarity ≥ 0.999 before it is returned. No glyph moves; a page justified with kashidas still looks precisely as it did.
Presentation forms and tatweel. In every line it repairs, the text written to /ActualText is folded back to the letters — NFKC on the presentation-form blocks, applied after the reversal as above, so ﻻ comes out as ل then ا — and tatweel is removed. The detection folds each letter too, so a line written entirely in presentation forms still shows where its words begin and end.
What it does not do yet: a file stored in logical order but in presentation forms needs no reordering, so nothing is written for it and its text stays shaped. For that case, the NFKC step above, applied to the text that goes into /ActualText, is the fix today.
It is not applied unattended. Each line is shown to you as stored, as logical, and with the evidence for the verdict; lines where the evidence is weak are reported as undecided rather than counted as fine, and the repair runs only when you run it — because a tool that is confidently wrong about a language it cannot read is the worst possible outcome here.
Frequently asked questions
Is Arabic harder than Hebrew in a PDF?
Yes, in one specific way. Both scripts suffer the visual-order problem identically. Arabic adds contextual shaping: most letters have four forms depending on their position in a word, and a producer that stores the shaped presentation forms rather than the base characters produces text that renders correctly and is not searchable, not copyable, and not readable by a synthesiser.
What are presentation forms?
Unicode blocks U+FB50–U+FDFF and U+FE70–U+FEFF contain pre-shaped Arabic glyphs — initial, medial, final and isolated forms of each letter, plus ligatures. They exist for compatibility with older encodings. Text should be stored as base characters in U+0600–U+06FF and shaped by the renderer; text stored as presentation forms is a broken file that happens to look right.
Does my Arabic PDF need lang=ar or a regional variant?
ar is normally correct. A regional tag such as ar-EG or ar-MA changes the synthesiser's pronunciation, which matters for dialectal content and does not for Modern Standard Arabic. Do not use a regional tag to describe where the document was produced — it describes how the text should be read.
Do Arabic-Indic digits need special handling?
They need to be stored as what they are. Arabic-Indic digits (U+0660–U+0669) and Latin digits are different characters, and a document that uses ٤ should store U+0664, not 4. Both are weak-direction under the bidi algorithm and both keep left-to-right internal order inside right-to-left text, which surprises people every time.
Related guides
- Hebrew or Arabic text reversed when copied from a PDFYou copy a line of Hebrew or Arabic out of a PDF and it pastes backwards. Why it happens, a ten-second test that tells file from app, and how to fix it.
- Hebrew PDF accessibility: the three failures that matterVisual-order storage, wrong document language, and left-to-right column order. All three are invisible to a sighted reviewer and to every mainstream checker.
- How to fix PDF reading orderA working method for finding and repairing reading order, free in Acrobat and faster in Taggart, including the two-column case that costs the most time.
- How to check if a PDF is accessible: four free checkersCheck PDF accessibility free, online or on your own machine: four checkers against PDF/UA and WCAG, what each catches, and the failures none of them see.
Related failure conditions
- TG-RTL-001 Right-to-left text is stored in visual orderOlder Israeli government, legal and DTP systems lay out Hebrew by reversing the character order and then rendering left-to-right. The page looks correct, but the stored text is backwards. Extracting it gives you the sentence mirrored, and the bidi algorithm then reverses it a second time.
- TG-RTL-002 A right-to-left run has no language declarationThe document declares en-US at the catalog and never overrides it, so Hebrew paragraphs inherit English.
- TG-RTL-003 A mixed-direction run is not correctly orderedHebrew sentences containing English product names, dates, percentages or citation numbers are the hardest bidi case. Producers frequently reverse the RTL and leave the LTR runs alone, or reverse everything.
- TG-RTL-004 Reading order is not right-to-left awareAuto-tagging tools order blocks left-to-right, top-to-bottom. In a Hebrew two-column layout the correct order is right column first.
- TG-RTL-005 Right-to-left punctuation or numerals are misplacedA full stop that renders at the left edge of a Hebrew line must be stored at the end of the logical string, not the beginning. Brackets must be stored as the logical opening/closing character, not the visually mirrored one.
Check your own file. Taggart's validator is free and unlimited — no page cap, no watermark, and no account at all up to 60 pages.
Last updated .