feat(core): add gettext_noop marker and translation-catalog fixture - #601
feat(core): add gettext_noop marker and translation-catalog fixture#601hamza-56 wants to merge 1 commit into
Conversation
The frontend metadata dataclasses (DisplayInfo, SidebarEntry) are embedded in Pydantic response models, where a LazyString cannot go: their fields must stay plain str. gettext_noop marks such literals for extraction while returning them unchanged; the stored source string is translated with gettext() at the rendering boundary. The translation_catalog fixture in sparkth.lib.testing lets any test (core or plugin) assert on a real translation by compiling a single-message catalog onto the LOCALE_DIRS hook. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@claude-review |
|
Claude finished @hamza-56's task in 2m 28s —— View job Claude Code Review
Reviewed all 7 changed files against Overall assessmentApprove-worthy. No blocking or correctness issues found. A couple of low-priority nits below. What's good
Suggestions (Low)
Notes
|
| `locale_context("<lang>")` or an `Accept-Language` header: | ||
|
|
||
| ```python | ||
| def test_detail_is_translated(client, translation_catalog): |
There was a problem hiding this comment.
The example body uses await client.post(...) but the function is declared with a plain def. The suite runs asyncio_mode = "auto", so this test would need to be an async def to actually await. As written, copying this pattern produces a SyntaxError (await outside an async function).
| def test_detail_is_translated(client, translation_catalog): | |
| async def test_detail_is_translated(client, translation_catalog): |
|
|
||
| def test_the_core_locale_dir_is_registered_at_import() -> None: | ||
| assert LOCALE_DIRS.get(LOCALE_DIR) == LOCALE_DIR | ||
| def test_gettext_noop_returns_the_message_unchanged(catalog_dir: Path) -> None: |
There was a problem hiding this comment.
Minor: this test requests catalog_dir, but gettext_noop never consults a catalog (it returns its argument verbatim), so the fixture is unused here — it registers a Spanish catalog that has no bearing on the assertion. Dropping the parameter makes the test's intent (pure identity, independent of any catalog) clearer:
def test_gettext_noop_returns_the_message_unchanged() -> None:
with locale_context("es"):
assert gettext_noop(TRANSLATED[0]) == TRANSLATED[0]
Part of: Sparkth UI, emails, API errors, and AI-generated content are English-only
First layer of the i18n stack (#601 → #602 → #603 → #604 → #606 → #607) that follows up the translation foundations from #590.
What
Adds the missing marking primitive and the shared test tooling that the string-marking PRs stacked on top rely on: a deferred
gettext_noopmarker for strings that must stay plainstr, and a fixture for asserting on real translations.Changes
gettext_noopmarking function, exported throughsparkth.lib.i18nand extracted via-k gettext_noop; for literals stored in plain-strfields (theDisplayInfo/SidebarEntrydataclasses embedded in Pydantic response models, where aLazyStringcannot go), translated later by passing the stored value throughgettext()at the rendering boundarytranslation_catalogfixture insparkth.lib.testing— compiles single-message catalogs onto theLOCALE_DIRShook so any test (core or plugin) can assert on an actual translationshipped_locale_dirssession fixture detaching the shipped catalog directories for the whole suite, so locally compiled.mofiles (make i18n.compile) never leak into assertions written against the English source fallbackHow to Test
uv run pytest tests/core/i18n(24 passed)make i18n.compile && uv run pytest— the suite stays green with compiled catalogs present (the detachment fixture at work); before this PR the compiled-catalog state broketest_gettext_returns_the_source_when_the_locale_has_no_catalogmake mypyandmake lint.backendare cleanNotes
No behavior change outside tests:
gettext_noophas no call sites yet (they arrive in #602/#603).This PR description was written with the assistance of an LLM (Claude).