2 Commits
Author SHA1 Message Date
vliaudatandClaude Opus 5 ed89d08172 fix: show one clock convention in English on the panel
The labels this application writes itself already read "6:30 pm", while
a translated notice kept whatever the French said, so the screen could
show "Closes at 6:30 pm" above "Delayed opening at 14:00". Two
conventions side by side on one panel.

The conversion is done in code, not by the prompt. The model is still
told to leave times alone — reading a clock and rewriting it is
deterministic work, and asking a language model to do it introduces a
failure mode for no benefit. Only HH:mm is touched, never a time that
already carries am or pm, so the pass is idempotent and years, dates
written 20/07 and percentages are left alone.

Hand-written translations are not rewritten: that wording was somebody's
explicit choice.

Verified against the live service: "Ouvert 10:00 – 13:00 puis 14:00 –
18:30" now comes back as "Open 10:00 am – 1:00 pm then 2:00 pm –
6:30 pm".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012cSY9pVhZmJUKNN7wf1Myd
2026-09-20 22:37:59 +02:00
vliaudatandClaude Opus 5 f68ce1c3a5 feat: translate French notices to English through api.loxi.ch
The service is neither Anthropic- nor OpenAI-compatible: it runs the
Claude Code CLI server-side and returns its output. Three consequences
are handled explicitly, each with a test.

The model is chosen by integer id, not by name, so the id is resolved
once from /api/models instead of being hard-coded into the environment —
a number in a .env file that silently points at the wrong model is a bad
trade for one HTTP call per process.

A failed CLI still answers HTTP 200. `exit_code` decides, not the status
line; trusting the status would store an empty translation and call it a
success. The test for this asserts a 200 carrying exit_code 1.

It really does start a process, so the timeout is thirty seconds rather
than the ten the spec assumed.

Answers are cleaned before use: models wrap text in quotes, prefix it
with "Translation:" and append notes often enough that stripping is
cheaper than re-prompting, and a stray quotation mark on a shop window
reads as a mistake.

The cache is keyed on the hash of the trimmed French text, so the same
notice is never paid for twice and whitespace does not cause a miss. The
write is an upsert: two concurrent saves of the same text should be a
no-op, not a crash.

Only the loxi adapter exists, behind the interface. Writing the
Anthropic and OpenAI adapters the spec asked for, with nothing calling
them, would be inventory rather than flexibility — the seam is the
interface, and it is there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012cSY9pVhZmJUKNN7wf1Myd
2026-09-20 20:13:28 +02:00