Skip to content

fix(v2): set LANG for pbpaste/pbcopy to prevent clipboard mojibake on macOS#5012

Open
veeceey wants to merge 5 commits intowailsapp:masterfrom
veeceey:fix/issue-4132-clipboard-encoding
Open

fix(v2): set LANG for pbpaste/pbcopy to prevent clipboard mojibake on macOS#5012
veeceey wants to merge 5 commits intowailsapp:masterfrom
veeceey:fix/issue-4132-clipboard-encoding

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 23, 2026

Fixes #4132

When a Wails app runs as a standalone macOS app (not launched from a terminal), the LANG environment variable is unset. pbpaste then defaults to an ASCII-compatible encoding, which turns non-ASCII clipboard content into garbage.

The fix ensures LANG=en_US.UTF-8 is set in the command's environment before invoking pbpaste/pbcopy, but only when LANG isn't already present — so it won't override anything the user has explicitly set.

Quick terminal demo showing the difference:

$ echo "你好世界 こんにちは" | pbcopy

$ LANG= pbpaste
Test: ???? ?????

$ LANG=en_US.UTF-8 pbpaste
Test: 你好世界 こんにちは

Summary by CodeRabbit

  • Bug Fixes
    • Improved macOS clipboard handling so copied and pasted text preserve UTF-8 characters and no longer appear garbled in packaged apps.
  • Documentation
    • Added a changelog entry noting the macOS clipboard mojibake fix.

When macOS apps are launched as standalone (not from terminal), the LANG
environment variable is unset. This causes pbpaste to default to an
ASCII-compatible encoding, resulting in mojibake for non-ASCII clipboard
content.

Fix by ensuring LANG=en_US.UTF-8 is set in the command environment when
it's not already present.

Fixes wailsapp#4132
@veeceey
Copy link
Author

veeceey commented Feb 23, 2026

Manual test results (macOS 15, M4)

Verified the fix works by testing pbpaste behavior with and without LANG:

$ echo "你好世界 こんにちは" | pbcopy

# Without LANG (simulates standalone app launch):
$ LANG= pbpaste
Test: ???? ?????

# With LANG=en_US.UTF-8 (what this PR does):
$ LANG=en_US.UTF-8 pbpaste
Test: 你好世界 こんにちは

Also confirmed that go build ./v2/internal/frontend/desktop/darwin/ compiles cleanly.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b34587e and cf15fd6.

📒 Files selected for processing (1)
  • website/src/pages/changelog.mdx

📝 Walkthrough

Walkthrough

Adds an ensureUTF8Env helper and applies it to the pbpaste and pbcopy command environments so macOS clipboard reads/writes run with LANG set to en_US.UTF-8 when LANG is unset.

Changes

Cohort / File(s) Summary
Clipboard UTF-8 Environment Fix
v2/internal/frontend/desktop/darwin/clipboard.go
Adds ensureUTF8Env() helper, imports os, and sets Cmd.Env = ensureUTF8Env(os.Environ()) for both ClipboardGetText (pbpaste) and ClipboardSetText (pbcopy). Adds explanatory comment about packaged macOS apps and LANG.
Changelog entry
website/src/pages/changelog.mdx
Adds a changelog line under "Fixed" describing the macOS clipboard mojibake fix and referencing the PR.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related issues

Suggested reviewers

  • makew0rld

Poem

🐇 I nibble at bugs beneath the moonlight,
LANG set to UTF-8, clipboard feels right.
Pastes no longer garble, copies hum bright,
A tiny rabbit hop fixed text’s flight. 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: setting LANG for pbpaste/pbcopy to fix clipboard mojibake on macOS.
Description check ✅ Passed The description covers the issue (Fixes #4132), problem context, solution approach, and includes a practical demo. The changelog was updated as required, and most template sections are addressed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
v2/internal/frontend/desktop/darwin/clipboard.go (1)

14-22: Consider os.LookupEnv for a cleaner, more idiomatic implementation.

os.LookupEnv explicitly distinguishes "not set" from "set to empty" without manual string slicing, and is the standard Go idiom for this pattern:

♻️ Proposed refactor
 func ensureUTF8Env() []string {
 	env := os.Environ()
-	for _, e := range env {
-		if len(e) > 5 && e[:5] == "LANG=" {
-			return env
-		}
+	if _, ok := os.LookupEnv("LANG"); !ok {
+		env = append(env, "LANG=en_US.UTF-8")
 	}
-	return append(env, "LANG=en_US.UTF-8")
+	return env
 }

This also correctly handles the case where LANG is set but empty (keeping the existing empty value rather than creating a duplicate entry), which the current loop misses due to the > 5 boundary.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@v2/internal/frontend/desktop/darwin/clipboard.go` around lines 14 - 22,
Replace the manual loop in ensureUTF8Env with os.LookupEnv: use
os.LookupEnv("LANG") to detect whether LANG is present (allowing an existing
empty value to be preserved) and, if not present, append "LANG=en_US.UTF-8" to
os.Environ(); ensure you return the original env unchanged when LANG is set
(including empty string) to avoid duplicating entries and to follow Go idioms.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@v2/internal/frontend/desktop/darwin/clipboard.go`:
- Line 17: The guard that checks environment entries uses len(e) > 5 && e[:5] ==
"LANG=" which misses the exact "LANG=" entry; update the check in the loop over
environment entries (the variable e) to use a correct boundary such as len(e) >=
5 && e[:5] == "LANG=" or, better, strings.HasPrefix(e, "LANG=") so entries equal
to "LANG=" are treated as matches and the function will early-return instead of
appending a second LANG variable.

---

Nitpick comments:
In `@v2/internal/frontend/desktop/darwin/clipboard.go`:
- Around line 14-22: Replace the manual loop in ensureUTF8Env with os.LookupEnv:
use os.LookupEnv("LANG") to detect whether LANG is present (allowing an existing
empty value to be preserved) and, if not present, append "LANG=en_US.UTF-8" to
os.Environ(); ensure you return the original env unchanged when LANG is set
(including empty string) to avoid duplicating entries and to follow Go idioms.

Replace manual string slicing with os.LookupEnv which is more idiomatic
and correctly handles the edge case where LANG is set to an empty string.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@v2/internal/frontend/desktop/darwin/clipboard.go`:
- Around line 14-20: The function ensureUTF8Env correctly uses
os.LookupEnv("LANG") to detect presence (including an empty LANG=) and only
appends "LANG=en_US.UTF-8" when absent, so no code change is required; keep the
current implementation (ensureUTF8Env) as-is and approve the change.

@leaanthony
Copy link
Member

Thanks 🙏 Please could you add an entry to the changelog located at website/src/pages/changelog.mdx?

@veeceey
Copy link
Author

veeceey commented Feb 28, 2026

Added changelog entry. Thanks for the review!

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.

Incorrect Clipboard Text Encoding when LANG Environment Variable is Empty on macOS

2 participants