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

Lexik Translation Ui Bundle Laravel Package

forci/lexik-translation-ui-bundle

Provides a web interface for managing translations with LexikTranslationBundle, letting teams browse, edit, and organize translation messages from a single dashboard. Ideal for Symfony apps that need a lightweight translation admin UI.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you start: this is a Symfony bundle, not a Laravel package. composer require in a Laravel app will get you nowhere — it expects a Symfony kernel, the lexik/translation-bundle translation storage layer, Twig, and Doctrine. Treat it as (a) something you'd use if you also run Symfony services, or (b) a reference implementation to copy for a Laravel equivalent. Both are covered below.

If you are in a Symfony app

  1. Prerequisite: lexik/translation-bundle installed and configured with Doctrine storage. This package is a UI shell over Lexik's storage/translation manager — it has nothing to render without it.

    # config/packages/lexik_translation.yaml
    lexik_translation:
        fallback_locale: en
        managed_locales: [en, fr, de]
        storage: doctrine   # verify the key name for your Lexik major version
    
  2. Install: composer require forci/lexik-translation-ui-bundle. Pin an exact version in composer.json ("forci/lexik-translation-ui-bundle": "x.y.z") — with 0 stars and 0 dependents there is no ecosystem pressure keeping BC breaks honest.

  3. Register the bundle in config/bundles.php. Read vendor/forci/lexik-translation-ui-bundle/ first: the bundle class namespace is in composer.json under autoload.psr-4, and the class name will be the file in the bundle root. Don't guess.

  4. Mount routes — find the routing file in Resources/config/ (routing.xml, routing.yaml, or PHP attributes on controllers) and import it under a prefix you control:

    # config/routes/lexik_translation_ui.yaml
    lexik_translation_ui:
        resource: "@ForciLexikTranslationUiBundle/Resources/config/routing.xml"
        prefix: /_translations
    

    Verify with php bin/console debug:router | grep -i transl.

  5. Lock it down immediately. This UI writes to your database. Add ^/_translations to security.yaml with ROLE_ADMIN (or a dedicated ROLE_TRANSLATOR), and in production put it behind an IP allowlist or an APP_ENV !== 'prod' guard. Do this before your first cache:clear, not after.

First use case — production missing-key triage. Log untranslated keys (framework.translator.logging: true or a listener on the Symfony\Component\Translation\Event\* events), then use the UI to add the missing key in the DB and have it live in seconds instead of a deploy cycle. That is the entire value proposition of DB-backed translations; if you aren't doing this, the bundle is dead weight.

If you are a Laravel developer

You cannot use this package directly. The transferable pattern is: translation catalog in the database + a writer UI on top, which pairs with spatie/laravel-translation-loader. Read this repo's controllers and templates as UX spec — the grid layout, per-locale columns, inline save, and import/export round-trip are the parts worth copying. A Filament resource or a single Livewire page over a language_lines table gets you 80% of it in an afternoon, with middleware-based auth you already understand.

Implementation Patterns

Pick a source of truth, then be religious about it

Three viable models; mixing two is where teams get hurt:

Model Files DB Deploy flow
Files canonical ✅ authoritative transient edit YAML → lexik:translations:import → deploy
DB canonical export artifact ✅ authoritative edit in UI → lexik:translations:export → commit → deploy
DB canonical, files ignored never read ✅ authoritative no deploy needed; DB is a shared service

The bundle shines only in model 2 or 3. Model 1 with this UI installed is a trap: translators edit the DB, the next deploy imports files over their work, and nobody notices until a customer does.

The dev → translator → deploy workflow

dev adds keys in code          →  bin/console lexik:translations:import
translator edits in UI         →  (no code, no deploy)
release prep                   →  bin/console lexik:translations:export --dir=translations
review + commit YAML           →  CI runs a diff check; unexpected deletions block the merge

The CI diff check is the single highest-value integration tip here: a translator deleting a key in the UI should show up as a reviewable YAML deletion, not as a silent null in production.

