feat: Full localization support (8 languages)#495
feat: Full localization support (8 languages)#495Lincb522 wants to merge 6 commits intosteipete:mainfrom
Conversation
- Add Localizable.xcstrings with 437 translation keys for en, zh-Hans, zh-Hant, ja, ko, fr, de, es - Add AppLanguage enum with per-app language switching via UserDefaults - Add language picker to General preferences with restart prompt - Configure Package.swift with defaultLocalization and Widget resources - Update package_app.sh to compile .xcstrings into .lproj bundles and inject CFBundleLocalizations into Info.plist
Apply localization to ~45 source files: - All Provider implementation and login flow files (19 providers) - Preferences panes (General, Display, Advanced, About, Debug, Providers) - Provider detail/sidebar/error views - Menu bar items and status item controller - Menu card, cost/credits history charts, usage pace text - Status indicators, overview tab, and cookie source UI Translations provided by AI; native speaker review welcome.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 709d1847e7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Scripts/package_app.sh
Outdated
| xcrun xcstringstool compile "$xcs" --output-directory "$PARENT_DIR" 2>/dev/null || true | ||
| rm -f "$xcs" |
There was a problem hiding this comment.
Fail build when xcstring compilation fails
In Scripts/package_app.sh, xcstringstool failures are explicitly ignored (|| true) and the source catalog is deleted immediately afterward. If xcrun/xcstringstool is unavailable or a catalog has a compile error, packaging still succeeds but all localized resources from that .xcstrings file are silently dropped from the shipped app, which makes localization regressions hard to detect and ship.
Useful? React with 👍 / 👎.
Sources/CodexBar/MenuCardView.swift
Outdated
| .font(.footnote) | ||
| Spacer() | ||
| Text(String(format: "%.0f%% used", min(100, max(0, self.section.percentUsed)))) | ||
| Text(String(localized: "\(Int(min(100, max(0, self.section.percentUsed))))% used")) |
There was a problem hiding this comment.
Preserve rounded percentage when localizing usage text
This replaces rounded formatting (%.0f) with Int(...), which truncates instead of rounds. For non-integer percentages (for example, 99.9), the UI now displays 99% used rather than 100% used, so the extra-usage indicator can underreport spend near thresholds.
Useful? React with 👍 / 👎.
- Fail the build when xcstringstool compile fails instead of silently discarding localized resources (P1) - Use .rounded() before Int conversion so 99.9% displays as 100% instead of being truncated to 99% (P2)
Send a system notification when any provider's usage reaches a configurable percentage (50/80/90/95%). The threshold is selectable in Preferences → General → Automation and defaults to off. The alert fires once per threshold crossing and resets when usage drops below the threshold again. Includes localized strings for all 8 languages.
6b9acdb to
533d488
Compare
- MenuDescriptor: menu actions, account/plan labels, quota text - MenuCardView: percent labels, API key limit, status messages - KeychainPromptCoordinator: all alert titles and messages - Provider implementations: placeholders, action labels, status text - Chart views: axis labels (Day, Credits, Cost, Service, Cap) - Window titles: Cursor Login, Buy Credits - Error view: Copy error, Show/Hide details - 70+ newly localized strings with translations for all 8 languages Made-with: Cursor
|
Thanks for PR @Lincb522 ! I have some comments, please take a look:
|
Instead of hardcoding the language list in Info.plist, scan the compiled .lproj directories in the app bundle and inject CFBundleLocalizations dynamically via PlistBuddy. This ensures the declared languages always match the actually available translations. Made-with: Cursor
|
Hi @ratulsarna, thanks for reviewing! I've addressed your feedback: 1. 2. Derive 3.
I've tested language switching with restart and it works consistently for the main app. The widget follows the system locale, which matches how other macOS apps handle it. Please let me know if anything else needs to be changed! |
Summary
.xcstrings)package_app.shupdated to compile.xcstringsinto.lprojbundles and injectCFBundleLocalizationsinto Info.plistWhat's included
Infrastructure
Package.swift: AddeddefaultLocalization: "en"and Widget resources configSources/CodexBar/Resources/Localizable.xcstrings: Main app string catalog (437 keys)Sources/CodexBarWidget/Resources/Localizable.xcstrings: Widget string catalogSources/CodexBar/AppLanguage.swift: Language enum +UserDefaults AppleLanguagesswitchingSettingsStorechanges: Language preference persistence + apply on launchPreferencesGeneralPane.swift: Language picker with restart promptString wrapping
MenuDescriptor,StatusItemController+Menu,MenuCardViewCostHistoryChartMenuView,CreditsHistoryChartMenuViewUsagePaceText,UsageStoreSupport,StatusItemController+ActionsWhat's NOT localized (by design)
Notes
main(commit 9d56dfd). All new providers (Kilo, OpenRouter, Ollama) are included.swift build.Test plan
swift buildpasses.lprojbundles are generated bypackage_app.sh