feat(translation): render-time translation core — settings, single-endpoint client, settled-only, cache - #700
Open
yunsheng111 wants to merge 9 commits into
Open
Conversation
The tauri-build resource.lib artifact only exists on Windows/MSVC, so the rustc-link-arg-tests directive handed every other platform's linker a path that does not exist and broke cargo test compilation of all integration-test binaries. A build script's #[cfg] describes the host, not the target, so the gate reads CARGO_CFG_TARGET_OS and CARGO_CFG_TARGET_ENV instead (the lib.rs #[link] side was already target-gated).
Render-time translation into the UI language without touching the agent, the prompt, or the session files. PR1 carries the settled-only core: provider settings with validation and change broadcast, one OpenAI/Claude/Gemini/Ollama-compatible client, sanity gates, content-addressed memory+disk cache, per-process counters, and consecutive-failure cooldown for the single configured endpoint. The acceptance decision has a single owner: translate_one runs normalize/marker-echo and the quality gates BEFORE any success report or cache insert — a parseable-but-refused reply is recorded as a gate rejection, never as an Ok, and never lands in the cache. Identity segments return skipped:true so the frontend bypasses its own gates (dissolving the cross-boundary predicate disagreement), and retry variants fold into the cache key so an escalated retry cannot hit the cached reply it just rejected.
Wire the translation module into both runtimes: twelve translation_* Tauri commands, the same twelve POST /api/translation_* routes, and the translation-settings-changed event bridge. Pool runtime events wait for the rotation pool (PR2).
Auth matrix, settings save/get roundtrip with key masking, identity translation returning skipped:true end to end, validation rejections, and the PR1 shape of the metrics/status endpoints — the axum wiring had no integration coverage before.
…rotocol Envelope builders, code-span masking ([[CBLK]] placeholders never leave the machine), numbered-request protocol with a lenient inline second pass, protocol-marker echo restoration, structure-flattening refusal, and per-chunk quality judgement helpers. Settings/stats API shapes match the single-endpoint backend (variant rides with every translate call).
… subscription The settings event subscription no longer opens unconditionally during render: binding succeeds before the bound flag is set, failures are caught (no unhandled rejection breaking vitest runs of untouched test files) and retried on the next mount. skipped results render verbatim past every frontend gate, and retry escalation carries the variant so the backend cache cannot serve the reply the gate just refused.
Text and reasoning parts translate through the settled hook — thinking translation is a real path now, not the dual-hook structure that could never issue a request. The original/translation toggle keeps its keyPrefix scoping.
Multi-row endpoint configuration with per-row test connection (no fallback: an incomplete row is reported as such, never silently tested through another row), enable toggle, target language, failure-threshold and cooldown settings, one-line call statistics, and an outbound-flow disclosure naming what leaves the machine — code spans never do.
95 keys per locale with genuine translations; locale key sets verified identical by script and by the repo's parity test.
This was referenced Sep 9, 2026
Open
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.
Summary
Re-grounded, settled-only core of the render-time translation middleware (#695), rebuilt from
mainas the first of three PRs splitting up #696 along the seams suggested in its review:The single acceptance owner
translate_oneruns marker-echo normalization and the quality gates before any success report or cache insert. A parseable-but-refused reply is recorded as a gate rejection — never an Ok (review I7), never cached (review I6). Identity segments returnskipped: trueand the frontend renders them verbatim past its own gates, so the two sides can no longer disagree about "already in the target language" (review I5). Retry escalation carries avariantthat folds into the cache key, so an escalated retry cannot hit the cached reply it just rejected.Other review items addressed here
build.rsgates theresource.liblink args byCARGO_CFG_TARGET_OS/CARGO_CFG_TARGET_ENV(a build script's#[cfg]describes the host), socargo testlinks again on macOS/Linux.subscribesucceeds, catches rejection (no unhandled rejection failing untouched vitest files), and retries on the next mount.test_connectionnever falls back to another provider; an incomplete row is reported as such.read_capped.Structure
src-tauri/src/translation/:settings.rs,endpoint.rs(single-endpoint selection + consecutive-failure cooldown),client.rs(protocol adapters, acceptance owner),mod.rs(orchestration, gates),cache.rs(variant-aware key),metrics.rs(single-row counters),prompt.rs; wired into desktop commands and the Axum router (12 routes) with integration coverage intests/translation_api.rs.lib/translation.ts(mask, numbered protocol, marker-echo restoration),use-translated-text.ts(settled), renderer integration, settings page with provider CRUD + outbound-flow disclosure (code spans never leave the machine), i18n keys in all 10 locales.Testing
tsc --noEmit: clean;eslinton touched files: cleanpnpm test: 437 files / 6429 tests passingcargo check+cargo clippy --all-targets -D warnings, desktop and server modes: cleancargo test --features test-utils(full, including integration binaries): 3616 lib tests + all integration binaries passingcargo test --no-default-features --bin codeg-server --lib: 3575 passingmacOS/Linux linking can't be exercised locally; the B1 fix reads the target triple from Cargo-provided env rather than
#[cfg]for exactly that reason.Follow-ups (tracked on #696): app-level settings provider, disk-cache compaction (I11), provider-dimension cache keys (I12), DeepL/Azure-style purpose-built API as a default path, log size-based rotation.