Skip to content

Add Russian localization and i18n foundation - #133

Open
DrMaks22 wants to merge 7 commits into
msitarzewski:mainfrom
DrMaks22:codex/ru-localization-i18n
Open

DrMaks22 wants to merge 7 commits into
msitarzewski:mainfrom
DrMaks22:codex/ru-localization-i18n

Conversation

@DrMaks22

@DrMaks22 DrMaks22 commented Jul 7, 2026 •

Copy link
Copy Markdown

Summary

This PR adds a lightweight Russian localization foundation for Brew Browser across both shipped shells: the Tauri/Svelte/Rust app and the native SwiftUI app. It is updated on upstream main through v0.7.1 / native 0.3.1, including the new Bundles feature.

The goal is not only Russian UI text, but a maintainable path for additional languages without pulling in a heavy i18n dependency.

What changed

  • Added and expanded the project-native UI message layer:
    • Tauri/Svelte: src/lib/i18n/en.ts, src/lib/i18n/ru.ts, src/lib/i18n/messages.ts
    • native SwiftUI: L10n facade plus Localizable.strings / Localizable.xcstrings resources
  • Localized visible UI across the app surfaces and the Bundles surface:
    • Dashboard, Library, Discover, Trending, Snapshots, Services, Activity, Settings, package detail, Bundles, bundle detail, confirmations, network/security/update/GitHub flows
  • Added Russian bundle prose overlays for the curated Bundles catalog in both builds:
    • src-tauri/data/bundles.ru.json
    • native/Sources/BrewBrowserKit/Resources/bundles.ru.json
  • Kept recipe/source data stable and language-neutral:
    • package tokens, brew commands, route/storage/API names, URLs, CLI flags, model/provider/product names are not translated
    • formula/cask semantics are preserved and rendered as Russian UI labels where the value is a user-facing type badge
  • Made live Bundles locale-aware without mixing stale translations into fresh live data:
    • bundled recipes use the embedded bundles.<locale>.json overlay
    • live refresh applies bundles.<locale>.json only when the live host provides a matching overlay; otherwise it keeps live English recipe prose intact
  • Updated CONTRIBUTING-bundles.md with the localization overlay contract and instructions for adding future languages.
  • Fixed a recipe validation issue found while syncing with upstream Bundles: agentic-web-dev now declares the third-party anomalyco/tap required for opencode.
  • Follow-up visual QA fixes from local installed builds:
    • Tauri Dashboard no longer exposes raw catalog source wire values such as (user-refreshed).
    • Tauri update-list kind badges now render Russian labels such as cask-пакет / формула without changing package identifiers or brew commands.
    • Native Dashboard no longer exposes the missing date.today key and translates user-refreshed as обновлён пользователем.
    • Added regression tests for these source/kind/date labels.

How future languages can be added

  1. Add app UI messages for the new locale in the existing message layer:
    • Tauri/Svelte: add src/lib/i18n/<locale>.ts and route it through the current message helpers.
    • native SwiftUI: add/update <locale>.lproj/Localizable.strings and Localizable.xcstrings resources, then include any new resources in native/Package.swift.
  2. Add Bundle prose overlays, not translated recipe files:
    • Tauri/Rust: src-tauri/data/bundles.<locale>.json
    • native SwiftUI: native/Sources/BrewBrowserKit/Resources/bundles.<locale>.json
  3. Keep overlay patches keyed only by stable recipe IDs, setup step indexes, and link URLs.
  4. Do not translate stable identifiers: package names, formula/cask wire values, brew commands, CLI flags, IDs, URLs, model/provider/product names.
  5. For package-level prose enrichment, add locale-keyed overlays (enrichment.<locale>.json) instead of mutating the base English catalog; search/index code should keep stable package IDs and add localized text as an additional display/search layer.
  6. Run the parity and project checks below.

Validation

Ran locally on this branch:

  • npm run check ✅
  • npm test ✅ — 8 files / 66 tests
  • node scripts/validate-recipes.mjs ✅ — 9/9 recipes valid, regenerated all bundled bundles.json copies
  • cargo test --manifest-path src-tauri/Cargo.toml ✅ — 691 passed, 6 ignored integration tests
  • cd native && swift build ✅
  • cd native && swift test ✅ — 204 Swift Testing tests passed
  • TypeScript locale parity ✅ — en.ts / ru.ts: strict key and placeholder parity passed
  • Native .strings parity ✅ — English/Russian resource parity passed in both native resource roots
  • Bundle overlay parity ✅ — Russian overlay covers all bundled recipe IDs in both Tauri and native resources
  • JSON / .xcstrings structural parse ✅
  • git diff --check ✅
  • Local installed-build smoke/visual QA ✅:
    • Tauri installed as /Applications/Brew Browser RU.app (com.zerologic.brew-browser, 0.7.1)
    • Native installed as /Applications/Brew Browser Native RU.app (com.zerologic.brew-browser-native, 0.3.1)
    • Checked Dashboard, Catalog, Trending, Snapshots, Activity, Bundles and native Dashboard after install.

