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 in Laravel

  1. Install the package:

    composer require gettext/translator
    
  2. Create a translator instance in app/Providers/AppServiceProvider.php:

    use Gettext\Translator;
    use Gettext\TranslatorFunctions;
    
    public function register()
    {
        $translator = new Translator();
        $translator->setLanguage(config('app.locale'));
    
        // Load translations from PHP arrays (generated from .po files)
        $translator->loadTranslations(
            resource_path('lang/gl/messages.php'),
            resource_path('lang/gl/validation.php')
        );
    
        // Register global translation functions
        TranslatorFunctions::register($translator);
    }
    
  3. Use translations in Blade:

    <h1><?= __('Welcome') ?></h1>
    <p><?= _e('Hello, %s!', ['name' => 'John']) ?></p>
    
  4. Generate translation files (one-time setup):

    • Convert .po files to PHP arrays using Gettext\Extractors\PhpArray:
      vendor/bin/php-gettext extract --format=php --output-dir=resources/lang/gl messages.po
      

First Use Case: Localizing a Form

// In a controller
public function showForm()
{
    $errors = [
        'email' => 'The email field is required.',
    ];

    return view('form', [
        'errors' => $errors,
    ]);
}
<!-- resources/views/form.blade.php -->
<form>
    <div class="error">
        @if($errors->has('email'))
            <p>{{ trans('validation.required', ['attribute' => __('Email')]) }}</p>
        @endif
    </div>
</form>

Implementation Patterns

1. Domain-Specific Translations

Leverage domains to organize translations (e.g., messages, validation, auth):

$translator->loadDomain('validation', resource_path('lang/gl/validation.php'));
echo $translator->gettext('validation.required', ['attribute' => 'Email']);

Laravel Integration Tip: Map Laravel’s default domains to this package’s domains in AppServiceProvider:

$translator->loadDomain('messages', resource_path('lang/gl/messages.php'));
$translator->loadDomain('validation', resource_path('lang/gl/validation.php'));

2. Hybrid Mode for Performance

Use GettextTranslator in production if the gettext extension is available:

use Gettext\GettextTranslator;

if (extension_loaded('gettext')) {
    $translator = new GettextTranslator();
    $translator->setLanguage(config('app.locale'));
    $translator->loadDomain('messages', base_path('resources/lang/gl/LC_MESSAGES'));
} else {
    $translator = new Translator();
    // Fallback to pure PHP
}

Workflow:

  • Development: Use Translator for debugging (e.g., missing translations).
  • Production: Auto-switch to GettextTranslator via AppServiceProvider.

3. Pluralization and Context

Handle pluralization with ngettext:

echo $translator->ngettext(
    'There is %d item.',
    'There are %d items.',
    $count,
    ['count' => $count]
);

Laravel Compatibility: Override Laravel’s pluralization logic in app/Providers/AppServiceProvider:

$translator->setPluralForm(
    Translator::PLURAL_RULES['es'] // Spanish plural rules
);

4. Blade Template Integration

Register global functions in AppServiceProvider:

TranslatorFunctions::register($translator);

Now use __(), _e(), trans(), etc., in Blade:

<p>{{ __('Hello, :name!', ['name' => $user->name]) }}</p>
<p>{{ _e('Escaped HTML: <b>bold</b>') }}</p>

Extraction Tip: Use Gettext\Extractors\PhpCode to scan Blade files for translation strings:

vendor/bin/php-gettext extract --format=php --output-dir=resources/lang/gl app/Views/*.blade.php

5. Dynamic Locale Switching

Change language per request (e.g., for user preferences):

$translator->setLanguage($request->get('locale', config('app.locale')));

Middleware Example:

public function handle($request, Closure $next)
{
    app('translator')->setLanguage($request->get('locale', 'en'));
    return $next($request);
}

6. Fallback Chain

Ensure missing translations fall back to default locale:

$translator->setFallbackLocale('en');
echo $translator->gettext('missing.key'); // Falls back to 'en/messages.php'

Laravel Sync: Mirror Laravel’s fallback chain in config/app.php:

'fallback_locale' => 'en',

Gotchas and Tips

Pitfalls

  1. File Path Confusion:

    • GettextTranslator expects .mo files in locale/LC_MESSAGES/domain.mo, while Translator uses .php arrays.
    • Fix: Use absolute paths or symlinks to align directories.
  2. Pluralization Mismatches:

    • Laravel’s default pluralization rules may differ from gettext standards.
    • Fix: Explicitly set plural rules:
      $translator->setPluralForm(Translator::PLURAL_RULES['es']);
      
  3. Caching .mo Files:

    • GettextTranslator compiles .po to .mo at runtime. Pre-compile for production:
      msgfmt resources/lang/gl/LC_MESSAGES/messages.po -o resources/lang/gl/LC_MESSAGES/messages.mo
      
  4. Blade Escaping:

    • _e() escapes HTML, but __() does not. Mixing them may cause XSS.
    • Tip: Use _e() for user-generated content.
  5. Domain Loading Order:

    • Later loadDomain() calls override earlier ones.
    • Fix: Load domains in dependency order (e.g., validation before messages).

Debugging Tips

  1. Missing Translations:

    • Check if the .php/.mo file exists and paths are correct.
    • Enable debug mode:
      $translator->setDebug(true);
      
  2. Locale Not Switching:

    • Verify setLanguage() is called before translations are loaded.
    • Check for typos in locale codes (e.g., gl_ES vs. gl).
  3. Performance Issues:

    • Profile with GettextTranslator vs. Translator:
      $start = microtime(true);
      $translator->gettext('key');
      echo microtime(true) - $start; // Compare results
      
  4. Pluralization Errors:

    • Test with known plural rules (e.g., Spanish, Russian).
    • Use ngettext() directly to isolate issues.

Extension Points

  1. Custom Extractors:

    • Extend Gettext\Extractors\ExtractorInterface to support new file formats (e.g., JSON).
  2. Translation Middleware:

    • Create middleware to set locale from headers/cookies:
      public function handle($request, Closure $next)
      {
          $locale = $request->cookie('locale') ?: config('app.locale');
          app('translator')->setLanguage($locale);
          return $next($request);
      }
      
  3. Translation Commands:

    • Build artisan commands for common tasks:
      php artisan translate:extract
      php artisan translate:compile
      
  4. Service Provider Integration:

    • Bind the translator to Laravel’s container:
      $this->app->singleton('translator', function () {
          $translator = new Translator();
          $translator->setLanguage(config('app.locale'));
          return $translator;
      });
      
    • Override Laravel’s trans() helper:
      app()->bind('translator', function () {
          return app('gettext.translator');
      });
      

Configuration Quirks

  1. Locale Directory Structure:

    • GettextTranslator expects:
      /locale/
        /gl/
          LC_MESSAGES/
            messages.mo
      
    • Translator expects:
      /resources/lang/
        gl/
          messages.php
      
  2. Default Locale:

    • Set in AppServiceProvider:
      $translator->setLanguage(config('app.locale'));
      
  3. Character Encoding:

    • Ensure .po files use UTF-8. Convert with:
      iconv -f ISO-8859-1 -t UTF-8 input.po
      
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.
redaxo/project
ilhamsyabani/laravel-volt-starter
thethunderturner/filament-latex
ghostcompiler/laravel-querybuilder
webrek/laravel-telescope-mongodb
anousss007/blatui
zatona-eg/zatona-eg-api
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects