DEV Community

Cover image for Laravel101: Exploring Middlewares - Unlocking Multilingual Functionality with Ease
Kazem
Kazem

Posted on

Laravel101: Exploring Middlewares - Unlocking Multilingual Functionality with Ease

In the previous article, we added user registration functionality to our project. In this article, we will focus on defining access and restrictions for users using middleware in Laravel. Properly defining access is crucial for any website, as we want to control what actions users can perform. For example, as you see in previous article, we don’t want just anyone to be able to add a new task to our site. We can achieve this by using middleware, let’s deep dive into middlewares in Laravel.

Middlewares

As the name suggests, Middlewares just like pipelines are commands that sit between our request to the server and the server’s response. You might be familiar with the Auth middleware from prior lesson.

Let’s get back to our project. If you navigate to the app/Http/Middleware directory, you will find some predefined middlewares. For example, one of these middlewares is PreventRequestsDuringMaintenance. When you activate this middleware, users will encounter a 503 error or a message indicating that the service is unavailable usually during you perform updates or maintenance on your service.

In Laravel, the php artisan down command is used to activate this mode, and php artisan up is used to stop it:

As you see in following pic when your app is in the maintenance mode then the middleware prevents any requests from being executed:

Image description

Certainly, it is also possible to exclude specific endpoints from the maintenance mode, To do that you need to add your desired endpoint into the except array:

class PreventRequestsDuringMaintenance extends Middleware
{
    /**
     * The URIs that should be reachable while maintenance mode is enabled.
     *
     * @var array<int, string>
     */
    protected $except = [
        //
    ];
}
Enter fullscreen mode Exit fullscreen mode

If you recall from the previous tutorial, you learned that we can add a middleware to an endpoint using the middleware function. Similarly, you can add a middleware to a group of routes using the group function, as shown below.:

// one route
Route::post('logout', LogoutController::class)->middleware('auth');

// or a group of routes
Route::group(['middleware' => 'auth'], function () {
    Route::resource('tasks', TaskController::class);
    Route::post('logout', LogoutController::class)->name('logout');
});
Enter fullscreen mode Exit fullscreen mode

Create a new Middleware

To create a custom middleware, we will use the following artisan command:

php artisan make:middleware <NameOfMiddleware>
Enter fullscreen mode Exit fullscreen mode

In Laravel, every middleware has a handler function where you can define its logic. This function takes two inputs: the request object and a closure. The request object allows you to access the data within the request, while the closure is a function that you can invoke to proceed with the middleware pipelines:

public function handle(Request $request, Closure $next)
{
   return $next($request);
}
Enter fullscreen mode Exit fullscreen mode

To use this middleware, we need to define it in the kernel.php file located in the Http folder. Let’s take a closer look at the kernel.php file. It contains three arrays, each serving a specific purpose.

The first array, middleware, is meant for middlewares that are globally applied to all requests.

The next array, middlewareGroups, is used for applying middlewares to specific group of routes.

Finally, we have the routeMiddleware array. In this array, middlewares are defined with a key, allowing us to apply a middleware to a specific route. For instance, if you look at the list, you will see auth mentioned, which demonstrates how we can apply it to desired routes.

Now, let’s try something interesting.

Multilingual Laravel Website

Sometimes we may need to make our website multilingual, and Laravel provides a convenient tool to facilitate this.

To set up language resources in Laravel, we first need to run the following command:

php artisan lang:publish 
Enter fullscreen mode Exit fullscreen mode

After running this command, you will notice that in the main directory of your project, there are PHP translation resources that include arrays with keys. These keys represent default terms that can be found in any application. You can add translations to these keys. However, having only an English resource might not be sufficient. Let’s say we want to add French as another language. It can be time-consuming to manually translate all the files and key values into French, especially if you’re not proficient in French.

Luckily, there is another way! You can add laravel-lang package to your project that simplifies the process. By running the following command, you can install the package and add French language resources to your lang directory:

composer require laravel-lang/common --dev

php artisan lang:add fr
php artisan lang:update
Enter fullscreen mode Exit fullscreen mode

Once you have set up the language resources, you can proceed to add translations for specific keys. For example, let’s say we want to add a translation for the key “welcome” in both English and French languages. You can do it like this:

>> lang/en.json:
"welcome": "Welcome to Laravel101 tutorials",

>> lang/fr.json
"welcome": "Bienvenue dans les tutoriels Laravel101",
Enter fullscreen mode Exit fullscreen mode

