"Add Spanish support" sounds like a single task until you've tried to do it properly. Translation touches every label on every screen, every validation message, every email template, every button, every navigation item, every notification — and, critically, every piece of content the customer themselves has created. A platform that hasn't designed for this from the start can usually be persuaded to swap strings in a few places, but the seams show quickly, and the seams are where users lose trust. We took the long way.
Localization on our platform is a per-user setting. Each person picks their language once, and the interface follows them everywhere — the menus, the forms, the views, the system messages, the scheduled-email headers, the error dialogs that appear on a bad network. Switching language is immediate. It doesn't require an administrator, a page reload, or a reinstall. Multiple users on the same tenant can work in different languages simultaneously without ever noticing the other exists.
The platform ships with several fully translated languages out of the box. Every hard-coded UI string — and there are thousands — has been audited and translated, not machine-dumped. That matters: machine translations get the vocabulary right and the idiom wrong, which is enough to make an otherwise polished product feel amateurish. The built-in translations are human-reviewed.
What sets the system apart is entity-level translation for the customer's own implementation. The types a tenant defines, the properties they attach, the modules they group them into, the saved queries and filters they configure — all of it is translatable into each of the tenant's active languages. A Czech-speaking user sees Zákazník; a German-speaking colleague viewing the same record sees Kunde; both are looking at the exact same type definition and the exact same record. The translations manager is a central UI that lists every translatable string in the implementation, with per-type filtering to keep focus when a large model accumulates a lot of text.
Consistency matters more than raw coverage, so the platform maintains a fallback chain. If a German translation is missing for a newly added property, the user doesn't see a blank; they see the platform's defined default — typically the implementation language — clearly marked so it stands out and invites a proper translation. Missing strings don't turn into embarrassing gaps in the UI, and they're easy to spot in the translations manager, which can filter down to entries that haven't been translated into a given language.
Filters and saved queries get the same treatment. A filter labeled Overdue invoices in one language shows up as its equivalent in another, and the underlying query is obviously the same piece of configuration in both. Users across regions share a vocabulary of saved views without anyone having to keep two parallel copies of each query in sync.
The REST API negotiates language the standard way, over HTTP. A consuming application can ask for responses in French and get the display labels and error messages in French, while the underlying data stays the same. That makes the API safe to use for white-label portals and partner integrations where the end user's language varies.
Keeping translations in sync as a data model evolves is its own small discipline, and the platform tries to make it manageable. When you add a new property or a new filter, the translations manager surfaces it as a pending entry. A small weekly review is often enough to keep coverage tight. For tenants that roll out to new regions, a single pass through the manager with a language-specific view is usually enough to close the loop on a new language.
Localization is one of those features that makes the difference between a platform that can be sold into international organizations and one that can't. We treat it as foundational, not as an afterthought, and it shows in the details — which is the best recommendation this kind of feature can give.