Notes:

  • Tauri release bundling locally reaches the .app bundle, then fails only at Developer ID signing because the maintainer certificate Developer ID Application: Michael Sitarzewski (7JQGQ7CRH8) is not present on this machine. For local visual QA I ad-hoc signed the app bundle; this does not change repo code or the maintainer release process.
  • Russian quality lint still reports heuristic warnings for preserved product/technology names such as Apple Silicon, Stable Diffusion, Flux, ComfyUI, OrbStack, Homebrew, GitHub, OSV.dev. I reviewed those manually and left them as non-translatable domain terms.
  • Source plural scanner is clean for src. On native sources it flags the centralized L10n helper methods themselves; those helpers contain explicit Russian plural forms and are intentional.

Maintainer-facing notes

  • This PR intentionally keeps the localization layer small and local to the repo.
  • Bundle recipes remain the canonical source contract; localized overlays are optional, narrow patches.
  • Unknown locales fall back to English.
  • Live Bundles avoid mixing newer live recipes with older embedded translations unless a matching live locale overlay exists.

@DrMaks22
DrMaks22 marked this pull request as ready for review July 7, 2026 16:15
@DrMaks22 DrMaks22 changed the title Add Russian UI localization Add Russian localization and i18n foundation Jul 7, 2026
DrMaks22 added 5 commits July 7, 2026 23:38
…-i18n

# Conflicts:
#	native/Package.swift
#	native/Sources/BrewBrowserKit/AppModel.swift
#	native/Sources/BrewBrowserKit/ContentView.swift
#	native/build-app.sh
#	src/lib/components/Library.svelte
#	src/lib/components/PackageDetail.svelte
#	src/lib/components/ResizeHandle.svelte
#	src/lib/components/Sidebar.svelte
#	src/lib/stores/ui.svelte.ts
@DrMaks22

Copy link
Copy Markdown
Author

Fresh installed-build QA pass after syncing to v0.7.1 / native 0.3.1:

  • Installed and launched Tauri locally as /Applications/Brew Browser RU.app (com.zerologic.brew-browser, 0.7.1).
  • Installed and launched native SwiftUI locally as /Applications/Brew Browser Native RU.app (com.zerologic.brew-browser-native, 0.3.1).
  • Local Tauri .app was ad-hoc signed for QA because the maintainer Developer ID cert is not available on my machine; the build otherwise reaches the release app bundle.
  • Visual QA found and fixed three RU polish regressions:
    • Tauri Dashboard no longer exposes (user-refreshed).
    • Tauri update-list type badges now render cask-пакет / формула in Russian UI.
    • Native Dashboard no longer exposes the missing date.today key and renders обновлён пользователем.
  • Re-ran checks after the fixes:
    • npm run check ✅
    • npm test ✅ — 8 files / 66 tests
    • cd native && swift build ✅
    • cd native && swift test ✅ — 204 tests

No maintainer comments/reviews were present when I checked; PR is still mergeable from GitHub's perspective.

@msitarzewski

Copy link
Copy Markdown
Owner

Thanks for this, and apologies it's sat a while — it's a substantial piece of work and I didn't want to give it a superficial review.

The design is the right one for this project: a dependency-free message layer (src/lib/i18n/* on the Tauri side, an L10n facade with Localizable.strings/.xcstrings on native) rather than pulling in a heavy i18n runtime. Keeping it current through 0.7.1 including Bundles was a real effort.

Plan: this is queued for the 0.8.0 cycle, not 0.7.3. Two reasons, neither about the quality of the work.

First, adding a localization layer is a standing commitment rather than a one-off merge — from that point on, every new string in every PR needs its en/ru pair or the UI drifts bilingual. That's a maintenance decision I want to make deliberately, with a plan for keeping translations current, instead of as part of clearing a queue.

Second, 0.7.3 is a security release. brew vulns output changed shape in Homebrew 6.0 and our parser was silently reporting "no known vulnerabilities" on machines that had them — on my own box it was hiding 57 findings across 20 packages, including two criticals. Nothing rides along with that release that could destabilise either shell.

What the PR needs when we pick it up: main has moved 15 commits since your base (9cbd8f0), and 21 files currently conflict — including BrewService.swift, AppModel.swift, DashboardView.swift, AboutView.swift and ContentView.swift, all of which were rewritten by a Rosetta 2 fix and an icon change. A rebase onto current main would be needed, and it's genuinely better coming from you than from me: you know which of your changes are load-bearing and I'd be guessing.

No rush on that — there's no point rebasing until we're actually in the 0.8.0 window, since main will move again. I'll comment here when that starts so you're not chasing a moving target.

One thing that would help in the meantime, if you're interested: a short note in the PR description on how you'd want new strings handled going forward — whether contributors add the ru value themselves, or whether untranslated keys fall back to English and get swept periodically. That's the part that decides whether this stays healthy after the initial merge.

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