GraphQL and Laravel translatable

by luigi laezza | 2nd June 2020 | Coding tips
In one of our latest custom made web application, we have been decided to give a try to GraphQl, one of the greatest advantages for us is that the client application can send a GraphQL query to get exactly what it needs, which makes development faster and cooperation with client application developers way easier.

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

As for that project we are using Laravel Nova, we decided to give a try to Lighthouse .

We must say that, being new to GraphQl we had to play a bit around before getting it working, but finally it wasn’t too bad.

With Lighthouse we have installed the companion package Playground and together it has been fantastic to see how our developers had fun transforming models into fully working api, seriously!

The application is multilingual so we needed to make some of our model’s attribute translatable, and for that we have been using the super useful package Spatie Laravel Translatable along with Nova Translatable which in my opinion is the best of his kind.

This make translating the attributes super easy and at the same time very sexy.

One more thing was left to do, make sure that when the client app would call our GraphQL api, the translatable attributes would be returned in a specific locale, as by default Spatie Laravel Translatable returns the translated attribute of the application default locale.

What we decided to do, using a Locale middleware that would allow us to send a “Content-Language” parameter in the header to switch the default application locale.

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;

class Locale {

    const SESSION_KEY = 'locale';

    public function handle(Request $request, Closure $next) {

        $fallbackLocale = config('translatable.fallback_locale');
        $locales = array_keys(config('translatable.locales'));

        $headerLocale = $request->header('Content-Language');

        $session = $request->getSession();

        if(!is_null($headerLocale) && in_array($headerLocale, $locales)){
            $locale = $headerLocale;
        }else if($request->has('lang') && in_array($request->get('lang'), $locales)) {
            $locale = $request->get('lang');
        }else if($session && $session->has(self::SESSION_KEY) && in_array($session->get(self::SESSION_KEY), $locales)){
            $locale = $session->get(self::SESSION_KEY);
        }else{
            $locale = $fallbackLocale;
        }

        if($locale){
            if($session){
                $session->put(self::SESSION_KEY, $locale);
            }
            app()->setLocale($locale);
        }

        return $next($request);
    }
}

The last thing that needed to be done, was to assign our new middleware to the schema.graphql file like in the example below

type Query @group(middleware: ["auth:api","locale"]) {
    me: User @auth
}

And voilà, a fully translatable GraphQl api with Laravel Nova, that was lot of fun, and we are planning to develop more applications with the same setup in the future.