Skip to content

Arabic, Hebrew and Hindi

Arabic, Hebrew and Hindi with Latin words and numbers inside them, a table laid out right to left, and six scripts justified with kashidas, the stretched joins of Arabic-style writing. Inter falls back to Noto fonts for the scripts it lacks, and the text is shaped with HarfBuzz (Tagua.Shaping.HarfBuzz).

Standards: PDF/A-2b · PDF/UA-1, checked with veraPDF on every change. Download the PDF.

Page 1 of the arabic, hebrew and hindi, rendered by Tagua.
  • The Unicode Bidirectional Algorithm, with embedded numbers
  • A right-to-left table
  • Font fallback from Inter to Noto
  • Kashida justification: Arabic, Syriac, N’Ko, Mandaic, Adlam, Mongolian
  • Each block tagged with its language (PDF/UA-1)
multilingual.report.yaml
# yaml-language-server: $schema=../schema/template.schema.json
# Right-to-left and complex scripts: Arabic, Hebrew and Hindi with embedded Latin words and numbers,
# a right-to-left table, Arabic, Syriac, N'Ko, Mandaic, Adlam and Mongolian justified with kashidas, and
# PDF/A-2b + PDF/UA-1. Inter falls back to Noto fonts for
# the scripts it lacks. Rendered with the HarfBuzz shaper (Tagua.Shaping.HarfBuzz).
version: 1
title: Multilingual text
culture: en-GB
document:
author: Acme Ltd
compliance: [pdf-a-2b, pdf-ua-1]
page:
size: A4
margins: 22mm
fonts:
Inter:
regular: fonts/Inter-Regular.ttf
bold: fonts/Inter-Bold.ttf
fallback: [NotoArabic, NotoHebrew, NotoDevanagari, NotoSyriac, NotoNKo, NotoMandaic, NotoAdlam, NotoMongolian]
NotoArabic: { regular: fonts/NotoSansArabic-Regular.ttf }
NotoHebrew: { regular: fonts/NotoSansHebrew-Regular.ttf }
NotoDevanagari: { regular: fonts/NotoSansDevanagari-Regular.ttf }
NotoSyriac: { regular: fonts/NotoSansSyriac-Regular.ttf }
NotoNKo: { regular: fonts/NotoSansNKo-Regular.ttf }
NotoMandaic: { regular: fonts/NotoSansMandaic-Regular.ttf }
NotoAdlam: { regular: fonts/NotoSansAdlam-Regular.ttf }
NotoMongolian: { regular: fonts/NotoSansMongolian-Regular.ttf }
styles:
default: { font: Inter, fontSize: 11pt, lineHeight: 1.6, color: "#1F1F1F" }
label: { fontSize: 8.5pt, color: "#6B6B6B", padding: 10pt 0 2pt 0 }
th: { fontWeight: bold, borderBottom: "0.75pt solid #1F1F1F", padding: 0 0 3pt 0 }
total: { fontWeight: bold, borderTop: "0.75pt solid #1F1F1F", padding: 3pt 0 0 0 }
data:
notice:
fields: { Arabic: string, Hebrew: string, Hindi: string, Syriac: string, Nko: string, Mandaic: string, Adlam: string, Mongolian: string, Invoice: string }
items:
fields: { Item: string, Quantity: int32, Price: decimal }
body:
dataset: notice
detail:
- content:
- { type: text, value: "Right-to-left and complex scripts", fontSize: 18pt, fontWeight: bold, tag: h1 }
- type: text
value: >-
Each paragraph takes its direction from its first strong character. Arabic and Hindi are
shaped with HarfBuzz; words and numbers in other scripts keep their own order.
- content:
- { type: text, value: "Arabic, justified with kashidas", style: label }
- layout: row # right to left: the narrow paragraph sits at the right
textDirection: rtl
content:
- { type: text, value: "{Arabic}", language: ar, align: justify, width: 330pt }
- content:
- { type: text, value: "Hebrew", style: label }
- { type: text, value: "{Hebrew}", language: he }
- { type: text, value: "Hindi", style: label }
- { type: text, value: "{Hindi}", language: hi }
- { type: text, value: "Syriac and N'Ko, justified with kashidas (tatweel and lajanyalan)", style: label }
- layout: row
textDirection: rtl
gap: 24pt
content:
- { type: text, value: "{Syriac}", language: aii, align: justify, width: 1fr }
- { type: text, value: "{Nko}", language: nqo, align: justify, width: 1fr }
- content:
- { type: text, value: "Mandaic, Adlam and Mongolian (set horizontally), justified with kashidas", style: label }
- layout: row
textDirection: rtl
gap: 24pt
content:
- { type: text, value: "{Mandaic}", language: myz, align: justify, width: 1fr }
- { type: text, value: "{Adlam}", language: ff-Adlm, align: justify, width: 1fr }
# Mongolian runs left to right: undo the row's inherited rtl for its words.
- { type: text, value: "{Mongolian}", language: mn-Mong, align: justify, width: 1fr, textDirection: auto }
- padding: 16pt 0 0 0
content:
- { type: text, value: "A right-to-left table (textDirection: rtl)", style: label }
- type: table
dataset: items
textDirection: rtl
language: ar
headerStyle: th
columns:
- { header: الصنف, value: "{Item}", width: 1fr }
- { header: الكمية, value: "{Quantity}", width: 60pt, align: end }
- { header: السعر, value: "{Price:N2}", width: 80pt, align: end }
footer:
- style: total
cells:
- { value: المجموع, span: 2, isHeader: true }
- { value: "{Sum(Quantity * Price):N2}", align: end }
- { type: text, value: "Invoice {Invoice} · فاتورة {Invoice} · חשבונית {Invoice}", style: label }
pageFooter:
- content:
- { type: text, value: "Page {PageNumber} of {TotalPages}", align: right, color: "#6B6B6B", fontSize: 8pt }

Save the template, put the fonts it names next to it (Inter and the Noto fonts are free, under the SIL Open Font License), and run:

Terminal window
tagua render multilingual.report.yaml --open

Without a data file, tagua render makes up sample rows from the field types; see Preview as you edit.