Replace hardcoded language enum/check flow with DB-backed language registry
Summary
This MR replaces the old hardcoded language-validation approach with a database- backed language registry and service-level validation.
Previously, adding a new language required code changes and a migration to update
the record language allow-list behavior. With this MR, languages become data
managed through a language table, and validation moves into the service layer.
What Changed
New language registry
Added a dedicated language table to persist allowed language values.
The table includes registry metadata such as:
idnamecreated_bycreated_atupdated_at
This table is now the source of truth for allowed languages.
Seeded default languages
The migration seeds the existing language set into the new registry, including NA
for compatibility with the current record flow.
Removed DB allow-list constraint from record flow
The old record-level hardcoded language constraint is removed.
This means we no longer need a new migration every time we want to support one more language value.
Added service-level language validation
Introduced a language service to handle:
- normalization of language values
- retrieving all languages
- validating single/multiple languages
- validating user language proficiencies
- creating new language entries
Added new endpoints
Added:
GET /languagesPOST /languages
Behavior:
GET /languages
- authenticated users can fetch available languages
POST /languages
- admin users can add a new language
- duplicate and normalization checks are handled in the service layer
Updated record/user validation flow
Refactored language handling in:
- record upload
- record update
- record review filters
- user language proficiencies
These flows now validate against the DB-backed registry instead of relying only on hardcoded enum typing.
Why This Change
The old design made taxonomy expansion expensive.
Adding one new language should be a data change, not a repeated schema-maintenance task. This MR fixes that by separating:
- persistence
- validation
- registry management
This gives us:
- easier extensibility
- less migration churn
- one source of truth for allowed languages
- consistent validation across records and users
Migration Impact
The included migration:
- creates the
languagetable - seeds existing default language values
- drops the old record language check-constraint
This is intended to be the last migration needed for future language additions in this area.
API Impact
New endpoints
GET /languages
Returns the current language registry entries.
POST /languages
Creates a new language registry entry.
Example:
{
"name": "marwari"
}