Cannot change language in Laravel - php

I have got a problem with my Laravel application - I am not able to change my app language and keep it set. After the next request to the server it goes back to default language set. The only thing which is possible is to change the default language in app.php file. I have recently updated my app to Laravel 5.22 - could it be connected with the problem mentioned above?
Would you have some kind of advice on this?
Thank you in advance for any kind of help

in you route group each time load the language
Route::group(['namespace' => 'Language'], function () {
require (__DIR__ . '/Routes/Language/Language.php');
});
in language.php(i have loaded in different route directory )
Route::get('lang/{lang}', 'LanguageController#swap');
in LaunguageController store in session to persist the selection
class LanguageController extends Controller
{
/**
* #param $lang
* #return \Illuminate\Http\RedirectResponse
*/
public function swap($lang)
{
session()->put('locale', $lang);
return redirect()->back();
}
}

Related

Laravel verify locale in url is same as user's locale from database

So in my LocaleMiddleware class (which is located in the web group of the middleware), I have the following:
if (Auth::check())
{
app()->setLocale($request->user()->getLocale()); // This just fetches the locale from the database for the given user
}
And then it just returns the next request. However, there is a slight issue for example when logging in. I need to use the return redirect()->intended(); option. This poses a problem when I have for example the following route that I point to:
https://www.example.com/es/cervezas/dos
The English variant of this url would be:
https://www.example.com/en/beers/two
My routes look like this for example:
Route::name('user.')->prefix(app()->getLocale())->group(function () {
Route::get(trans('routes.beers'), [BeersController::class, 'index'])->name('beers.index');
}
So in my routes I translate everything, and I also have slugs for each of my database models etc, which is why I always need to have the correct locale set but also I always need to have the correct locale in the url. If not I get not found exceptions when viewing specific model items or weird translations.
But one of the main problems is, when I go to the Spanish route for example (or any route for that matter in any language), after logging in, it will return the intended url/route, which will be the English one since en is the fallback locale.
So basically, what I was thinking is something along the lines of this, in my LocaleMiddleware class:
if (Auth::check())
{
app()->setLocale($request->user()->getLocale());
// Check if the segment locale is the same as the user locale
// IF NOT, redirect them
if(request()->segment(1) !== $request->user()->getLang())
{
return redirect()->route(request()->route()->getName()); // Not sure what to do here, doing this just creates an endless loop because the locale somehow was not updated yet it seems
}
}
Any ideas for a solution for this, in the LocaleMiddleware or anywhere else? Or am I going about this the wrong way entirely? Any pointers are appreciated!
Edit:
Now in my LoginController I have the following:
protected function authenticated(Request $request, $user)
{
app()->setlocale($user->getLocale());
dd(app()->getLocale()); // This is the correct locale, `es` or `nl`
dd(route('beers.index')); // This just always shows the English route
}
How come the app()->getLocale() shows the correct locale but the route is still always in the default locale? And of course, how to fix that?
Usually you have access to the user in the login function before redirecting.
In many of my projects there is an admin panel and I use the same default login endpoint. During the login process I check where the user is an admin or not and decide where to redirect him.
Here's an example of the store function in App\Http\Controllers\Auth\LoginController in a laravel 8 project:
/**
* Handle an incoming authentication request.
*
* #param \App\Http\Requests\Auth\LoginRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
if (Auth::user()->hasRole('admin')) {
return redirect()->intended(RouteServiceProvider::ADMIN_HOME);
}
return redirect()->intended(RouteServiceProvider::HOME);
}
So I believe that if you edit your redirection logic in the login controller it should work, because you have access the user, before you actually redirect him.

Localization issue in laravel application

I have two domains directing to a single laravel application.
test_en.site
test_fr.site
MY REQUIREMENT
test_en.site need to load the English content by default and test_fr.site need to load the French content.
(If a user accesses to test_en.site, still the user can change the language to French, and if a user accesses to test_fr.site user can change the language to English.)
WHAT I HAVE DONE SO FAR
In order to check the domain and load the correct language accordingly, in my Middleware, Localization.php I have added the following condition.
app/Http/Middleware/Localization.php
<?php
namespace App\Http\Middleware;
use App;
use Closure;
class Localization
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (session()->has('locale')) {
App::setLocale(session()->get('locale'));
return $next($request);
}
// load english by default if the root is test_en.site or else load french for other domains
else {
$locale = $request->root() == 'http://test_en.site' ? 'En' : 'Fr';
App::setLocale($locale);
return $next($request);
}
}
}
PROBLEM
I created two virtual hosts for the same project with two test domains and tried in my local then it works well...
But when I tested this out on the live server it keeps loading the English for the French domain too.
$locale = $request->root() == 'http://test_en.site' ? 'En' : 'Fr';
App::setLocale($locale);
return $next($request)
I even tried using the getHost() method instead of root() but that too works only in the local server...
Where am I doing wrong and How can I fix this, as this code works fine in the local I'm struggling to find the solution...
your code is correct, I think you forgot to add it into Kernel.php
if it still not work
try this snippet instead
p/s edited
// get subdomain
$url_array = explode('.', parse_url($request->url(), PHP_URL_HOST));
$subdomain = $url_array[0]; // in your case it should be test_en/test_fr
$languages = ['test_en' => 'en', 'test_fr' => 'fr'];
App::setLocale($languages[$subdomain]);
return $next($request);
You can try use https://github.com/movemoveapp/laravel-localization localization package. Your problem describe here https://github.com/movemoveapp/laravel-localization#localization-switch-by-domain-names.
How to use?
In your case you have:
test_en.site - En version
test_fr.site - Fr version
Install package and add to .env file new environments
LOCALIZATION_DOMAIN_NAME_EN=test_en.site
LOCALIZATION_DOMAIN_NAME_FR=test_fr.site
A next step modify your web routes in routes/web.php, like to
Route::group([
'middleware' => [ 'localizationDomainRedirect' ]
], function()
{
Route::get('/', function()
{
return View::make('index');
});
});
So, by http://test_en.site/ opened En version, by http://test_fr.site - Fr.

Laravel change language via URL/Route

Fairly new to Laravel and I'm trying to add a functionality that allows the user to switch between two languages by clicking a button in a header.blade.php file. So far I've got it so there's a test.php file in the respective lang directories with test strings and have managed to get <p>{{__('test.test')}}</p> to display the correct language when manually set. At the moment I'm not sure if this is actually calling the route to update the language or if the logic I have for updating it is wrong since I get no errors and I'm using barryvdh/laravel-debugbar to debug.
My logic for the button:
<button href="{{ url('language', config('app.locale') == 'en' ? 'fr' : 'en') }}">{{ config('app.locale') }}</button>
In routes/web.php:
Route::get('/language', 'LanguageController#show');
Route::post('/language/{lang}', 'LanguageController#update');
LanguageController.php, created via php artisan make:controller --api
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class LanguageController extends Controller
{
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
return App::getLocale();
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//Tried the following
config(['app.locale' => $id]);
App::setlocale($id);
}
}
Questions:
Is this the correct way to update the language at runtime?
How can I tell if my api calls are being made?
How can I achieve this inside of a template .vue file?
Is making a Controller for the language redundant?
Would the inner HTML of my button change if the locale was changed?
Is affecting config files at runtime bad practice?
--Edit--
I should also mention that the only reason I made a controller for this is because I had the route calls in web.php use a function instead however, they stated they were Closure running php artisan route:list and with the research I found I couldn't tell if that was correct
You are on the right way, but there is something missing.
You can't use the configuration to edit at runtime the language.
Save local language in user Session and create a new middleware to set on each request the language saved in session.
I found this article that can help you, localization-laravel

"App::getLocale()" returns default language instead of current in custom service provider

I'm making a js localizator using service provider, and I need to get current locale to fetch current lang translations and pass to js. Everything works, but App::getLocale() keeps returning default app language.
I tried to do this using both middlware and view composer based on others issue threads in laracasts and stackoverflow, but nothing helps.
Here's links
https://laracasts.com/discuss/channels/laravel/get-current-locale-in-app-service-provider
Getting locale language at provider class in Laravel
Laravel get getCurrentLocale() in AppServiceProvider
class JstranslateServiceProvider extends ServiceProvider
{
protected $langPath;
public function __construct()
{
$locale = App::getLocale();
$this->langPath = resource_path('lang/'.$locale);
dd($locale);
}
}
dd($locale); output is always 'en', despite the current language.
I made js localization using this guide Link, it seems to be working for them
Do this outside of a constructor in the Service Provider.
These classes are instantiated before Laravel does anything so it is likely whatever you have written in your middleware/view composer hasn't taken affect.
Instead you should be doing this either in the boot or register method.
Getting locale in boot and putting everything in composer solved my issue.
public function boot()
{
Cache::forget('translations');
view()->composer("layouts.app", function () {
$locale = App::getLocale();
if($locale == 'us')
$locale = 'en';
$this->langPath = resource_path('lang/'.$locale);
Cache::rememberForever('translations', function () {
return collect(File::allFiles($this->langPath))->flatMap( function ($file) {
return [
($translation = $file->getBasename('.php')) => trans($translation),
];
})->toJson(JSON_UNESCAPED_UNICODE);
});
});
}
I'm using Lumen version 5.8 and figured out how to get the current locale:
app('translator')->getLocale();

Middleware not following the condition - Laravel 5.7

I am trying to implement a user registration system in Laravel 5.7 where I am facing an issue.
I have two tables for Users- Admin(created by copying default Laravel auth),
new routes, new middleware for admin. Every thing works fine while using guards.
I was trying to limit the user login by adding Approve/Disapprove functionality.
I added an extra column - admin(boolean) to the Users table.
In Login controller - LoginController.php Page, I added
protected function authenticated($request, $user)
{
if ( $request->user()->admin != 1)
// if($user->admin != 1)
{
return redirect()->route('approval');
}
else
{
return redirect('/engineer');
}
}
so that, when the admin is 1 I am directed to '/engineer' where as in other case I am directed to 'approval'.
It works as desired!.
Issue I am now facing is that if I try to access the 'engineer'
using user whose not approved I am able to access the page. I am not sure how to restrict it. The page is still restricted to public.
Since the controller will be accessed by both the user and admin, I used __construct in the controller
web.php
Route::resource('engineer', 'engineerController');
engineerController.php
public function __construct()
{
$this->middleware('auth:web,admin');
}
My Understanding is that the condition is only checked when the user logs in and there after its exits.
Do I need to create a new middle ware in order to keep the authorised page intact?
I am a self learner and new to laravel. I am pretty sure that I am not following the right practice. I started something and was trying to follow it till I finish. Please guide me through it.
Along with it please let me how could I have done it better.
You would need to define a Middleware that would check if the Engineer is approved or not.
Obviously, you would also need to keep that in an is_approved column for example.
<?php
namespace App\Http\Middleware;
use Closure;
class CheckEngineerApproval
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (! auth()->user->is_approved) {
return redirect('user.approve');
}
return $next($request);
}
}
Then, add it in your $routeMiddleware array in your Kernel.
protected $routeMiddleware = [
//
//
'engineer.approved' => \App\Http\Middleware\CheckEngineerApproval::class,
];
Finally, you can add the Middleware in your Controller's constructor as well.
public function __construct()
{
$this->middleware(['auth:web','admin','engineer.approved']);
}

Categories