PDFPipe

Accessibility and structure / Document language

Setting the document language in a PDF

A language tag in the catalogue that tells a screen reader which voice and pronunciation rules to use for the document, and per-element tags for passages that differ.

Where this API stands

This API does not produce this standard, and there is no option that would. What follows is what the requirement actually is and where a rendered document stands against it. This API does not write /Lang into the catalogue and has no option that sets it. What it does do is render your markup faithfully, and `<html lang="de">` in that markup is exactly the thing a downstream tagger reads to decide what to put in /Lang, so getting it right in the template is the whole of your side of the job. The same applies to a `lang` attribute on an individual element: a `<span lang="fr">` around a French clause is the signal that later becomes /Lang on that structure element, and it costs one attribute today.

What the standard requires

The requirements as a checker enforces them, rather than as a procurement document paraphrases them. A file satisfies all of these or it satisfies none of them.

  • /Lang in the document catalogue, carrying a BCP 47 tag such as en-GB, de-DE or fr-CA.
  • /Lang on a structure element for any passage in a different language from the document default, which is what stops a French clause in an English contract being read with English phonetics.
  • The tag has to be the language the text is actually in, not the locale of the system that produced it, and those are frequently different.
  • PDF/UA requires the document default to be present and correct, and treats a missing one as a failure rather than a warning.
  • Region subtags matter to a speech engine for pronunciation and for date reading, so en-GB and en-US are not interchangeable in practice even though both are valid.

Who asks for this

Accessibility audits check for it because it is a one-line fix with a large effect on comprehension. It also matters for anyone whose documents are read aloud in a second language, which includes a lot of public sector correspondence and anything that goes out in a bilingual jurisdiction.

What it looks like in a file

The concrete form of the thing being described, so you can recognise it in a document you have been handed rather than only in a specification.

html
<!doctype html>
<!-- The document default. Drive it from the invoice's own locale field,
     never from the server's. -->
<html lang="de-DE">
  <head><meta charset="utf-8"><title>Rechnung 2026-0481</title></head>
  <body>
    <h1>Rechnung</h1>
    <p>Zahlbar innerhalb von 30 Tagen.</p>

    <!-- A passage in another language carries its own tag, which becomes
         /Lang on that structure element when the file is tagged. -->
    <p lang="en-GB">Terms and conditions apply as set out overleaf.</p>
  </body>
</html>

What to do about it

Set `lang` on the html element of every template, and set it from the document's own data rather than hard-coding it, because a template that produces invoices in three languages needs three values. Add `lang` on any inline passage that switches language. Then, when tagging happens, the language information is already in the source and does not have to be reconstructed by someone who does not speak the language in question.

How to check a file rather than assume

`mutool show file.pdf trailer/Root` shows /Lang if it is there. PAC 2024 reports a missing or invalid document language as a distinct checkpoint, and Acrobat's accessibility check lists it under "Primary language". For per-element languages, PAC's structure tree view shows the tag on each element that carries one.

The mistake people make here

Setting the language once, in a base template, and never again. A document generation pipeline that serves several markets ends up sending German invoices declared as English, which is worse than declaring nothing: a screen reader will confidently mispronounce every word rather than fall back to the user's own default.

Frequently asked

Does this API produce Document language?

Not produced by this API. This API does not write /Lang into the catalogue and has no option that sets it. What it does do is render your markup faithfully, and `<html lang="de">` in that markup is exactly the thing a downstream tagger reads to decide what to put in /Lang, so getting it right in the template is the whole of your side of the job. The same applies to a `lang` attribute on an individual element: a `<span lang="fr">` around a French clause is the signal that later becomes /Lang on that structure element, and it costs one attribute today.

Can I turn on the pdf_a option and be done?

No. The option writes an XMP packet declaring PDF/A-1b into the document catalogue, and the render response comes back carrying a warning that says in as many words that this is best-effort and that full conformance requires tagged structure and an embedded ICC profile. It is a claim written into the file, not a certificate earned by it, and a validator checks the claim against the bytes. Read the warning array in the response rather than taking the absence of an error as a pass.

Should I convert before rendering or after?

After, always. A conformance converter rewrites colour, embeds profiles, sets boxes and stamps metadata on a finished PDF. Trying to satisfy a conformance target from the source side means guessing at what the converter would have done, and the guesses that go wrong are expensive: flattening transparency you did not need to flatten changes what the page looks like.

Standards this one is confused with

The neighbours that matter are the ones people mistake for this, not the ones that sort next to it.

Conformance is decided after a file exists. Render the document, then check it, then convert only what the checker actually flags.