Translations & i18n
Translations & i18n
Frappe is multilingual at the framework level — strings wrapped with _() (server) or __() (client) are translated based on the user's language.
Setting a user's language
User → Language picks the preferred language. The desk re-renders in it. Each user has their own setting.
Where languages live
| Where | What |
|---|---|
| Language DocType | ISO codes and labels (en, nl, de, fr, …) |
| System Settings → Language | Site-wide default for Guest visitors |
| Translation DocType | Per-string overrides for the current site |
Built-in translations
Frappe and ERPNext ship translations contributed via Crowdin. Dutch (nl) coverage is strong; less common languages vary.
Custom translations
To override a label site-wide, open Translation → New:
- Source Text: "Sales Invoice"
- Translated Text: "Customer Order" (or your preferred term)
- Language: en
The desk uses your override immediately for the chosen language. Useful when you want industry-specific terminology ("Job" instead of "Project", "Patient" instead of "Customer").
Translating your own app
In Python: wrap user-facing strings with _("My text"). In JS: use __("My text"). Then:
bench --site mysite generate-translations # extracts to CSV
# translate the CSV
bench --site mysite import-translations # imports back
Document content
The translation system handles UI strings — not document body content. For multilingual customer-facing output (invoices in Dutch vs English), use the language field convention on Customer / Print Format / Email Template.