Add a new language
Ship a new UI locale across webapp, mobile, extension, and API error strings.
This guide walks through adding a locale to Bondery. English (en) is the reference — every namespace file must exist for the new locale before CI passes.
Register the locale
Add an entry to packages/schemas/locale/supported-locales.json:
{ "code": "fr", "flag": "fr", "nativeName": "français" }Keep default as en. If the locale needs a Postgres enum value, the postgresEnum block in that file documents the shared enum name (supported_locale).
Copy locale files
Duplicate the English tree:
cp -r packages/translations/src/locales/en packages/translations/src/locales/frEvery JSON path under en/ must exist for the new code. CI compares file trees and fails on missing or extra files.
Translate values in place — do not rename keys or namespaces.
Add exonyms to Languages namespace
Each locale has a Languages.json file listing human-readable names for every supported language code. Add the new locale's exonyms to all locale folders (en, cs, de, and your new one).
pnpm run check:i18n:structure verifies parity against supported-locales.json.
Regenerate hooks and types
pnpm run build -w @bondery/translationsThis updates generated hooks, Catalog types, and i18next augmentations. Commit the generated artifacts with your locale JSON.
Translate API error strings
API error messages shown in product UI use the translations package. Add keys for any new error copy under the relevant namespace and run:
pnpm run check:api-errors:translationsVerify locally
pnpm run i18n:status
pnpm run check:i18nFix any missing keys or hardcoded strings the scanners report. Switch language in the webapp or mobile settings to spot-check UI.
Update docs
Add the locale to the table in Internationalization (i18n) and, if user-facing, note it in Changelog.
Related
- Internationalization (i18n) — hooks, namespaces, and CI overview
packages/translations/README.md