Speak your users'
language.
Every string in the app and the admin is a typed Paraglide message. A new language is one JSON file, and anything you have not translated yet falls back to English.
One file per language. The whole product follows.
No i18n framework to wire, no provider to mount, no extraction pass. The catalog is already there; you add a locale to it.
Register the locale
step 1Translate the values
step 2Ship it
step 3
Strings that fail the build, not the user.
Paraglide compiles the catalog into typed functions, so the compiler reads your copy the same way it reads your code.
Every string is a message function
m.billing_upgrade_cta()A renamed key stops the build, not the user
TS2339Untranslated keys fall back to English
fallback: enPacks merge their copy into your catalog
messages/en.jsonEven pack nav labels stay translatable
sidebar + settings tabs
any
Español日本語DeutschpolskiУкраїнськаPortuguêsLanguage you want, not a picker list
locales is your array in project.inlang/settings.json. There is no supported-languages table.
1 file
messages/pl.json
app
admin
packs
To add a whole language
messages/<locale>.json beside the English one. Your locale files are never touched by installs.
0
teams packmergedbilling packmergednotifications packmergedHardcoded strings in any pack
Install merges each pack's messages into en.json, and re-running compose produces no diff.
Feature packs to grow with
Every pack ships real source code: frontend, backend, and admin surfaces where the feature needs them. Add them when you need them, one command each.
Questions, answered
Ship in their language.
Start from the free starter, add locale files as your users arrive, and keep every string typed along the way.
any locale / typed messages / english fallback