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

Translation Laravel Package

symfony/translation

Symfony Translation component for internationalizing PHP apps: create a Translator, load messages from arrays, files, or other loaders, handle locales and domains, and translate strings at runtime. Part of the Symfony ecosystem and works well standalone.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package (if not using Laravel’s built-in translation):

    composer require symfony/translation
    

    (Note: Laravel already bundles this component; no extra install needed for core functionality.)

  2. Configure locales in config/app.php:

    'locale' => 'en',
    'fallback_locale' => 'en',
    'supportedLocales' => [
        'en' => 'English',
        'fr' => 'Français',
        'es' => 'Español',
    ],
    
  3. First translation use case:

    • Define translations in resources/lang/{locale}/messages.php:
      return [
          'welcome' => 'Welcome, :name!',
          'validation' => [
              'required' => 'The :attribute field is required.',
          ],
      ];
      
    • Use in Blade:
      {{ __('messages.welcome', ['name' => 'John']) }}
      
    • Or in PHP:
      $translated = trans('messages.welcome', ['name' => 'John']);
      
  4. Dynamic locale switching (e.g., based on user preference):

    app()->setLocale($user->locale);
    

Implementation Patterns

1. Translation Domains

Organize translations by domain (e.g., validation, auth, notifications) for modularity:

// Load a specific domain
$translator->trans('validation.required', [], null, 'validation');

// In Laravel, domains are auto-loaded from `resources/lang/{locale}/{domain}.php`

2. Loader Integration

Leverage Symfony’s loaders for non-PHP formats (e.g., YAML, JSON, XLIFF):

use Symfony\Component\Translation\Loader\YamlFileLoader;

// Add YAML loader for translations
$loader = new YamlFileLoader();
$translator->addLoader('yaml', $loader);
$translator->addResource('yaml', 'path/to/translations.yml', 'fr_FR');

3. Caching Translations

Cache translations for performance (Laravel handles this automatically via FileCache):

$translator = new Translator('en', new FileCache(), new ArrayLoader());

4. Parameterized Messages

Use placeholders for dynamic content:

// Translation file
'email.subject' => 'Your order #:order_id is confirmed!';

// Usage
trans('email.subject', ['order_id' => 12345]);

5. Fallback Logic

Configure fallback locales in config/app.php:

'fallback_locale' => 'en',

If fr_FR translation is missing, it falls back to en.

6. Validation Messages

Override Laravel’s default validation messages:

// resources/lang/fr/validation.php
return [
    'required' => 'Le champ :attribute est obligatoire.',
];

7. Locale-Specific Formatting

Use Symfony’s Intl integration for dates, numbers, and plurals:

use Symfony\Component\Translation\TranslatorInterface;

// Format a date for the current locale
$formattedDate = $translator->transChoice(
    'There is {0} no message|{1} one message|[2,*] %count% messages.',
    2,
    ['%count%' => 2]
);

8. Testing Translations

Mock translations in tests:

$translator = $this->createMock(TranslatorInterface::class);
$translator->method('trans')->willReturn('Mocked translation');
$this->app->instance(TranslatorInterface::class, $translator);

9. Integration with Blade Directives

Create custom Blade directives for reusable translation logic:

// app/Providers/BladeServiceProvider.php
Blade::directive('transChoice', function ($expression) {
    return "<?php echo app('translator')->transChoice({$expression[0]}, {$expression[1]}, {$expression[2]}); ?>";
});

// Usage in Blade
@transChoice('messages.plural', count($items), ['%count%' => count($items)])

10. Translation Management Workflow

  1. Extract strings from code/views using tools like laravel-translation-manager.
  2. Push to Crowdin/Lokalise via CLI or API:
    php vendor/bin/translation:push --locale=fr --force
    
  3. Pull translations back:
    php vendor/bin/translation:pull --locale=fr
    

Gotchas and Tips

Pitfalls

  1. Locale Mismatch in URLs

    • If using route-based locales (e.g., /fr/dashboard), ensure middleware sets the locale:
      public function handle($request, Closure $next) {
          $locale = $request->segment(1);
          if (in_array($locale, config('app.supportedLocales'))) {
              app()->setLocale($locale);
          }
          return $next($request);
      }
      
  2. Caching Issues

    • Clear translation cache after pulling new translations:
      php artisan cache:clear
      
    • Laravel’s FileCache stores translations in bootstrap/cache/.
  3. Missing Fallback Locale

    • Always define fallback_locale in config/app.php to avoid runtime errors.
  4. YAML/JSON Parsing Errors

    • Ensure files are UTF-8 encoded. Use yaml or json loaders for non-PHP formats:
      $translator->addResource('yaml', 'path/to/translations.yml', 'fr_FR');
      
  5. Pluralization Rules

    • Symfony uses ICU rules for plurals. Test edge cases (e.g., Arabic, Russian) with:
      $translator->transChoice('messages.items', 1, ['%count%' => 1]);
      
  6. Translation Keys Collisions

    • Avoid duplicate keys across domains. Use namespacing (e.g., auth.login, validation.email).
  7. Third-Party Loader Quirks

    • Crowdin/Lokalise: Use --force flag to avoid partial file overwrites:
      php vendor/bin/translation:push --locale=en --force
      
    • CSV Loaders: Empty lines may break parsing (fixed in v8.0.4+).
  8. Deprecated Methods

    • Avoid TranslatableMessage::__toString() (deprecated in Symfony 8). Use trans() or getMessage() instead.

Debugging Tips

  1. Check Loaded Resources

    $resources = $translator->getCatalogue('fr_FR')->getResources();
    dump($resources);
    
  2. Enable Debug Mode

    $translator->setFallbackLocale('en');
    $translator->setDebug(true); // Logs missing translations
    
  3. Validate Locale Codes

    • Use valid BCP-47 codes (e.g., en_US, fr_CA). Avoid en-us (hyphen vs. underscore).
  4. Test Locale-Specific Formatting

    • Use IntlDateFormatter for dates:
      use Symfony\Component\Intl\Intl;
      echo Intl::formatDateTime('2023-01-01', Intl::bestMatch('fr_FR', null, Intl::GREGORIAN, Intl::TRADITIONAL));
      

Extension Points

  1. Custom Loaders Create a loader for your format (e.g., Markdown):

    use Symfony\Component\Translation\Loader\LoaderInterface;
    
    class MarkdownLoader implements LoaderInterface {
        public function load($resource, $locale, $domain = 'messages') {
            $content = file_get_contents($resource);
            return ['content' => Markdown::parse($content)];
        }
    }
    
  2. Translation Filters Add filters to modify translations dynamically:

    $translator->addFilter('uppercase', function ($message) {
        return strtoupper($message);
    });
    // Usage: trans('message.key', [], 'uppercase')
    
  3. Event Listeners Listen to translation events (e.g., translator.message.not_found):

    $translator->addListener('translator.message.not_found', function ($event) {
        Log::warning("Missing translation: {$event->getId()}");
    });
    
  4. Laravel Service Provider Extend Laravel’s translator binding:

    public function register() {
        $this->app->extend('translator', function ($translator) {
            $translator->addLoader('custom', new CustomLoader());
            return $translator;
        });
    }
    

Performance Optimizations

  1. Preload Translations Load all locales at boot (tradeoff: higher memory usage):
    $translator->addResource('array', $translations, 'en');
    $translator
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport