Skip to content

fix(ios): localize Settings accessibility labels#105859

Merged
steipete merged 2 commits into
mainfrom
fix/apple-i18n-accessibility-label
Jul 13, 2026
Merged

fix(ios): localize Settings accessibility labels#105859
steipete merged 2 commits into
mainfrom
fix/apple-i18n-accessibility-label

Conversation

@steipete

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where localized Settings action accessibility labels could fall back to raw English, and where the Mac app i18n packaging guard failed after the last guarded wrapper was removed.

Why This Change Was Made

Keep localized label keys typed as LocalizedStringKey, wrap them explicitly for SwiftUI accessibility lookup, and guard against both raw String signatures and direct raw accessibility labels.

User Impact

VoiceOver receives localized Settings action labels. Mac app packaging no longer fails on the stale guard invariant.

Evidence

  • corepack pnpm apple:i18n:check
  • corepack pnpm test test/scripts/apple-app-i18n.test.ts (13 passing)
  • Blacksmith Testbox focused proof
  • Autoreview: clean, no actionable findings

@openclaw-barnacle openclaw-barnacle Bot added app: ios App: ios scripts Repository scripts size: XS maintainer Maintainer-authored PR labels Jul 13, 2026
@steipete
steipete force-pushed the fix/apple-i18n-accessibility-label branch from af978e9 to 401ad0f Compare July 13, 2026 02:12
@clawsweeper

clawsweeper Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 12, 2026, 10:29 PM ET / July 13, 2026, 02:29 UTC.

Summary
Changes iOS Settings action titles to localized SwiftUI values, strengthens Apple i18n guards, and refreshes the generated native localization inventory.

PR surface: Other +2. Total +2 across 3 files.

Reproducibility: yes. from source, but not from a live device: the gateway action accepted a raw String and passed it directly to the accessibility-label overload, while no native VoiceOver reproduction was attached.

Review metrics: none identified.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦐 gold shrimp
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Complete the queued iOS build and in-progress macOS Swift checks on head 401ad0fc270a00ab5cb915b0210b5eafd17e6c20.
  • Capture a redacted non-English VoiceOver before/after recording or accessibility output for one affected Settings action.

Risk before merge

  • [P2] The PR body provides focused scanner and test results but no native VoiceOver before/after evidence showing the localized announcement on a non-English device.
  • [P1] The Apple-specific build matrix is not complete yet: ios-build is queued and macos-swift is still running on the reviewed head.

Maintainer options:

  1. Decide the mitigation before merge
    Land the typed localized-title change and matching scanner guard after Apple CI completes, ideally with a redacted device or simulator VoiceOver demonstration confirming the spoken non-English labels.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] The patch has no actionable code defect, but its protected maintainer label and incomplete Apple checks require normal human merge review rather than automated repair.

Security
Cleared: The SwiftUI typing, scanner patterns, and generated inventory changes introduce no concrete security or supply-chain concern.

Review details

Best possible solution:

Land the typed localized-title change and matching scanner guard after Apple CI completes, ideally with a redacted device or simulator VoiceOver demonstration confirming the spoken non-English labels.

Do we have a high-confidence way to reproduce the issue?

Yes from source, but not from a live device: the gateway action accepted a raw String and passed it directly to the accessibility-label overload, while no native VoiceOver reproduction was attached.

Is this the best way to solve the issue?

Yes; typing the title as LocalizedStringKey at the shared helper boundary and guarding against recurrence is narrower and more maintainable than localizing individual call sites independently.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against e9e7d385e013.

Label changes

Label changes:

  • add P2: This is a bounded iOS accessibility-localization bug affecting Settings actions, with limited blast radius and no evidence of data loss, security exposure, or core-runtime failure.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The external-contributor proof gate does not apply because steipete is listed as an official repository maintainer; nevertheless, native VoiceOver evidence would materially strengthen the user-impact claim.

Label justifications:

  • P2: This is a bounded iOS accessibility-localization bug affecting Settings actions, with limited blast radius and no evidence of data loss, security exposure, or core-runtime failure.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The external-contributor proof gate does not apply because steipete is listed as an official repository maintainer; nevertheless, native VoiceOver evidence would materially strengthen the user-impact claim.
Evidence reviewed

PR surface:

Other +2. Total +2 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 3 235 233 +2
Total 3 235 233 +2

What I checked:

  • Localized action title: The gateway action helper changes its title from String to LocalizedStringKey and constructs the accessibility label from Text(title), keeping the visible and spoken label on SwiftUI's localized path. (apps/ios/Sources/Design/SettingsProTabSections.swift:767, 401ad0fc270a)
  • Sibling Settings labels: The other Settings row and toggle accessibility labels are made explicit Text values while retaining their existing localized title type. (apps/ios/Sources/Design/SettingsProTabSections.swift:874, 401ad0fc270a)
  • Regression guard: The Apple localization scanner adds checks for a raw String gateway-action signature and direct .accessibilityLabel(title) usage in this Settings module. (scripts/apple-app-i18n.ts:281, 401ad0fc270a)
  • Generated inventory: The second commit refreshes the checked-in native source inventory after the guard and source changes; the provided diff shows metadata line updates rather than a new localization contract. (apps/.i18n/native-source.json:539, 401ad0fc270a)
  • Automated validation: GitHub reports the native-i18n, lint, production-type, guard, security, and broad Node checks successful on the current head; ios-build remains queued and macos-swift remains in progress. (401ad0fc270a)
  • Repository ownership map: The repository contribution guide identifies Peter Steinberger (steipete) as an official project maintainer, providing an independent ownership signal beyond authorship of this PR. (CONTRIBUTING.md, e9e7d385e013)

Likely related people:

  • steipete: The repository maintainer map names Peter Steinberger, and he authored both focused commits for the iOS Settings and Apple localization-guard surfaces. (role: official repository maintainer and Apple app contributor; confidence: high; commits: 3e075abd1ec3, 401ad0fc270a; files: apps/ios/Sources/Design/SettingsProTabSections.swift, scripts/apple-app-i18n.ts, apps/.i18n/native-source.json)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jul 13, 2026
@steipete
steipete merged commit c81ae04 into main Jul 13, 2026
118 of 123 checks passed
@steipete
steipete deleted the fix/apple-i18n-accessibility-label branch July 13, 2026 02:33
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

steipete added a commit that referenced this pull request Jul 13, 2026
…ility labels

0aabf56 relaxed the wrapper contract to .accessibilityLabel(title) while
the same pattern stayed in RAW_LOCALIZATION_BYPASSES, and #105859 then
restored Text(title) in SettingsProTabSections.swift, leaving main's
apple-app-i18n guard failing in both directions. Revert the contract to the
original required pattern; both guard tables validate against current main.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 13, 2026
* fix(ios): preserve localized accessibility labels

* chore(i18n): refresh native source inventory
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 13, 2026
…ility labels

488277d relaxed the wrapper contract to .accessibilityLabel(title) while
the same pattern stayed in RAW_LOCALIZATION_BYPASSES, and openclaw#105859 then
restored Text(title) in SettingsProTabSections.swift, leaving main's
apple-app-i18n guard failing in both directions. Revert the contract to the
original required pattern; both guard tables validate against current main.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: ios App: ios maintainer Maintainer-authored PR P2 Normal backlog priority with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. scripts Repository scripts size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant