Skip to content

Improve Simplified Chinese (zh-Hans) localization for visible UI#1145

Merged
steipete merged 9 commits into
steipete:mainfrom
Yuxin-Qiao:fix-zh-hans-visible-ui-localization
May 26, 2026
Merged

Improve Simplified Chinese (zh-Hans) localization for visible UI#1145
steipete merged 9 commits into
steipete:mainfrom
Yuxin-Qiao:fix-zh-hans-visible-ui-localization

Conversation

@Yuxin-Qiao
Copy link
Copy Markdown
Contributor

Summary

Improve Simplified Chinese (zh-Hans) localization quality for visible CodexBar UI.

This PR focuses on user-visible zh-Hans polish in menu/card/dashboard areas:

  • menu actions and labels
  • usage/pace labels
  • storage/cost/credits and chart helper text
  • cleanup panel visible labels
  • MiniMax visible usage detail labels in menu UI

It fixes mixed Chinese/English labels in visible UI paths by routing labels through localization, adding missing keys, and polishing Simplified Chinese terminology.

Scope

  • No new language added
  • zh-Hant untouched
  • No provider data semantics changes
  • Product/provider/model names remain unchanged
  • Model usage keeps token; API/auth contexts use 令牌

Files

21 files changed, centered on:

  • Sources/CodexBar/Resources/en.lproj/Localizable.strings
  • Sources/CodexBar/Resources/zh-Hans.lproj/Localizable.strings
  • visible UI localization call sites
  • formatting helpers used by visible menu/card/chart UI

Validation

  • plutil -lint Sources/CodexBar/Resources/en.lproj/Localizable.strings
  • plutil -lint Sources/CodexBar/Resources/zh-Hans.lproj/Localizable.strings
  • ./Scripts/lint.sh lint
  • swift build --target CodexBarCore
  • swift test --filter Localization
  • git diff --check

Local proof

Tested with a freshly built local app using appLanguage = zh-Hans.

The app process path was confirmed as the local PR worktree build:
/Users/yuxinqiao/Developer/CodexBar-zh-hans-visible-ui/CodexBar.app

and not /Applications/CodexBar.app.

Local proof screenshots were captured under artifacts/ for manual review. They contain local account/session/usage details, so they were not committed or uploaded unredacted.

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 25, 2026

Codex review: needs maintainer review before merge. Reviewed May 26, 2026, 4:40 AM ET / 08:40 UTC.

Summary
This PR routes visible menu/card/dashboard and UsageFormatter labels through localization, expands en/zh-Hans string tables, polishes Simplified Chinese terminology, and adds focused localization tests.

Reproducibility: not applicable. as a bug reproduction; this is a localization polish PR. The changed behavior is source-reviewable and the contributor provided a redacted real-app zh-Hans screenshot after the fix.

Review metrics: 3 noteworthy metrics.

  • Changed surface: 31 files, +1013/-166. The change spans shared UI, core formatting, resources, and tests, so maintainer review should treat it as a broad localization sweep.
  • String resource delta: 169 en keys added; 165 zh-Hans keys added; 10 zh-Hans entries changed. Large string-table changes carry placeholder, fallback, and wording compatibility risk beyond normal CI.
  • Test surface: 2 test files added, 5 test files changed. The PR includes focused regression coverage for dynamic labels and formatter localization, which reduces but does not eliminate UI compatibility risk.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster ✨ media proof bonus
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:

  • Wait for the current CI run to complete cleanly.
  • Have a maintainer spot-check the zh-Hans wording and English/system-language fallback behavior before merge.

Risk before merge

  • Head CI was still in progress at review time, so maintainers should wait for the required checks before merging.
  • The branch rewires shared formatter and menu string resolution across existing visible UI, so maintainers should accept the English/system-language fallback and zh-Hans wording compatibility risk before merge.

Maintainer options:

  1. Merge after CI and language spot-check (recommended)
    If checks complete cleanly and maintainers are comfortable with the shared formatter/menu localization sweep, this can land as the zh-Hans visible UI pass.
  2. Pause for narrower localization batches
    If the broad surface feels too risky, ask for the formatter bridge and visible copy changes to be split into smaller PRs.

Next step before merge
No automated repair target remains; a maintainer should wait for CI and decide whether the broad localization compatibility risk is acceptable.

Security
Cleared: No security or supply-chain concern was found; the diff touches app UI localization, string resources, tests, and a core formatting helper without new dependencies, scripts, permissions, or secret handling.

Review details

Best possible solution:

Land the localization sweep after CI finishes and a maintainer accepts the broad UI wording/compatibility risk, preserving provider semantics and keeping any further polish as narrow follow-ups.

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

Not applicable as a bug reproduction; this is a localization polish PR. The changed behavior is source-reviewable and the contributor provided a redacted real-app zh-Hans screenshot after the fix.

Is this the best way to solve the issue?

Yes, this is a maintainable direction because it reuses the existing L(...) resource-bundle path and adds focused formatter/label tests. The remaining decision is whether maintainers accept the broad wording and compatibility surface in one PR.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 7c751570b7e9.

Label changes

Label justifications:

  • P2: This is a normal-priority user-visible localization improvement with limited blast radius but broad UI touch points.
  • merge-risk: 🚨 compatibility: The PR changes shared formatter and menu localization behavior that existing users see in current English/system-language and zh-Hans UI paths.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (screenshot): The PR includes inspected screenshot proof from a freshly built local app with appLanguage set to zh-Hans, showing visible Simplified Chinese menu/card UI after the fix.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR includes inspected screenshot proof from a freshly built local app with appLanguage set to zh-Hans, showing visible Simplified Chinese menu/card UI after the fix.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR includes inspected screenshot proof from a freshly built local app with appLanguage set to zh-Hans, showing visible Simplified Chinese menu/card UI after the fix.
Evidence reviewed

What I checked:

  • Repository policy read: Read the full target AGENTS.md; its SwiftPM, focused-test, and UI/runtime validation guidance was applied to this PR review. (AGENTS.md:1, 7c751570b7e9)
  • Current main gap: Current main still has unlocalized visible call sites and lacks the new UsageFormatter localization provider hook, so the PR is not already implemented on main. (7c751570b7e9)
  • Formatter localization implementation: The PR adds configurable localization and locale providers in UsageFormatter and uses them for reset, updated, credit, and percent suffix text. (Sources/CodexBarCore/UsageFormatter.swift:15, 8bdac15cef0b)
  • App localization bridge: The app configures UsageFormatter to resolve through the CodexBar resource bundle and appLanguage locale. (Sources/CodexBar/Localization.swift:115, 8bdac15cef0b)
  • String table coverage: The PR adds visible UI keys for dynamic cost, reset, pace, storage, cleanup, and MiniMax labels in both en and zh-Hans resources. (Sources/CodexBar/Resources/zh-Hans.lproj/Localizable.strings:649, 8bdac15cef0b)
  • Real behavior proof: Downloaded and inspected the redacted screenshot from the PR comment; it shows a freshly built CodexBar menu rendering visible Simplified Chinese menu/card labels. (8bdac15cef0b)

Likely related people:

  • steipete: Current-main blame for Localization.swift, UsageFormatter.swift, MenuCardView+Costs.swift, and MenuCardView+MiniMax.swift points to the v0.29.1/main setup commits by Peter Steinberger. (role: current-main introducer and recent area contributor; confidence: high; commits: 333d584a4950, 7c751570b7e9; files: Sources/CodexBar/Localization.swift, Sources/CodexBarCore/UsageFormatter.swift, Sources/CodexBar/MenuCardView+Costs.swift)
  • Yuxin-Qiao: The same contributor previously had a merged MiniMax quota-card PR touching MenuCardView+MiniMax.swift and MiniMax usage parsing, which overlaps one of the visible UI surfaces localized here. (role: MiniMax feature contributor and adjacent localization contributor; confidence: medium; commits: 357da59c6b83, 8358a4942884, aaa3576fe1ff; files: Sources/CodexBar/MenuCardView+MiniMax.swift, Sources/CodexBarCore/Providers/MiniMax/MiniMaxUsageFetcher.swift, Tests/CodexBarTests/MiniMaxProviderTests.swift)
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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 253c0499cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


