Skip to content

feat(desktop-gpui): localize the settings window and pages - #3424

Merged
richiemcilroy merged 80 commits into
mainfrom
i18n/settings-surfaces
Oct 26, 2026
Merged

richiemcilroy merged 80 commits into
mainfrom
i18n/settings-surfaces

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Localizes every Settings page in the GPUI app so that, once the language picker ships in release builds, a non-English system no longer sees a half-English Settings window.

What changed

545 new settings.* keys, translated into zh-CN, ja, fr, es, de and hi following locales/GLOSSARY.md.

  • settings_window.rs: the sidebar (account row, update links, Sign In/Out/Cancel), the Recordings and Screenshots pages (import buttons, filter tabs, empty states, row tooltips, badges, delete and corrupted-recording dialogs), and the Recording quality page (Studio tiers, Instant resolution summaries, Sharing).
  • settings_pages.rs: Shortcuts, CLI, Transcription, Experimental (including the dev-only switch-back overlay), Feedback, the Diagnostic Report, System Information, Changelog, Plan & license, Integrations (index, S3 and Google Drive), and Automations (triggers, actions, conditions, editor fields, templates).
  • store.rs: the display labels of the settings_enum! options. The stored JSON values are unchanged. UpdateChannel stays Stable/Nightly, as the glossary requires.

Sentences rewritten as whole messages

  • Shortcut descriptions. These were one phrase built from fragments, then capitalized for the row description and spliced into "Saved. Press ⌘⇧4 in any app to ...". Each of the 30 effects is now a pair of whole messages: effect.*, which completes the saved message, and sentence.*, the row description. Languages need different grammatical forms for the two uses.
  • Separate messages instead of fragments for:
    • the Recordings empty state (six messages instead of "No"/"No matching" + tab)
    • "Runs for every ..." (one message per trigger, instead of a lowercased phrase)
    • "Saved ... Removed from X."
    • "Cached/Updated {time}"
    • "{n} item(s)", now a plural table
  • Inline elements. The CLI sentence around the cap code span and the S3 sentence around the guide link use a {command}/{guide} placeholder. The code formats the message with a marker and splits it around the marker, so each language can put the element wherever its grammar needs.
  • Uppercase group labels. The automation group labels are stored uppercase in the catalog. This replaces a per-frame to_uppercase(), and scripts without letter case keep their normal text.

Live language switching

  • Placeholders are now set while the page paints, the same way the main window does it:
    • the two library search fields
    • the transcription term field
    • the feedback text field
    • the license key field
    • the automation editor fields that hold words (rule name, window title, organization ID, project folder)
  • Const tables hold fn() -> &'static str, so they resolve at render time, not at startup. This covers the Studio tiers, Instant summaries, outcome cards, S3 fields and provider, and the capture-target, clipboard and compression options.

Deliberately left in English

  • Product and plan names: Cap Pro, Cap Free, Studio, Instant, Google Drive, AWS S3, Cloudflare R2, Supabase, MinIO, plus the MP4/GIF/MOV, POST/PUT/GET and 720p/1080p/1440p/4K labels.
  • Example values in placeholders: S3 keys, endpoints, paths, the webhook body.
  • The project-name preview values ("Instant", "Window", "Safari"). They are file-name values.
  • Diagnostic report data. The missing-sidecar reason is written into the report in English. The page swaps in the translated no_cli_sync when it displays it.
  • Logs and engine errors. Logs, the profile fetch errors (log-only), "Failed to serialize the report: {error}", and technical {error} text from the engine or the network.
  • Formatting: byte sizes (B/KB/MB/GB) and dates keep their current formatting. There is no locale-aware formatter in src/i18n yet.
  • Other files: the upload status badge label (upload/queue.rs) and the diagnostic mode/stage labels (diagnostics.rs) belong to other files and are not part of this change.

English is unchanged

  • Plain keys. src/i18n/settings_surface_tests.rs pairs every plain key with the literal it replaced. A key count keeps it complete. Separately, every plain English value was checked to appear verbatim as a string literal in the files on main.
  • Parameterized and plural keys. Each one is asserted against the format! it replaced, with plural cases 0, 1, 2 and 5.
  • Shortcut effects. settings_pages's shortcut_effects_match_the_sentences_they_replaced keeps a copy of the old fragment assembly. It checks every action against every after-capture setting, Instant link setting and mode. Each phrase must equal the old assembly, and each sentence must equal the old capitalized form.
  • Existing tests for the empty states, account name, rule names and templates still pass unchanged.
  • src/i18n/tests.rs gets one filter line, so its key count skips the settings keys. Their pairs live in the new test file.

Fit

  • Sidebar buttons and select options: Sign In/Out/Cancel and the post-deletion/main-window select options carry max_px budgets checked by translations_fit_their_width_budgets.
  • Sidebar update link now truncates.
  • CLI path labels use a minimum width instead of a fixed 64px, so longer labels push the value over instead of overflowing. The English layout is identical.

CI

CI run 40380983725 passed: the GPUI builds and the app tests on macOS arm64, macOS Intel, Linux and Windows, plus Format (Cargo). The repo's Clippy job covers only the root workspace, so it skips apps/desktop-gpui.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no new actionable issue was established.

Summary

Localizes the Settings pages across seven catalogs and adds checks that preserve the existing English messages.

  • Settings pages show translated labels and messages in seven languages.
  • The app menu adds actions for opening recent recordings and getting help.
  • The tray lets people choose a recording mode and use capture shortcuts.
  • People can choose whether updates download automatically, wait, or never download.
  • Linux camera capture avoids copying each frame's input bytes and reuses FFmpeg buffers.
  • Several platform and module edits keep existing behavior unchanged.

Reviews (3) · Last reviewed commit: "Merge settings i18n" · Reviewed by Greptile

ItsEeleeya and others added 30 commits October 17, 2026 04:50
Move the Cap menu onto AppKit: the model in `menus.rs` gains Check for
Update, Preferences…, Help destinations, Open File… and Import Media…, and
`platform.rs` patches the standard items after gpui installs the bar —
About becomes `orderFrontStandardAboutPanel:` (the gpui action and its
panel plumbing are gone), autoenables is off so the model owns the enabled
state, and the File menu gets the NSDocumentController-backed Open Recent
list fed by `add_recent_document` on every editor open.

Check for Update resolves to three states (check / download / restart)
and is now rewritten in the live `NSMenuItem` by row position rather than
reinstalling the menu bar, so an open menu survives a status change; the
version and the macOS download percentage ride an `NSMenuItemBadge` on
macOS 14+, and the other platforms only rebuild when the state changes.

Bumps the app to objc2 0.6.5 / objc2-app-kit 0.3.2 / block2 0.6 and
migrates the native code to those bindings.
Give the tray its own AppKit menu: a mode picker (the current mode as a
section header with the mode icons on macOS 14+, the ✓-ticked Recording
Mode submenu on older macOS and on Windows), record/take-screenshot rows,
Previous ▸ with cover-cropped thumbnails, Import Media…, Settings and
Upload Logs, plus the version and the SF Symbols for each row.

The Previous thumbnails reuse the Recents thumbnail cache for JPEG
sources instead of decoding full-resolution originals, which is what the
warm-scan tests cover, and the header follows the palette's highlighted
row in italic.
Fix the tray row's Settings glyph (`gear`, not `gearshape`) and the macOS
26 window symbol, document the File menu (Open File…, Import Media…, Open
Recent), the Help destinations and the live update row.
# Conflicts:
#	.github/workflows/ci.yml
#	apps/chrome-extension/src/offscreen/recorder.test.ts
#	apps/desktop-gpui/kernels/Cargo.toml
#	apps/desktop-gpui/kernels/src/thumbnail.rs
#	apps/desktop-gpui/src/app_windows.rs
#	apps/desktop-gpui/src/camera_blur_portable.rs
#	apps/desktop-gpui/src/controls_window.rs
#	apps/desktop-gpui/src/editor_edits.rs
#	apps/desktop-gpui/src/editor_window.rs
#	apps/desktop-gpui/src/library.rs
#	apps/desktop-gpui/src/main.rs
#	apps/desktop-gpui/src/main_window.rs
#	apps/desktop-gpui/src/menus.rs
#	apps/desktop-gpui/src/mode_select_window.rs
#	apps/desktop-gpui/src/platform.rs
#	apps/desktop-gpui/src/settings_window.rs
#	apps/desktop-gpui/src/target_thumbnails.rs
#	apps/desktop-gpui/src/tray.rs
#	apps/media-server/src/__tests__/lib/media-routes-real-world.integration.test.ts
#	apps/media-server/src/__tests__/lib/recording-verification.integration.test.ts
#	apps/media-server/src/__tests__/lib/storage-upload.test.ts
#	apps/media-server/src/__tests__/routes/lifecycle.test.ts
#	apps/media-server/src/lib/media-video.ts
#	apps/media-server/src/lib/recording-packet-proof.ts
#	apps/media-server/src/lib/recording-timing.ts
#	apps/media-server/src/routes/video.ts
#	apps/mobile/app/(tabs)/upload.tsx
#	apps/mobile/src/screens/dashboard-upload-visibility.test.tsx
#	apps/web/__tests__/unit/add-folder-videos.test.ts
#	apps/web/__tests__/unit/analytics-chart-dates.test.ts
#	apps/web/__tests__/unit/desktop-recording-source.test.ts
#	apps/web/__tests__/unit/finalize-desktop-recording.test.ts
#	apps/web/__tests__/unit/folder-access.test.ts
#	apps/web/__tests__/unit/loom-import-start.test.ts
#	apps/web/__tests__/unit/media-processing-workflows.test.ts
#	apps/web/__tests__/unit/media-server-progress.test.ts
#	apps/web/__tests__/unit/mobile-email-session.test.ts
#	apps/web/__tests__/unit/notification-read-state.test.ts
#	apps/web/__tests__/unit/s3-bucket-connections.test.ts
#	apps/web/__tests__/unit/segment-playlist-route.test.ts
#	apps/web/__tests__/unit/video-pipeline-recovery.test.ts
#	apps/web/__tests__/unit/video-processing-recovery.test.ts
#	apps/web/actions/folders/folder-access.ts
#	apps/web/actions/loom.ts
#	apps/web/actions/notifications/mark-as-read.ts
#	apps/web/actions/spaces/get-space-videos.ts
#	apps/web/app/(org)/dashboard/analytics/components/ChartArea.tsx
#	apps/web/app/s/[videoId]/_components/utils/parse-transcript-vtt.ts
#	apps/web/lib/desktop-recording-source-checkpoint.ts
#	apps/web/lib/desktop-recording-source.ts
#	apps/web/lib/loom-import-start.ts
#	apps/web/lib/loom-import-upload.ts
#	apps/web/lib/loom-media-dispatch.ts
#	apps/web/lib/video-pipeline-recovery.ts
#	apps/web/lib/video-processing-recovery.ts
#	apps/web/workflows/finalize-desktop-recording.ts
#	apps/web/workflows/import-loom-video.ts
#	crates/enc-ffmpeg/src/mux/ogg.rs
#	crates/enc-ffmpeg/src/video/h264.rs
#	crates/enc-ffmpeg/src/video/h264_packet.rs
#	crates/enc-ffmpeg/src/video/packed_yuv.rs
#	crates/project/src/caption_timing/projection_tests.rs
#	crates/project/src/configuration.rs
#	crates/project/src/configuration/style_resolution_tests.rs
#	crates/recording/src/instant_recording/linux_camera.rs
#	crates/recording/src/screenshot.rs
#	crates/rendering/src/frame_pipeline.rs
#	crates/rendering/src/lib.rs
#	crates/scap-targets/src/platform/linux.rs
#	packages/database/types/metadata.ts
#	packages/sdk-recorder/__tests__/recorder-options.test.ts
#	packages/sdk-recorder/src/index.ts
#	packages/web-backend/src/S3Buckets/S3ConnectionPool.ts
#	scripts/prepare-gpui-dependency.sh
#	scripts/prepare-gpui-dependency.test.mjs
ItsEeleeya and others added 17 commits October 26, 2026 19:47

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Capy found no issues.

View 1 other finding in Capy.

Open in Capy

@vercel

vercel Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cap-status Ready Ready Preview Oct 26, 2026 8:40pm UTC

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Capy found no issues.

Open in Capy

@richiemcilroy

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread apps/desktop-gpui/src/menus.rs
Comment thread apps/desktop-gpui/src/hotkeys.rs
@richiemcilroy

Copy link
Copy Markdown
Member Author

@greptileai review

@richiemcilroy
richiemcilroy merged commit 5183a4d into main Oct 26, 2026
63 checks passed

This branch was successfully deployed

2 active deployments
Preview – cap-web — 4a9b312d Deployed Oct 26, 2026 by vercel[bot]
Preview – cap-status — 4a9b312d Deployed Oct 26, 2026 by vercel[bot]
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.

3 participants