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

Intl Bundle Laravel Package

sonata-project/intl-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sonata-project/intl-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        SonataIntlBundle\SonataIntlBundle::class => ['all' => true],
    ];
    
  2. Configuration: Add to config/packages/sonata_intl.yaml:

    sonata_intl:
        locale_default: en
        locale_fallback: en
        locales: [en, fr, es, de]
        timezone: Europe/Paris
    
  3. First Use Case: Use the IntlListener to automatically detect and set the locale from:

    • URL parameter (?locale=fr)
    • Browser accept-language header
    • Session cookie (sonata_intl_locale)

    Example route:

    // config/routes.yaml
    sonata_intl_locale:
        path: /{_locale}
        defaults: { _locale: en }
        requirements:
            _locale: en|fr|es|de
    

Implementation Patterns

Common Workflows

  1. Locale Switching in Controllers:

    use SonataIntlBundle\Helper\IntlHelper;
    
    public function index(IntlHelper $intlHelper)
    {
        $currentLocale = $intlHelper->getCurrentLocale();
        // Use $currentLocale in logic or pass to view
    }
    
  2. Translating with Current Locale:

    {{ 'homepage.title'|trans }}
    

    (Automatically uses the current locale from IntlHelper.)

  3. Dynamic Locale Selection:

    $intlHelper->setCurrentLocale('es'); // Force locale for a request
    
  4. Timezone Handling:

    $timezone = $intlHelper->getCurrentTimezone();
    $formattedDate = (new \DateTime())->setTimezone($timezone)->format('Y-m-d');
    
  5. Integration with Forms:

    use SonataIntlBundle\Form\Type\LocaleType;
    
    $builder->add('locale', LocaleType::class, [
        'choices' => ['en' => 'English', 'fr' => 'Français'],
        'expanded' => true,
        'multiple' => false,
    ]);
    

Advanced Patterns

  1. Custom Locale Detection: Extend the LocaleDetector service:

    # config/services.yaml
    SonataIntlBundle\Intl\LocaleDetector:
        arguments:
            $detectors: ['sonata_intl.locale_detector.session', 'sonata_intl.locale_detector.url', 'app.custom_locale_detector']
    

    Define a custom detector:

    // src/Service/CustomLocaleDetector.php
    class CustomLocaleDetector implements LocaleDetectorInterface
    {
        public function detect(): ?string
        {
            // Custom logic (e.g., API request, user profile)
            return 'es';
        }
    }
    
  2. Locale-Specific Routes:

    # config/routes.yaml
    app_home:
        path: /{_locale}/home
        defaults: { _controller: 'App\Controller\HomeController::index', _locale: en }
        requirements:
            _locale: en|fr|es
    
  3. Database Locale Storage: Store user preferences in the database and hydrate the IntlHelper:

    $userLocale = $user->getLocale(); // Assume User entity has getLocale()
    $intlHelper->setCurrentLocale($userLocale);
    
  4. Fallback Logic: Override the fallback chain in config:

    sonata_intl:
        locale_fallbacks: [en, fr, es] # Custom fallback order
    

Gotchas and Tips

Pitfalls

  1. Locale Not Persisting:

    • Ensure the IntlListener is registered (it is by default in Symfony 5+).
    • Check for typos in locale_default or locales array in config.
    • Verify the _locale route parameter is correctly named in your routes.
  2. Timezone Mismatches:

    • The bundle sets the timezone based on sonata_intl.timezone in config. If dates appear incorrect, validate this setting matches your application’s expectations.
    • Timezone changes may affect cached data (e.g., Doctrine entities with created_at fields).
  3. Translation Fallbacks:

    • If translations are missing, ensure the locale_fallback chain includes a locale with complete translations (e.g., en as the last fallback).
  4. Route Caching:

    • Clear route cache after adding/removing locale-aware routes:
      php bin/console cache:clear
      
  5. Session Locale Cookie:

    • The bundle sets a cookie (sonata_intl_locale) to persist the user’s choice. If this doesn’t work:
      • Check session.storage.handler in Symfony config (e.g., session.storage.mock_file for testing).
      • Ensure same_site and secure cookie flags are compatible with your deployment (e.g., HTTPS).

Debugging Tips

  1. Log Current Locale: Add a temporary controller method to debug:

    public function debugLocale(IntlHelper $intlHelper)
    {
        return new Response(
            'Current Locale: '.$intlHelper->getCurrentLocale().'<br>'.
            'Available Locales: '.implode(', ', $intlHelper->getAvailableLocales())
        );
    }
    
  2. Check Detector Order: The first detector to return a non-null locale wins. Use dump() to inspect:

    $detectors = $container->get('sonata_intl.locale_detector');
    foreach ($detectors as $detector) {
        dump(get_class($detector), $detector->detect());
    }
    
  3. Override Locale Programmatically: Temporarily force a locale in tests or debugging:

    $intlHelper->setCurrentLocale('fr');
    

Extension Points

  1. Custom Detectors: Implement LocaleDetectorInterface and tag it as a service:

    services:
        app.custom_locale_detector:
            class: App\Service\CustomLocaleDetector
            tags: [sonata_intl.locale_detector]
    
  2. Modify Locale List Dynamically: Override the LocaleList service:

    // src/Service/CustomLocaleList.php
    class CustomLocaleList extends LocaleList
    {
        public function getLocales(): array
        {
            return ['en', 'fr', 'es', 'de', 'ja']; // Add/remove locales
        }
    }
    

    Register it in config/services.yaml:

    SonataIntlBundle\Intl\LocaleList: '@app.custom_locale_list'
    
  3. Event Listeners: Listen to sonata.intl.locale.switch to react to locale changes:

    use SonataIntlBundle\Event\LocaleSwitchEvent;
    
    public function onLocaleSwitch(LocaleSwitchEvent $event)
    {
        $newLocale = $event->getLocale();
        // Log, update user session, or trigger other logic
    }
    

    Register the listener:

    services:
        App\EventListener\LocaleSwitchListener:
            tags:
                - { name: kernel.event_listener, event: sonata.intl.locale.switch, method: onLocaleSwitch }
    
  4. Override Twig Extensions: Extend or replace the IntlTwigExtension for custom filters/filters:

    // src/Twig/AppExtension.php
    class AppExtension extends \Twig\Extension\AbstractExtension
    {
        public function getFilters()
        {
            return [
                new \Twig\TwigFilter('custom_trans', [$this, 'customTranslate']),
            ];
        }
    }
    

    Register it after the Sonata extension in config/services.yaml:

    SonataIntlBundle\Twig\IntlTwigExtension:
        tags: [twig.extension]
    App\Twig\AppExtension:
        tags: [twig.extension]
        arguments: ['@sonata_intl.intl_helper'] # Inject if needed
    

Performance Notes

  • Avoid Overriding Detectors Unnecessarily: Each detector is called sequentially until one returns a locale. Add custom detectors only if needed.
  • Cache Locale Lists: The LocaleList service is cached by default. Extend it only if you need dynamic locale management.
  • Use Route Parameters for Public Sites: For public-facing sites, rely on URL parameters (/{_locale}) for better SEO and explicit user control.
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