You might be wondering how to use it, right? Well, it’s quite simple!

To utilize it, you just need to use a handy helper function called __('key') within your Blade files. For example, if you have a "welcome" key in your language resources, you can display it on the home page of your app like this:

@extends('layouts.app')

@section('title', 'Home Page')

@section('content')
   <div class="flex flex-center justify-between mb-4">
      <h1 class="text-xl font-bold ">{{ __('welcome') }}</h1>
  </div>
@endsection
Enter fullscreen mode Exit fullscreen mode

Additionally, to change the locale of your application to use a specific language, you can modify the locale value inside the config/app.php file of your project. Now set the locale to 'fr' and here is the result:

Image description

When it comes to translation, there are a few tips that can come in handy. One useful technique is to use the getLocale function to set the language in an HTML tag, like this:

<html lang="{{ app()->getLocale() }}">
Enter fullscreen mode Exit fullscreen mode

Another useful feature is the ability to include dynamic values within translations:

By passing an array of key-value pairs as a second parameter to the helper function, you can specify the keys you want to use for dynamic values. For example:

__('hello', ['user' => $username])
Enter fullscreen mode Exit fullscreen mode

In the above example, the key 'user' is defined for this purpose, allowing you to insert the $username dynamically into the translation.

Image description

There is also a function called trans_choice that lets you translate selectively based on a given input. It allows you to choose between singular and plural forms of a word. For instance, consider the following example:

//  translate file
return [
 'model'  => 'book|books'
];

// in blade:
{{ trans_choice('default.model',  1 ) }}
>>> book 

{{ trans_choice('default.model',  2 ) }}
>>> books
Enter fullscreen mode Exit fullscreen mode

Great! We’ve covered the basics of translation files and the tools Laravel provides for language management. Now, let’s explore how we can dynamically set the language based on user selection using functions and sessions in Laravel.

Assuming the default language of our site is English, we can configure the language and define the necessary translation keys using helper functions in the config files.

To handle language selection by the user, we can create a controller called LocaleController and define a store function as follows:

use Illuminate\Http\Request;

class LocaleController extends Controller
{
    public function __invoke(Request $request)
    {
        session(['locale' => $request->locale]);
        return redirect()->back();
    }
}
Enter fullscreen mode Exit fullscreen mode

To access this function, we define an appropriate route:

Route::post('/locale', LocaleController::class)->name('locale.store');
Enter fullscreen mode Exit fullscreen mode

To display a language selection menu in the navigation blade file, you can add the following code:

Image description

The menu mentioned above allows users to send a request to the server to indicate their desired language. However, there’s still more work to be done. We need to retrieve the selected language from every request on the server, and this can be achieved using a middleware:

php artisan make:middleware SwitchLocaleMiddleware
Enter fullscreen mode Exit fullscreen mode

Once you’ve executed the command, navigate to the app/Http/Middleware directory and define the middleware as follows:

public function handle(Request $request, Closure $next): Response
{
    if (Session::has('locale'))
        App::setLocale(Session::get('locale'));

    return $next($request);
}
Enter fullscreen mode Exit fullscreen mode

Here we use two object: Session, and App which defined globally and are accessible with session() and app() you can access session from request like $request->session()

The App facade is a powerful object that enables us to work with various services within our project. Today, we’ll use it to set the app’s locale.

The Session provides a convenient and straightforward way to access data specific to the current user’s request. In Laravel, you have multiple options for managing session data, including file, Redis, encrypted cookies, and database. By default, Laravel is configured to use the file session driver, which is suitable for many applications. In our case, we’re using the session to store the user’s locale.

Now, open the Kernel file located in the app/Http directory and add this middleware to the end of the $middlewareGroups array and in web group because the session driver defined here, like this:

protected $middlewareGroups = [
  'web' => [
    // Other middleware entries...
    \App\Http\Middleware\LanguageMiddleware::class,
  ]
];
Enter fullscreen mode Exit fullscreen mode

That’s it! By following these steps, you’ll have a multilingual site where you can define the translation keys in the respective language folders. The final output will be as follows :

Image description

That’s fantastic 😍!

In this tutorial, we explored Laravel Middlewares and discovered how they can be used to enhance our application, particularly in achieving multilingual functionality.

I hope you found this tutorial helpful, happy coding!

Top comments (2)

Collapse
 
igormihacic profile image
Igor Mihačič

Very good series and clear explanation. Tnx

Collapse
 
kazemmdev profile image
Kazem

It's great to hear that, Thank you