andrewdwallo/transmatic
Transmatic brings automatic multilingual support to Laravel Eloquent models. Add the trait, mark translatable attributes, and it stores and syncs translations per locale using Google Translate—so you can ship localized content without manual language files or duplicate columns.
transmatic is Andrew Wallo's Laravel translation-management package. v1.2.0's headline change is Laravel 12 support — the only functional addition in this release — so treat this version as the minimum for any Laravel 12 application.
Minimal setup:
composer require andrewdwallo/transmatic
php artisan vendor:publish --tag="transmatic-config"
php artisan migrate
First places to look:
config/transmatic.php — the published config is the map of the package. Read it end-to-end before writing any code; it controls locales, storage/driver choices, and the route/UI registration.php artisan list | grep transmatic — the package exposes artisan commands; these are the fastest way to see what it actually does in your app.First use case: point the package at a small, non-critical set of translation keys or one model's translatable attributes, run the sync/import command, and verify the round-trip (DB → files, files → DB) before touching production translations. Because it stores translations, treat the first run as a migration rehearsal on a throwaway database.
Compatibility note for this release: if you are on Laravel 11 and pinning ^1.1, nothing in v1.2.0 forces an upgrade — the only other change is a Dependabot bump of aglipanci/laravel-pint-action in CI, which does not ship in the package. Upgrade when you move to Laravel 12, or opportunistically to stay on a supported branch.
Config-first wiring. Resolve everything through config('transmatic.*') rather than hard-coding locales or paths. In tests, override config with config([...]) in setUp() so you never depend on the developer's local .env.
Environment separation. Translation management is a write-heavy, destructive-if-wrong concern. Gate the package's routes/UI behind a non-production middleware or Gate in AppServiceProvider:
Gate::define('manage-translations', fn ($user) => $user->isAdmin() && ! app()->isProduction());
Deploy pipeline integration. The natural workflow is: developers edit source strings in code → a CI/deploy step runs the package's sync command → translations land in the database or the locale files → cache is cleared. Wire it as a deploy hook rather than a manual step, and make it idempotent so re-running is safe.
Model translation pattern. For translatable attributes, keep the source-of-truth column and the translation storage distinct, and read through the package's accessor rather than joining tables by hand. Wrap bulk writes in DB::transaction() — translation sync across N locales is N×M writes and a partial failure leaves you with a locale that silently falls back.
Testing. Assert on resolved strings, not on rows in the translations table — the table schema is package-internal and has changed across minor versions historically. Use assertSame(__('key'), 'expected') after setting the locale explicitly with App::setLocale().
Multi-tenant / multi-locale. If your app has per-tenant locales, keep the tenant locale resolution in your own middleware and let the package handle storage only. Mixing the two is where this kind of package usually gets painful.
php artisan config:cache will freeze transmatic config values; if you toggle locales at runtime the cached config wins. Always config:clear locally after editing .env, and remember route:cache can mask newly registered package routes.vendor:publish. When you bump to a later release, re-publish into a temp path and diff against your copies — new config keys silently default to null otherwise, which produces confusing "feature does nothing" behaviour.fallback_locale means a missing translation renders the fallback string rather than failing. In tests, set config(['app.fallback_locale' => null]) (or assert against the key itself) when you actually want to catch gaps.laravel-pint-action change in this release is workflow-only; it does not affect your composer.lock. Don't go hunting for a code diff — the v1.2.0 payload is Laravel 12 constraint widening."andrewdwallo/transmatic": "^1.2" is the correct constraint for L12 projects. If Composer resolves to 1.1.x you will hit a framework constraint conflict that surfaces as an unrelated-looking install error.Verdict on v1.2.0: low-risk, additive release. No breaking changes, no deprecations. The only action item is upgrading the constraint if you are moving to Laravel 12.
How can I help you explore Laravel packages today?