Skip to content

feat(i18n): add spanish and french message catalogs - #604

Open
hamza-56 wants to merge 1 commit into
i18n-mark-pluginsfrom
i18n-es-fr-catalogs
Open

feat(i18n): add spanish and french message catalogs#604
hamza-56 wants to merge 1 commit into
i18n-mark-pluginsfrom
i18n-es-fr-catalogs

Conversation

@hamza-56

@hamza-56 hamza-56 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Part of: Sparkth UI, emails, API errors, and AI-generated content are English-only

Fourth layer of the i18n stack (#601#602#603#604#606#607).

What

Ships the Spanish and French message catalogs for the 117 strings marked in the layers below, so Accept-Language: es and fr actually serve translated content.

Changes

  • feat(i18n): sparkth/locale/{es,fr}/LC_MESSAGES/messages.po, pybabel-initialized from the extracted template and fully filled (117 messages each)

How to Test

  1. make i18n.compile (required — the runtime loads the compiled .mo, which stays git-ignored)
  2. make run.backend, then curl -s -X POST localhost:8000/api/v1/auth/login -H 'Content-Type: application/json' -H 'Accept-Language: es' -d '{"username":"ghost","password":"nope"}'{"detail":"Usuario o contraseña incorrectos"}; repeat with Accept-Language: fr{"detail":"Nom d'utilisateur ou mot de passe incorrect"}
  3. uv run pytest stays green with the compiled catalogs present (1760 passed)

Notes

The translations are LLM-authored and pending native-speaker review (the SUPPORTED_LANGUAGES comment's review bar). Spanish uses informal address (tú), French formal (vous). Deployment note: serving translations requires compiled catalogs; #606 (stacked on this PR) compiles them into the Docker image at build time.

This PR description and the initial translations were written with the assistance of an LLM (Claude).

Extracted with pybabel from the marked strings and filled with initial es
and fr translations so the negotiated locales serve real content. The
translations are LLM-authored and pending native-speaker review; the .pot
template and compiled .mo files stay git-ignored build artifacts, so
deployments must run make i18n.compile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hamza-56

Copy link
Copy Markdown
Contributor Author

@claude-review

@claude

claude Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Claude finished @hamza-56's task in 2m 48s —— View job


Review: Spanish & French message catalogs

  • Read both .po catalogs and the extraction workflow
  • Verify translations against source strings (coverage, placeholders, plurals, register)
  • Check .po metadata headers & formatting hygiene
  • Post review feedback

Overall: LGTM to merge. These are clean, complete, and technically correct catalogs. The remaining items are cosmetic/native-review nits — none are blocking, which matches the PR's own "pending native-speaker review" note.

What I verified

  • Coverage — both catalogs carry all 117 messages (118 msgid lines incl. the header); no empty and no #, fuzzy entries. Accept-Language: es/fr will serve real translations for every marked string.
  • Placeholders (the thing that actually breaks at runtime) — all preserved. Every #, python-brace-format entry keeps its exact tokens, including the trickier ones: {scope!r} / {scope_object_id!r} (exceptions.py:81), the format spec {limit:.0f} (files.py:120), {status_code}, {allowed}/{model}/{provider}, {conversation_uuid}, etc. I checked each of the ~28 brace-format msgids in both files — no dropped or renamed placeholders, so str.format(...) won't raise KeyError.
  • Plural-Forms headers correct per language (es: n != 1, fr: n > 1); no msgid_plural entries in the catalog anyway.
  • Register is consistent as advertised — ES informal (tú: reactívalo, inténtalo), FR formal (vous: veuillez réessayer).
  • Nice localization touches: 30MB → 30 Mo for French (mégaoctet), Hi {name}, → Hola {name}: (Spanish salutation colon), proper nouns left untranslated (Canvas, Open edX, Google Drive, Slack TA Bot).

Note: the CI sandbox blocked me from running msgfmt -c --check-format / pybabel, so the checks above are a line-by-line manual audit rather than a tool run. Worth running make i18n.compile locally (as the PR's test steps already say) to get the compiler's own format-consistency pass before merge.

Suggestions (all Low / non-blocking)

  1. Header metadata placeholders (es & fr, lines 8–14) — Project-Id-Version: sparkth VERSION, Report-Msgid-Bugs-To: EMAIL@ADDRESS, Language-Team: <LL@li.org> are left at pybabel defaults. Cosmetic; inline comment posted.
  2. French typography — French convention puts a (narrow) non-breaking space before : ; ? ! and inside guillemets; the catalog uses plain ASCII spaces (e.g. Rôle introuvable : {role_name}, … prise en charge ;). Consistent as-is, so purely a polish item for the native-speaker pass.
  3. "whitelist" → lista blanca / liste blanche — literal and understandable; modern inclusive-language guidance tends toward lista de permitidos / liste d'autorisation. Defer to the native reviewer.
  4. Catalog-drift safety net (process, likely out of scope for this layer)messages.pot and *.mo are git-ignored and only the .po files are tracked, and I don't see a test/CI check asserting the catalogs' msgids still match the currently-marked source strings. When a marked string later changes, the catalogs can silently fall out of sync until someone remembers make i18n.update. A small CI step (pybabel extract + msgcmp, failing on new/obsolete entries) would catch that. Flagging as a follow-up, not a change requested on this PR.

Test coverage

No new logic is introduced (these are data files), and test_i18n.py already exists for the marking layers, so I don't consider missing tests blocking here. If you want belt-and-suspenders, a tiny parametrized test that installs the es/fr locale and asserts one known string round-trips (e.g. Incorrect username or password → Usuario o contraseña incorrectos) would guard against a broken/missing compiled catalog. Optional.
· branch i18n-es-fr-catalogs

Comment on lines +8 to +14
"Project-Id-Version: sparkth VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-08-14 07:25+0500\n"
"PO-Revision-Date: 2026-08-14 07:25+0500\n"
"Last-Translator: Hamza Shafique <hamza.shafique1@arbisoft.com>\n"
"Language: es\n"
"Language-Team: es <LL@li.org>\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (Low): the pybabel-init placeholder headers are left unfilled here — Project-Id-Version: sparkth VERSION, Report-Msgid-Bugs-To: EMAIL@ADDRESS, and Language-Team: es <LL@li.org> (same in the fr catalog). These are cosmetic and don't affect runtime lookup, but since the header is the one place a translator's metadata lives, consider filling in a real project version / bugs-to address (or dropping the noise). Non-blocking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant