Skip to content

fix(desktop): ensure UTF-8 locale in macOS terminals - #6591

Closed
Kiri110K wants to merge 2 commits into
pingdotgg:mainfrom
Kiri110K:fix/desktop-terminal-utf8-locale
Closed

fix(desktop): ensure UTF-8 locale in macOS terminals#6591
Kiri110K wants to merge 2 commits into
pingdotgg:mainfrom
Kiri110K:fix/desktop-terminal-utf8-locale

Conversation

@Kiri110K

@Kiri110K Kiri110K commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

What Changed

Terminals opened in the macOS desktop app ran with a US-ASCII character locale instead of UTF-8.

The POSIX login-shell probe now also reads LANG, LC_ALL and LC_CTYPE, and hydrates whichever of them the launch environment is missing. If macOS still reports no character locale after that, LC_CTYPE falls back to the platform-native UTF-8 value — the same value Terminal.app uses when a region has no matching locale. Values already present in the launch environment always win. Linux gets the hydration but never the fallback, and Windows is untouched.

Why

Apps launched from Finder inherit no LANG or LC_* variables. macOS then defaults to US-ASCII, so zsh's line editor edits multi-byte input byte by byte: one backspace deletes half of a Cyrillic or accented character, and any tool that reads the locale picks an ASCII encoding.

Reading the login shell first, rather than jumping straight to the fallback, keeps the user's own locale intact — someone running ru_RU.UTF-8 keeps their language, collation and messages instead of being flattened to a bare UTF-8 ctype. The fallback only fills a gap nobody else filled, and only sets the character category, so it never overrides a language the user did choose.

On surfaces: npx t3 is started from a terminal and already inherits the locale, so the Electron launch path was the only broken one. Because the desktop app is also commonly the host server, web and mobile clients connected to it get the same fix in the terminals they open.

Verification

Before and after, reproducible on any Mac without the app:

$ env -i /bin/zsh -c 'locale charmap'
US-ASCII
$ env -i LC_CTYPE=UTF-8 /bin/zsh -c 'locale charmap'
UTF-8

zsh, bash, perl and locale all accept the bare UTF-8 ctype on Darwin without emitting warnings.

Four focused tests cover the behaviour: the fallback when the launch environment has no locale, hydration from the login shell, launch-environment values winning over the shell's, and Linux not receiving the fallback.

apps/desktop tests pass (518) and tsgo --noEmit for that package is clean.

UI Changes

Not applicable; this change has no UI surface.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (not applicable; no UI changes)
  • I included a video for animation/interaction changes (not applicable; no animation or interaction changes)

Implemented with GPT-5.6-Sol using the Codex harness in T3 Code.


Note

Low Risk
Startup-time env patching for embedded terminals only; inherited locales win and behavior is covered by focused tests with no auth or data-path changes.

Overview
Fixes US-ASCII terminals when the macOS desktop app is launched without LANG/LC_* (e.g. from Finder) by extending the POSIX login-shell environment install in DesktopShellEnvironment.

The login-shell probe now captures LANG, LC_ALL, and LC_CTYPE. If the launch environment has no non-empty locale among those three, the shell values are applied as a set so a shell LC_ALL cannot override an inherited LANG. Any locale already present in the launch environment is left unchanged. On darwin only, if there is still no locale after probing, LC_CTYPE is set to UTF-8; Linux gets hydration only, with no fallback.

Four tests cover fallback, shell hydration, inherited-locale precedence, and Linux not receiving the fallback.

Reviewed by Cursor Bugbot for commit 23981d7. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix UTF-8 locale handling in macOS terminals when no locale is inherited

  • Extends login shell probing in DesktopShellEnvironment.ts to include LANG, LC_ALL, and LC_CTYPE.
  • When none of these locale variables are present in the launch environment, all three are hydrated as a group from the login shell output.
  • On macOS, if no locale variables are found after hydration, LC_CTYPE is explicitly set to 'UTF-8' to guarantee UTF-8 character handling.
  • An existing LANG in the launch environment is never overridden by a login shell LC_ALL, preventing silent locale downgrades.

Macroscope summarized 23981d7.

Terminals opened in the macOS desktop app ran with a US-ASCII character
locale. Apps launched from Finder inherit no LANG or LC_* variables, and
macOS then falls back to US-ASCII, so zsh's line editor edits multi-byte
input byte by byte — one backspace deletes half of a Cyrillic or accented
character, and any tool that reads the locale picks an ASCII encoding.

The POSIX login-shell probe now also reads LANG, LC_ALL and LC_CTYPE and
hydrates whichever the launch environment is missing, so a user running
ru_RU.UTF-8 keeps their language and collation. When macOS still reports
no character locale after that, LC_CTYPE falls back to the platform-native
UTF-8 value, which fixes character handling without forcing a language,
collation or message locale on anyone.

Implemented with GPT-5.6-Sol using the Codex harness in T3 Code.
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ced6d1d5-98d7-4842-a5ac-186b02c01b00

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 14, 2026
Comment thread apps/desktop/src/shell/DesktopShellEnvironment.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 23981d7

This is a well-scoped bug fix that ensures UTF-8 locale handling for macOS Finder-launched apps. The implementation is defensive (only applies when no locale exists), limited to locale variables, and has comprehensive test coverage.

You can customize Macroscope's approvability policy. Learn more.

Locale variables outrank each other: LC_ALL beats LC_CTYPE beats LANG.
Hydrating them per key let the login shell's LC_ALL silently outrank a
LANG the launch environment had already set, producing a locale that
existed in neither source. A user with LANG=ru_RU.UTF-8 in .zshenv and
LC_ALL=C in .zshrc got a US-ASCII terminal they never asked for, because
only the interactive shell probe sees the .zshrc export.

The three variables are now taken as one set from a single source: if the
launch environment supplies any of them, the login shell's values are left
alone. The UTF-8 fallback moves inside that branch, where it was already
the only case that could reach it.

Reported by macroscopeapp on pingdotgg#6591.

Implemented with Claude Opus 5 using the Claude Code harness in T3 Code.
@Kiri110K

Copy link
Copy Markdown
Contributor Author

Oups, was already done in #6236

@Kiri110K Kiri110K closed this Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant