calamandrei-lorenzo/laravel-browser-lang

Auto detect browser language with middleware.

Maintainers

Package info

github.com/CalamandreiLorenzo/laravel-browser-lang

pkg:composer/calamandrei-lorenzo/laravel-browser-lang

Transparency log

Statistics

Installs: 30

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

3.0.2 2026-08-20 08:43 UTC

This package is auto-updated.

Last update: 2026-08-20 08:44:08 UTC


README

Auto detect browser default language

Build Status Pipeline Status Code Coverage Latest Stable Version Latest Unstable Version Total Downloads License

This package makes available a middleware that auto-detects the language accepted by the browser and sets it as the current locale.

The Accept-Language header is parsed following RFC 9110: quality factors drive the priority, q=0 marks a refused language, and the * wildcard is ignored. The first language the application can actually serve wins.

Compatibility

Package PHP Laravel
3.x 8.2 – 8.4 12.x, 13.x
2.x 8.1 – 8.4 10.x – 13.x, see below
1.x 7.4 6.x, 7.x

Install 3.x. Version 2.0.0 declares support for Laravel 10 and 11, which turned out to be a claim Composer cannot honour: both branches are past end of life and carry an unpatched CRLF injection advisory covering every release in them (PKSA-mdq4-51ck-6kdq, fixed in 12.60.0 and 13.10.0 only). Composer refuses to install any 10.x or 11.x, so on those versions 2.0.0 does not resolve at all, and on Laravel 12 and 13 it behaves exactly like 3.x. Dropping the two dead branches is the only difference between them, which is why 3.x is a major: the supported range narrowed.

Installing

composer require calamandrei-lorenzo/laravel-browser-lang

Optionally, you can publish the config file:

php artisan vendor:publish --provider="CalamandreiLorenzo\\LaravelBrowserLang\\ServiceProvider" --tag=config

Configuration

return [
    // Request header inspected by the middleware.
    'language_header' => 'Accept-Language',

    // Class turning the header into a locale, resolved through the container.
    'header_conversion' => CalamandreiLorenzo\LaravelBrowserLang\HeaderConversion::class,

    // Locales the application can serve. The value listed here is the one
    // handed to App::setLocale(), so "pt_BR" and "pt-BR" are both fine.
    'available_locales' => ['en'],

    // Used when the browser asks for nothing the application can serve.
    // null keeps the current application locale.
    'fallback_locale' => null,

    // Alias registered for the middleware. Set to null to register it yourself.
    'middleware_alias' => 'detect-language',
];

Locale matching is done in three steps, in order: exact match (en-GB against en-GB), primary subtag (en-GB against en), and finally any available locale sharing the primary subtag (en-US against en-GB).

Usage

The detect-language alias is registered by the package, so the middleware is usable right away:

Route::middleware('detect-language')->group(static function () {
    // routes
});

Registering it globally

In bootstrap/app.php:

use CalamandreiLorenzo\LaravelBrowserLang\Http\Middleware\BrowserLang;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(BrowserLang::class);
    })
    ->create();

Custom header conversion

Implement HeaderConversionInterface and point the config at it:

use CalamandreiLorenzo\LaravelBrowserLang\HeaderConversionInterface;

class MyHeaderConversion implements HeaderConversionInterface
{
    public function convert(string $header): string
    {
        // ...
    }
}
// config/browser-lang.php
'header_conversion' => MyHeaderConversion::class,

The class is resolved through the container, so constructor injection is available. The interface is bound too, which means HeaderConversionInterface can be type-hinted anywhere in the application.

Upgrading to 3.x

  • PHP 8.2 and Laravel 12 are now the minimum supported versions. Coming from 2.0.0, this is the only change: no code, config or behaviour differs between the two.
  • Everything below applies when coming from 1.x.
  • The middleware now reads the header_conversion config key. Releases before 2.0 documented header_conversion but actually read an undocumented resolver key; both are accepted, header_conversion takes precedence.
  • When no requested language is available the middleware no longer fails; it falls back to fallback_locale, or to the current application locale when that is null.
  • Quality factors are now honoured, so the browser's preferred language wins instead of the leftmost one.
  • A detect-language middleware alias is registered automatically. Set middleware_alias to null to opt out.

Testing

composer update
composer test
composer check-style

composer.lock is not committed, so composer update is what resolves the dependencies. Both pipelines run composer test against every supported PHP and Laravel combination, and composer check-style on the newest.

Contributing

The repository is mirrored on both hosts, and either issue tracker works: GitHub or GitLab.

You can contribute in one of three ways:

  1. File bug reports using one of the issue trackers.
  2. Answer questions or fix bugs reported there.
  3. Contribute new features.

The code contribution process is not very formal. You just need to make sure that you follow the PSR-1, PSR-4 and PSR-12 coding guidelines. Any new code contributions must be accompanied by unit tests where applicable.

License

MIT