Scoping and permissions

  • Split by domain (messages, validators, admin) — catalogs over ~500 keys get unusable in one grid. Filter server-side via the bundle's domain parameter, not client-side.
  • Two roles minimum: read-only viewers (product, support) and writers (translators). If the bundle ships a single controller action for saving, enforce read-only at the firewall level with a separate access_control entry rather than trusting the template to hide buttons.
  • Consider per-locale restriction if you use external translators — a French agency should not be able to edit German copy.

Cache and deploy integration

Translation edits in the DB are invisible until the Symfony translation cache is rebuilt in prod. Wire it into your deploy or your save path:

php bin/console cache:clear
php bin/console translation:warmup prod   # if you pre-warm

If you can't clear cache on every save, use the debug translator in staging only and accept a short lag in prod, or add a small event subscriber that invalidates the catalogue for the affected locale on save.

Headless / mixed environments

If your Laravel app needs to read translations written via this Symfony UI, don't duplicate the write path. Point Laravel's translation loader at the same table (or expose a small read-only JSON endpoint from Symfony and cache it in Redis with a TTL keyed on a translations_version row). Shared table + spatie/laravel-translation-loader is less code and fewer moving parts than an endpoint, if the schema matches.

Gotchas and Tips

Licensing is the first thing to resolve, not the last. The repo reports NOASSERTION — no recognized LICENSE file. LexikTranslationBundle itself is MIT, but a fork/extraction with no license grant is legally "all rights reserved" by default. Before this goes into anything commercial, open an issue asking the maintainer to add a LICENSE file, or budget for a clean-room reimplementation from the Lexik original (MIT, so you can lift it legally).

Zero stars, zero dependents means zero safety net. No Stack Overflow answers, no CVE feed coverage, no one else hitting the bug before you. Concretely: pin the version, vendor a fork under your own namespace if you need patches, and add a smoke test that boots the kernel and hits the index route so an upgrade can't silently break the UI. Read every file in the bundle before trusting it — it's a small package, and it sits on a write path to production data.

The UI runs on raw translation-table writes with no optimistic locking. Two translators on the same key = last write wins, silently, including on the same locale. If your team is more than one translator, that's a real data-loss path. Mitigate with per-domain assignment (one owner per domain) or add a updated_at-based conflict check in a forked controller.

Template overrides are your main extension point. Symfony's bundle override convention applies: create templates/bundles/ForciLexikTranslationUiBundle/<path> to override views without touching vendor/. Confirm the exact view paths from Resources/views/ first — get the directory name wrong and your override silently does nothing. Same for controllers: override the route to your own controller and call the bundle's as a parent, rather than editing vendor code.

Debugging checklist when the grid is empty or saves don't stick:

  • debug:router | grep -i translation — are routes actually mounted?
  • debug:container | grep -i lexik — is the storage service wired to Doctrine, or still on the filesystem?
  • Check managed_locales — a locale not in this list won't render as a column and its values may be silently dropped.
  • Check the translation table has rows: run an import before opening the UI. An empty table looks identical to a broken bundle.
  • Saving but not seeing it: 95% of the time it's the translation cache, not the write.

Performance cliffs. The grid loads all keys for a domain in one page. At ~2–3k keys it becomes unusable and starts timing out behind a proxy. If you're heading there, filter by domain aggressively and add pagination in a fork; don't discover this with a translator on a deadline.

Never expose it publicly, even briefly. "I'll secure it after I check it works" is how translation tables get edited by strangers. Add the firewall entry in the same commit that mounts the route. Also confirm the bundle's forms carry CSRF tokens — unverified third-party bundles are a common place to find them missing — and check the save action against your CSRF config if it's stateless.

Missing-key logging is the feature that justifies the DB. If you're not capturing untranslated keys from production traffic, the UI is just a worse YAML editor. Turn on translator logging in a low-traffic window, let it accumulate for a week, then batch through the UI. That loop — log, triage, edit, ship without deploy — is the actual day-to-day value.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect