Translation Manager — Improvement & Growth Plan
Package: capell-app/translation-manager · Kind: package · Tier: premium · Product group: Capell Admin · Bundle: admin · Status: Draft
1. Snapshot
Section titled “1. Snapshot”Translation Manager is an admin-only Filament package (single surface: admin) that turns Laravel language files into an editable source-vs-target comparison grid at /admin/translation-manager. All domain behaviour lives in 17 thin Actions (src/Actions) that delegate to two pluggable contracts — TranslationSourceResolver (default ConfigTranslationSourceResolver, discovers app + Composer-package + vendor resources/lang dirs) and TranslationFileStore (default FileTranslationFileStore, reads/writes PHP and JSON lang files with override-path safety) — plus an optional TranslationAITranslator (default NullTranslationAITranslator). It owns no migrations, settings, or DB tables (database.migrations: false), and produces no frontend output. Third-party deps are minimal: lorisleiva/laravel-actions, spatie/laravel-data, spatie/laravel-package-tools. Nine Data classes (src/Data) carry every boundary payload — no anonymous arrays leak between layers.
The supports / soft-dependency pattern is implemented correctly and is worth highlighting. composer.json lists capell-app/ai-orchestrator under suggest (not require); capell.json lists it under dependencies.supports. TranslationManagerServiceProvider::registerOptionalAIOrchestratorModule() guards with interface_exists(AIOrchestratorModule::class) and class_exists(AIOrchestratorModuleRegistry::class) and only registers inside an afterResolving(AIOrchestratorModuleRegistry::class, …) callback, so the AIOrchestrator-typed classes in src/Integrations/AI/ are never autoloaded when the orchestrator is absent. This is the clean inversion of a hard dependency: the package runs standalone with a Null translator and lights up AI drafting only when the orchestrator is installed and binds a real TranslationAITranslator.
Current marketplace summary: “Manage Capell language files from one Filament page with side-by-side locale editing, missing and stale key checks, safe override writes, and optional reviewed AI drafting.” Screenshot coverage now matches the package contract: the marketplace card plus all five docs/screenshots.json captures are committed and declared in capell.json (empty state, comparison grid, create locale, duplicate locale, and optional AI translate selected).
2. Improvements (existing functionality)
Section titled “2. Improvements (existing functionality)”-
CSV/XLIFF/PO import-export and publish-readiness are surfaced in the UI —
TranslationManagerPage::getHeaderActions()now exposes CSV, XLIFF, and PO export actions, an import action with format selection, a publish-readiness notification action, a missing-key scan action, and Save. Coverage exercises those header actions through the page state and verifies streamed export/import/readiness behavior. —src/Filament/Pages/TranslationManagerPage.php,tests/Feature/Filament/TranslationManagerPageTest.php— Shipped -
Needs-attention filtering is available — the page filter supports
needs_attentionandfilteredEntries()returns missing, stale, and changed entries as the translator work queue. The filter selection is persisted between visits with the rest of the browser state. —src/Filament/Pages/TranslationManagerPage.php,resources/views/filament/pages/translation-manager.blade.php,tests/Feature/Filament/TranslationManagerPageTest.php— Shipped -
Done/Shipped: raw grid controls were replaced with Filament-native controls. The page now wraps source/file/filter selectors in
x-filament::input.wrapper+x-filament::input.select, usesx-filament::input.checkboxfor selectable entries, wraps editable target textareas in Filament input wrappers, and receives stable entry indexes fromTranslationManagerPage::loadEntries()instead of doing per-rowarray_searchwork in Blade. —resources/views/filament/pages/translation-manager.blade.php,src/Filament/Pages/TranslationManagerPage.php. -
Source/locale/file/filter selection persists between visits —
TranslationManagerPagestores the selected source, source locale, target locale, file, and filter in session, restores valid selections onmount(), and refreshes the readiness matrix without resetting the translator’s working context. —src/Filament/Pages/TranslationManagerPage.php,tests/Feature/Filament/TranslationManagerPageTest.php— Shipped -
Done/Shipped: AIOrchestrator module registration is typed.
registerOptionalAIOrchestratorModule()checks the optional AI Orchestrator classes exist, then registers inside anafterResolving(AIOrchestratorModuleRegistry::class, ...)callback against the typed registry and calls$registry->register(...)directly. —src/Providers/TranslationManagerServiceProvider.php— S -
Accepted residual risk: large XLIFF exports are in-memory.
exportCsv()usesphp://temp;ExportTranslationEntriesToXliffActionbuilds a fullDOMDocumentand returns a string. This is acceptable for current admin language-file sizes and documented as an assumption; chunked XLIFF output should be a future scale task only if real translation sets exceed practical memory. —src/Actions/ExportTranslationEntriesToXliffAction.php— S
3. Missing Features (gaps)
Section titled “3. Missing Features (gaps)”Tie-back to capabilities[] (16 declared) and standard translation-workflow norms:
-
Done/Shipped: inline missing-key detection / app scanning.
ScanMissingTranslationKeysActionscans configured code paths for__()/@lang()references missing from language files, the page exposes a “Scan missing keys” header action, and the manifest declares thetranslation.files.code-missing-key-scancapability. —src/Actions/ScanMissingTranslationKeysAction.php,src/Filament/Pages/TranslationManagerPage.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: translation memory / glossary.
BuildTranslationMemorySuggestionsActionreuses exact source-value translations across files,TranslateSelectedEntriesActionreturns memory suggestions before AI calls, and save-time glossary validation enforces configured terms per locale. —src/Actions/BuildTranslationMemorySuggestionsAction.php,src/Actions/TranslateSelectedEntriesAction.php,src/Support/FileTranslationFileStore.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: machine-translation review/approval workflow. AI/memory suggestions land in
pendingAiSuggestionsinstead of immediately overwriting target values; translators must accept or reject each suggestion before Save writes it. Coverage verifies rejected suggestions do not change target values. —src/Filament/Pages/TranslationManagerPage.php,tests/Feature/Filament/TranslationManagerPageTest.php. -
Done/Shipped: PO / gettext import-export. The package ships
ExportTranslationEntriesToPoActionandImportTranslationEntriesFromPoAction, declares them incapell.json, exposes PO import/export in the page header action set, and covers round-trip import/export behavior. —src/Actions/*PoAction.php,src/Filament/Pages/TranslationManagerPage.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: per-locale completeness dashboard.
TranslationManagerPagebuildsreadinessMatrixacross target locales and the Blade page renders locale-level file, entry, missing, stale, changed, extra, fallback, and ready/needs-work state. —src/Filament/Pages/TranslationManagerPage.php,resources/views/filament/pages/translation-manager.blade.php,tests/Feature/Filament/TranslationManagerPageTest.php. -
Done/Shipped: fallback-chain awareness. Comparison reads the configured Laravel fallback locale, marks empty target keys as
fallbackwhen fallback content exists, exposes a fallback filter/status label, and includes fallback counts in publish readiness. —src/Support/FileTranslationFileStore.php,resources/views/filament/pages/translation-manager.blade.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: pluralization / parameter validation. Save validates that translated strings preserve source placeholders and pipe-delimited plural-form structure before writing. —
src/Support/FileTranslationFileStore.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: partial-override merge. Read-side comparison merges source and Laravel override files so per-key overrides match runtime behavior instead of fully shadowing the source file. —
src/Support/FileTranslationFileStore.php,tests/Feature/TranslationManagerActionsTest.php.
Table-stakes already shipped: source/target grid, key-level stale detection when source-hash metadata exists, CSV/XLIFF/PO import-export, locale create/duplicate, safe override-path writes, fallback awareness, publish readiness, and optional reviewed AI drafting.
4. Issues / Risks
Section titled “4. Issues / Risks”-
Done/Shipped: partial override files merge with source files.
FileTranslationFileStore::readMerged()now combines package source values with Laravel override values for read/comparison paths, while write paths still target the safe override location unless package source writes are explicitly enabled. Coverage proves a partiallang/vendor/<ns>/<locale>/<file>.phpoverride no longer hides un-overridden source keys. —src/Support/FileTranslationFileStore.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: stale detection is key-level when metadata exists. Writes store per-key source hashes in sidecar metadata, and comparison prefers those hashes to decide
changedversusstale, falling back to file mtime only when legacy metadata is unavailable. —src/Support/FileTranslationFileStore.php,tests/Feature/TranslationManagerActionsTest.php. -
Done/Shipped: health label and admin query budget match reality.
TranslationManagerHealthChecknow runs real diagnostics for the admin surface, service bindings, and required configuration, so the manifest health label names those exact checks instead of a generic install-health promise. The package remains file-backed and database-free, soperformance.adminQueryBudgetcorrectly stays at0. —src/Health/TranslationManagerHealthCheck.php,capell.json,tests/Unit/ManifestRequirementsTest.php. -
Accepted residual risk: file writes share the admin page permission.
canAccess()gates onExtensionsPage::canManageExtensions(),package_source_writesdefaults tofalse, and package/vendor writes go through safe Laravel override paths. Finer-grained per-source write permissions would harden larger teams, but the current package scope treats translation editing as an extension-management permission. —src/Filament/Pages/TranslationManagerPage.php,capell.jsonpermissions — security. -
Done/Shipped: filesystem scans are request-local cached and invalidated after writes.
FileTranslationFileStorenow memoizes locale discovery, file listings, and comparison data per source/locale/file during the request, then flushes that source cache whenever translations are written. Source discovery was already memoized separately. Evidence:TranslationManagerActionsTestusesCountingFilesystemto prove repeat file/comparison reads do not rescan untilSaveTranslationEntriesActionwrites and invalidates the cache. —src/Support/FileTranslationFileStore.php,tests/Feature/TranslationManagerActionsTest.php,tests/Fixtures/CountingFilesystem.php— performance budget. -
Done/Shipped: source discovery is request-local memoized.
ConfigTranslationSourceResolver::sources()caches its resolved source list inresolvedSources, and the service provider binds the resolver as a singleton, so Composer package discovery and provider reflection run once per request. —src/Support/ConfigTranslationSourceResolver.php,src/Providers/TranslationManagerServiceProvider.php— performance. -
Public-output safety: N/A but worth a guard test — the package has
surfaces: ["admin"]and emits no frontend HTML, so the Capell public-output rules do not apply. No risk found; no action needed beyond noting it in the manifest (alreadyfrontend: [],cacheable: false). -
Accepted residual risk: package UI strings ship in English only. The package is itself translatable through Laravel language files, but this repository only ships
resources/lang/en/*. Additional bundled locales are a product/content task rather than an implementation blocker for the current package plan. —resources/lang/en— i18n. -
Accepted residual risk: scale/concurrency tests remain future hardening. Coverage is genuinely strong across Actions, file store, page Livewire state, AI module, manifest, and Data boundaries, including path-traversal rejection, override-write defaults, partial-override merge, placeholder/plural/glossary validation, fallback status, translation memory, PO import/export, and page header actions. Remaining gaps are concurrent-write / last-write-wins on
write()and very large file export memory. —tests/— test debt.
5. Marketplace & Selling
Section titled “5. Marketplace & Selling”Critique. The current summary and composer description diverge. capell.json summary is a 40-word feature dump (editor, workflow actions, stale detection, CSV+XLIFF, publish readiness, AI drafting, override writes) — comprehensive but unreadable as a one-liner, and it advertises CSV/XLIFF/publish-readiness that have no UI entry point (see §2), risking a “where is it?” support load. The composer description (“File-based Laravel translation management for Capell and Filament admin panels.”) is accurate but generic and undersells the differentiators (override safety, AI drafting, no-DB footprint).
Improved one-sentence summary: Edit, translate, and ship your Capell language files from one Filament screen — with side-by-side source/target comparison, stale-key detection, and AI drafting that never touches a database.
Improved 3–4 sentence description: Translation Manager gives admins a file-based editor for every Laravel language file in your Capell app and its packages, without migrations or new tables. Compare source and target locales side by side, spot missing and stale keys at a glance, and create or duplicate locales in one click. Edits to package and vendor strings are written safely to Laravel’s override paths, so upgrades never clobber your translations. Install AI Orchestrator to add one-click AI drafting for selected keys, with review before anything is saved.
Screenshot/media coverage. The marketplace card plus all five docs/screenshots.json captures are now committed and declared in capell.json: empty state, comparison grid, create-locale modal, duplicate-locale modal, and AI translate-selected. A short GIF of the create→translate→save loop would still improve the listing, but the static Marketplace screenshot contract is reconciled.
Pricing / tier / bundle. tier: premium, bundle: admin, proposedLicense: paid, requestedCertification: first-party, supportPolicy: priority — appropriate for a developer/agency tool. Position inside the admin bundle as the localisation utility. The no-DB, override-safe footprint is a genuine premium justification (low risk to install).
Cross-sell. Hard requires capell-app/admin + capell-app/core. Soft supports capell-app/ai-orchestrator — make this the headline upsell: “Add AI Orchestrator for AI translation drafting.” Bundle into an Extension Suite alongside seo-suite (translated SEO metadata per locale) and ai-orchestrator (MT). Cross-link the README’s “Best Used With” (currently Welcome Tour / Diagnostics / Foundation Theme) to add ai-orchestrator and seo-suite, which are far more relevant to the localisation buyer.
Differentiators / value props / target buyer. Differentiators: upgrade-safe override writes; zero database footprint; clean optional-AI integration via supports; XLIFF interop. Target buyer: agencies and developers running multi-locale Capell sites who need to localise package/vendor strings without forking vendor files. Value prop: “localise your whole app — including third-party packages — without migrations and without losing edits on upgrade.”
Keywords/tags (8–12): translation, localization, i18n, l10n, language-files, xliff, csv-import, filament, multilingual, ai-translation, vendor-overrides, capell-admin.
6. Prioritized Roadmap
Section titled “6. Prioritized Roadmap”| Item | Bucket | Effort | Impact | Section ref |
|---|---|---|---|---|
| Wire CSV/XLIFF import-export + publish-readiness into page header actions | Done | M | High | §2, §3 |
| Ship the 4 required + 1 optional screenshots (fix screenshots.json mismatch) | Done | S | High | §1, §5 |
| Fix partial-override merge so editor view matches Laravel runtime | Done | M | High | §4 |
| Done/Shipped: Correct manifest healthChecks label / adminQueryBudget to match reality | Done | S | Med | §4 |
| Done/Shipped: Memoize source discovery + locale/comparison filesystem scans. Evidence: file-listing and comparison caches are request-local and flush after translation writes, with focused filesystem-count coverage. | Done | S | Med | §4 |
Done/Shipped: Rewrite summary + composer description; add ai-orchestrator/seo-suite cross-sell. Evidence: capell.json and package composer.json now use conservative editor-focused copy, declare/suggest AI Orchestrator and SEO Suite as optional pairings, README/docs copy matches shipped behavior, and ManifestRequirementsTest locks the manifest/composer wording. | Done | S | Med | §5 |
| Add placeholder/plural preservation validation on save | Done | M | High | §3 |
| Add MT review gate (accept/reject AI drafts before write) | Done | M | High | §3 |
| Per-locale completeness/coverage matrix view (uses existing readiness data) | Done | M | Med | §3 |
| Key-level stale detection (replace file-mtime heuristic) | Done | M | Med | §4 |
| Persist last source/locale/file selection per user | Done | S | Med | §2 |
| Fallback-chain awareness (“covered by fallback” status) | Done | M | Med | §3 |
Missing-key detection via code scanning of __()/@lang() | Done | L | High | §3 |
| Translation memory / glossary for consistent reuse | Done | L | Med | §3 |
| PO/gettext import-export for Crowdin/Weblate/Poedit interop | Done | M | Med | §3 |
| Done/Shipped: Replace raw blade grid controls with Filament-native selector, checkbox, and input-wrapper components, with stable page-provided row indexes instead of per-row Blade lookup | Done | L | Med | §2 |