Skip to content

Powerful translations manager for Laravel (auto translate, find dead/missing keys, ...)

License

Notifications You must be signed in to change notification settings

ElegantEngineeringTech/laravel-translator

Repository files navigation

All-in-One Translations Manager for Laravel

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Laravel Translator

Easily manage all your Laravel translation strings with powerful features:

  • Translate strings into other languages using DeepL, OpenAI, or custom services.
  • Proofread translations to fix grammar and syntax automatically (via OpenAI or custom services).
  • Find missing translation strings across locales.
  • Detect unused translation keys in your codebase.
  • Sort translations in natural order.

Try Laratranslate – A Powerful UI for Managing Translations

Laratranslate


Table of Contents

  1. How does it work?
  2. Installation
  3. Configuring the Driver
  4. Configuring the Locales
  5. Configuring the Code Scanner
  6. Sorting and Formatting
  7. Automatic Translation
  8. Proofreading Translations
  9. Identifying Untranslated Translations
  10. Detecting Missing Translations
  11. Detecting Dead Translations

How does it work?

This package will directly modify your translation files like /lang/en/messages.php or /lang/fr.json for example.

Both PHP and JSON files are supported.

Advanced features like dead translations detection will scan your entire codebase to find unused translation strings.

Installation

Install the package via Composer:

composer require elegantly/laravel-translator --dev

Add the following line to your .gitignore file:

storage/.translator.cache

Publish the configuration file:

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

Configuring the Driver

This package uses a driver-based architecture. By default, it supports two standard drivers: PHP and JSON.

  • Use the PHP driver if you store your translation strings in .php files, such as /lang/en/message.php.
  • Use the JSON driver if you store your translation strings in .json files, such as /lang/fr.json.

You can also create custom drivers for alternative storage methods, such as a database.

Set the default driver in the configuration file:

use Elegantly\Translator\Drivers\PhpDriver;

return [
    /**
     * Possible values: 'php', 'json', or a class-string implementing Driver.
     */
    'driver' => PhpDriver::class,

    // ...
];

Note

All features are supported in both the PHP and JSON drivers.

Configuring the Locales

Automatic Detection

By default, this package will attempt to determine the locales defined in your application by scanning your lang directory.

You can customize this behavior in the configuration file.

use Elegantly\Translator\Support\LocaleValidator;

return [
    // ...
    'locales' => LocaleValidator::class,
    // ...
];

Manual Setup

To set the locales manually, use the following configuration:

return [
    // ...
    'locales' => ['en', 'fr', 'es'],
    // ...
];

Configuring the Code Scanner

Service: searchcode.

Features:

Both the detection of dead and missing translations rely on scanning your code.

  • Missing translations are keys found in your codebase but missing in translation files.
  • Dead translations are keys defined in your translation files but unused in your codebase.

Requirements

At the moment, this package can only scan the following files:

  • .php
  • .blade.php

Note

If you use a React or Vue frontend, it would not be able to scan those files, making this feature irrelevant.

The default detector uses nikic/php-parser to scan all your .php files, including the Blade ones.

In order to be able to detect your keys, you will have to use one of the following Laravel function:

  • __(...),
  • trans(...)
  • trans_choice(...)
  • \Illuminate\Support\Facades\Lang::get(...)
  • \Illuminate\Support\Facades\Lang::has(...)
  • \Illuminate\Support\Facades\Lang::hasForLocale(...)
  • \Illuminate\Support\Facades\Lang::choice(...)
  • app('translator')->get(...)
  • app('translator')->has(...)
  • app('translator')->hasForLocale(...)
  • app('translator')->choice(...)

Or one of the following Laravel Blade directive:

  • @lang(...)

Here is some example of do's and don'ts:

__('messages.home.title'); // âś… 'messages.home.title' is detected

foreach(__('messages.welcome.lines') as $line){
    // âś… 'messages.welcome.lines' and all of its children are detected.
}

$key = 'messages.home.title';
__($key); // ❌ no key is detected

Included Paths

Specify paths to scan for translation keys. By default, both .php and .blade.php files are supported.

return [
    'searchcode' => [
        'paths' => [
            app_path(),
            resource_path(),
        ],
    ],
];

Excluded Paths

