Accept language can contain multiple weighted entries

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the web-development category.

Last Updated: 2024-04-18

In the Project S code, I had middleware that set the locale to the contents of the Accept-Language header.

<?php
    $requestedLocale = $request->header('Accept-Language');
    if (! empty($requestedLocale)) {
        app()->setLocale($requestedLocale);

        return next($request);
    }
}

This seemed fine on my machine. But then we got exceptions in production.

Why? Because some browsers sent monstrous locales like:

en_US,en;q=0.9,de_DE;q=0.8,de;q=0.7

The fix was to anticipate and parse these. I used a built-in function to parse the priorities

<?php

$requestedLocale = $request->header('Accept-Language');
if (! empty($requestedLocale)) {

    // Handle weighted locales like and return the preferred single language
    // en_US,en;q=0.9,de_DE;q=0.8,de;q=0.7
    $locale = $request->getPreferredLanguage(self::SUPPORTED_LOCALES);
    app()->setLocale($locale);
}