Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Translator Laravel Package

gettext/translator

Lightweight PHP translation layer for gettext/gettext. Use Translator to load PHP array translations without the native gettext extension, or GettextTranslator to leverage the extension with the same API. Includes global helper functions for template-friendly __().

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require gettext/translator
    
  2. Choose a translator class:
    • For pure PHP (no gettext extension):
      use Gettext\Translator;
      $t = new Translator();
      
    • For hybrid mode (uses gettext if available):
      use Gettext\GettextTranslator;
      $t = new GettextTranslator();
      
  3. Load translations:
    • For .php arrays (generated by Gettext\Extractors\PhpArray):
      $t->loadTranslations('locales/es/messages.php');
      
    • For .mo files (native gettext format):
      $t->loadDomain('messages', 'path/to/locales');
      
  4. Register global functions (for Blade templates):
    use Gettext\TranslatorFunctions;
    TranslatorFunctions::register($t);
    
    Now use __('key') in Blade like Laravel’s trans() helper.

First Use Case: Localizing a Blade View

  1. Generate translation files from your Blade templates:
    vendor/bin/php-gettext-extract --format=php --output=locales/es/messages.php resources/views/*.blade.php
    
  2. Edit the generated .php file to add translations:
    return [
        'welcome' => '¡Bienvenido!',
        'items' => [
            'one' => '1 artículo',
            'other' => '{0} artículos',
        ],
    ];
    
  3. Use in Blade:
    <h1><?= __('welcome') ?></h1>
    <p><?= __('items', 5) ?></p> <!-- Pluralization -->
    

Implementation Patterns

1. Service Provider Integration

Register the translator as a Laravel service provider to avoid manual instantiation:

// app/Providers/GettextServiceProvider.php
namespace App\Providers;

use Gettext\Translator;
use Gettext\TranslatorFunctions;
use Illuminate\Support\ServiceProvider;

class GettextServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton('gettext.translator', function () {
            $t = new Translator();
            $t->loadTranslations(config('gettext.locales.*.*.php'));
            return $t;
        });

        $this->app->booting(function () {
            TranslatorFunctions::register(app('gettext.translator'));
        });
    }
}

Register in config/app.php:

'providers' => [
    // ...
    App\Providers\GettextServiceProvider::class,
],

2. Dynamic Locale Switching

Bind the translator to the current locale (e.g., from app() or middleware):

// app/Http/Middleware/SetLocale.php
public function handle($request, Closure $next)
{
    $locale = $request->header('Accept-Language') ?? config('app.locale');
    app('gettext.translator')->setLanguage($locale);
    return $next($request);
}

3. Domain-Specific Translations

Load different domains for different parts of the app (e.g., validation, auth):

$t = new GettextTranslator();
$t->loadDomain('validation', 'locales/'.app()->getLocale().'/LC_MESSAGES');
$t->loadDomain('auth', 'locales/'.app()->getLocale().'/LC_MESSAGES');

4. Blade Directives for Context

Extend Blade to support context-aware translations (e.g., gettext('key', 'context')):

// app/Providers/BladeServiceProvider.php
Blade::directive('gettext', function ($expression) {
    return "<?php echo app('gettext.translator')->gettext({$expression}); ?>";
});

Usage in Blade:

<p>@gettext('welcome')</p>

5. Fallback Chain

Combine with Laravel’s fallback mechanism:

$t = new Translator();
$t->loadTranslations('locales/es/messages.php');
$t->loadTranslations('locales/en/messages.php', 'fallback'); // Fallback locale

6. Translation Extraction Workflow

Automate extraction from Blade/PHP files:

# Extract strings from Blade templates
vendor/bin/php-gettext-extract --format=php --output=locales/es/messages.php resources/views/*.blade.php

# Extract strings from PHP classes
vendor/bin/php-gettext-extract --format=php --output=locales/es/messages.php app/Http/Controllers/*.php

7. Testing Translations

Mock the translator in tests:

$t = new Translator();
$t->loadTranslations([
    'welcome' => 'Test Translation',
]);
$this->app->instance('gettext.translator', $t);

Gotchas and Tips

Pitfalls

  1. File Paths in .mo Files:

    • GettextTranslator expects .mo files in the standard locale/LC_MESSAGES/domain.mo structure.
    • Fix: Use absolute paths or configure the domain path correctly:
      $t->loadDomain('messages', base_path('locales'));
      
  2. Pluralization Mismatches:

    • Laravel’s default pluralization rules may differ from gettext standards.
    • Fix: Explicitly define plural forms in your .php translation files:
      return [
          'items' => [
              'one' => '1 artículo',
              'other' => '{0} artículos',
          ],
          'plural_forms' => 'nplurals=2; plural=(n != 1);', // Spanish example
      ];
      
  3. Global Function Overrides:

    • Registering TranslatorFunctions globally may conflict with Laravel’s __() helper.
    • Fix: Unregister Laravel’s helper first or use a namespace:
      TranslatorFunctions::register($t, '__gettext');
      // Now use `__gettext('key')` instead of `__('key')`.
      
  4. Caching .mo Files:

    • .mo files are compiled binaries. Changes require recompilation:
      msgfmt locales/es/LC_MESSAGES/messages.po -o locales/es/LC_MESSAGES/messages.mo
      
    • Tip: Use a Laravel command to automate this:
      // app/Console/Commands/CompileGettext.php
      public function handle()
      {
          $locales = ['es', 'fr'];
          foreach ($locales as $locale) {
              $this->compileLocale($locale);
          }
      }
      
      protected function compileLocale($locale)
      {
          $poFiles = glob(resource_path("lang/{$locale}/*.po"));
          foreach ($poFiles as $poFile) {
              $moPath = str_replace('.po', '.mo', $poFile);
              $this->call('msgfmt', [
                  'input' => $poFile,
                  'output' => $moPath,
              ]);
          }
      }
      
  5. Blade Caching Issues:

    • Blade caches compiled views, which may not reflect translation changes.
    • Fix: Clear Blade cache after updating translations:
      php artisan view:clear
      
  6. Locale Detection:

    • GettextTranslator uses environment variables (LANG, LC_ALL) by default.
    • Fix: Override in Laravel’s AppServiceProvider:
      $t = new GettextTranslator();
      $t->setLanguage(app()->getLocale());
      

Debugging Tips

  1. Check Loaded Translations:

    $t->gettext('nonexistent_key'); // Returns the key if not found
    $t->gettext('nonexistent_key', true); // Returns `null` if not found (2nd param = strict)
    
  2. Log Missing Translations:

    $t->setMissingHandler(function ($key, $locale) {
        Log::warning("Missing translation: {$key} in {$locale}");
    });
    
  3. Validate .po/.mo Files:

    msgattrib locales/es/LC_MESSAGES/messages.po  # Check for errors
    

Extension Points

  1. Custom Extractors:

    • Extend Gettext\Extractors\ExtractorInterface to support custom file formats (e.g., JSON):
      class JsonExtractor implements ExtractorInterface
      {
          public function extract($filePath)
          {
              $json = json_decode(file_get_contents($filePath), true);
              return $this->convertToPhpArray($json);
          }
      }
      
  2. Domain-Specific Loaders:

    • Create a custom loader for Laravel’s resources/lang structure:
      class LaravelDomainLoader
      {
          public function load($domain, $locale)
          {
              $path = resource_path("
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky