tomatophp/tomato-translations-module
Translations manager module for Tomato PHP admin panels. Add, edit, and organize languages and translation keys from a Filament UI, with import/export support and a simple interface for managing multilingual strings across your Laravel application.
The tomato-translations-module is part of the Tomato PHP ecosystem (built by Fady Mondy) and slots into a Filament-backed admin panel. At v1.0.1 it is a young module, so treat the first hour as discovery.
Install and register.
composer require tomatophp/tomato-translations-module
Then run the module's installer (Tomato modules conventionally expose php artisan tomato:translations:install or a vendor:publish for migrations/config). If the command differs, check the package's README and src/TranslationsServiceProvider.php for registered commands and publish tags.
Where to look first.
config/translations.php (or whatever the package publishes) — locales list, scan paths, storage driver.src/Console/ — the new JSON scan feature is almost certainly surfaced as an artisan command or a Filament action. Look for a ScanJson / JsonScan command.First use case (and the reason for v1.0.1).
Point the scanner at your module's lang/ directories and let it merge keys into whatever store the module uses (DB table, JSON files, or cache). The json scan feature added in this release is the headline: it walks JSON translation files (e.g. lang/en.json, lang/ar.json in each module) and pulls the keys into the translations manager so you can see missing/extra entries per locale.
php artisan tomato:translations:scan --json
(Verify the exact flag — likely --json or a json argument — against php artisan list after install.)
Sanity check. Open the Filament panel, navigate to Translations, confirm keys were imported and grouped by module/locale.
1. Module-aware scanning. The v1.0.1 JSON scan is aimed at modules, not just the host app. The typical pattern is to register modules in config and let the scanner iterate:
// config/translations.php (illustrative)
'modules' => [
'blog' => base_path('Modules/Blog/lang'),
'shop' => base_path('Modules/Shop/lang'),
'vendor/ui' => base_path('vendor/tomatophp/tomato-ui/lang'),
],
Then the scanner globs *.json under each path and upserts keys. If the package uses module discovery (e.g. nwidart/laravel-modules), it will read module.json — check whether you need to enable that in config.
2. Run it on a schedule. Because scanning is idempotent (it upserts), the most common day-to-day pattern is a scheduled job so translation drift is caught automatically:
// routes/console.php or Kernel::schedule
Schedule::command('tomato:translations:scan --json')->daily();
3. CI gate.
Add a CI step that runs the scan with a --dry-run (if supported) and fails on missing keys. This is the single highest-value workflow for a translations module — it stops "untranslated key" bugs from reaching production.
4. Filament workflow.
Typical usage is: scan → review imported keys in the Filament table → edit/translate inline → export/publish. Pair the resource with Filament's ->pollingInterval() if you want the table to refresh after a scheduled scan fires.
5. Editing alongside developers.
Because the module stores keys, not necessarily values, a good pattern is: developers own keys in JSON (lang/en.json), the module owns translations in the DB, and a publish/export command writes back into the module's lang/ files. Check whether the package offers an export command; if not, this is the obvious extension point.
6. Multi-locale RTL.
Tomato is heavily used for Arabic-first projects — configure locales in the natural RTL order and verify the Filament table renders the locale column group sensibly.
src/Console/ before trusting the README, and pin the version in composer.json until the API stabilises.{"auth": {"failed": "..."}}) may be flattened to dot-notation (auth.failed). If you rely on nested arrays in your lang/*.json, verify the scanner preserves or flattens them consistently with Laravel's __() lookup.updateOrCreate, firstOrCreate, or overwrites — this affects which module "owns" a translation.config/view caches and the module's own cache (if any) may hold stale translation state. php artisan optimize:clear after a big scan is a cheap habit.vendor/ paths. If you configure the scanner to walk vendor/tomatophp/*/lang, remember that composer update can wipe edits. Never translate by editing vendor files directly — use the module's store.php artisan filament:about and the service provider's ->plugin() registration.mergeConfigFrom), and the scanner command is usually a good candidate to subclass if you need custom glob logic (e.g. only scan modules modified since the last commit).-vvv), then confirm the *.json files exist and are valid JSON (json_decode failures are typically swallowed quietly). One malformed JSON file can abort a whole directory walk.How can I help you explore Laravel packages today?