escolalms/translations
Translation management for Laravel applications from EscolaLMS. Organize and edit language strings, manage locale files, and expose translations through the API, making multilingual content easy to maintain.
escolalms/translations is the EscolaLMS package that moves Laravel translations out of lang/*.php and into the database, then exposes them over an authenticated REST API so non-developers can edit copy without a deploy. It is a 0.1.x package — treat it as moving fast and pin it.
composer require escolalms/translations
# publish config + migrations (tags vary; check the README for the exact tag list)
php artisan vendor:publish --provider="EscolaLMS\Translations\Providers\TranslationsServiceProvider"
php artisan migrate
Where to look first, in order:
config/escolalms-translations.php — locale list, table name, cache toggle, and whether the DB loader is enabled.src/Providers/* — confirm the service provider is auto-discovered and see whether it rebinds translation.loader.src/Http/Controllers + src/Routes — the actual API surface, including the Swagger-annotated admin endpoints that 0.1.1 touched.src/Console — any import/export commands; this is where file→DB migration lives.First use case to prove the install end-to-end: import your existing lang/ files into the DB, hit the admin list endpoint for a locale, edit one key, and confirm the change appears via __() without clearing anything manually.
php artisan tinker
>>> __('validation.required') // should resolve from DB after import
If that returns the file value and not your DB edit, the loader is not swapped and nothing else in the package will behave as documented.
Bootstrap the DB from files once, then stop shipping strings. Use the package's import command (or wrap it in your own Artisan command iterating lang/*/*.php) inside a seeder so fresh environments are populated deterministically. Keep the lang/ files in the repo as the seed of truth, but treat the DB as the runtime source after that.
Scope edits by group/namespace. Translations are keyed by group (Laravel's file.group.key convention). Give the admin API consumers a group filter rather than exposing the whole table — it maps cleanly to how the frontend admin panel organizes screens, and it keeps permission scoping sane.
Wire the admin routes behind EscolaLMS's usual stack. These packages assume auth + the strict-permission middleware for admin endpoints. Register the permissions in your seeder and gate the translation table on a dedicated permission (e.g. a translations-manage ability) rather than reusing a general admin role — translation editing is a content role, not an engineering one.
Serve translations to SPAs as a single locale payload. Rather than letting the frontend issue per-key requests, add a thin controller over the package's repository that returns { group: { key: value } } for one locale and cache it. This is the highest-leverage integration point: one cached endpoint covers the whole UI.
Invalidate cache on write. If the config enables translation caching, an update through the API must bust the relevant locale/group key. Do it in a model observer or an event listener on the package's save event, not in the controller, so seeders and console edits get the same behavior.
In tests, seed translations explicitly. Use RefreshDatabase, then run a small fixture seeder that inserts only the keys under test. Asserting on __() against a half-imported translation table produces failures that look like logic bugs but are data bugs.
Wrap the package behind your own thin service. One class with get, set, import, export methods that delegates to the package. When 0.1.x breaks something (it will), you change one file.
lang/ file and see no change, that is why. Decide the precedence deliberately and document it.UPDATE on the translations table (bypassing the API), run php artisan cache:clear or the package's own cache command before debugging anything else.0.1.1 change (fix swagger) is documentation metadata only — no schema, route, or behavior change. You only observe it if you run php artisan l5-swagger:generate and inspect the generated spec for the translation endpoints. Nothing to migrate, nothing to re-test beyond your normal suite. Do regenerate and commit the spec if you vendor it.0.x version pinning. 0.1.0 → 0.1.1 looks like a patch, but pre-1.0 packages reserve the right to break in patch releases. Pin to an exact version in composer.json rather than ^0.1.utf8mb4 on the translations table and matching collation; the default Laravel migration may not be enough depending on your DB version.__() returns DB value in tinker? Work top-down — in practice it is almost always step 2 or 3.How can I help you explore Laravel packages today?