11 KiB
Platform Localization Implementation Plan
Execution note: implement task-by-task in the current session. Do not use subagents. Use TDD for every production boundary and keep commits scoped to a single repository.
Goal: Add persisted System/Russian/English language selection to Verstak Desktop, localize the shell and all official plugins, and establish the public SDK contract used by future multilingual plugins.
Architecture: Desktop owns the application preference, locale resolution,
shell catalogs, safe plugin-catalog loading, and a generic runtime bridge. Each
plugin owns its manifest and UI catalogs and accesses them through
api.i18n. Manifest literals remain English fallbacks. Locale changes update
mounted UI without remounting plugin components.
Tech stack: Go/Wails backend tests, Svelte 4 and plain JavaScript frontend, TypeScript SDK with Vitest, JSON Schema, browserless Node plugin smoke tests, Playwright mocked-Wails E2E.
Global Constraints
~/git/verstakis UI reference only; do not copy its implementation.- Core must not contain official plugin messages or depend on official plugin IDs.
- Official and third-party plugins use the same manifest and runtime API.
- Store only
system,ru, oren; default tosystem. - Resolve
ru-*system locales toru, everything else toen. - Do not remount plugins on locale changes or discard form/editor state.
- Preserve existing unrelated generated Wails binding changes in the desktop worktree.
- Add tests before production changes and observe each focused test fail before implementing its boundary.
Task 1: SDK localization contract
Files:
- Modify
verstak-sdk/schemas/manifest.json - Modify
verstak-sdk/src/types.ts - Modify
verstak-sdk/src/plugin-api.ts - Modify
verstak-sdk/src/test-utils.ts - Modify
verstak-sdk/src/plugin-api.test.ts - Generated by build:
verstak-sdk/dist/*
Contract produced:
interface PluginLocalizationConfig {
defaultLocale: string;
locales: Record<string, string>;
}
interface PluginI18nAPI {
getLocale(): 'ru' | 'en';
t(key: string, params?: Record<string, string | number>, fallback?: string): string;
onDidChangeLocale(listener: (locale: 'ru' | 'en') => void): Unsubscribe;
}
- Add failing schema/type/mock tests for a valid manifest localization block, required default catalog, safe relative paths, API shape, fallback, interpolation, and locale-change notification.
- Run
npm test -- --run src/plugin-api.test.tsand confirm RED. - Add
localizationto the JSON Schema and TypeScript manifest types. - Add
i18ntoVerstakPluginAPIand configurable locale/messages tocreateMockPluginAPI. - Run focused tests GREEN.
- Run
npm test,npm run lint, andnpm run build. - Commit only SDK source/schema/generated dist changes.
Task 2: Desktop application language setting
Files:
- Modify
verstak-desktop/internal/core/appsettings/manager.go - Modify
verstak-desktop/internal/core/appsettings/manager_test.go - Modify
verstak-desktop/internal/api/app.go - Modify
verstak-desktop/internal/api/app_test.go
Behavior: missing language becomes system; valid updates persist; invalid
updates return an error; unrelated settings remain unchanged.
- Add failing manager tests for default, reload, and preservation.
- Add failing API tests for
GetAppSettingsand accepted/rejected patches. - Run focused Go tests and confirm RED.
- Add
Languagetoappsettings.Config, default/load normalization, and update handling without changing unrelated values. - Expose and validate
languagein the Wails API. - Run focused tests GREEN.
- Run
gofmton changed Go files andgo test ./internal/core/appsettings ./internal/api.
Task 3: Plugin localization metadata and safe catalog loading
Files:
- Modify
verstak-desktop/internal/core/plugin/plugin.go - Modify
verstak-desktop/internal/core/plugin/plugin_test.go - Modify
verstak-desktop/internal/api/app.go - Modify
verstak-desktop/internal/api/app_test.go - Generated Wails bindings are intentionally not regenerated over existing user changes; frontend imports call the binding only after generation is explicitly reconciled.
Backend API:
GetPluginLocalization(pluginID, locale string) (map[string]string, string)
- Add failing manifest parsing tests for localization metadata.
- Add failing API tests for declared catalog reads, locale fallback input, malformed JSON, non-string values, missing declarations, absolute paths, backslashes, traversal, and containment.
- Run focused Go tests and confirm RED.
- Add localization manifest structs and the read-only safe catalog API.
- Run focused tests GREEN and
go test ./internal/core/plugin ./internal/api.
Task 4: Frontend localization service
Files:
-
Add
verstak-desktop/frontend/src/lib/i18n/catalogs/en.js -
Add
verstak-desktop/frontend/src/lib/i18n/catalogs/ru.js -
Add
verstak-desktop/frontend/src/lib/i18n/index.js -
Add
verstak-desktop/frontend/tests/i18n-test.mjs -
Modify
verstak-desktop/frontend/src/main.js -
Modify
verstak-desktop/frontend/src/lib/test/wails-mock.js -
Add a failing standalone Node test for preference validation, system locale resolution, interpolation, shell fallback, plugin catalog fallback, subscription, and contribution-copy localization.
-
Run
node frontend/tests/i18n-test.mjsand confirm RED. -
Implement the framework-independent locale store and catalog cache.
-
Initialize it from
GetAppSettingsbefore mounting Svelte. -
Extend the Wails mock with language state and plugin catalogs.
-
Run the focused test GREEN and
npm run build.
Task 5: Runtime api.i18n bridge
Files:
-
Modify
verstak-desktop/frontend/src/lib/plugin-host/VerstakPluginAPI.js -
Modify
verstak-desktop/frontend/src/lib/plugin-host/PluginBundleHost.svelte -
Modify
verstak-desktop/frontend/tests/plugin-api-contributions-test.mjs -
Modify
verstak-desktop/frontend/tests/bundle-host-test.cjs -
Extend bridge tests first to require
getLocale,t, and disposableonDidChangeLocalebehavior. -
Confirm focused RED.
-
Preload the plugin catalog before mount and expose the i18n service through the public API.
-
Keep locale subscriptions under existing API disposal cleanup.
-
Translate host loading/error states through shell catalogs.
-
Confirm bridge/bundle tests GREEN.
Task 6: Language selector and shell migration
Files:
-
Modify
verstak-desktop/frontend/src/App.svelte -
Modify every Svelte file under
verstak-desktop/frontend/src/lib/shell/ -
Modify every Svelte file under
verstak-desktop/frontend/src/lib/plugin-manager/ -
Modify
verstak-desktop/frontend/src/lib/plugin-host/PluginBundleHost.svelte -
Modify
verstak-desktop/frontend/e2e/status-bar.spec.js -
Add
verstak-desktop/frontend/e2e/localization.spec.js -
Modify
verstak-desktop/frontend/tests/shell-source-contract-test.mjswhere assertions intentionally depend on translated literals. -
Add failing E2E assertions for the language submenu/radio state, persistence, Russian system locale, English fallback, and live shell update.
-
Confirm focused Playwright RED.
-
Add the language submenu to StatusBar and persist changes through
UpdateAppSettings. -
Replace shell user-facing literals with shell catalog keys, including aria labels, tooltips, empty/loading/error/confirmation text.
-
Localize copies of plugin manifests and contributions before display.
-
Confirm focused E2E GREEN, standalone shell tests GREEN, and frontend production build GREEN.
Task 7: Official plugin localization declarations and catalog checks
Files:
-
Modify every
verstak-official-plugins/plugins/*/plugin.json -
Add
locales/en.jsonandlocales/ru.jsonunder every official plugin -
Add
verstak-official-plugins/scripts/check-locales.mjs -
Modify
verstak-official-plugins/scripts/check.sh -
Modify relevant plugin smoke harness API mocks under
verstak-official-plugins/scripts/ -
Add the locale checker first and confirm it fails for missing metadata and catalogs.
-
Add localization declarations to all 13 manifests.
-
Add English and Russian manifest/contribution keys to all catalogs.
-
Verify catalog parity, string-only values, safe paths, and required derived manifest keys.
-
Run
./scripts/check.shGREEN before migrating runtime UI strings.
Task 8: Plain-JavaScript official plugin UI migration
Files:
- Modify
frontend/src/index.jsfor activity, browser-inbox, default-editor, file-preview, files, journal, notes, platform-test, search, secrets, todo, and trash. - Expand each plugin's
locales/en.jsonandlocales/ru.json. - Modify focused
scripts/smoke-*-plugin.jstests.
For each plugin, repeat independently:
- Add a failing bilingual rendering assertion and a locale-change state preservation assertion to its existing smoke test.
- Add a local
thelper backed only byapi.i18n. - Replace user-visible literals, attributes, empty/loading/error states, confirmation prompts, and known validation messages with stable keys.
- Subscribe once at mount, update only rendered text/state, and unsubscribe at unmount.
- Run the focused plugin smoke test GREEN before moving to the next plugin.
Do not translate IDs, paths, user data, logs, API labels in diagnostics, or provider-returned values.
Task 9: Svelte Sync plugin migration
Files:
-
Modify
verstak-official-plugins/plugins/sync/frontend/src/SyncSettings.svelte -
Modify
verstak-official-plugins/plugins/sync/frontend/src/SyncStatusBar.svelte -
Modify
verstak-official-plugins/plugins/sync/frontend/src/index.js -
Expand
verstak-official-plugins/plugins/sync/locales/en.json -
Expand
verstak-official-plugins/plugins/sync/locales/ru.json -
Modify Sync smoke/E2E tests as appropriate.
-
Add failing English/Russian and live-change assertions.
-
Bridge
api.i18ninto reactive Svelte state without remounting. -
Translate UI labels and known status/error chrome.
-
Run Sync plugin build and focused tests GREEN.
Task 10: Full verification and documentation
Files:
-
Modify
verstak-docs/04_Plugin_System.md -
Modify
verstak-docs/07_Full_Implementation_Roadmap.md -
Modify other contract docs only where the implemented behavior requires it.
-
Run SDK:
npm test,npm run lint,npm run build. -
Run desktop backend:
go test -count=1 ./...andgo vet ./.... -
Run desktop standalone frontend tests, production build, and focused then full
npm run test:e2e. -
Run official plugins:
./scripts/check.shand all plugin builds. -
Run
git diff --checkin every changed repository. -
Inspect changed-file lists and ensure pre-existing Wails generated changes are not staged or overwritten.
-
Update docs to match only verified behavior.
-
Commit scoped changes in each repository.
-
Report exact verification labels. If native Wails/WebKit was not exercised, state:
GUI behavior was not verified in the real desktop shell.