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 helps internationalize PHP apps with a powerful Translator, loaders, and resources (arrays, files, etc.). Define locales, add message catalogs, and translate strings with parameters and pluralization support across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require symfony/translation
    

    For Laravel, use symfony:translation as a dependency (often included via symfony/http-kernel or symfony/framework-bundle).

  2. Basic Setup:

    • Define translations in resources/lang/{locale}/{domain}.php (Laravel convention) or custom files.
    • Register the translator in Laravel’s service container (via config/app.php or a service provider):
      $translator = new \Symfony\Component\Translation\Translator('en');
      $translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
      $translator->addResource('php', __DIR__.'/../resources/lang/en/messages.php', 'en');
      app()->singleton('translator', fn() => $translator);
      
  3. First Use Case: Translate a string in a Blade view or controller:

    // Blade: @lang('messages.welcome')
    // PHP: app('translator')->trans('messages.welcome', ['%name%' => 'John']);
    

Where to Look First

  • Laravel Integration: Check vendor/symfony/translation/README.md for loader examples (PHP, YAML, JSON, XLIFF).
  • Laravel’s Built-in Translator: If using Laravel, leverage its built-in Translator facade (trans() helper) which wraps Symfony’s translator.
  • Configuration: Review config/app.php for locale defaults and fallback chains.

Implementation Patterns

Core Workflows

  1. Translation Loading:

    • Static Files: Use PhpFileLoader, YamlFileLoader, or JsonFileLoader for structured catalogs.
      $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
      $translator->addResource('yaml', $loader->load($filePath), 'en');
      
    • Dynamic Sources: Fetch translations from a database or API using a custom loader (implement LoaderInterface).
  2. Message Domains: Organize translations by domain (e.g., validation, auth) for modularity:

    $translator->addResource('yaml', $loader->load($filePath), 'en', 'validation');
    trans('validation.required', [], 'validation'); // Domain specified last
    
  3. Pluralization and Interpolation: Handle plural rules (e.g., Arabic, Russian) and dynamic values:

    // messages.php
    'apples' => 'You have {count, plural, =0 {no apples} one {one apple} other {# apples}}.',
    trans('messages.apples', ['%count%' => 5]); // "You have 5 apples."
    
  4. Fallback Chains: Define fallback locales to avoid missing translations:

    $translator->setFallbackLocales(['en' => ['fr', 'es']]);
    
  5. Caching: Cache compiled translations for performance:

    $translator->setCacheDir(__DIR__.'/../var/cache/translations');
    

Laravel-Specific Patterns

  1. Service Provider Binding: Bind Symfony’s translator to Laravel’s container in a service provider:

    public function register()
    {
        $this->app->singleton('translator', function ($app) {
            $translator = new \Symfony\Component\Translation\Translator($app['config']['app.locale']);
            $translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
            $translator->addResource('php', __DIR__.'/../../resources/lang/'.$app['config']['app.locale'].'/messages.php', $app['config']['app.locale']);
            return $translator;
        });
    }
    
  2. Blade Directives: Use Laravel’s @lang directive or trans() helper:

    @lang('messages.welcome', ['name' => $user->name])
    
  3. Validation Messages: Extend Laravel’s validator with custom translation domains:

    $validator = Validator::make($data, $rules, [], [], [
        'messages' => trans('validation.messages'),
    ]);
    
  4. Middleware for Locale Switching: Dynamically switch locales based on user preferences or headers:

    public function handle($request, Closure $next)
    {
        $locale = $request->header('Accept-Language') ?: config('app.locale');
        app('translator')->setLocale($locale);
        return $next($request);
    }
    
  5. Translation Dump: Export translations for external tools (e.g., Crowdin, Lokalise):

    php artisan translation:dump --format=json --domain=messages --locale=fr
    

Integration Tips

  • APIs: Use TranslatorInterface to inject translations into controllers or services.
  • Testing: Mock translations in tests:
    $translator = $this->createMock(TranslatorInterface::class);
    $translator->method('trans')->willReturn('Mocked translation');
    $this->app->instance(TranslatorInterface::class, $translator);
    
  • CLI Tools: Leverage Symfony’s TranslationPushCommand to sync translations with external services (e.g., Crowdin):
    php artisan translation:push --service=crowdin --token=your_token
    

Gotchas and Tips

Pitfalls

  1. Loader Registration Order:

    • Loaders are registered per locale/domain. Ensure the correct loader is added before calling addResource:
      // Wrong: Loader not registered for 'en' before adding resource
      $translator->addResource('yaml', $filePath, 'en');
      
      // Correct:
      $translator->addLoader('yaml', new YamlFileLoader());
      $translator->addResource('yaml', $filePath, 'en');
      
  2. Caching Issues:

    • Clear cache when translations change:
      php artisan cache:clear
      php artisan view:clear
      
    • For Symfony’s cache, manually delete files in var/cache/translations.
  3. Pluralization Rules:

    • Not all languages support pluralization. Use Intl for complex rules (e.g., Arabic’s 6 forms):
      $translator->setFallbackLocale('en'); // Fallback if pluralization fails
      
  4. File Paths in Loaders:

    • Absolute paths are preferred for loaders to avoid issues with relative paths in shared hosting:
      $translator->addResource('php', realpath(__DIR__.'/../../resources/lang/en/messages.php'), 'en');
      
  5. Locale Negotiation:

    • Laravel’s AppServiceProvider may override Symfony’s locale. Ensure consistency:
      // In AppServiceProvider boot()
      $locale = request()->header('X-Locale') ?: config('app.locale');
      app('translator')->setLocale($locale);
      
  6. XLIFF Loader Quirks:

    • The XliffFileLoader requires valid XLIFF 1.2 files. Invalid files may throw cryptic errors. Validate with:
      xmllint --noout your_file.xlf
      
  7. StaticMessage Deprecation:

    • In Symfony 8+, TranslatableMessage::__toString() is deprecated. Use getMessage() or trans() directly:
      // Avoid:
      echo $message; // Deprecated
      
      // Use:
      echo $message->getMessage();
      

Debugging Tips

  1. Missing Translations:

    • Check fallback locales and ensure files exist for all locales:
      if (!$translator->has('messages.welcome', 'fr')) {
          dd($translator->getFallbackLocales()); // Debug fallback chain
      }
      
    • Verify file paths with file_exists() before loading.
  2. Loader Errors:

    • Wrap loader calls in try-catch blocks to log errors:
      try {
          $translator->addResource('yaml', $loader->load($filePath), 'en');
      } catch (\Exception $e) {
          Log::error('Translation load error: '.$e->getMessage());
      }
      
  3. Performance Bottlenecks:

    • Profile translation calls with Xdebug or Blackfire. Caching is critical for large catalogs:
      $translator->setCacheDir(sys_get_temp_dir().'/translation_cache');
      
  4. Pluralization Debugging:

    • Test plural rules with the Intl library directly:
      use Symfony\Component\Intl\Intl;
      Intl::getMessageFormatter('en', '{count, plural, =0 {zero} one {one} other {many}}', 5)->getMessage();
      

Extension Points

  1. Custom Loaders:
    • Implement LoaderInterface for databases or APIs:
      class DatabaseLoader implements LoaderInterface {
          public function load
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope