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 Bundle Laravel Package

jms/translation-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require jms/translation-bundle
    

    Add to config/bundles.php (Symfony) or config/app.php (Laravel via bridge):

    JMS\TranslationBundle\JMSTranslationBundle::class => ['all' => true],
    
  2. Configuration: Publish the default config:

    php artisan vendor:publish --provider="JMS\TranslationBundle\JMSTranslationBundle" --tag=config
    

    Key settings in config/jms_translation.php:

    • locales: Define supported locales (e.g., ['en', 'fr']).
    • default_locale: Set default (e.g., 'en').
    • fallback_locale: Fallback for missing translations (e.g., 'en').
  3. First Use Case: Translate a string in a controller or blade:

    $translator = app('translator');
    echo $translator->trans('Hello world'); // Uses default locale
    echo $translator->transChoice('There is %count% apple', $count, ['%count%' => 1]); // Pluralization
    
  4. Translation Files: Create a translations directory in your project root (or configure custom path). Example structure:

    translations/
        messages.en.yml
        messages.fr.yml
    
    # translations/messages.en.yml
    hello_world: "Hello world"
    apples: "There is %count% apple|There are %count% apples"
    

Implementation Patterns

Core Workflows

1. Translation Extraction

  • Automatic Extraction: Use the jms:translation:extract command to scan controllers, views, and classes for __() or trans() calls:

    php artisan jms:translation:extract en
    

    Outputs a .pot file (e.g., messages.pot) with extractable strings.

  • Manual Extraction: Add placeholders in code:

    $name = trans('user.greeting', ['name' => $user->name]);
    

2. Locale Switching

  • Runtime Switching: Dynamically change locale in middleware or controllers:

    $translator->setLocale('fr');
    

    Or via URL parameter (use JMS\TranslationBundle\Translation\TranslationListener):

    // config/routes.php
    $router->addRoute('locale_switch', '/{_locale}', 'App\Controller\LocaleController::switchLocale');
    
  • Session-Based Locale: Store locale in session and restore it on each request:

    $request->getSession()->set('locale', 'fr');
    

3. Pluralization and Interpolation

  • Plural Rules: Define locale-specific plural rules in config/jms_translation.php:

    'pluralization' => [
        'en' => ['rule' => 'one', 'vars' => ['count']],
        'fr' => ['rule' => 'traditional', 'vars' => ['count']],
    ],
    

    Use in translations:

    # messages.fr.yml
    apples: "Il y a %count% pomme|Il y a %count% pommes"
    
  • Interpolation: Pass variables dynamically:

    trans('user.welcome', ['name' => 'John']);
    
    # messages.en.yml
    user.welcome: "Welcome, %name%!"
    

4. Domain-Specific Translations

  • Domain Isolation: Organize translations by domain (e.g., validation, user):

    translations/
        validation.en.yml
        user.fr.yml
    

    Translate by domain:

    $translator->trans('validation.required', [], 'validation');
    
  • Domain Fallbacks: Configure fallback domains in config/jms_translation.php:

    'fallback_domains' => ['validation' => 'messages'],
    

5. Integration with Laravel

  • Service Provider: Bind the translator to Laravel’s container in AppServiceProvider:
    public function register()
    {
        $this->app->singleton('translator', function ($app) {
            return \JMS\TranslationBundle\Translation\TranslationService::getTranslator();
        });
    }
    
  • Blade Directives: Extend Blade for fluent syntax:
    Blade::directive('trans', function ($expression) {
        return "<?php echo app('translator')->trans($expression); ?>";
    });
    
    Usage in Blade:
    @trans('user.greeting')
    

Advanced Patterns

1. Custom Translator Adapter

  • Extend JMS\TranslationBundle\Translation\TranslatorInterface for custom logic (e.g., database-backed translations):
    class DatabaseTranslator implements TranslatorInterface
    {
        public function trans($id, array $parameters = [], $domain = 'messages', $locale = null)
        {
            // Custom logic (e.g., query DB)
            return parent::trans($id, $parameters, $domain, $locale);
        }
    }
    
  • Register in config/jms_translation.php:
    'translator' => App\Services\DatabaseTranslator::class,
    

2. Translation Validation

  • Validate translations during extraction:
    php artisan jms:translation:validate en
    
  • Customize validation rules in config/jms_translation.php:
    'validation' => [
        'required' => true,
        'max_length' => 255,
    ],
    

3. Translation Testing

  • Mock translations in tests:
    $translator = $this->getMockBuilder('JMS\TranslationBundle\Translation\TranslatorInterface')
        ->getMock();
    $translator->method('trans')->willReturn('Mocked translation');
    $this->app->instance('translator', $translator);
    
  • Test pluralization:
    $this->assertEquals('1 apple', $translator->transChoice('apples', 1));
    

4. Translation Caching

  • Enable caching for performance:
    'cache' => [
        'enabled' => true,
        'provider' => 'file', // or 'redis', 'memcached'
    ],
    
  • Clear cache after updates:
    php artisan cache:clear
    

Gotchas and Tips

Pitfalls

1. Locale Negotiation Conflicts

  • Issue: Multiple locale negotiation strategies (e.g., URL, session, browser) may override each other.
  • Fix: Prioritize strategies in config/jms_translation.php:
    'locale_negotiation_strategies' => [
        'url', // Highest priority
        'session',
        'browser',
    ],
    

2. Missing Translation Fallbacks

  • Issue: Fallback locales may not work as expected if the chain is broken.
  • Fix: Explicitly set fallback locales for each domain:
    # config/jms_translation.php
    'fallback_locales' => [
        'fr' => ['en'],
        'es' => ['en'],
    ],
    

3. Pluralization Rule Mismatches

  • Issue: Incorrect pluralization due to mismatched rules (e.g., using en rule for fr).
  • Fix: Verify plural rules in config/jms_translation.php and test edge cases (e.g., count = 0, count = 2).

4. Translation Extraction Gaps

  • Issue: The extractor may miss dynamic translations (e.g., concatenated strings).
  • Fix: Manually add placeholders or use comments:
    // trans('user.greeting', ['name' => $name]); // Dynamic
    

5. Caching Stale Translations

  • Issue: Translations aren’t updated after changes due to aggressive caching.
  • Fix: Clear cache or use cache tags:
    'cache' => [
        'enabled' => true,
        'tags' => ['translations'],
    ],
    
    Then clear by tag:
    php artisan cache:tags:clear translations
    

Debugging Tips

1. Enable Debug Mode

  • Log translation issues to storage/logs/translation.log:
    'debug' => true,
    

2. Dump Translation Data

  • Inspect loaded translations:
    $translator->getCatalogue()->all('messages', 'en');
    

3. Check Locale Resolution

  • Debug current locale:
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui