optimistdigital/nova-translations-loader
A Laravel Nova package that loads PHP translation files into the Nova front-end, making existing language strings available to Vue components and tools without duplication. It supports multiple locales and lets you localize custom Nova cards, fields, and tools using your app's existing translation f...
Architecture fit. This is a narrow, single-purpose utility that sits in the admin layer of a Laravel Nova deployment. Its job is one thing: take translation files that already exist in a package's resources/lang directory and register them as namespaced translations Nova's Vue frontend can resolve at render time. It is not a localization platform, not a translation management system, and not a runtime i18n layer — it is registration boilerplate removal. The architecture question therefore isn't "does this fit our system" but "do we have enough Nova extension surface for boilerplate removal to matter." We author or maintain multiple Nova packages (Tools, Cards, Fields, internal Resources) that each ship strings, and each would otherwise carry its own copy of the same registration block. That is the only condition under which this earns a dependency. With one or two packages, a short loop in a base service provider does the same work with zero third-party surface.
Integration feasibility. Low effort. The integration is a composer require in the extension package's composer.json (a hard require, not dev — the tool's UI renders raw keys without it), a published config for scanned paths/namespaces, and a single NovaTranslationsLoader::loadTranslations(...) call in each package's service provider boot(). The package itself is a service provider plus a small loader class, readable in one sitting. The realistic effort is not the code change; it is (a) inventorying and deleting existing manual loadTranslationsFrom()/addNamespace() calls so we don't double-register, and (b) proving the strings actually reach the browser in a running panel with more than one locale.
Technical risk. Contained but non-trivial in three specific places:
my-tool::title rendered in the admin UI and the first assumption is an application bug. No automated test catches this for us; it surfaces as untranslated strings in employee-facing screens.The blast radius is what makes this acceptable: it touches internal, employee-facing admin tooling only. A failure degrades back-office usability, not customer experience. The decision rule should be stated explicitly — this does not reach customer-facing surfaces without a separate review.
Key questions.
composer.json constraints on PHP, Laravel, and laravel/nova permit this on every environment, including CI and queue workers? (Verify with composer why-not outl1ne/nova-translations-loader.)Stack fit. Requires Laravel Nova, ideally 5.x. Assumes standard Laravel localization conventions — resources/lang/{locale}/{namespace}.php, namespace equal to the package handle, fallback_locale populated. The loader imposes a convention more than it imposes technology, and that is a feature: every internal Nova package ends up looking the same, and a new package inherits the pattern by copying a neighbor.
Migration path. Sequence matters more than the code change:
loadTranslationsFrom(), addNamespace(), and any hand-rolled registration loops. This is the step that prevents silent overwrites.boot() call in a single tool. Verify a known localized string renders in a running panel in both locales. Do not proceed on a config-level assertion.NovaPackageServiceProvider base class that each package extends. This is the point where the dependency pays for itself.Compatibility. Two dimensions. First, Nova major alignment: the package line tracks a Nova major, so a Nova upgrade is a gate to verify, not a reason to upgrade. Record the package version next to the Nova version per environment. Second, locale coverage: every configured locale and the fallback_locale must have a file, otherwise a missing de file falls back to the key rather than to en. Treat locale completeness as a release checklist item, not a runtime concern.
Sequencing against the roadmap. Do not open a dedicated initiative, budget line, or vendor conversation for this. It should ride along inside existing Nova work or an existing localization effort — the natural trigger is a Nova 5 upgrade (where this clears a compatibility checklist line) or the point at which a third or fourth internal Nova package needs translated strings. If the only Nova work on the roadmap is a single tool, skip the dependency and hand-register.
Host-app overrides. Ship sane defaults in each package's en file and let the application override a specific string with its own lang file. This is the capability product stakeholders will actually ask for — per-deployment copy changes without forking the package. But do not promise the override precedence until it is proven: the common assumption that Laravel's normal vendor-override rules apply is exactly the kind of thing a file-reading loader can silently invert. Test which file wins explicitly.
Maintenance. Low absolute effort, low but real continuity risk. The codebase is small enough to read and fork in hours, which converts "maintainer disappears" from a project risk into a scheduled task. The genuine ongoing cost is version tracking at Nova major boundaries — a stalled project at a Nova upgrade boundary is the realistic failure scenario, and the response is a fork, not a negotiation. Assign an owner now, while the dependency is cheap to reason about.
Support. None in the vendor sense. No SLA, no security review trail, no escalation path. Acceptable strictly because of scope: internal admin tooling. The dependency register should record the pin, the Nova version pairing per environment, and the fork-as-exit note so a future engineer doesn't have to rediscover the risk profile.
Scaling. Two axes. Package count: value increases with the number of Nova packages, since it replaces N copies of registration boilerplate with one convention — this is the whole economic case. Request-path cost: translations are captured at boot rather than re-read per locale switch, but if discovery runs per request rather than being cached, we are touching the filesystem on every admin page load. Cheap today; a latency footnote as package count grows. Watch it if the internal package estate expands significantly.
Failure modes. Ordered by likelihood and by how they present:
php artisan config:cache is the classic — if the loader reads config at boot, a stale cache points at the wrong path or skips discovery. Then compiled assets, then Nova's asset state, then the browser. php artisan optimize:clear plus a hard reload resolves most "it worked yesterday" reports.Ramp-up. Near zero for a Laravel-fluent engineer — the README plus one read of src/ is sufficient, though verify current class names because the package moved from the optimistdigital to the outl1ne namespace in 5.x, which invalidates older snippets found in the wild. The non-obvious learning is procedural, not technical: failures are silent and only reproduce in a rendered panel, so the ramp-up investment should go into the release checklist, not into documentation. One line — "load a Nova screen in a non-default locale and confirm a known localized string renders" — catches nearly every failure mode above, and is worth more than any unit test asserting Lang::has().
How can I help you explore Laravel packages today?