feat(invoice): add Noto Sans Thai fallback font for Thai glyphs

Merged
PI
24d ago
+13-0

Summary

Thai characters in invoice and receipt PDFs now render with Noto Sans Thai instead of showing up blank.

What

  • Adds NotoSansThai-Regular.ttf and NotoSansThai-Bold.ttf (~38 KB each, from the official notofonts repository) to server/polar/invoice/fonts/.
  • Registers Thai in InvoiceGenerator as an always-loaded fallback font, the same way Hebrew and Arabic are. ReceiptGenerator builds on InvoiceGenerator, so receipts get it too.
  • Extends test_generator_registers_unicode_fallback_fonts to check that เธ resolves to the Thai font in regular and bold.

Why

Neither PP Neue Montreal nor the existing Noto fallbacks include the Thai block (U+0E00โ€“U+0E7F), so Thai customer names, addresses and line items rendered as empty space.

How

The fonts are small, so they're committed next to the Hebrew and Arabic fonts. They aren't downloaded at Docker build time like the CJK fonts (which are tens of MB each), so dev, test and production all have them without changes to the Dockerfile.

fpdf2 runs without a text shaper here, so I rendered a sample invoice to check that stacked vowel and tone marks display correctly. The sample has a Thai customer name in bold and a Thai line item with Thai digits:

Invoice rendered with a Thai customer name and line item

The image is hosted in commit 7ad13f8 on this branch, and the next commit removes it, so it's not part of the diff.

Checklist

  • This PR addresses a single concern (one bug fix, one feature, one refactor)
  • The diff is reasonably sized and easy to review
  • New functionality is covered by tests
  • Linting and type checking pass (uv run task lint && uv run task lint_types): ruff lint and format are clean, and the tests/invoice and tests/receipt suites pass (109 passed, 4 skipped). mypy was not run locally.
  • No unrelated changes or drive-by fixes are included

๐Ÿค– Generated with Claude Code

https://claude.ai/code/session_01TJbggMDA6pDQESPPFpoHB8


Generated by Claude Code