Exclude irrelevant paths for optimized scanning, such as test files or unrelated directories.

return [
    'searchcode' => [
        'excluded_paths' => [
            'tests'
        ],
    ],
];

Ignored Translation Keys

Ignore specific translation keys:

return [
    'searchcode' => [
        'ignored_translations' => [
            'countries', // Ignore keys starting with 'countries'.
        ],
    ],
];

Sorting and Formatting

CLI Commands

Sort translations with the default driver:

php artisan translator:sort

Specify a driver for sorting:

php artisan translator:sort --driver=json

Using Code

Sort translations programmatically with the default driver:

use Elegantly\Translator\Facades\Translator;

Translator::sortTranslations(locale: 'fr');

Specify a driver:

Translator::driver('json')->sortTranslations(locale: 'fr');

Automatic Translation

Service: translate.

Before translating, configure a translation service. The package supports:

  • OpenAI
  • DeepL

Custom translation services can also be implemented.

Configuring OpenAI

Define your OpenAI credentials in the configuration file or via environment variables:

return [
    // ...

    'services' => [
        'openai' => [
            'key' => env('OPENAI_API_KEY'),
            'organization' => env('OPENAI_ORGANIZATION'),
            'request_timeout' => env('OPENAI_REQUEST_TIMEOUT'),
        ],
    ],

    // ...
];

Configuring DeepL

Add your DeepL API key to the configuration file or environment variables:

return [
    // ...

    'services' => [
        // ...
        'deepl' => [
            'key' => env('DEEPL_KEY'),
        ],
    ],

    // ...
];

CLI Translation

Display all keys defined in the source locale (English) but not translated in the target (French):

php artisan translator:untranslated en fr

Translate untranslated English strings into French:

php artisan translator:untranslated en fr --translate

Translate using a specific driver:

php artisan translator:untranslated en fr --translate --driver=json

Add a new locale (French) with their translations from a source (English):

php artisan translator:add-locale fr en --translate

Programmatic Translation

Translate translations programmatically with the default driver:

Translator::translateTranslations(
    source: 'en',
    target: 'fr',
    keys: ['validation.title', ...]
);

Specify a driver for translation:

Translator::driver('json')->translateTranslations(
    source: 'en',
    target: 'fr',
    keys: ['My Title', ...]
);

Proofreading Translations

Service: proofread.

Proofreading corrects the grammar and syntax of your translation strings.

Currently, OpenAI is the only built-in service, but custom services can be implemented.

To configure OpenAI, see Configuring OpenAI.

CLI Proofreading

Proofread all strings in the target locale (English).

php artisan translator:proofread en

Programmatic Proofreading

Proofread translations with the default driver:

Translator::proofreadTranslations(
    locale: 'fr',
    keys: ['auth.email', ...]
);

Specify a driver:

Translator::driver('json')->proofreadTranslations(
    locale: 'fr',
    keys: ['My Title', ...]
);

Identifying Untranslated Translations

Find keys defined in one locale but missing in another.

CLI Usage

Display all keys defined in the source locale (English) but not in the target locale (French).

php artisan translator:untranslated en fr

Programmatic Usage

Translator::getUntranslatedTranslations(source: 'en', target: 'fr');

Detecting Missing Translations

Service: searchcode. Configuration: Configuring the Code Scanner

Missing translations are keys found in your codebase but missing in translation files.

CLI Usage

Find keys defined in your codebase but missing in your locale (English) using your default driver:

php artisan translator:missing en

Specify a driver:

php artisan translator:missing en --driver=json

Add the missing keys to your driver:

php artisan translator:missing en --sync

Programmatic Usage

Translator::getMissingTranslations(locale: 'en');

Detecting Dead Translations

Service: searchcode. Configuration: Configuring the Code Scanner

Dead translations are keys defined in your locale (English) but unused in your codebase.

CLI Usage

php artisan translator:dead en

Programmatic Usage

Translator::getDeadTranslations(locale: 'fr');

Testing

Run tests using:

composer test

Changelog

See the CHANGELOG for recent updates.


Contributing

Check the CONTRIBUTING guide for details.


Security Vulnerabilities

Report security vulnerabilities via GitHub or email.


Credits


License

This package is licensed under the MIT License. See the License File for more details.