mcamara/laravel-localization

repository·master·Indexed 25 days ago

https://github.com/mcamara/laravel-localization

A Laravel package providing i18n capabilities, including automatic language detection from browsers, smart routing with translatable URLs, and redirection middleware for SEO and user sessions. It supports localized route segments, translatable route parameters via the LocalizedUrlRoutable interface, and custom route caching through the LoadsTranslatedCachedRoutes trait.

Tokens
7K
Snippets
17
Records
36
Agent score
84%

What's inside mcamara/laravel-localization

  1. Configure supported locales via a Service Provider

    master

    Instead of using a static config file, you can use a ConfigServiceProvider to dynamically set the laravellocalization configuration settings. This is useful for overriding default settings or setting them based on application logic.

    Common keys include:

    • laravellocalization.supportedLocales: An array defining supported languages with their name, script, and native names.
    • laravellocalization.useAcceptLanguageHeader: Boolean to determine if the Accept-Language header should be used.
    • laravellocalization.hideDefaultLocaleInURL: Boolean to determine if the default locale should be hidden from the URL.
    <?php namespace App\Providers;
    
    use Illuminate\
    Support\ServiceProvider;
    
    class ConfigServiceProvider extends ServiceProvider {
    	public function register()
    	{
    		config([
    			'laravellocalization.supportedLocales' => [
    				'ace' => array( 'name' => 'Achinese', 'script' => 'Latn', 'native' => 'Aceh' ),
    				'ca'  => array( 'name' => 'Catalan', 'script' => 'Latn', 'native' => 'català' ),
    				'en'  => array( 'name' => 'English', 'script' => 'Latn', 'native' => 'English' ),
    			],
    
    			'laravellocalization.useAcceptLanguageHeader' => true,
    
    			'laravellocalization.hideDefaultLocaleInURL' => true
    		]);
    	}
    }
  2. Configure locale for PHPUnit tests

    master

    Because the package detects the active route during the application bootstrap, running tests can result in 404 errors because the route cannot be determined. To fix this, manually define the locale prefix in your TestCase by setting the environment variable LaravelLocalization::ENV_ROUTE_KEY and refreshing the application.

    use Illuminateoundation\Testing\TestCase as BaseTestCase;
    use Mcamara\LaravelLocalization\LaravelLocalization;
    
    abstract class TestCase extends BaseTestCase
    {
        protected function refreshApplicationWithLocale(string $locale): void
        {
            self::tearDown();
            putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale);
            self::setUp();
        }
    
        protected function tearDown(): void
        {
            putenv(LaravelLocalization::ENV_ROUTE_KEY);
            parent::tearDown();
        }
    }
    
    final class HomeControllerTest extends TestCase
    {
        public function it_can_visit_the_home_page()
        {
            $this->refreshApplicationWithLocale('en');
    
            $response = $this->get('/en');
    
            $response->assertStatus(200);
        }
    }
  3. Install Laravel Localization in Laravel 5.4 and below

    master

    For older versions of Laravel (5.4 and below), you must manually register the service provider and the facade in config/app.php.

    // Register the service provider in config/app.php
    'providers' => [
        // [...]
        Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider::class,
    ],
    
    // Register the LaravelLocalization facade in config/app.php
    'aliases' => [
        // [...]
        'LaravelLocalization' => Mcamara\LaravelLocalization\Facades\LaravelLocalization::class,
    ],
  4. Implement translatable route parameters

    master

    To support translated slugs in URLs (e.g., /en/article/important-change vs /es/articulo/cambio-importante), your model must implement the \Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable interface.

    1. Implement getLocalizedRouteKey($locale): This method must return the translated slug for the given locale.
    2. Implement resolveRouteBinding($slug): Overwrite this method to find the model instance using the translated slug.

    Example Implementation:

    use Mcamara\
    LaravelLocalization\\Interfaces\\LocalizedUrlRoutable;
    
    class Article extends Model implements LocalizedUrlRoutable
    {
        public function getLocalizedRouteKey($locale)
        {
            // Return the slug for the specific locale
            return $this->slugs()->where('locale', $locale)->first()->slug;
        }
    
        public function resolveRouteBinding($slug)
        {
            return static::findByLocalizedSlug($slug)->first() ?? abort(404);
        }
    }
    public function resolveRouteBinding($slug)
    {
            return static::findByLocalizedSlug($slug)->first() ?? abort(404);
    }
  5. Implement localized routes

    master

    To make your routes translatable and locale-aware, wrap them in a group using LaravelLocalization::setLocale() as the prefix. This automatically handles the locale prefix in the URL and sets App::getLocale() accordingly.

    // routes/web.php
    use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
    
    Route::group(['prefix' => LaravelLocalization::setLocale()], function() {
        Route::get('/', function() {
            return View::make('hello');
        });
    
        Route::get('test', function() {
            return View::make('test');
        });
    });
  6. Configure locale for Pest tests

    master

    In Pest, you can handle locale detection in tests by creating a helper function that refreshes the application with a specific locale and using the afterEach hook to clean up the environment variable.

    // Pest.php
    use Mcamara\LaravelLocalization\LaravelLocalization;
    
    function refreshApplicationWithLocale(string $locale):
    {
        /** @var \Tests\TestCase $test */
        $test = test();
    
        $test->tearDown();
        putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale);
        $test->setUp();
    }
    
    pest()->afterEach(function () {
        putenv(LaravelLocalization::ENV_ROUTE_KEY);
    });
    
    // YourTest.php
    test('it can visit the home page', function () {
        refreshApplicationWithLocale('en');
    
        $response = $this->get('/en');
    
        $response->assertStatus(200);
    });
  7. Implement Translated Routes

    master

    You can translate route segments (e.g., /en/about and /es/acerca) by following these steps:

    1. Ensure the localize middleware is applied to your route group.
    2. Create a routes.php file in resources/lang/**/ (or lang/**/ for Laravel 9+) for each language. This file should return an array mapping the internal route key to the translated segment.
    3. Use LaravelLocalization::transRoute() within your routes/web.php to define the routes.

    Example routes.php (Spanish):

    return [
        "about"    =>  "acerca",
        "article"  =>  "articulo/{article}",
    ];

    Example Route Definition:

    Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => ['localize']], function () {
        Route::get(LaravelLocalization::transRoute('routes.about'), function () {
            return view('about');
        });
    });
    <?php
    // resources/lang/es/routes.php
    return [
        "about"    =>  "acerca",
        "article"  =>  "articulo/{article}",
    ];
  8. Use redirect middleware for SEO and UX

    master

    It is strongly recommended to use redirect middleware to ensure users and search engines are always directed to a fully qualified localized URL (e.g., /en/test instead of /test).

    To apply redirection and view path logic, add the middleware to your route group:

    Route::group([
        'prefix' => LaravelLocalization::setLocale(),
        'middleware' => [ 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath' ]
    ], function() {
        // Localized routes here
    });
    Route::group(
    [
        'prefix' => LaravelLocalization::setLocale(),
        'middleware' => [ 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath' ]
    ], function() {
        // ...
    });
  9. Publish Laravel Localization configuration

    master

    To customize the localization settings, publish the configuration file to config/laravellocalization.php using the following Artisan command.

    php artisan vendor:publish --provider="Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider"
  10. Register Laravel Localization middleware

    master

    You must register the package middleware to enable routing and redirection features.

    For Laravel 11+ (bootstrap/app.php):

    return Application::configure(basePath: dirname(__DIR__))
        ->withMiddleware(function (Middleware $middleware) {
            $middleware->alias([
                'localize'                => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
                'localizationRedirect'    => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
                'localeSessionRedirect'   => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
                'localeCookieRedirect'    => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
                'localeViewPath'          => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
            ]);
        });

    For Laravel 10 and below (app/Http/Kernel.php):

    protected $middlewareAliases = [
        'localize'                => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
        'localizationRedirect'    => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
        'localeSessionRedirect'   => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
        'localeCookieRedirect'    => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
        'localeViewPath'          => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
    ];
    // Example for Laravel 11
    return Application::configure(basePath: dirname(__DIR__))
        ->withMiddleware(function (Middleware $middleware) {
            $middleware->alias([
                'localize'                => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
                'localizationRedirect'    => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
                'localeSessionRedirect'   => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
                'localeCookieRedirect'    => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
                'localeViewPath'          => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class,
            ]);
        });
  11. Enable route caching for localized routes

    master

    By default, this package is incompatible with Laravel's standard route caching (php artisan route:cache). To enable caching for localized routes, you must use the LoadsTranslatedCachedRoutes trait.

    For Laravel 11 and newer

    Add the trait to your AppServiceProvider and register the routes in the boot method:

    use Mcamara\LaravelLocalization\Traits\LoadsTranslatedCachedRoutes;
    
    class AppServiceProvider extends ServiceProvider
    {
        use LoadsTranslatedCachedRoutes;
    
        public function boot(): void
        {
            RouteServiceProvider::loadCachedRoutesUsing(fn () => $this->loadCachedRoutes());
        }
    }

    For versions before Laravel 11

    Add the trait to your RouteServiceProvider:

    use Mcamara\LaravelLocalization\Traits\LoadsTranslatedCachedRoutes;
    
    class RouteServiceProvider extends ServiceProvider
    {
        use LoadsTranslatedCachedRoutes;
    }

    Commands

    • Cache routes: php artisan route:trans:cache
    • Clear cache: php artisan route:trans:clear
    • List routes for a locale: php artisan route:trans:list {locale} (e.g., php artisan route:trans:list en)
    php artisan route:trans:cache
    php artisan route:trans:clear
    php artisan route:trans:list en