Title: Fetch frontend language options dynamically from backend `/languages`
Summary
This MR removes the frontend’s static language source for record/profile selectors and replaces it with a shared dynamic fetch from the backend language registry endpoint.
The backend now manages languages through the language table and exposes them
via:
GET /api/v1/languages
This MR updates the client app so language selectors stop using hardcoded values and instead consume that backend source.
Problem
Previously, the frontend maintained its own static language list.
That meant:
- the client could drift from the backend registry
- newly added backend languages would not appear in the frontend
- multiple screens duplicated language option logic
- maintenance remained manual even after backend language management became dynamic
What Changed
Shared language source
Updated the shared frontend language module to become the central dynamic source for language options.
It now:
- fetches the language list from the backend
- exposes reusable language data for selectors
- keeps a small built-in fallback so components/tests still render safely before the API responds
Replaced static language consumers
Updated the main language-selecting screens to consume the shared dynamic source instead of local hardcoded lists.
Covered flows include:
- content upload/content input
- peer review edit
- media detail edit
- record details edit
- profile preferences default language
- complete profile language proficiency selection
Preserved existing submission behavior
This MR does not change the payload contract sent to the backend.
Language values are still submitted as plain strings. Only the source of available options changed.
Preserved current profile defaults
The profile flow still keeps its existing default seeded proficiency entries, but the available option list itself is now driven by the backend language source.
Implementation Notes
The client repo already had a shared src/lib/languages.ts, but it was still
static.
This MR refactors it into a reusable dynamic source and updates all current consumers to read from that shared module.
A built-in fallback list is retained so:
- selectors still render immediately
- tests that do not mock the backend language request do not fail just because the request is unresolved
- the backend remains the preferred live source whenever available
Files / Areas Touched
Main areas updated:
- shared frontend language module
- upload/content input language selector
- peer review language selector
- media detail edit language selector
- record details edit language selector
- profile default language selector
- complete profile language proficiency selector
API Usage
This MR depends on the existing authenticated backend endpoint:
GET /api/v1/languages
Expected response shape:
string[]
No backend API changes are introduced by this MR.
Behavior After This MR
After this change:
- frontend language selectors use the backend language registry
- newly added backend languages become available in the frontend automatically
- record/profile language option sources are unified
- manual frontend language list maintenance is no longer required for backend registry changes
Verification
Verified in corpus-client-app with:
npm run type-check
npm run build