Locale resolvers

Adjust how the context locale is resolved

📘

This is an article for advanced users of Frontastic.

Frontastic has a built-in mechanism of how a website visitor's locale (for example, en_US) is resolved. It's an important part of the context which is used to determine translations, currencies, and all related things. Since the locale is a very specific aspect and resolving the locale differs a lot between different web applications, you can also explicitly overwrite just this aspect. We match the languages from the Accept-Language header the user sends (the browser locale) against the languages available in your Project and default to the default language. If this mechanism doesn't fit your needs, you might want to implement a different logic, for example, based on the user's geolocation do geo-IP-based guessing of locales or binding a default selected locale to the domain the user visited.

The default algorithm used to detect the website visitors' locale can be seen in the base implementation of the LocaleResolver. But it works basically like this:

  1. If a locale was already detected or even changed by the visitor, use it from their session
  2. Detect preferred language by matching the Accept-Language header sent by the browser against the locales configured in the project.yml
  3. Fallback to the defaultLanguage configured for the project

In order to implement your own algorithm, you basically need to extend the LocaleResolver class and override the method

public function determineLocale(Request $request, Project $project): string

So, you can use the current Request and the configuration of your project and need to return a locale in the format specified by ISO/IEC 15897, also known as POSIX locale, for example, [email protected].

You can basically perform anything in this method to determine the locale of the visitor, but it's important to consider the following points:

  • This code is executed on every request so it's wise to not perform time-consuming tasks here or cache the result in the visitor's session
  • You can't access the Context in this method because this method is actually used to create the Context

If you're sure you want to implement this, you can override the Frontastic service using the Symfony service container in your project:

<service                                                                
    id="Frontastic\Catwalk\ApiCoreBundle\Domain\Context\LocaleResolver"
    class="Frontastic\Customer\LocaleResolver"
>                                                                       
    <!-- constructor arguments
    for example:
    <argument type="service" id="GeoIp2\Database\Reader" /> -->
  
</service>

Then you can create the PHP class accordingly – it must extend the Frontastic\Catwalk\ApiCoreBundle\Domain\Context\LocaleResolver and follow its interface:

namespace Acme\MyDecorators\Domain;

use Frontastic\Catwalk\ApiCoreBundle\Domain\Context\LocaleResolver as BaseLocaleResolver;
use Symfony\Component\HttpFoundation\Request;
use GeoIp2\Database\Reader;

class LocaleResolver extends BaseLocaleResolver
{
    /**
  * @var Reader
  */
    
    private $geoIpReader;

    public function __construct(Reader $geoIpReader)
    {
      $this->geoIpReader = $geoIpReader;
    }

    public function determineLocale(Request $request, Project $project): string
    {
      // Return the full locale, maybe use something like the GeoIpReader...
      return '[email protected]';
    }
}

You might need to clear the Symfony cache to have this adjustment take effect.