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

Laravel Locales Laravel Package

chinleung/laravel-locales

Add easy locale support to Laravel with simple config and helper functions. Set and get the current locale with locale(), and manage supported locales with locales(), prioritizing app.locales over package config. Supports Laravel 6–13 (versioned).

View on GitHub
Deep Wiki
Context7

Getting Started

Publish the configuration file to define supported locales:

php artisan vendor:publish --provider="ChinLeung\LaravelLocales\LaravelLocalesServiceProvider" --tag="config"

Update config/app.php with your supported locales:

'locales' => ['en', 'fr', 'es', 'zh'],

Use the locale() helper to get/set the current locale:

// Get current locale
$currentLocale = locale(); // 'en'

// Set new locale
locale('fr'); // 'fr'

Use the locales() helper to manage supported locales:

// Get supported locales
$supportedLocales = locales(); // ['en', 'fr', 'es', 'zh']

// Update supported locales
locales(['en', 'fr', 'zh']);

Implementation Patterns

1. Locale Switching in Controllers

Use the locale() helper to dynamically switch locales based on user input or session:

public function switchLocale(Request $request, $locale)
{
    if (in_array($locale, locales())) {
        locale($locale);
        $request->session()->put('locale', $locale);
        return back();
    }
    abort(400, 'Unsupported locale');
}

2. Locale-Aware Routing

Combine with Laravel’s route groups and middleware for URL-based locale switching:

Route::middleware(['set-locale'])->group(function () {
    Route::get('/blog', [BlogController::class, 'index']);
});

Create a middleware (app/Http/Middleware/SetLocale.php):

public function handle(Request $request, Closure $next)
{
    $locale = $request->segment(1);
    if (in_array($locale, locales())) {
        locale($locale);
    }
    return $next($request);
}

3. Dynamic Locale Selection

Use the locales() helper to fetch supported locales for UI dropdowns:

public function getSupportedLocales()
{
    return collect(locales())->mapWithKeys(function ($code) {
        return [$code => trans("languages.$code")];
    });
}

4. Fallback Logic

Implement fallback locales in middleware or controllers:

public function handle(Request $request, Closure $next)
{
    $locale = $request->segment(1) ?? session('locale') ?? config('app.fallback_locale');
    if (!in_array($locale, locales())) {
        $locale = config('app.fallback_locale');
    }
    locale($locale);
    return $next($request);
}

5. Associative Locale Arrays

Leverage associative arrays for UI-friendly labels:

// config/locales.php
'locales' => [
    'en' => ['code' => 'en', 'name' => 'English'],
    'fr' => ['code' => 'fr', 'name' => 'Français'],
],

Access in Blade:

<select>
    @foreach (locales() as $code => $locale)
        <option value="{{ $code }}" {{ locale() === $code ? 'selected' : '' }}>
            {{ $locale['name'] ?? $code }}
        </option>
    @endforeach
</select>

6. Integration with Localization Packages

Combine with spatie/laravel-translatable for model translations:

use ChinLeung\LaravelLocales\Facades\Locale;

public function store(Request $request)
{
    $post = new Post();
    $post->translate()->title = $request->input('title_' . Locale::get());
    $post->save();
}

Gotchas and Tips

Pitfalls

  1. Config Overrides:

    • The locales() helper overrides app.locales in config/app.php. Ensure consistency between both.
    • Fix: Use locales() sparingly; prefer config('app.locales') for static lists.
  2. Middleware Conflicts:

    • Custom locale middleware may conflict with Laravel’s built-in SetLocaleMiddleware.
    • Fix: Disable Laravel’s middleware in app/Http/Kernel.php if using custom logic:
      protected $middleware = [
          // Remove or comment out:
          // \Illuminate\Foundation\Http\Middleware\SetLocale::class,
      ];
      
  3. Route Caching:

    • Locale-based routes may break after php artisan route:cache if locales are dynamic.
    • Fix: Cache routes separately per locale or use php artisan route:clear in deployment.
  4. Session Bloat:

    • Storing locales in sessions for every request can bloat session storage.
    • Fix: Use cookies or URL parameters for stateless locale switching.
  5. Associative Array Quirks:

    • Associative locale arrays (e.g., ['en' => 'English']) require exact key matching in locales() calls.
    • Fix: Validate input before updating:
      $newLocales = ['en' => 'English', 'fr' => 'Français'];
      if (count(array_intersect(array_keys($newLocales), locales())) > 0) {
          locales(array_keys($newLocales));
      }
      

Debugging Tips

  1. Check Current Locale: Use Tinker to verify the active locale:

    php artisan tinker
    >>> locale();
    
  2. Validate Supported Locales: Ensure locales() returns the expected array:

    >>> locales();
    ['en', 'fr', 'es']
    
  3. Middleware Debugging: Add logging to debug locale-setting middleware:

    public function handle($request, Closure $next)
    {
        \Log::info('Setting locale to:', [$request->segment(1)]);
        locale($request->segment(1));
        return $next($request);
    }
    
  4. Route Debugging: Use route:list to verify locale-based routes:

    php artisan route:list | grep "/blog"
    

Extension Points

  1. Dynamic Locale Providers: Override the locales() helper in a service provider:

    use ChinLeung\LaravelLocales\Facades\Locale;
    
    public function boot()
    {
        Locale::macro('getDynamicLocales', function () {
            return Cache::remember('supported_locales', 60, function () {
                return DB::table('locales')->pluck('code')->toArray();
            });
        });
    }
    
  2. Custom Facade Macros: Add locale-specific macros to the App facade:

    use Illuminate\Support\Facades\Facade;
    
    Facade::macro('getCurrentLocaleName', function () {
        $code = app()->getLocale();
        $locales = config('locales.locales', []);
        return $locales[$code]['name'] ?? $code;
    });
    
  3. Locale Fallback Middleware: Create a reusable fallback middleware:

    public function handle($request, Closure $next)
    {
        $locale = $request->segment(1) ?? session('locale') ?? config('app.fallback_locale');
        if (!in_array($locale, locales())) {
            session()->flash('error', 'Unsupported locale. Falling back to default.');
            locale(config('app.fallback_locale'));
            return redirect()->back();
        }
        locale($locale);
        return $next($request);
    }
    

Performance Considerations

  1. Avoid locales() in Loops: Cache the result of locales() if used frequently:

    $supportedLocales = locales(); // Cache this value
    foreach ($supportedLocales as $locale) { ... }
    
  2. URL-Based Locales: For high-traffic sites, URL-based locales (e.g., /fr/blog) may increase route resolution time. Fix: Use route caching with locale-specific groups:

    php artisan route:cache --locale=fr
    
  3. Session Storage: If using session-based locales, consider:

    • Shortening session names (localel).
    • Using cookies for stateless locale persistence.

Testing Strategies

  1. Locale Switching Tests: Test locale changes in controllers and middleware:

    public function test_locale_switching()
    {
        $response = $this->post('/locale/fr');
        $response->assertRedirect();
        $this->assertEquals('fr', locale());
    }
    
  2. Fallback Tests: Verify fallback behavior for unsupported locales:

    public function test_locale_fallback()
    {
        $this->app->setLocale('xx');
        $this->assertEquals(config('app.fallback_locale'), locale());
    }
    
  3. Route Tests: Test locale-aware routes:

    public function test_locale_routes()
    {
        $response = $this->get('/fr/blog');
        $response->assertStatus(200);
        $this->assertEquals('fr', locale());
    }
    
  4. Configuration Tests: Ensure locales() respects `config/app.php

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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi