fix(desktop): ensure UTF-8 locale in macOS terminals - #6591
Conversation
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.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
ApprovabilityVerdict: 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.
|
Oups, was already done in #6236 |
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_ALLandLC_CTYPE, and hydrates whichever of them the launch environment is missing. If macOS still reports no character locale after that,LC_CTYPEfalls back to the platform-nativeUTF-8value — 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
LANGorLC_*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-8keeps their language, collation and messages instead of being flattened to a bareUTF-8ctype. 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 t3is 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:
zsh,bash,perlandlocaleall accept the bareUTF-8ctype 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/desktoptests pass (518) andtsgo --noEmitfor that package is clean.UI Changes
Not applicable; this change has no UI surface.
Checklist
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 inDesktopShellEnvironment.The login-shell probe now captures
LANG,LC_ALL, andLC_CTYPE. If the launch environment has no non-empty locale among those three, the shell values are applied as a set so a shellLC_ALLcannot override an inheritedLANG. Any locale already present in the launch environment is left unchanged. On darwin only, if there is still no locale after probing,LC_CTYPEis set toUTF-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
DesktopShellEnvironment.tsto includeLANG,LC_ALL, andLC_CTYPE.LC_CTYPEis explicitly set to'UTF-8'to guarantee UTF-8 character handling.LANGin the launch environment is never overridden by a login shellLC_ALL, preventing silent locale downgrades.Macroscope summarized 23981d7.