Skip to content

fix(ui): Orchestrate settings follow the current language - #684

Merged
Tryanks merged 2 commits into
mainfrom
fix/orchestrate-settings-language
Oct 9, 2026
Merged

Tryanks merged 2 commits into
mainfrom
fix/orchestrate-settings-language

Conversation

@Tryanks

@Tryanks Tryanks commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

After switching the UI language in Settings, the Orchestrate panel kept the previous language's add buttons and description placeholders until restart. It resolved those strings once, when it was built, instead of at render time like everything else in the panel. Switching language only re-applies the locale and refreshes the window (settings_page.rs language_row), so anything resolved early stays stale.

 ProviderModelPicker (Add trigger)
-  TriggerKind::Add(SharedString)        // label resolved by the caller at construction
+  TriggerKind::Add(&'static str)        // translation key, resolved in trigger() at render

 OrchestrateSettingsPanel
   new()
-    ProviderModelPicker::add(…, tr!("orchestrate.decisions.add"), …)
+    ProviderModelPicker::add(…, "orchestrate.decisions.add", …)
   rebuild_rows()
-    TextareaState::new(…).placeholder(tr!("orchestrate.children.description_placeholder"))
+    TextareaState::new(…)
   render()
+    for each row: if textarea placeholder ≠ tr!(description_placeholder) → set_placeholder

The textarea state owns its placeholder, so the panel refreshes it in render when it differs. The composer does the same thing (applied_placeholder → set_placeholder). ProviderModelPicker::add has one caller, this panel. No new type, field or abstraction.

Evidence

Synthetic profile (TCODE_DATA_DIR throwaway, HOSTNAME="Sample desktop"), language set to 简体中文, then Settings → General → Language → English, then Orchestrate, with no restart. The desktop pair has the first collaboration description cleared so its placeholder shows. The phone pair shows only the Add button fix: in it the description is not cleared, so no placeholder is visible. The placeholder is covered by the regression test below.

  • Before (origin/main d1b3438): the "Add" button stays Chinese on both. On desktop, the placeholder also stays Chinese.
    before desktop
    before phone
    After: "Add collaboration model" shows right after the switch on both, and on desktop the English placeholder shows too. Through the accessibility tree, all four description placeholders and "Add execution model" also read English on both shells.
    after desktop
    after phone

Regression test, added: orchestrate_settings::tests::switching_language_relocalizes_the_description_placeholder. It uses the existing Settings test seam: TestLocaleGuard, WorkspaceStore::new_attached and store::tests::seed_full_scope, as in archived_delete_uses_response_worktree_sharing_and_preserves_the_cleanup_choice.

apply_locale(zh-CN); mount OrchestrateSettingsPanel (built as SettingsPage::new builds it); draw
  assert row[0].description placeholder == tr!(description_placeholder) in zh-CN
apply_locale(English); window.refresh(); draw      // the two calls the language row makes
  assert English ≠ zh-CN string
  assert row[0].description placeholder == tr!(description_placeholder) in English

The test mounts the panel itself rather than the whole SettingsPage. Reading the row textareas from a SettingsPage test would mean widening SettingsPage.orchestrate_panel and OrchestrateSettingsPanel.child_rows for the test alone. Mounting the panel tests the same code: SettingsPage::new builds this panel the same way, and the language row makes the same two calls.

It fails on origin/main (main's two production files, with this test module appended):

FAIL orchestrate_settings::tests::switching_language_relocalizes_the_description_placeholder
assertion `left == right` failed
  left: "描述模型优势、适合任务、局限,以及不同思考程度的选择建议…"
 right: "Describe the model’s strengths, suitable tasks, limits, and how to choose among its reasoning efforts…"

It passes on this branch. No test was changed or deleted.

Checks run on the final commit:

  • cargo fmt --all --check: clean
  • cargo clippy --workspace --all-targets --locked -- -D warnings: finished, no warnings
  • cargo nextest run --workspace --locked: 1094 tests run: 1094 passed, 13 skipped
  • cargo machete: no unused dependencies

Gaps: the mobile (iOS/Android) and Web builds were left to CI. Dark theme was checked on the phone shell but not attached. Narrow width is the phone shot.

  • This change alters the wire protocol, so the next release needs a
    PROTOCOL_VERSION bump: a note was added under "Unreleased" above the
    constant in crates/protocol/src/lib.rs (the number itself changes only
    when the release is cut — CONTRIBUTING.md, principle 9).

Merge Danger

Door: two-way

Blast Radius: cosmetic

UI strings only, in Settings → Orchestrate. Nothing on the wire or in persisted state changes. The per-row placeholder comparison runs on each panel render, over a handful of rows.

Closes #645

@Tryanks
Tryanks marked this pull request as ready for review October 9, 2026 11:54
@Tryanks
Tryanks enabled auto-merge (squash) October 9, 2026 11:54
@Tryanks
Tryanks merged commit d53972a into main Oct 9, 2026
7 checks passed
@Tryanks
Tryanks deleted the fix/orchestrate-settings-language branch October 9, 2026 12:07
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.

Settings → Orchestrate keeps the previous language until restart

1 participant