Repository navigation
Localize package display strings missing from app catalogs - #5829
Conversation
SPM package sources are not scanned by Xcode's string-catalog extraction, so display strings that live only in packages never got backfilled into the host app catalogs and rendered English-only in Japanese. Add the 40 missing keys with en+ja: - iOS (ios/cmux/Resources/Localizable.xcstrings): 22 CmuxMobileTerminal keys (shortcut settings-editor names + PgUp/PgDn keycap titles). - macOS (Resources/Localizable.xcstrings): 18 CmuxSettingsUI keys (workspace selection/badge colors, preferred editor, desktop notifications, active team, socket-password-empty, browser import hints). Keys are marked extractionState "manual" since they are package-owned and cannot be auto-extracted into the app target catalog. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdded 680 lines of localized string entries across two xcstrings resource files: general app settings, browser import, account team, notification settings, and workspace color labels in the root Resources file; terminal keyboard input accessory and shortcut name labels in the iOS cmux Resources file. All entries include English and Japanese translations with ChangesLocalization String Additions
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 21✅ Passed checks (21 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR backfills 40 string-catalog keys that SPM packages expose via
Confidence Score: 3/5The iOS changes are safe to merge as-is. The macOS changes fix Japanese but leave 18 other supported locales falling back to English for all 18 newly added settings strings. The macOS catalog already ships translations for Arabic, German, Spanish, French, Korean, and 13 other locales across thousands of strings, so the 18 new settings keys introducing an en/ja-only gap will render English copy to users in those locales — the same regression this PR is correcting for Japanese. Resources/Localizable.xcstrings needs translations for the 18 missing locales on every newly added key. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["String(localized: key, bundle: .main)"] --> B{Key in host app catalog?}
B -->|Yes - locale match| C["✅ Localized string rendered"]
B -->|Yes - en only| D["⚠️ English fallback rendered"]
B -->|No| E["⚠️ defaultValue rendered (English)"]
subgraph iOS["iOS catalog (en + ja only)"]
F["22 new keys\nterminal.shortcut.name.*"]
F --> G["✅ en ✅ ja — fully covered"]
end
subgraph macOS["macOS catalog (20 locales)"]
H["18 new keys\nsettings.* + browser.import.*"]
H --> I["✅ en ✅ ja"]
H --> J["❌ ar ❌ bs ❌ da ❌ de ❌ es ❌ fr\n❌ it ❌ km ❌ ko ❌ nb ❌ pl ❌ pt-BR\n❌ ru ❌ th ❌ tr ❌ uk ❌ zh-Hans ❌ zh-Hant"]
end
A --> iOS
A --> macOS
Reviews (1): Last reviewed commit: "Localize package display strings missing..." | Re-trigger Greptile |
| } | ||
| } | ||
| }, | ||
| "browser.import.hint.subtitle": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Import bookmarks, history, and cookies from Safari, Chrome, Firefox, Brave, Edge, or Arc. Already-imported entries are deduped automatically." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Safari、Chrome、Firefox、Brave、Edge、Arc からブックマーク、履歴、Cookie をインポートします。インポート済みの項目は自動的に重複排除されます。" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.account.activeTeam": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Active Team" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "アクティブなチーム" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.account.activeTeam.none": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "None" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "なし" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.app.preferredEditor": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Open Files With" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "ファイルを開くアプリ" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.app.preferredEditor.placeholder": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "e.g. code, zed, subl" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "例: code、zed、subl" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.automation.socketPassword.empty": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Enter a password first." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "先にパスワードを入力してください。" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.browser.import.hint.settingsNote": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Shown until you import or dismiss it on a blank tab." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "空のタブでインポートするか閉じるまで表示されます。" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.notifications.desktop.action.enable": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Enable" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "有効にする" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.notifications.desktop.sendTest": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Send Test" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "テストを送信" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.notifications.desktop.status.unknown": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Permission unknown" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "権限が不明です" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.notifications.desktop.subtitle.notDetermined": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Desktop notifications are not enabled yet." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "デスクトップ通知はまだ有効になっていません。" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.notifications.sound.custom.panelTitle": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Choose Notification Sound" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "通知音を選択" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.workspaceColors.notificationBadgeColor": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Notification Badge" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "通知バッジ" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.workspaceColors.notificationBadgeColor.reset": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Reset" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "リセット" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.workspaceColors.notificationBadgeColor.subtitle": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Color of the unread notification badge on workspace tabs." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "ワークスペースタブの未読通知バッジの色。" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.workspaceColors.selectionColor": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Selection Highlight" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "選択ハイライト" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.workspaceColors.selectionColor.reset": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Reset" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "リセット" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| "settings.workspaceColors.selectionColor.subtitle": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Background color of the selected workspace in the sidebar." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "サイドバーで選択中のワークスペースの背景色。" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
macOS catalog: 18 new keys missing translations for 18 of 20 supported locales
The macOS Localizable.xcstrings already carries full coverage for ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, and zh-Hant across a large portion of its existing strings (e.g. ko covers ~1715 strings, de/es/fr cover ~1321 each). Every one of the 18 new keys adds only en and ja entries, so users in those 18 locales will fall back to the English defaultValue for all the newly backfilled settings strings — the same class of bug this PR is fixing for Japanese.
Rule Used: Flag production user-facing text that is not fully... (source)
What
SPM package sources are not scanned by Xcode's string-catalog extraction, so display strings that live only in packages never got backfilled into the host app catalogs. They resolve via
Bundle.mainagainst the linking app's catalog, and with the key absent they rendered the EnglishdefaultValueeven in Japanese.This backfills the 40 missing keys with en+ja into the two app catalogs (additions only, no English-visible change):
ios/cmux/Resources/Localizable.xcstrings): 22CmuxMobileTerminalkeys — shortcut settings-editor names (terminal.shortcut.name.*) and thePgUp/PgDnkeycap titles.Resources/Localizable.xcstrings): 18CmuxSettingsUIkeys — workspace selection/badge colors, preferred editor, desktop notifications, active team, socket-password-empty, browser import hints.Keys are marked
extractionState: "manual"since they are package-owned and cannot be auto-extracted into the app target catalog.Audit context
All other localizing packages are fully covered:
CmuxSettings,CmuxUpdater,CmuxUpdaterUI,CmuxMobileSupport, andCmuxSwiftRenderUI(which owns its own.modulecatalog). No package that emits display strings is shared between the macOS and iOS app targets today, so there is no cross-catalog duplication gap.Verification
Only difference is visible in Japanese locale; English is unchanged. JSON validated; every package
String(localized:)key now resolves in the correct catalog.🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Backfilled package-owned display strings into the iOS and macOS app catalogs so Japanese translations render correctly instead of falling back to English. Adds 40 en+ja keys; English UI is unchanged.
ios/cmux/Resources/Localizable.xcstrings: 22CmuxMobileTerminalkeys (terminal shortcut names; PgUp/PgDn).Resources/Localizable.xcstrings: 18CmuxSettingsUIkeys (workspace colors, preferred editor, desktop notifications, active team, socket-password-empty, browser import hints).extractionState: "manual"since they live in SPM packages.Written for commit a0a82bd. Summary will update on new commits.
Summary by CodeRabbit