feat(api): let users read and set their preferred language - #582
Open
abdulrafey1 wants to merge 3 commits into
Open
feat(api): let users read and set their preferred language#582abdulrafey1 wants to merge 3 commits into
abdulrafey1 wants to merge 3 commits into
Conversation
The frontend picker and the static-UI translation layer both need this list; serving it keeps the allowlist defined once instead of duplicated client-side. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PATCH /user/me validates the tag against the supported-language allowlist in the request model, so an unsupported value is a 422 before any domain logic runs. GET returns the raw column, null included, so the frontend can tell a user who never chose from one who chose English. get_current_user takes Depends(get_async_session); FastAPI caches that dependency per request, so current_user is already attached to the same session the route body uses. PATCH mutates it directly instead of re-fetching or refreshing after commit (open_session defaults to expire_on_commit=False, so the in-memory value never goes stale). The test double for get_current_user takes the same dependency for the same reason, so a value one request writes is visible to a later request on the same client. That rewrote _override_current_user — the shared helper the three pre-existing is_admin tests also call — from a detached make_transient snapshot to a live select(User) on the request session; those three tests are themselves left unmodified and still pass. Also covers the PATCH auth gate (401 unauthenticated) and that a PATCH only ever writes to the caller's own row. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
openapi.json is a gitignored build artifact and is not committed; only the generated TypeScript client changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Exposes the preferred-language setting over the API so clients can list the supported languages and set or clear a user's choice.
Changes
GET /api/v1/languages, returning the supported languages and the platform defaultPATCH /api/v1/user/meto set or clear the preference, and addlanguageto the user schemaHow to Test
uv run pytest tests/api/v1/test_language.py tests/api/v1/test_user.py -q— 16 tests pass.curl http://localhost:7727/api/v1/languages -H "Authorization: Bearer $TOKEN"returns the three languages and"default": "en"; without the header it returns 401.curl -X PATCH .../api/v1/user/me -d '{"language":"es"}'returns 200;GET /api/v1/user/methen reports"language": "es".-d '{"language":"en-US"}'returns 422 and leaves the column untouched — matching is exact and case-sensitive.-d '{"language":null}'clears the preference back tonull.Notes
No migration.
GET /mereturns the raw stored value,nullincluded, so a client can tell "never chose" from "chose English"; resolving to the default isresolve_language's job.languageis a required field on the request body, so an explicitnullclears the preference while omitting the field is a 422 rather than a silent no-op.Generated content does not consult this preference yet — that arrives with prompt injection in a later change.
This description was written with the assistance of an LLM (Claude).