Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Filament Chained Translation Manager Laravel Package

statikbe/laravel-filament-chained-translation-manager

A Filament plugin for Laravel that adds a translation manager to browse and edit your app's language files right in the admin panel. It supports chained machine translation via Google, DeepL, OpenAI and more, making it easy to keep every locale up to date.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the plugin alongside its underlying chained translator, publish what it needs, and migrate:

composer require statikbe/laravel-filament-chained-translation-manager

# publish config + migrations (pick the package's provider/tag from the prompt)
php artisan vendor:publish

php artisan migrate

The migrations create the language_lines table (the database translation store from spatie/laravel-translation-loader, which the chained translator layers on top of Laravel's file loader).

Register the plugin in the panel you want editors to use:

use Statikbe\FilamentChainedTranslationManager\ChainedTranslationManagerPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->id('admin')
        // ...
        ->plugin(ChainedTranslationManagerPlugin::make());
}

First place to look: the published config file (typically config/filament-chained-translation-manager.php). That is where navigation group/label, the list of locales shown in the UI, and excluded translation groups live. After registering, log in and open the Translations page in the sidebar.

First real use case: a marketer fixes a typo in a Dutch CTA string and it goes live immediately — no PR, no deploy — while lang/nl/*.php stays the committed source of truth for developers.

Implementation Patterns

File-first, DB-override. Keep keys defined in lang/ and let the manager write runtime overrides to the database. The chain resolves DB → files → fallback locale, so a missing DB row costs nothing and a DB row silently wins. This is the intended workflow: developers ship keys, editors ship copy.

Locale parity. The locale list in the plugin config must match what your app actually resolves (app()->getLocale(), your config/app.php locales, and Filament's panel locales). Add a locale in four places or don't add it at all — mismatched codes produce empty columns in the UI and untranslated pages in the app.

Access control. This is a write-capable admin tool that mutates live copy. Gate it at the panel level (canAccessPanel() on your User model) or through the plugin's authorization hook if your version exposes one. Don't rely on "it's hidden in the nav" — URLs are guessable.

Environment parity. DB translations don't travel with your code. Write a small artisan command that exports language_lines to JSON/YAML, commit it, and seed it on staging/production. Otherwise every environment has different copy and bug reports become unreproducible.

Bulk file → DB import. New keys don't appear in the manager until they exist in a lang file (or are inserted directly). Run php artisan list | grep -i translation to see whether an importer ships with your version; if not, a 30-line command over FileLoader + the Translation model is the standard workaround, and pairs nicely with a CI job.

Reverse sync for review. Because DB rows shadow files, "the translation lives in git" requires an export step. Export changed rows back into lang/*.php, commit, then delete those rows so the file regains authority. Do this before big refactors.

Per-panel scoping. Register the plugin only on the admin panel. For multi-brand/multi-tenant setups, subclass the page or use separate databases — there's no built-in per-tenant translation scoping.

Gotchas and Tips

  • The DB shadows your lang files. The single biggest source of "I edited the file and nothing changed." Check language_lines first, then the file, then the cache.
  • Cache invalidation. The chained translator caches lookups. Saves through the UI invalidate, but seeders and direct DB inserts do not — run php artisan optimize:clear after any bulk change.
  • Missing keys are invisible. The manager lists keys that exist somewhere; a typo in __('checkout.recap') will never surface as "missing." Add the key to the file (or use a key-extraction tool) before expecting editors to find it.
  • Placeholder and pluralization breakage is silent. :name vs :Name, missing | separators, wrong {0}/[1,*] ranges — all render as literal text rather than throwing. Add a test asserting key translations with placeholders render correctly.
  • Composite index length. The unique index on (locale, group, key) can exceed limits on older MySQL/utf8mb4 setups. Use MySQL 8, or set Schema::defaultStringLength(191). Keys longer than 255 chars won't fit either — don't use sentences as keys.
  • Exclude vendor groups. validation, pagination, auth, passwords, and filament:: namespaces are package-owned. Hide them in the config so editors don't "fix" strings that the next composer update overwrites.
  • HTML injection. Editors can put markup in values. If it's rendered with {!! !!}, you've given them a scripting surface. Prefer escaped output; sanitize where you can't.
  • No audit trail by default. There's no updated_by column. Add model events on the Translation model if compliance or "who broke the homepage" matters.
  • migrate:fresh wipes editor work. Backup or seed language_lines in every non-production reset.
  • Version pinning. Filament major versions move fast; check the release notes for the Filament/Laravel combination before upgrading either. Pin statikbe/* in composer.json and upgrade deliberately.
  • Extension points: publish and override the page/resource class for custom columns or filters, swap the Translation model in config, and use excluded_groups for scoping. Everything else (navigation, labels) is config-driven — check the published config before subclassing.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource