dejwcake/admin-translations
A Laravel package for managing application translations from your admin panel, letting you edit and organize language strings through a database-backed interface instead of editing language files by hand.
Build vs. buy for localization tooling. This package sits between "do nothing" and "buy a TMS." It ships a DB-backed translation store that overrides file-based translations (DB wins via array_replace_recursive), a source scanner (admin-translations:scan-and-save) to bootstrap keys, Excel import/export via maatwebsite/excel, and a full admin CRUD UI at /admin/translations with admin.translation.{index,edit,rescan} gates. That is a credible "TMS-lite" for a single Laravel app — enough to defer a Crowdin/Lokalise/Phrase decision by a year or more, and enough to evaluate whether you actually need translator workflows before paying for them.
Whether copy changes require a deploy. The DB-override model moves translation edits out of the release train: marketing or regional leads update strings in the admin panel and they take effect without a PR, CI run, or deploy window. This is the single most valuable capability here and should be the deciding factor. It is also the one that creates a governance obligation (see below), so treat it as an explicit product decision, not a side effect.
A platform-level dependency, not a leaf dependency. TranslationServiceProvider replaces Laravel's translation loader with TranslationLoaderManager. Adopting this package makes your i18n read path depend on it, across every __()/@lang call in the app. That is an architecture commitment requiring sign-off — the correct comparison is "do we want our translation resolution owned by a 0-star fork," not "should we add a dev helper."
Locale expansion cost model. Because keys are scanned from source and stored in the DB with per-locale, per-group organization, adding locale N+1 becomes an editor task rather than an engineering task. Roadmap question this answers: can we commit to three new markets next quarter without a headcount ask?
Translation agency / vendor workflow. Excel import/export means you can hand a spreadsheet to an agency and round-trip it back, with no TMS contract. Informs procurement: at what volume does Excel round-tripping break down and a TMS earn its license?
Fork strategy and maintenance ownership. This is a fork of brackets/admin-translations under the Brackets\AdminTranslations namespace, part of the Craftable ecosystem, at 0 stars. The real PM decision is not "adopt or not" but "fork-and-own vs. track upstream": who patches it, do we contribute back, and how do we stay mergeable. Budget a named owner before adoption, or don't adopt.
Platform upgrade sequencing. The package requires PHP ^8.5 and Laravel 13, tested on MariaDB 12.3 and PostgreSQL. This is a hard gate — it forces your framework upgrade to lead or trail package adoption, and it may disqualify you outright today. It also means adoption is a forcing function for the Laravel 13 migration, which may be an argument for or against depending on where you are.
Release and rollback risk tolerance. 2.3.2 is a behavior-preserving maintenance release ("nothing to do when upgrading"), with .gitattributes export-ignore trimming tests, Docker, and QA config from dist archives. Low-risk bump, no roadmap slot, small supply-chain hygiene win. Routine.
Consider adopting when:
Look elsewhere when:
Translation::getTranslationsForGroupAndNamespace() caches indefinitely and is invalidated only on the model's saved/deleted events. Any write path that bypasses the model leaves stale strings live.To executives. This is a free, self-hosted translation management layer for our Laravel admin panel. It lets non-engineers update customer-facing copy in multiple languages without a deploy, and it lets us hand spreadsheets to translation agencies instead of buying a TMS license. The strategic value is speed: launching a new locale becomes an editorial task, not an engineering project. Two costs to weigh honestly: it is a small, single-maintainer open-source fork (no vendor, no SLA), so we need an internal owner, and it requires Laravel 13 / PHP 8.5, which ties adoption to our next platform upgrade. Recommendation: pilot on one secondary locale with a named owner and a rollback plan, then decide on wider rollout. Do not adopt before the platform upgrade lands.
To engineering. It is not a leaf dependency: TranslationServiceProvider swaps Laravel's translation loader for TranslationLoaderManager, which merges file and DB translations with array_replace_recursive — DB wins, on every __()/@lang call in the app. Practical consequences:
Translation::getTranslationsForGroupAndNamespace() caches forever and is cleared only on the model's saved/deleted events. Every write path must go through the model or explicitly clear the cache. This belongs in the code review checklist, not just the docs.ScanAndSaveService soft-deletes all translations then restores/creates what it finds, inside a transaction. Keep it transactional, gate it behind admin.translation.rescan, and never let it run untested against production data.text and metadata are jsonb; behaviour differs between MariaDB and PostgreSQL. Any change touching those columns needs both matrices green.declare(strict_types=1), final readonly classes, no facades (inject contracts), no app()/helpers except trans()/__(), sprintf() over interpolation, #[Override] except on trait overrides (PHP 8.5.3 segfault), aliased Config/Cache repository contracts. Note the parent-type caveat on untyped Laravel properties like $fillable.export-ignore trimming tests, Docker, and QA config from the dist archive. Internals moved to phpmd 3, added coverage printing, and cleaned up LangFileKeyCollector types with no behavior change. Safe to bump; confirm the lockfile diff is version-only.Caveat to state plainly in any decision record. The assessment currently filed in the package repo (assessment-pm.md) describes this as a dev-time key collector with no admin UI and no runtime delivery. The AGENTS.md and README contradict that: it is a DB-backed translation manager that replaces the loader, serves translations at runtime, and ships an admin UI, source scanning, and Excel import/export. Discard the prior framing before it drives a decision. Verify the actual API surface, route/gate wiring, and behaviour against our Laravel version directly rather than inferring from changelogs — the release notes alone materially understate what we would be adopting.
How can I help you explore Laravel packages today?