Document Stack
Document Stack
Docs

Localization & Internationalization

Generate documents in multiple languages with proper formatting for dates, currencies, and text direction.

Overview

Document Stack supports generating documents in any language. Since templates use data binding, localization is handled through the data you pass to the API — the template stays the same, and the content adapts based on your data.

Language Through Data

The simplest approach is to pass localized strings in your API data:

English data
{
  "invoiceTitle": "Invoice",
  "dateLabel": "Date",
  "totalLabel": "Total",
  "customerName": "John Smith",
  "invoiceDate": "January 15, 2025",
  "total": "$1,250.00"
}
German data
{
  "invoiceTitle": "Rechnung",
  "dateLabel": "Datum",
  "totalLabel": "Gesamt",
  "customerName": "Hans Müller",
  "invoiceDate": "15. Januar 2025",
  "total": "1.250,00 €"
}

The same template works for both — field elements display whatever text you send.

Date Formatting

Format dates on the client side before sending to the API. Different locales expect different formats:

LocaleFormatExample
US EnglishMM/DD/YYYY01/15/2025
UK EnglishDD/MM/YYYY15/01/2025
GermanDD.MM.YYYY15.01.2025
JapaneseYYYY年MM月DD日2025年01月15日
ISOYYYY-MM-DD2025-01-15
Format dates per locale
const date = new Date("2025-01-15");

// US English
date.toLocaleDateString("en-US"); // "1/15/2025"

// German
date.toLocaleDateString("de-DE"); // "15.1.2025"

// Japanese
date.toLocaleDateString("ja-JP"); // "2025/1/15"

// Long format
date.toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
}); // "January 15, 2025"

Currency Formatting

Currency symbols and number formatting vary by locale:

Format currencies
const amount = 1250.5;

// US Dollar
new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
}).format(amount); // "$1,250.50"

// Euro (German)
new Intl.NumberFormat("de-DE", {
    style: "currency",
    currency: "EUR",
}).format(amount); // "1.250,50 €"

// Japanese Yen
new Intl.NumberFormat("ja-JP", {
    style: "currency",
    currency: "JPY",
}).format(amount); // "¥1,251"

// Indian Rupee
new Intl.NumberFormat("en-IN", {
    style: "currency",
    currency: "INR",
}).format(amount); // "₹1,250.50"

Number Formatting

Thousands separators and decimal points differ across locales:

LocaleThousandsDecimalExample
US/UK,.1,250.50
Germany/France.,1.250,50
Switzerland'.1'250.50
India,.1,250.50

Use Intl API

Always use JavaScript's built-in Intl.NumberFormat and Intl.DateTimeFormat for formatting. They handle locale-specific rules automatically.

Multi-Language Templates

You have two approaches for supporting multiple languages:

  • One template, localized data — Use field elements for all text (including labels) and pass translated strings in the data. Best for simple documents.
  • Per-language templates — Create separate templates for each language with static text in the local language. Best when layout changes significantly.

Font Support for Non-Latin Scripts

When generating documents in languages with non-Latin scripts, ensure your template uses fonts that support those characters:

  • CJK (Chinese, Japanese, Korean) — Use Noto Sans CJK or similar
  • Arabic / Hebrew — Use fonts with RTL support
  • Devanagari (Hindi) — Use Noto Sans Devanagari
  • Thai — Use Noto Sans Thai

Character Support

If characters appear as boxes or question marks in the generated PDF, the selected font doesn't support those characters. Switch to a font with the required character set.

Next Steps