lara28580's avatar

How to set the language dynamically

I am trying to set the language in my app dynamically, based on users stored language. I am storing the language of the user in the users db. I am using the mcamara/laravel-localization package. So far I tried it with a middleware to set the language of the user but no success.

Middleware

if($user = Auth::user()) {
   App::setLocale($user->lang);   
  LaravelLocalization::setLocale($user->lang);
}
 return $next($request);

The problem is the url does not have the lang code in the url.

0 likes
7 replies
Merklin's avatar

In app.blade.php, in the beginning:

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">

In this case, app()->getLocale() should return a string like en-EN or de-DE

If app()->getLocale() returns string like en_EN, de_DE and so on, you can use:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

Also, you can take a look of this package: https://github.com/amiranagram/localizator. I find it easier to use.

1 like
lara28580's avatar

This is already in my app.blade.php because I am using breeze.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

The problem is I can't generate the right urls based on the users stored language.

Merklin's avatar

I don't know your exact configuration, as I'm not familiar with this package, but this is my middleware:

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

        if (
            isset(auth()->user()->language)
            && auth()->user()->language
            && array_key_exists(auth()->user()->language, Config::get('languages'))
        ) {
            if (session()->has('applocale') && array_key_exists(session()->get('applocale'), config('languages'))) {
                App::setLocale(session()->get('applocale'));
            } else {
                Session::put('applocale', auth()->user()->language);
            }
        }

        if (session()->has('applocale') && array_key_exists(session()->get('applocale'), config('languages'))) {
            App::setLocale(session()->get('applocale'));
        } else { // This is optional as Laravel will automatically set the fallback language if there is
            // none specified
            App::setLocale(config('app.fallback_locale'));
        }

        return $next($request);
    }

At the bottom of routes/web.php

Route::get('lang/{lang}', [LanguageController::class, 'switchLang'])->name('lang.switch');

The Controller:

final class LanguageController extends Controller
{
    public function switchLang(string $lang): RedirectResponse
    {

        if (array_key_exists($lang, Config::get('languages'))) {
            Session::put('applocale', $lang);
        }

        return Redirect::back();
    }
}
1 like
lara28580's avatar

@Merklin Thanks for you detailed answer but I think with my package this will not work.

lara28580's avatar

Tried it like so

public function handle(Request $request, Closure $next): Response
    {
        if ($request->user()) {
            return redirect()->to(LaravelLocalization::getLocalizedURL($request->user()->lang, route($request->route()->getName()), [], true));
        }

        return $next($request);
    }

I get the error too many redirects. I have to somehow force the db lang, but dont know how.

lara28580's avatar

I think it is working now. What I have done is the following

 public function handle(Request $request, Closure $next): Response
    {
        if ($user = Auth::user()) {
            App::setLocale($user->lang);
            Session::put('locale', $user->lang);
            LaravelLocalization::setLocale($user->lang);
        }

        return $next($request);
    }

Seems to work.

Please or to participate in this conversation.