Laravel101: Exploring Middlewares - Unlocking Multilingual Functionality with Ease
Tags: laravel, php, middleware, laravel101
Published: 2023-08-17 19:07:04

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](https://laravel.com/docs/10.x/middleware) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pq6jom7rhzvs5vkbaq4z.png)


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:
```php
class PreventRequestsDuringMaintenance extends Middleware
{
    /**
     * The URIs that should be reachable while maintenance mode is enabled.
     *
     * @var array<int, string>
     */
    protected $except = [
        //
    ];
}
```

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.:
```php
// 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');
});
```


## Create a new Middleware

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

```sh
php artisan make:middleware <NameOfMiddleware>
```

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:
```php
public function handle(Request $request, Closure $next)
{
   return $next($request);
}
```
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:

```sh
php artisan lang:publish 
```

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](https://github.com/Laravel-Lang/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:

```sh
composer require laravel-lang/common --dev

php artisan lang:add fr
php artisan lang:update
```

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:

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

>> lang/fr.json
"welcome": "Bienvenue dans les tutoriels Laravel101",
```

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:

```php
@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
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zn4whgvpd9g8ypt78u7o.png)


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
<html lang="{{ app()->getLocale() }}">
```
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:

```php
__('hello', ['user' => $username])
```

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


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8e9eurx5x9msce5wvuz.png)


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:
```php
//  translate file
return [
 'model'  => 'book|books'
];

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

{{ trans_choice('default.model',  2 ) }}
>>> books
```

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:
```php
use Illuminate\Http\Request;

class LocaleController extends Controller
{
    public function __invoke(Request $request)
    {
        session(['locale' => $request->locale]);
        return redirect()->back();
    }
}
```
To access this function, we define an appropriate route:

```php
Route::post('/locale', LocaleController::class)->name('locale.store');
```

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


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6y4vyonqc6fhz6wkguto.png)


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:

```sh
php artisan make:middleware SwitchLocaleMiddleware
```

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

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

    return $next($request);
}
```

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:

```php
protected $middlewareGroups = [
  'web' => [
    // Other middleware entries...
    \App\Http\Middleware\LanguageMiddleware::class,
  ]
];
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zi2c6b76gozjvekr546j.gif)

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!