288 lines
28 KiB
Markdown
288 lines
28 KiB
Markdown
# Implementation Plan: Platform Localization v1 (DE/EN)
|
|
|
|
**Branch**: `252-platform-localization-v1` | **Date**: 2026-04-28 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/252-platform-localization-v1/spec.md`
|
|
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/252-platform-localization-v1/spec.md`
|
|
|
|
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
|
|
|
|
## Summary
|
|
|
|
- Add one bounded locale foundation for the platform runtime only: admin and tenant panels use the full locale precedence chain (`explicit override -> user preference -> workspace default -> system default`), while the system panel uses the v1 subset (`explicit override -> system default`) because it authenticates a separate platform actor.
|
|
- Keep persistence narrow and repo-native: store the workspace default locale through the existing workspace settings infrastructure, persist the personal locale preference directly on the workspace-bound user surface, and avoid a generic preferences framework, a second settings stack, or a second preference store for `PlatformUser`.
|
|
- Translate the panel shell and the highest-signal governance surfaces first, including the shared context bar, auth copy, Findings, Baseline Compare, representative workspace and tenant membership tables, monitoring and operations feedback, and customer-safe review or report viewer chrome, while keeping exports, audit logs, JSON payloads, and other machine-readable artifacts invariant.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4 (Laravel 12)
|
|
**Primary Dependencies**: Filament v5 + Livewire v4, Laravel translator, existing workspace settings stack (`SettingsRegistry`, `SettingsResolver`, `SettingsWriter`), current panel providers, existing Filament notifications and view layer
|
|
**Storage**: PostgreSQL via one workspace-bound user-owned locale preference field plus one workspace-owned locale default setting; translation catalogs in `apps/platform/lang/en` and `apps/platform/lang/de`
|
|
**Testing**: Pest unit and feature tests via Laravel Sail
|
|
**Validation Lanes**: fast-feedback, confidence
|
|
**Target Platform**: Monorepo Laravel web application in `apps/platform` with admin, tenant, and system Filament panels
|
|
**Project Type**: web
|
|
**Performance Goals**: No extra remote calls during locale resolution, constant-time locale lookup from request/session + current user + workspace settings, and no measurable overhead on ordinary panel navigation or Livewire round-trips
|
|
**Constraints**: Exactly two locales (`en`, `de`), no `apps/website` scope, no new global-search semantics, no RBAC behavior change, invariant CSV/JSON/audit/raw payloads, and no generic preference framework
|
|
**Scale/Scope**: One locale resolver, one request-time locale application seam, one workspace default setting, one workspace-bound personal preference path, system-panel explicit-override support only, and first-wave translation coverage for shell/auth plus core governance surface families
|
|
|
|
## Filament v5 / Panel Notes
|
|
|
|
- **Livewire v4.0+ compliance**: The slice stays inside existing Filament v5 pages, widgets, resources, render hooks, and Livewire-backed request flows. No Livewire v3 assumptions or compatibility work are introduced.
|
|
- **Provider registration location**: No panel/provider registration changes are planned. Existing Laravel 12 + Filament provider registration remains in `bootstrap/providers.php`.
|
|
- **Global search**: No new global-search resource is introduced and no global-search routing or authorization semantics are changed. Localization only affects visible copy where current search access already exists.
|
|
- **Destructive and high-impact actions**: No destructive action is added by this slice. Locale preference and workspace default changes are low-risk settings mutations; they still use existing authorization and settings audit paths where applicable.
|
|
- **Asset strategy**: No new panel or shared assets are planned. Deployment remains unchanged, including `cd apps/platform && php artisan filament:assets` when registered Filament assets are deployed elsewhere in the product.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: changed surfaces
|
|
- **Native vs custom classification summary**: mixed
|
|
- **Shared-family relevance**: shell navigation, auth copy, workspace settings, notifications, status messaging, dashboard and compare surfaces, customer-safe report viewers
|
|
- **State layers in scope**: shell, page, detail, URL-query or session
|
|
- **Audience modes in scope**: operator-MSP, support-platform, customer-read-only
|
|
- **Decision/diagnostic/raw hierarchy plan**: decision-first on shell and core governance surfaces; diagnostics-second on monitoring and operational feedback surfaces; support/raw payloads stay third and unchanged
|
|
- **Raw/support gating plan**: unchanged capability-gated or collapsed raw detail; localization applies only to surrounding UI copy, not to raw payloads or audit artifacts
|
|
- **One-primary-action / duplicate-truth control**: the shell remains the one place where language is chosen intentionally; all other surfaces consume the resolved locale and do not become independent configuration surfaces
|
|
- **Handling modes by drift class or surface**: review-mandatory because mixed-language drift across shell, notifications, and core governance surfaces would undercut the shared locale contract immediately
|
|
- **Repository-signal treatment**: review-mandatory
|
|
- **Special surface test profiles**: global-context-shell, standard-native-filament, shared-detail-family
|
|
- **Required tests or manual smoke**: functional-core, state-contract
|
|
- **Exception path and spread control**: no page-local locale state, no custom translation framework, no second shell, and no localized machine artifacts
|
|
- **Active feature PR close-out entry**: Guardrail
|
|
|
|
## Review Outcome
|
|
|
|
- **Outcome class**: acceptable-special-case
|
|
- **Workflow outcome**: keep
|
|
- **Why this remains acceptable**: the package touches multiple surface families, but every change is still anchored to one shared locale contract and a tightly bounded first-wave translation inventory.
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes
|
|
- **Systems touched**: `bootstrap/app.php`, panel providers (`AdminPanelProvider`, `TenantPanelProvider`, `SystemPanelProvider`), shared topbar render hook and `resources/views/filament/partials/context-bar.blade.php`, existing auth/login pages, workspace settings infrastructure, `User` model persistence, `PlatformUser`-backed system auth behavior, translation catalogs under `lang/`, Filament notifications, and representative governance/detail pages and report viewers
|
|
- **Shared abstractions reused**: existing translation helpers (`__()` and Laravel translator), existing settings registry/resolver/writer, current workspace context resolution, current panel render hooks, and existing Filament notification and page/resource surfaces
|
|
- **New abstraction introduced? why?**: one bounded `LocaleResolver` plus one request-time application seam are justified because the repo currently lacks any single locale precedence decision that can serve shell, auth, Livewire, notifications, and report viewers consistently
|
|
- **Why the existing abstraction was sufficient or insufficient**: Laravel translation helpers are already sufficient for rendering translated strings, and the workspace settings infrastructure is already sufficient for a workspace default on admin and tenant planes. They are insufficient because there is no central locale resolution contract and no workspace-bound user locale preference path today.
|
|
- **Bounded deviation / spread control**: no generic preferences registry, no page-local language switches, and no second translation catalog scheme beyond standard Laravel `lang/{locale}` files
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: no
|
|
- **Central contract reused**: N/A
|
|
- **Delegated UX behaviors**: N/A
|
|
- **Surface-owned behavior kept local**: localized copy only on existing run and monitoring surfaces
|
|
- **Queued DB-notification policy**: N/A
|
|
- **Terminal notification path**: N/A
|
|
- **Exception path**: none
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: no
|
|
- **Provider-owned seams**: N/A
|
|
- **Platform-core seams**: locale resolution, glossary translation, UI copy, and viewer chrome language behavior
|
|
- **Neutral platform terms / contracts preserved**: `Finding`, `Baseline`, `Drift`, `Risk Accepted`, `Evidence Gap`, `Run`, `Alert`, `Workspace`, `Tenant`
|
|
- **Retained provider-specific semantics and why**: none; provider payloads remain untranslated and raw where they already exist
|
|
- **Bounded extraction or follow-up path**: none
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
|
|
- Inventory-first: PASS - the slice changes operator-facing runtime copy and locale choice only; it does not introduce new inventory or backup truth.
|
|
- Read/write separation: PASS - the only new writes are low-risk preference mutations using existing user/workspace ownership and current settings patterns.
|
|
- Graph contract path: PASS - no new Microsoft Graph path is introduced.
|
|
- Deterministic capabilities: PASS - authorization semantics for shell, workspace settings, and read-only viewers remain unchanged.
|
|
- RBAC-UX: PASS - `/admin`, `/admin/t`, and `/system` remain separated; language choice does not alter 404 versus 403 semantics.
|
|
- Workspace isolation: PASS - workspace selection and tenant selection stay authoritative, and locale does not create a second context layer.
|
|
- RBAC-UX destructive confirmation: N/A - no destructive action is introduced.
|
|
- RBAC-UX global search: PASS - search scope and visibility remain unchanged.
|
|
- Tenant isolation: PASS - translated labels and fallback text must not leak inaccessible tenant or workspace information.
|
|
- Run observability: PASS - no new run family or start flow is introduced.
|
|
- OperationRun start UX: N/A - no start semantics change.
|
|
- Ops-UX 3-surface feedback: PASS - only existing copy becomes locale-aware; lifecycle and notification mechanics stay unchanged.
|
|
- Ops-UX lifecycle: N/A - no lifecycle contract change.
|
|
- Ops-UX summary counts: N/A - no summary shape change.
|
|
- Ops-UX guards: N/A - no new run guard family is planned.
|
|
- Ops-UX system runs: N/A - unchanged.
|
|
- Automation: N/A - no new queued or scheduled workflow family is introduced.
|
|
- Data minimization: PASS - no new sensitive payload storage is introduced.
|
|
- Test governance (TEST-GOV-001): PASS - the plan stays in focused unit + feature lanes with explicit proof commands and limited fixture growth.
|
|
- Proportionality (PROP-001): PASS - persistence stays to one workspace-bound user-owned preference and one workspace setting; one resolver is the narrowest viable shared seam.
|
|
- No premature abstraction (ABSTR-001): PASS - no registry, strategy system, or framework is planned beyond one locale resolver and supported-locale allowlist.
|
|
- Persisted truth (PERSIST-001): PASS - the new persisted values represent real workspace-bound user and workspace-owned preference truth, while the system plane remains explicit-override or system-default only.
|
|
- Behavioral state (STATE-001): PASS - the locale set changes real request behavior, formatting, and translated surface output.
|
|
- UI semantics (UI-SEM-001): PASS - the plan favors direct domain-to-translation mapping instead of a new interpretation framework.
|
|
- Shared pattern first (XCUT-001): PASS - existing translator, panel hooks, settings stack, and existing page/resource surfaces are reused first.
|
|
- Provider boundary (PROV-001): PASS - localization is platform-core and provider-neutral.
|
|
- V1 explicitness / few layers (V1-EXP-001, LAYER-001): PASS - one resolver, one middleware path, two locales, and a bounded first-wave surface inventory.
|
|
- Spec discipline / bloat check (SPEC-DISC-001, BLOAT-001): PASS - the whole locale foundation remains in one coherent spec and explicitly avoids website/email/framework drift.
|
|
- Badge semantics (BADGE-001): PASS - translated badges continue to use existing central semantics rather than new color or state mappings.
|
|
- Filament-native UI (UI-FIL-001): PASS - the slice extends existing Filament pages/resources/widgets, login pages, and render-hook partials.
|
|
- Filament-native UI local Blade/Tailwind: PASS - existing custom Blade surfaces like the shared context bar and selected viewer shells remain in Filament visual language.
|
|
- UI/UX surface taxonomy (UI-CONST-001 / UI-SURF-001): PASS - no new surface type is introduced.
|
|
- Decision-first operating model (DECIDE-001): PASS - shell choice happens once, and primary governance surfaces stay decision-first.
|
|
- Audience-aware disclosure (DECIDE-AUD-001 / OPSURF-001): PASS - localization improves readability without exposing hidden diagnostics or translating raw payloads.
|
|
- UI/UX inspect model (UI-HARD-001): PASS - no inspect/open model changes are planned.
|
|
- UI/UX action hierarchy (UI-HARD-001 / UI-EX-001): PASS - existing action hierarchy remains intact.
|
|
- UI/UX scope, truth, and naming (UI-HARD-001 / UI-NAMING-001 / OPSURF-001): PASS - canonical nouns remain stable across translated shells and pages.
|
|
- UI/UX placeholder ban (UI-HARD-001): PASS - no placeholder controls are planned.
|
|
- UI naming (UI-NAMING-001): PASS - translated labels preserve `Verb + Object` semantics and canonical domain vocabulary.
|
|
- Operator surfaces (OPSURF-001): PASS - shell, governance, monitoring, and customer-safe viewers stay explicit and bounded.
|
|
- Operator surface page contract: PASS - the spec already defines the affected surface contracts.
|
|
- Filament UI Action Surface Contract: PASS - no new action family is introduced beyond one shell-level locale control and a workspace settings field.
|
|
- Filament UI UX-001 (Layout & IA): PASS - the slice extends existing shells, settings, and detail surfaces only.
|
|
- Action-surface discipline (ACTSURF-001 / HDR-001): PASS - language choice stays on the shell or settings surfaces and is not duplicated on every page.
|
|
- UI review workflow: PASS - guardrail classification, shell ownership, fallback behavior, and invariant machine-format rules remain explicit in this plan.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**: `Unit` for locale precedence and validation; `Feature` for request-time application, workspace and personal preference flows, translated core surfaces, localized feedback, and invariant machine-format behavior
|
|
- **Affected validation lanes**: `fast-feedback`, `confidence`
|
|
- **Why this lane mix is the narrowest sufficient proof**: the core risk is deterministic resolution and rendered surface behavior across existing request paths, not browser-only interaction nuance or heavy governance semantics
|
|
- **Narrowest proving command(s)**:
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Localization/LocaleResolverTest.php`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Localization/AuthAndSystemSurfaceLocalizationTest.php tests/Feature/Localization/LocalePreferenceFlowTest.php tests/Feature/Localization/WorkspaceDefaultLocaleTest.php tests/Feature/Filament/Localization/CoreGovernanceSurfaceLocalizationTest.php`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Localization/LocalizedNotificationFormattingTest.php tests/Feature/Localization/TranslationFallbackGuardTest.php tests/Feature/Localization/MachineFormatInvarianceTest.php`
|
|
- **Fixture / helper / factory / seed / context cost risks**: limited to users, workspaces, memberships, workspace settings, session override state, and representative governance surface fixtures; add one focused wrong-plane or non-member and missing-capability proof path without widening the test family
|
|
- **Expensive defaults or shared helper growth introduced?**: no - implementation should reuse existing factories and add only thin locale helpers where repeated assertions demand it
|
|
- **Heavy-family additions, promotions, or visibility changes**: none
|
|
- **Surface-class relief / special coverage rule**: global-context-shell proof for request-wide locale behavior, standard-native relief for ordinary Filament surfaces, and shared-detail-family proof for localized report viewer chrome with invariant artifacts
|
|
- **Closing validation and reviewer handoff**: rerun the exact targeted commands above, verify admin login, tenant panel, and system panel locale continuity, verify unsupported locale fallback behavior, verify dashboard plus core governance surfaces do not render raw keys, verify wrong-plane or non-member 404 and member-but-no-capability 403 behavior stays unchanged under locale changes, and verify exported or audited machine formats remain stable with no new remote locale lookups introduced
|
|
- **Budget / baseline / trend follow-up**: none expected beyond ordinary feature-local growth
|
|
- **Review-stop questions**: does one resolver truly own locale precedence, does Livewire preserve the selected locale, does the first-wave translation scope stay bounded, and do exports or audit payloads remain invariant
|
|
- **Escalation path**: document-in-feature if one surface family needs temporary English-only fallback; follow-up-spec only if a later broader email or website localization program becomes necessary
|
|
- **Active feature PR close-out entry**: Guardrail
|
|
- **Why no dedicated follow-up spec is needed**: the planned work stays bounded to the platform runtime and current high-signal governance surfaces; broader public-site or multi-locale expansion remains explicitly out of scope
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/252-platform-localization-v1/
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── contracts/
|
|
│ └── locale-resolution-and-translation-governance.logical.openapi.yaml
|
|
├── checklists/
|
|
│ └── requirements.md
|
|
└── tasks.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
apps/platform/
|
|
├── app/
|
|
│ ├── Http/
|
|
│ │ └── Middleware/
|
|
│ │ └── ApplyResolvedLocale.php
|
|
│ ├── Models/
|
|
│ │ └── User.php
|
|
│ ├── Providers/
|
|
│ │ ├── AppServiceProvider.php
|
|
│ │ └── Filament/
|
|
│ │ ├── AdminPanelProvider.php
|
|
│ │ ├── TenantPanelProvider.php
|
|
│ │ └── SystemPanelProvider.php
|
|
│ ├── Services/
|
|
│ │ ├── Localization/
|
|
│ │ │ └── LocaleResolver.php
|
|
│ │ └── Settings/
|
|
│ │ ├── SettingsResolver.php
|
|
│ │ └── SettingsWriter.php
|
|
│ └── Support/
|
|
│ └── Settings/
|
|
│ └── SettingsRegistry.php
|
|
├── bootstrap/
|
|
│ └── app.php
|
|
├── database/
|
|
│ └── migrations/
|
|
│ └── *_add_preferred_locale_to_users_table.php
|
|
├── lang/
|
|
│ ├── de/
|
|
│ └── en/
|
|
├── resources/views/
|
|
│ └── filament/
|
|
│ ├── partials/context-bar.blade.php
|
|
│ ├── pages/
|
|
│ ├── widgets/
|
|
│ └── system/
|
|
└── tests/
|
|
├── Feature/
|
|
│ ├── Filament/Localization/
|
|
│ └── Localization/
|
|
└── Unit/
|
|
└── Localization/
|
|
```
|
|
|
|
**Structure Decision**: Single Laravel/Filament application inside `apps/platform`, with one new bounded localization resolver, one request-time locale application path, one workspace-bound user preference mutation path, one workspace-owned default setting, system-panel explicit-override support only, and focused translation catalog growth for selected existing surfaces.
|
|
|
|
## Likely Implementation Surfaces
|
|
|
|
- `bootstrap/app.php` plus a new `app/Http/Middleware/ApplyResolvedLocale.php` for request-time locale application in ordinary web requests and panel traffic
|
|
- `app/Providers/Filament/AdminPanelProvider.php`, `TenantPanelProvider.php`, and `SystemPanelProvider.php` for consistent panel-level middleware and shell affordances
|
|
- `resources/views/filament/partials/context-bar.blade.php` as the shared topbar language-control anchor for the admin and tenant panels
|
|
- current auth pages such as `app/Filament/Pages/Auth/Login.php` and `app/Filament/System/Pages/Auth/Login.php` for translated login and auth-adjacent copy
|
|
- `app/Models/User.php` plus a user migration for the personal locale preference field, while `PlatformUser` remains on explicit override plus system default only
|
|
- `app/Support/Settings/SettingsRegistry.php`, `app/Services/Settings/SettingsResolver.php`, `app/Services/Settings/SettingsWriter.php`, and `app/Filament/Pages/Settings/WorkspaceSettings.php` for the workspace-owned default locale path and audit-backed save semantics
|
|
- a new `app/Services/Localization/LocaleResolver.php` for precedence, supported-locale validation, and fallback behavior
|
|
- `lang/en/*` and new `lang/de/*` catalogs for shell, Findings, Baseline Compare, monitoring, operations, workspace or tenant management tables, and customer-safe review or report viewer shells
|
|
- representative existing surfaces such as `app/Filament/Pages/TenantDashboard.php`, `app/Filament/System/Pages/Dashboard.php`, `app/Filament/Resources/FindingResource.php`, `app/Filament/Pages/BaselineCompareLanding.php`, `resources/views/filament/pages/baseline-compare-landing.blade.php`, `resources/views/filament/widgets/tenant/tenant-review-pack-card.blade.php`, `app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php`, and `app/Filament/Resources/Workspaces/RelationManagers/WorkspaceMembershipsRelationManager.php`
|
|
- localized feedback surfaces such as current Filament notifications, validation messages, and relative-time labels already present across monitoring, onboarding, and review surfaces
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|-----------|------------|-------------------------------------|
|
|
| One bounded `LocaleResolver` | Shell, auth, Livewire, notifications, and report viewers need one deterministic locale source | Page-local or panel-local locale reads would drift immediately and make fallback behavior inconsistent |
|
|
| One new workspace locale setting plus one personal preference field | The roadmap precedence chain requires real persisted workspace and user truth | Session-only locale switching would not satisfy inherited defaults or stable user choice |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: The product is partially translation-aware but not intentionally localized. Operators cannot choose a language reliably, and current core surfaces mix raw English with extracted translations.
|
|
- **Existing structure is insufficient because**: Laravel translation helpers alone do not answer which locale to use, when to inherit workspace defaults, how to persist a user choice, or how to keep Livewire and report-viewer surfaces aligned.
|
|
- **Narrowest correct implementation**: exactly two locales, one locale resolver where admin/tenant panels use the full precedence chain and the system panel uses explicit override plus system default, one workspace-bound user preference field, one workspace setting, one request-time application path, and a bounded first-wave translation inventory on existing high-signal surfaces.
|
|
- **Ownership cost created**: ongoing EN/DE catalog maintenance, one resolver, one migration, one workspace setting key, and regression tests for fallback plus invariant machine formats.
|
|
- **Alternative intentionally rejected**: a generic preferences framework, broad website/email program, or translating every page first was rejected because the current release needs a runtime foundation, not a full localization platform.
|
|
- **Release truth**: current-release truth. Core governance, monitoring, and customer-safe review surfaces already need language continuity in the live platform.
|
|
|
|
## Phase 0 — Research (output: `research.md`)
|
|
|
|
See: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/252-platform-localization-v1/research.md`
|
|
|
|
Goals:
|
|
- Confirm the narrowest persistence shape for user preference plus workspace default without creating a generic preferences subsystem.
|
|
- Confirm the cleanest request-time locale application seam across normal web and Livewire requests for all three current panels, while keeping the system panel on explicit override plus system default only.
|
|
- Confirm which first-wave governance and viewer surfaces are already translation-aware enough to translate now and which ones still rely on raw English strings.
|
|
- Confirm invariant machine-format boundaries for exports, audit entries, report payloads, and raw evidence.
|
|
|
|
## Phase 1 — Design & Contracts (outputs: `data-model.md`, `contracts/`, `quickstart.md`)
|
|
|
|
See:
|
|
- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/252-platform-localization-v1/data-model.md`
|
|
- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/252-platform-localization-v1/contracts/locale-resolution-and-translation-governance.logical.openapi.yaml`
|
|
- `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/252-platform-localization-v1/quickstart.md`
|
|
|
|
Design focus:
|
|
- Persist one personal locale preference directly on the workspace-bound user-owned surface and one workspace default locale through the existing settings infrastructure.
|
|
- Add one bounded locale resolver plus one request-time middleware or application path shared by admin, tenant, and system panels, with explicit override plus system default only on the system plane.
|
|
- Place the user-facing locale switch on the existing shared shell or context surface instead of inventing a new page shell.
|
|
- Translate first-wave shell, governance, monitoring, and customer-safe viewer surfaces using standard Laravel catalogs and controlled English fallback.
|
|
- Keep exports, audit logs, raw JSON, and machine-readable artifacts invariant even when the surrounding UI becomes locale-aware.
|
|
|
|
## Implementation Close-Out
|
|
|
|
- **Workflow outcome**: keep.
|
|
- **Validation lanes completed**: fast-feedback and confidence.
|
|
- **Targeted proof results**:
|
|
- `./vendor/bin/sail artisan test --compact tests/Unit/Localization/LocaleResolverTest.php ... tests/Feature/Localization/MachineFormatInvarianceTest.php` passed with 15 tests and 103 assertions.
|
|
- `./vendor/bin/sail artisan test --compact tests/Feature/SettingsFoundation/WorkspaceSettingsAuditTest.php tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php tests/Feature/SettingsFoundation/WorkspaceSettingsViewOnlyTest.php` passed with 18 tests and 248 assertions.
|
|
- `./vendor/bin/sail artisan test --compact tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php` passed with 24 tests and 135 assertions.
|
|
- `./vendor/bin/sail bin pint --dirty --format agent` passed.
|
|
- `git diff --check` passed.
|
|
- **Browser smoke result**: passed on `http://localhost/admin/settings/workspace`, `http://localhost/admin/t/18000000-0000-4000-8000-000000000180`, and `http://localhost/admin/reviews/workspace`. The smoke verified the shared language switch from English to German, German locale menu state, tenant dashboard German navigation/title, customer review workspace German viewer chrome, no raw `localization.*` keys, and no current browser console errors from the tested tab.
|
|
- **Guardrail close-out**: acceptable-special-case / keep remains valid because the implementation still uses one resolver, one middleware seam, one user preference field, one workspace setting key, standard Laravel catalogs, and no localized machine artifact path.
|
|
- **document-in-feature note**: broader pre-existing Workspace Settings sections and deeper diagnostic/payload text outside the locale setting and review/report chrome may still render English in German mode. This is recorded as existing unrelated localization debt rather than widened into this first platform-runtime slice; the active implementation localizes the new locale controls, workspace default locale field, core shell/dashboard labels, Findings/Baseline catalog coverage, notifications, and customer-safe review/report chrome.
|