Skip to content

Localize Foreman with Xcode 26 generated string symbols#60

Merged
kyleve merged 4 commits into
mainfrom
foreman-generated-string-symbols
Jul 6, 2026
Merged

Localize Foreman with Xcode 26 generated string symbols#60
kyleve merged 4 commits into
mainfrom
foreman-generated-string-symbols

Conversation

@kyleve

@kyleve kyleve commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Migrate the Foreman app and ForemanCore to Xcode 26 String Catalogs with generated symbols, replacing hardcoded English literals with type-safe LocalizedStringResource references (Text(.detailEmptyTitle), String(localized: .workerExitedWithCode(code:)), etc.).
  • Add Localizable.xcstrings for both targets (v1.1, manual extraction, named placeholders like %(code)lld / %(message)@). The en values match the previous literals byte-for-byte so tests asserting exact error text still pass; proper nouns (Foreman, cursor-agent) and dynamic data stay literal.
  • Wire it up: resources + STRING_CATALOG_GENERATE_SYMBOLS=YES on the Foreman target in Project.swift, and .process("Resources") on ForemanCore in Package.swift.
  • Document the workflow (module + root AGENTS.md/README.md). Verified symbol generation runs under both the Tuist/xcodebuild flow and a plain swift build (Swift 6.2 builds SwiftPM targets with the Swift Build engine), so ForemanCore compiles either way.

Test plan

  • ./swiftformat --lint
  • ./ide --no-open (Tuist generate)
  • tuist build Foreman
  • tuist test Foreman-macOS-Tests
  • swift build --target ForemanCore after rm -rf .build (confirms symbols generate under SwiftPM)

Made with Cursor

kyleve and others added 4 commits July 5, 2026 22:02
Introduce a per-module Localizable.xcstrings for the Foreman app target and
ForemanCore, wire the app target's STRING_CATALOG_GENERATE_SYMBOLS build
setting and Resources glob in Project.swift, and process ForemanCore's
Resources in Package.swift. Groundwork: catalogs are added but not yet
referenced.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace every hardcoded literal in the Foreman app views with the type-safe
LocalizedStringResource symbols generated from Localizable.xcstrings (Text(.x),
Button(.x), .help(.x), Text(.statusFailedReason(reason:)), etc.). The app name
and the cursor-agent CLI name stay literal, and dynamic data is passed as
placeholder arguments.

Co-authored-by: Cursor <cursoragent@cursor.com>
Route worker failure reasons, the scan/save/login errors and config-load
fallback, and CursorAgentLocator.NotFoundError through String(localized: .x)
against ForemanCore's catalog. The en values match the current literals
verbatim, so tests asserting exact reason/message text still pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add Localization sections to the Foreman and ForemanCore docs (catalog-first
keys, named placeholders, no bundle: .module) and note the STRING_CATALOG_
GENERATE_SYMBOLS wiring in the root AGENTS.md. Call out that symbol generation
runs only under the Tuist/xcodebuild flow, not plain swift build.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kyleve kyleve enabled auto-merge (squash) July 6, 2026 02:12
@kyleve kyleve merged commit 9b6620c into main Jul 6, 2026
3 checks passed
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.

1 participant