Skip to content

Add pt-BR + localize redesigned views + locale parity guard (supersedes #76)#101

Merged
momenbasel merged 1 commit into
momenbasel:mainfrom
edufalcao:feature/localization-pt-br
May 23, 2026
Merged

Add pt-BR + localize redesigned views + locale parity guard (supersedes #76)#101
momenbasel merged 1 commit into
momenbasel:mainfrom
edufalcao:feature/localization-pt-br

Conversation

@edufalcao
Copy link
Copy Markdown
Contributor

Summary

Supersedes #76. Rebased onto current main to pick up #70 (Arabic), #75 (FDA TCC), #80 (dashboard redesign + appearance toggle), and #83 (AI history). Retargets the localization work to the new view structure and brings every bundled locale to key parity, enforced by a new XCTest case.

Replaces #76 — the previous branch shared no history with current main and SmartScanView (which the old PR localized) has been deleted, so a fresh PR was clearer than continuing the closed thread. See #76's review comments for the full original context.

What's in this PR

New languages and infrastructure

  • Brazilian Portuguese (pt-BR) added alongside the existing en / es / ja / ar / zh-Hans / zh-Hant locales. Registered in knownRegions via xcodegen.
  • Settings → General → Language picker with System Default, English, Spanish, Japanese, Arabic, Portuguese (Brazil), Chinese (Simplified), Chinese (Traditional). Persists the choice to settings.general.appLanguage and toggles AppleLanguages (the macOS bundle-localization mechanism).
  • AppLanguage + AppLanguagePreferences extracted to PureMac/Models/AppLanguage.swift. apply(_:defaults:) only mutates AppleLanguages and never touches AppleLocale, so the user's locale-derived formatting (dates, numbers, currency) stays intact regardless of UI language choice.
  • Relaunch prompt + button after changing the language, because AppleLanguages is consumed on app startup. The relaunch uses /usr/bin/open -n so the relaunched instance picks up the new bundle.

View-level localization (retargeted to current main)

  • DashboardView (replaces the old SmartScanView): hero / scanning / completed / cleaning / cleaned states; StatCard, Suggestion, LegendDot, StorageGauge, ScanningGauge, CategoryToggleRow. Dynamic strings use String(format: String(localized: ...)) so locale-specific number formatting stays correct.
  • MainWindow: section labels (Overview / Applications / Cleanup), nav rows (Dashboard, Installed Apps, Orphaned Files), FDA toast, error alert, footer status, empty-state fallback.
  • CategoryDetailView: navigation title, toolbar buttons, sort labels, confirmation dialog, file-list header, and the new hero card.
  • AppListView / AppFilesView / OrphanListView: searchable prompts, navigation titles with counts, refresh / uninstall / remove flows, empty / loading states, context-menu actions, alert dialogs.
  • OnboardingView: intro / instructions / granted / diagnostics sub-views, including featureCard and stepRow helpers (now LocalizedStringKey-typed) and ProtectedPath labels.
  • SettingsView: tab labels, section titles, search-sensitivity options + descriptions, language picker, scheduling settings.
  • AppearancePill: .help(...) tooltip routed through LocalizedStringKey so the appearance segments are translated.

AppState test injection points

AppState's init now accepts performStartupTasks, locationsProvider, and appFileScanner so the scan-for-app-files path can be exercised by a unit test without touching the filesystem. appFileScanLocationCount / currentAppFileSearchLocationCount were added so the in-progress scan UI shows the location count instead of the placeholder discovered-files count.

Tests

  • LocalizationFilesTests — parses every PureMac/*.lproj/Localizable.strings and fails if any locale drifts from en. This is the guard the maintainer asked for; with the dashboard surface now localized, it also catches any future drift in the new strings.
  • AppLanguagePreferencesTests — verifies apply(.english, defaults:) sets AppleLanguages = ["en"] and apply(.system, defaults:) removes the override, both while preserving AppleLocale.
  • AppStateTests — verifies scanForAppFiles reports the location count while results are pending and then resolves to the sorted discovered files via the injected scanner.

Build infrastructure

  • project.yml now registers the PureMacTests target and a shared PureMac scheme that builds both targets and runs the tests, so xcodebuild test -scheme PureMac works from a clean checkout.
  • PureMac.xcodeproj/xcshareddata/xcschemes/PureMac.xcscheme checked in.

Locale key counts

en       227 keys
es       227 keys
ja       227 keys
ar       227 keys
pt-BR    227 keys
zh-Hans  227 keys
zh-Hant  227 keys

The zh-Hant drift from #76's review was resolved by rebuilding the file from the canonical en key set during this rebase.

Verification

plutil -lint PureMac/{en,es,ja,ar,pt-BR,zh-Hans,zh-Hant}.lproj/Localizable.strings
# → OK for every file

xcodebuild test -project PureMac.xcodeproj -scheme PureMac \
  -destination 'platform=macOS' \
  -only-testing:PureMacTests \
  CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY=''
# → Executed 4 tests, with 0 failures
#   AppLanguagePreferencesTests: 2 / 2 passed
#   AppStateTests:               1 / 1 passed
#   LocalizationFilesTests:      1 / 1 passed

xcodebuild -project PureMac.xcodeproj -scheme PureMac \
  -configuration Debug -destination 'platform=macOS' build \
  CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY=''
# → BUILD SUCCEEDED

Test plan

  • xcodegen generate (matches the committed .xcodeproj)
  • xcodebuild -scheme PureMac -configuration Debug build succeeds
  • xcodebuild test -scheme PureMac -only-testing:PureMacTests reports 4 tests, 0 failures
  • Launch the app, walk through onboarding in English to confirm no regression
  • Open Settings → General → Language, switch to Portuguese (Brazil), relaunch via the button, and spot-check that:
    • Sidebar reads Visão geral / Aplicativos / Limpeza
    • Dashboard hero reads Armazenamento / livres de %@
    • Switching to Sistema (padrão) after relaunch falls back to the system language
  • Spot-check ar for RTL safety: section headers and toolbar buttons should mirror correctly under the new dashboard
  • Run a smart scan and a category clean to confirm no localized string references a missing key (would surface as the English fallback)

AI Assistance Disclosure

This PR was prepared with Claude Code (Anthropic) under human direction. The maintainer's review comment on #76 was the spec; the human reviewed and approved the rebase scope, the choice to retarget rather than reapply, and the final translations before publication.

🤖 Generated with Claude Code

…y guard

Rebases PR momenbasel#76 onto upstream/main (post momenbasel#70 Arabic, momenbasel#75 FDA TCC, momenbasel#80
dashboard redesign, momenbasel#83 AI history). Adds pt-BR alongside the existing
locales and brings every bundled locale (en/es/ja/ar/pt-BR/zh-Hans/
zh-Hant) to key parity, then enforces that parity in CI via a new
XCTest case.

UI changes
- Localize the full user-facing surface across the redesigned views
  (DashboardView replacing SmartScanView; MainWindow's Overview/
  Applications/Cleanup sidebar; CategoryDetailView's hero card;
  AppListView/AppFilesView/OrphanListView; the new OnboardingView
  flow; AppearancePill; SettingsView tabs).
- Wrap dynamic strings with String(format: String(localized: ...))
  so locale-specific number/format substitutions stay correct.
- Add a Settings > General Language picker covering System Default
  plus every bundled language, with a relaunch prompt because
  AppleLanguages is consumed at app startup.

Infrastructure
- Extract AppLanguage + AppLanguagePreferences into Models/.
  AppLanguagePreferences.apply only touches AppleLanguages and
  preserves AppleLocale.
- Wire AppState with injection points (performStartupTasks,
  locationsProvider, appFileScanner) so the scan-for-app-files path
  is exercised by a unit test without touching the real filesystem,
  and expose appFileScanLocationCount /
  currentAppFileSearchLocationCount so the in-progress scan UI
  shows the location count instead of the placeholder discovered-files
  count.

Tests
- LocalizationFilesTests: parses every PureMac/*.lproj/
  Localizable.strings and fails if any locale drifts from en.
- AppLanguagePreferencesTests: verify apply(.english) and
  apply(.system) modify only AppleLanguages.
- AppStateTests: verifies scanForAppFiles publishes the location
  count while results are pending, then resolves to the sorted
  discovered files.

Build
- project.yml registers PureMacTests and a shared scheme so
  `xcodebuild test` works from a clean checkout. xcodeproj
  regenerated via xcodegen.

Verification
- plutil -lint OK for all 7 .strings files (227 keys each).
- xcodebuild test -only-testing:PureMacTests: 4 tests, 0 failures.
- xcodebuild build -configuration Debug: SUCCEEDED.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@momenbasel momenbasel force-pushed the feature/localization-pt-br branch from dd7b661 to dddb053 Compare May 23, 2026 03:38
@momenbasel momenbasel merged commit 691478c into momenbasel:main May 23, 2026
momenbasel added a commit that referenced this pull request May 23, 2026
Bundles three user-facing fixes and one new feature for the next release:

- #103: Protected-app uninstall now routes admin-required paths through
  the vetted CleaningEngine admin cleaner (fixes #93/#95/#97/#102).
- #96: Orphan-file context menu uses activateFileViewerSelecting +
  exposes Copy Path / Move to Trash per row.
- #92: AppInfoFetcher.appSize drops the broken directory-inode fast
  path; sums per-file allocated size so installed-app sizes match
  Finder's Size on disk.
- #101: pt-BR localization, locale parity test guard, Settings language
  picker.
- #99: Sparkle Stage 1 - opt-in UpdateService with Releases-page
  fallback. Signed-appcast work tracked in #104.
@edufalcao edufalcao deleted the feature/localization-pt-br branch May 23, 2026 13:18
momenbasel pushed a commit that referenced this pull request May 24, 2026
Supersedes #76.

- Adds Brazilian Portuguese (pt-BR) localization with 227 keys at parity with en.
- Localizes the post-#80 dashboard surface (DashboardView, MainWindow, CategoryDetailView, AppListView, AppFilesView, OrphanListView, OnboardingView, SettingsView, AppearancePill).
- Settings → General → Language picker with System Default + every bundled language. Mutates only AppleLanguages on apply (AppleLocale preserved so number/date/currency formatting follows the host locale).
- Extracts AppLanguage + AppLanguagePreferences into Models/.
- Relaunch prompt after language switch (AppleLanguages is consumed at startup) via /usr/bin/open -n.
- AppState gains injection points (performStartupTasks, locationsProvider, appFileScanner) so the app-file scan path is unit-testable.
- New PureMacTests target with three test cases: LocalizationFilesTests (locale key-parity guard), AppLanguagePreferencesTests, AppStateTests. project.yml registers the test target + shared scheme.

Rebased onto post-#103 main; AppState.swift @published additions kept side-by-side.
momenbasel added a commit that referenced this pull request May 24, 2026
Bundles three user-facing fixes and one new feature for the next release:

- #103: Protected-app uninstall now routes admin-required paths through
  the vetted CleaningEngine admin cleaner (fixes #93/#95/#97/#102).
- #96: Orphan-file context menu uses activateFileViewerSelecting +
  exposes Copy Path / Move to Trash per row.
- #92: AppInfoFetcher.appSize drops the broken directory-inode fast
  path; sums per-file allocated size so installed-app sizes match
  Finder's Size on disk.
- #101: pt-BR localization, locale parity test guard, Settings language
  picker.
- #99: Sparkle Stage 1 - opt-in UpdateService with Releases-page
  fallback. Signed-appcast work tracked in #104.
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.

2 participants