public enum UsageFormatter {
private static func localized(_ key: String) -> String {
NSLocalizedString(key, tableName: "Localizable", bundle: .main, value: key, comment: "")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve localized strings from the CodexBar resource bundle

UsageFormatter.localized now calls NSLocalizedString with bundle: .main, but this repo’s UI localization path uses CodexBar_CodexBar.bundle (via L(...)) and an appLanguage override. In app-language modes like zh-Hans, updatedString/resetLine/creditsString can fall back to English keys because they bypass that bundle selection logic, so this change leaves visible strings untranslated in those paths.

Useful? React with 👍 / 👎.

Comment on lines +35 to +39
if provider == .bedrock {
let label = Self.bedrockLatestBillingDayLabel(from: snapshot)
if let sessionTokens {
return "\(label): \(sessionCost) · \(sessionTokens) tokens"
return String(format: L("Today: %@ · %@ tokens"), sessionCost, sessionTokens)
}
return "\(label): \(sessionCost)"
return String(format: L("Today: %@"), sessionCost)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep Bedrock session label tied to latest billing day

For Bedrock, sessionCost comes from the latest available billing entry, which can lag behind today; replacing the Bedrock-specific label with a hardcoded Today misdates the number whenever AWS Cost Explorer is delayed. That makes the shown daily spend inaccurate from the user’s perspective even though the numeric value is from an earlier day.

Useful? React with 👍 / 👎.

Comment on lines +53 to +55
return String(format: L("Last 30 days: %@ · %@ tokens"), monthCost, monthTokens)
}
return "\(windowLabel): \(monthCost)"
return String(format: L("Last 30 days: %@"), monthCost)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Respect configured history window in token usage summary

The month summary line is now hardcoded to Last 30 days, but this snapshot already carries a configurable historyDays window (1–365). When users set a non-30-day history window, the label no longer matches the aggregated cost/token values, which is misleading for usage analysis.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 25, 2026
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels May 25, 2026
@Yuxin-Qiao
Copy link
Copy Markdown
Contributor Author

proof-main-after-fix-1-redacted-safe Added redacted real UI proof for the zh-Hans visible UI localization pass.

The screenshot was captured from a freshly built local app with appLanguage = zh-Hans; the running app path was confirmed as the PR worktree build, not /Applications/CodexBar.app.

It shows the visible menu/card UI rendered in Simplified Chinese, including usage/pace labels, cost/storage/menu actions, and chart-related UI. Private account/session/usage details were redacted.

Recent validation after the latest fixes:

  • plutil -lint en/zh-Hans — passed
  • ./Scripts/lint.sh lint — passed
  • swift build --target CodexBarCore — passed
  • swift test --filter UsageFormatterTests — passed
  • swift test --filter UsagePaceTextTests — passed
  • swift test --filter Localization — passed
  • swift test --filter BedrockMenuCardTests — passed
  • git diff --check — passed

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 26, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 26, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels May 26, 2026
@Yuxin-Qiao
Copy link
Copy Markdown
Contributor Author

Thanks for the review.

I’ll stop making changes on this PR unless maintainers request anything else.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8bdac15cef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


func codexBarLocalizedLocale() -> Locale {
let language = appLanguageDefaults().string(forKey: "appLanguage") ?? ""
guard !language.isEmpty else { return .current }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Align fallback locale with selected localization

When appLanguage is unset, codexBarLocalizedLocale() now returns .current, but localizedBundle() falls back to available app localizations (often English). On systems whose preferred locale is unsupported (for example de-DE), this produces mixed-language output like English labels with German relative-time/date fragments in UsageFormatter and chart/detail text. This is a regression from the prior stable-English formatter behavior and will affect users running in system-language mode without an explicit app-language override.

Useful? React with 👍 / 👎.

@steipete steipete merged commit 2deb0f5 into steipete:main May 26, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. 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.

2 participants