ipsumlab/laravel-auto-translations

Automatically generates missing translation keys (JSON) by intercepting __(), trans() and @lang() calls in Laravel.

Maintainers

Package info

gitlab.com/ipsumlab/laravel-auto-translations

Issues

pkg:composer/ipsumlab/laravel-auto-translations

Transparency log

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

1.0.0 2026-07-11 11:45 UTC

This package is not auto-updated.

Last update: 2026-07-11 16:09:10 UTC


README

Composer package for Laravel >= 5.8 that automatically generates missing translation keys in JSON format by intercepting every call to __(), trans() and the Blade @lang() directive.

Handy during development: write your markup with __('Save changes') and, if the key is missing, it gets added on its own to lang/{locale}.json (or resources/lang/{locale}.json on Laravel versions prior to 9), ready to be translated.

Features

  • No changes needed to your application code: works on __(), trans(), trans_choice() and @lang(), since they all go through the same Laravel Translator, which this package extends.
  • Enabled by default only in the local environment (configurable).
  • Ignores empty strings.
  • Ignores "structured" keys already handled by Laravel's PHP translation files (e.g. validation.required, auth.failed, pagination.previous), so it never interferes with their resolution.
  • Safe writes via flock(): no JSON corruption even with multiple concurrent requests (useful with php artisan serve, Octane, queue workers, etc.).
  • Publishable config for enabling/disabling, overwriting existing keys, and choosing the target locale.
  • Registers itself automatically thanks to Laravel's package auto-discovery: no need to touch AppServiceProvider.

Requirements

  • PHP ^7.1.3|^8.0
  • Laravel >= 5.8 (tested up to the most recent versions)

Installation

1. Require the package via Composer

composer require ipsumlab/laravel-auto-translations

Thanks to extra.laravel.providers in the package's composer.json, AutoTranslatorServiceProvider is registered automatically via Laravel's package auto-discovery. You don't need to add anything to app/Providers/AppServiceProvider.php or to config/app.php.

If you've disabled package discovery for this package (i.e. you have a dont-discover entry in your app's composer.json), register the provider manually in config/app.php:

'providers' => [
    // ...
    Ipsumlab\AutoTranslations\AutoTranslatorServiceProvider::class,
],

2. (Optional) Publish the config

php artisan vendor:publish --tag=auto-translator-config

This creates config/auto-translator.php, where you can customize whether the package is enabled, whether existing keys get overwritten, the target locale, and which translation groups (validation, auth, etc.) are ignored:

return [
    'enabled' => env('AUTO_TRANSLATOR_ENABLED', app()->environment('local')),
    'overwrite_existing' => env('AUTO_TRANSLATOR_OVERWRITE', false),
    'locale' => env('AUTO_TRANSLATOR_LOCALE', null),
    'ignored_groups' => ['validation', 'auth', 'passwords', 'pagination'],
];

If you skip this step, the package still works out of the box using these same defaults (config values are merged automatically via mergeConfigFrom()).

3. (Optional) Wire it into your own AppServiceProvider

The package works without touching any of your own provider files. If you'd rather wire the binding yourself — for example to keep full control over provider order, or to swap it in only under certain conditions — you can replicate the same logic directly inside app/Providers/AppServiceProvider.php:

use Ipsumlab\AutoTranslations\Translation\AutoTranslator;

public function register()
{
    $this->app->singleton('translator', function ($app) {
        $trans = new AutoTranslator($app['translation.loader'], $app['config']['app.locale']);
        $trans->setFallback($app['config']['app.fallback_locale']);

        return $trans;
    });
}

In that case you can remove Ipsumlab\AutoTranslations\AutoTranslatorServiceProvider from your discovered providers (via dont-discover) to avoid registering the binding twice.

Environment variables (.env)

VariableDefaultDescription
AUTO_TRANSLATOR_ENABLEDtrue only if APP_ENV=localEnables/disables the package
AUTO_TRANSLATOR_OVERWRITEfalseIf true, overwrites keys already present in the JSON with the placeholder
AUTO_TRANSLATOR_LOCALE(empty = current app locale)Forces the locale to write missing keys into, e.g. en

Example .env:

AUTO_TRANSLATOR_ENABLED=true
AUTO_TRANSLATOR_OVERWRITE=false
AUTO_TRANSLATOR_LOCALE=en

How it works

  1. The package's provider replaces Laravel's translator binding with Ipsumlab\AutoTranslations\Translation\AutoTranslator, a subclass of Illuminate\Translation\Translator.
  2. Every time get() (used by __() and trans()) or choice() (used by trans_choice()) is called, the class:
    • lets Laravel resolve the translation as usual;
    • if the returned value matches the key itself, it means the translation is missing;
    • skips the key if it's empty;
    • skips the key if it belongs to an existing structured group (validation.*, auth.*, etc., or any group listed in ignored_groups, or any group for which a lang/{locale}/{group}.php file actually exists);
    • otherwise calls JsonTranslationWriter, which opens lang/{locale}.json with flock(LOCK_EX), adds the missing key (initial value = the key itself, as a placeholder) and rewrites the file atomically.
  3. If the key already exists in the JSON file and overwrite_existing is false (default), it's left untouched: translations you've already filled in by hand are never lost.

Example

{{-- resources/views/welcome.blade.php --}}
<h1>@lang('Welcome to our application')</h1>
<p>{{ __("Don't have an account?") }}</p>

On the first page load (with the package enabled), lang/en.json is created or updated:

{
    "Don't have an account?": "Don't have an account?",
    "Welcome to our application": "Welcome to our application"
}

From there you can go in and fill in the actual translations on the right-hand side.

Important notes

  • Performance: every missing key triggers a file open with a lock. This is meant for development/staging use; that's why it's enabled by default only when APP_ENV=local. Avoid leaving it enabled in production.
  • Language file path: the package automatically detects whether the app uses resources/lang (Laravel <= 8) or lang/ (Laravel >= 9, via app()->langPath()), including any custom path configuration.
  • Key source: as with all of Laravel's JSON translation functionality, the key must be the exact string used in __() / trans() / @lang(); slightly different strings (spacing, casing, punctuation) will generate separate entries.
  • Config/translation caching: if you run php artisan config:cache in production, keep in mind that environment variables read inside the config file get "frozen" — that's fine, since the package should be disabled in production anyway.

License

MIT.