fix(translation): 翻译不会生效时不再进入翻译态(胶囊误报 + 空转 LLM) - #908
Merged
H-Chris233 merged 4 commits intoAug 5, 2026
Conversation
两个症状同源:`translation_modifier_seen` 的语义只是「按过 Shift」, 而「是否真的翻译」的判定散落在读取侧,胶囊那一侧漏了目标语言检查。 - 没在翻译页选目标语言,录音中按 Shift → 光标处显示「正在翻译」, 但 end_session 走的是普通润色,什么也没翻。 - 目标语言等于用户唯一的工作语言(例:工作语言只勾了简体中文、目标也选 简体中文)→ 源语言必定就是目标语言,仍会照常发起一次 LLM 翻译往返, 纯浪费时延和 token。 新增 `types::translation_effective` 作为唯一判定入口,并把判定收到写入侧 (`mark_translation_modifier_seen`):该函数每次按键才跑一次,读一次 prefs 无所谓;而读取侧之一是音频回调线程上的 emit_capsule,按帧执行, 不能碰偏好锁(capsule_focus.rs 既有注释已就此立过规矩)。收紧后 flag 的 语义变成「本次会话真的要翻译」,胶囊提示与 polish 分派读同一个真值。 工作语言有多个时不拦:中/英双语用户把目标设成英文是正常用法(说中文出 英文),源语言无法预先判定。简体/繁体是语言列表里两个独立条目,简→繁 仍照常翻译。安卓浮层的 start_dictation_with_translation 一并走同一个 gate。 「按了但不翻」的情况会记一条 INFO 说明原因,否则用户只看到胶囊没提示, 无从判断是没生效还是没按到。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
后端已经不会在这种组合下发起翻译(上一个 commit),但用户在设置页看不出 任何异常:状态灯仍写「已启用」,按 Shift 却什么也不会发生,只能靠翻日志 才知道为什么。 - 翻译目标语言卡片下方出现一条警示:说明这个组合不会生效,并给出两条 出路(换目标语言,或多勾一个工作语言)。 - 「已启用 / 未启用」状态灯改为同时看目标语言和这个冗余判定,不再谎报。 判定逻辑抽成 `lib/translationTarget.ts`,与后端 `translation_effective` 同一套规则(多工作语言不拦、简→繁不误判),两侧各带单测钉住契约。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
…e + 修正安卓 overlay 日志
审查跟进(PR Open-Less#908):mark_translation_active 的实际行为是「只在翻译会 生效时置位并返回是否置位」,名字却像无条件 setter,改为 arm_translation_if_effective 更诚实;translation_effective 里的 matches!([only] if ...) 改写为显式 len==1 + trim 相等(语义完全等价)。 行为零变化:translation_effective 6 个单测全过(backend-tests), cargo check 全绿。
bigsongeth
added a commit
to bigsongeth/openless
that referenced
this pull request
Aug 5, 2026
beta 一次进了 13 个提交,其中三条正是本地 daily 上那批私货合上游了 (Open-Less#910 历史落点+重试、Open-Less#908 翻译、Open-Less#909 概览),daily 的 patch queue 相应缩小。 冲突只有 selection.rs 一处,而且 HEAD 侧是空的:beta 的选区润色 macOS 移植 (Open-Less#926)在同一位置加了 current_front_app_pid 与 Windows/其他平台的 current_front_app,本分支在附近加了 bundle_id_for_pid(闸门按元素归属判定用)。 两者互不相干,取 beta 侧即可。 解完核对:bundle_id_for_pid 仍在(1 处),current_front_app 三个定义分属 macOS / Windows / 其他平台且 cfg 互斥,current_front_app_pid 无重复。 验证:cargo check 干净、cargo test --lib 1032 passed(beta 带来 30 个新用例)、 tsc --noEmit 干净、npm test 通过。 Co-Authored-By: Claude Opus 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.
User description ## 问题 「翻译」这个功能有两个入口条件,但判定散落在读取侧,胶囊那一侧漏了一个条件。 1. 没设目标语言,按 Shift 也会显示「正在翻译」 后端判定翻译要同时满足「按过 Shift」和「设了目标语言」(
Relevant files Bug fix coordinator.rs +9/-7 dictation.rs +5/-2 hotkey_loops.rs +29/-5 types.rs +94/-0 translationTarget.ts +24/-0 Translation.tsx +25/-1
Localization en.ts +1/-0 ja.ts +1/-0 ko.ts +1/-0 zh-CN.ts +1/-0 zh-TW.ts +1/-0
Tests translationTarget.test.ts +42/-0
___
dictation.rs),但胶囊只看了前者(capsule_focus.rs):rust let translation = !selection_polish && inner.translation_modifier_seen.load(Ordering::SeqCst);于是用户没在翻译页选目标语言、录音中按了 Shift → 光标处显示「正在翻译」,而end_session走的是普通润色,什么也没翻。日志里能同时看到这两行:[coord] translation modifier seen during Listening [style-pack] runtime dispatch ... translation_active=false2. 目标语言 = 唯一的工作语言时,仍然发起一次翻译 工作语言只勾了简体中文、翻译目标也选简体中文 —— 源语言必定就是目标语言,翻译是可证的空操作,但仍然照常发起一次 LLM 往返:[coord] translation mode → target=「简体中文」 working=["简体中文"] [llm] POST ... provider=codex_oauth model=gpt-5.5 [llm] codex HTTP 200 stream done; total chars=673.4 秒 + 一次 token 消耗,换回一段和输入同语言的文字。 ## 改动 新增types::translation_effective作为唯一判定入口,并把判定收到写入侧(arm_translation_if_effective)。 判定放在写入侧而不是读取侧,是因为读取侧之一是emit_capsule—— 它在音频回调线程上按帧执行,不能碰偏好锁(capsule_focus.rs既有注释已经就此立过规矩,capsule_style 就是为此走的原子缓存)。而arm_translation_if_effective每次按下修饰键才跑一次,读一次 prefs 无所谓。 收紧后translation_active的语义从「按过 Shift」变成「本次会话真的要翻译」,胶囊提示与 polish 分派读同一个真值,不会再漂移。 刻意不拦的情况: - 工作语言有多个时不拦。中/英双语用户把目标设成英文是正常用法(说中文出英文),源语言无法预先判定。 - 简体 → 繁体照常翻译。它们是语言列表里两个独立条目,简→繁是真实转换。 安卓浮层的start_dictation_with_translation一并走同一个 gate。 「按了但不翻」会记一条 INFO 说明原因,否则用户只看到胶囊没提示,无从判断是没生效还是没按到。 前端同步:翻译页在「目标语言 = 唯一工作语言」时给出提示并给两条出路(换目标语言 / 多勾一个工作语言),状态灯不再谎报「已启用」。判定逻辑抽成lib/translationTarget.ts,与后端同一套规则。 ## 验证 - 后端 6 个单测 + 前端 9 条断言,钉住「多工作语言不拦」「简→繁不误判」两条边界 -cargo check/cargo test --lib/npm test(pretest自动跑npm run build) 全绿 - 本地装机实测 🤖 Generated with Claude Code ___ ### PR Type Bug fix ___ ### Description - Centraltranslation_effectiveguard prevents no-op LLM translations. - Sets flag only when translation is genuinely effective. - Warns users when target equals sole working language. - Adds tests for backend and frontend translation guards. ___ ### Diagram Walkthroughmermaid flowchart LR A["Shift pressed / overlay start"] --> B["translation_effective gate"] B -->|"not effective"| C["plain polish (no LLM)"] B -->|"effective"| D["translation mode"] D --> E["same flag for capsule and dispatch"]File Walkthrough
6 files
Update translation flag comment and Android overlay gateUse translation_effective for polish/translate dispatchArm translation_active flag with effectiveness checkAdd translation_effective helper with unit testsAdd frontend translation availability helpersWarn when translation target is redundant5 files
Add English warning for redundant targetAdd Japanese warning for redundant targetAdd Korean warning for redundant targetAdd Simplified Chinese warning for redundant targetAdd Traditional Chinese warning for redundant target1 files
Add tests for translation target helpers