Change language in Laravel 5 - laravel

I just begin to use Laravel 5.4, In the login.blade.php i have
I don't like to put plain text in html code, is there a solution to make all the texts in seperate lang files to use them dynamically?
Thank you

The resources/lang folder contains localization files. The file name corresponds to the view that it will be used. In order to get a value from this file, you can simply use the following code:
`Lang::geConfig;
use Session;
class Locale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//$raw_locale = Session::get('locale');
$raw_locale = $request->session()->get('locale');
if (in_array($raw_locale, Config::get('app.locales'))) {
$locale = $raw_locale;
}
else $locale = Config::get('app.locale');
App::setLocale($locale);
return $next($request);
}
}
In app/Http/Kernel.php in $middlewareGroups=[ ... ] add the following line:
\App\Http\Middleware\Locale::class,
In routes/web.php add:
Route::get('setlocale/{locale}', function ($locale) {
if (in_array($locale, \Config::get('app.locales'))) {
session(['locale' => $locale]);
}
return redirect()->back();
});

Try this!
{{ #lang('messages.login') }}
Now Add login key with it's value under language file as below
return['login'=>'Login']; // write inside messages file
and Set your APP Config Local Variable Like 'en','nl','us'
App::setLocale(language name); like 'en','nl','us'

Laravel has a localization module.
Basically, you create a file, ex: resources/lang/en/login.php and put
return [
'header' => 'Login'
];
And in your template you use #lang('login.header') instead of Login.
You can have as many files in your /resources/lang/en directory and using #lang blade directive you put your file name (without extension) and desired value separated with dot.

Related

Segments are not getting shifted / Cannot get correct arguments in Controller

I am trying to implement a simple localization for an existing Laravel project.
Implementing Localization based on the following tutorial:
https://laraveldaily.com/multi-language-routes-and-locales-with-auth/
Here is the simplified code before localization implementation:
web.php
Route::get('/poll/{poll_id}', 'App\Http\Controllers\PollsController#view');
PollsController#view
public function view($poll_id){
echo "poll_id: ".$poll_id;
}
TEST
URL: http://domain.name/poll/1
RESULT: poll_id: 1
Here are the simplified changes required for localization and the result I get:
web.php
Route::group(['prefix' => '{locale}', 'where' => ['locale' => '[a-zA-Z]{2}'], 'middleware' => 'setlocale'], function() {
Route::get('/poll/{poll_id}', 'App\Http\Controllers\PollsController#view');
});
Middleware/SetLocale
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next){
app()->setLocale($request->segment(1));
return $next($request);
}
}
PollsController#view remained unchanged.
Now, when I open the following URL (http://domain.name/en/poll/1), the result is:
RESULT: poll_id: en
QUESTION
Is there a way to ignore "'prefix' => '{locale}'" in controller or get arguments somehow shifted so that in the controller I still get poll_id=1, not locale=en?
PS. The easiest fix would be to add another argument to PollsController#view in the following way, but it does not smell well and then I would need to add locale argument to all functions, although I do not use it there:
public function view($locale, $poll_id){
echo "poll_id: ".$poll_id;
}
In your middleware you can tell the Route instance to forget that route parameter so it won't try to pass it to route actions:
public function handle($request, $next)
{
app()->setLocale($request->route('locale'));
// forget the 'locale' parameter
$request->route()->forgetParameter('locale');
return $next($request);
}

Laravel 5.4 proper way to store Locale setLocale()

I need to know. What is the proper way to store Locale for user. If for each users' request I change the language by
App::setLocale($newLocale);
Would not it change language for my whole project and for other requests as well? I mean when one user changes language it will be used as default for other users.
Thanks in advance
If you set App::setLocale() in for example in your AppServiceProvider.php, it would change for all the users.
You could create a middleware for this. Something like:
<?php
namespace App\Http\Middleware;
use Closure;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
app()->setLocale($request->user()->getLocale());
return $next($request);
}
}
(You need to create a getLocale() method on the User model for this to work.)
And then in your Kernel.php create a middleware group for auth:
'auth' => [
\Illuminate\Auth\Middleware\Authenticate::class,
\App\Http\Middleware\SetLocale::class,
],
And remove the auth from the $routeMiddleware array (in your Kernel.php).
Now on every route that uses the auth middleware, you will set the Locale of your Laravel application for each user.
I solved this problem with a controller, middleware, and with session.
This worked for me well, hope it helps you.
Handle the user request via the controller:
Simply set the language to the users session.
/**
* Locale switcher
*
* #param Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function switchLocale(Request $request)
{
if (!empty($request->userLocale)) {
Session::put('locale', $request->userLocale);
}
return redirect($request->header("referer"));
}
Route to switch locale:
Route::post('translations/switchLocale}', ['as' => 'translations.switch', 'uses' => 'Translation\TranslationController#switchLocale']);
Middleware to handle the required settings:
In the Middleware check the user's session for the language setting, if its pereset set it.
/**
* #param $request
* #param Closure $next
* #param null $guard
* #return mixed
*/
public function handle(Request $request, Closure $next, $guard = null)
{
if (Session::has('locale')) {
App::setLocale(Session::get('locale'));
}
}
Lastly the switching form:
{!! Form::open(["route" => "translations.switch", "id" => "sideBarLocaleSelectorForm"]) !!}
{!! Form::select("userLocale", $languages, Session::get("locale")) !!}
{!! Form::close() !!}
<script>
$(document).on("change", "select", function (e) {
e.preventDefault();
$(this).closest("form").submit();
})
</script>
When someone loads your website it uses the default which is set in the config file.
The default language for your application is stored in the config/app.php configuration file.
Using the App::setLocale() method would only change for a specific user which I assume would be set in the session, the config file value would not be altered.
You may also change the active language at runtime using the setLocale method on the App facade
You could see this in action yourself by opening your website in two different browsers (as they would be using two different sessions) then changing the locale in one and seeing the default load in the other.
https://laravel.com/docs/5.4/localization#introduction
You could create a middleware like below.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if (auth()->check() && $languageId = auth()->user()->language_id) {
$locale = Language::find($languageId)->locale;
app()->setLocale($locale);
}
if ($request->lang) {
app()->setLocale($request->lang);
}
return $next($request);
}
}
I was facing the same problem, the locale was changing in session but not in config. So have checked the session's locale in every blade and controller and set the default the language instant from there, here is the code on my blade file
#php
if(\Session::get('locale') == 'en')
\App::setLocale('en');
else
\App::setLocale('bn');
#endphp
Hope it will help you

how can i detect language in laravel 5.1 api for validation error?

I have a api in laravel and I want return validation errors in user's language. how can I specify language in laravel api?
for example response this :
if ($validator->fails()) {
return response()->json([
'errors' => $validator->getMessageBag()->getMessages(),
], 400);
}
return best for each language. fa and en.
There is No need Of Doing All This
You can Do this in your resources Folder
1)Laravel's localization features provide a convenient way to retrieve strings in various languages, allowing you to easily support multiple languages within your application. Language strings are stored in files within the resources/lang directory. Within this directory there should be a subdirectory for each language supported by the application
For step by step guide check this link : https://laravel.com/docs/5.3/localization
1) create a middleware in App/Http/Middleware
localization.php
and write these in that:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Foundation\Application;
/**
* Class Localization
*
* #author Mahmoud Zalt <mahmoud#zalt.me>
*/
class Localization
{
/**
* Localization constructor.
*
* #param \Illuminate\Foundation\Application $app
*/
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
*
* #return mixed
*/
public function handle($request, Closure $next)
{
// read the language from the request header
$locale = $request->header('Content-Language');
// if the header is missed
if(!$locale){
// take the default local language
$locale = $this->app->config->get('app.locale');
}
// check the languages defined is supported
if (!array_key_exists($locale, $this->app->config->get('app.supported_languages'))) {
// respond with error
return abort(403, 'Language not supported.');
}
// set the local language
$this->app->setLocale($locale);
// get the response after the request is done
$response = $next($request);
// set Content Languages header in the response
$response->headers->set('Content-Language', $locale);
// return the response
return $response;
}
}
2) Register the middleware in the Middlewares
for this. go to App\Http\Kernel.php
add in this array that there is in kernel file:
protected $middleware = []
this one.
\App\Http\Middleware\Localization::class,
3) add this to the app.php in config dir
'supported_languages' => ['en' => 'English', 'fa' => 'persian'],
4) create language folder in the lang folder "resources/lang" for your language (in this case it is [fa] next to [en]) and of course set your files there. for this question only copy validation.php file to your fa folder and change error text.
5) set the header "Content-Language" in your request to ([en] or [fa]).

Laravel owner middleware not working

I created a middleware (app/Http/Middleware/AbortIfNotOwner.php), this is code from another Stackoverflow post
<?php
namespace App\Http\Middleware;
use Closure;
use DB;
class AbortIfNotOwner
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $resourceName
* #return mixed
*/
public function handle($request, Closure $next, $resourceName)
{
$resourceId = $request->route()->parameter($resourceName);
$user_id = \DB::table($resourceName)->find($resourceId)->user_id;
if ($request->user()->id != $user_id) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
I register it in the app\Http\Kernel.php
protected $routeMiddleware = [
'owner' => 'App\Http\Middleware\AbortIfNotOwner',
];
and in my route file I have:
Route::group(['middleware' => ['owner:bids']], function() {
Route::get('user/{id}/bids', ['as' => 'buyer_bids', 'uses' => 'User\Buyer\BidsController#getBidsPerUser']);
});
When I run this code I get an
ErrorException in AbortIfNotOwner.php line 23: Trying to get property
of non-object
This refers to the following lines in the middleware:
> $resourceId = $request->route()->parameter($resourceName);
> $user_id = \DB::table($resourceName)->find($resourceId)->user_id;
The issue seems to be that resourceId is null I think. I do have a field user_id in the bids table, so am not sure what is wrong. The route URL is like /user/2/bids.
EDIT - SOLVED
I found that the below works:
$user_id = \DB::table($resourceName)->find($request->id)->user_id;
instead of
$resourceId = $request->route()->parameter($resourceName);
$user_id = \DB::table($resourceName)->find($resourceId)->user_id;
This works with the routes like
Route::get('/{id}/bids'
EDIT - SOLVED - Other solution
$resourceId = $request->route()->parameter($resourceName);
$user_id = \DB::table($resourceName)->find($resourceId)->user_id;
will work if the route is changed to
Route::get('/{bids}/bids'
... instead of
Route::get('/{id}/bids'...
Change your route like this Route::get('user/{bids}/bids'... becasse to get a route parameter like this $request->route()->parameter('name') it has to match the parameter name in the route, meaning the bolded one user/{bids}/bids.
\DB::table($resourceName)->find($resourceId) is returning null (no results), so there's no user_id property to it. Check that you've found a result before attempting to access its properties.
Same thing for $request->user()->id - if $request->user() is null due to the user not being logged in, it'll fail.

Upgrading from Laravel 4.2 to Laravel 5 - Container

I still have some trouble understanding all the changes from Laravel 4.2 to 5.0.
I have already managed to import all my models, controllers, config etc. I have namespaced almost everything but one thing that I can't seem to manage is to transform this code from 4.2 app\filters.php to my new 5.0 application.
Here's part of the code with some added explanations below that I'm having problems with. The following code was added so that we can conveniently ask for the permissions inside a group for all the actions/visible fields for the current user.
if(App::make('Authflag', $usergroup->id)->can(GroupPermissions::EDIT_MEMBERS)) ...
Code from 4.2:
App::before(function($request) {
App::instance('Authflags', array());
App::bind('Authflag', function($app, $param) {
$authflags = App::make('Authflags');
if(isset($authflags[$param]))
{
return $authflags[$param];
}
// Calculate generate flag value
$authflags[$param] = $authflag;
App::instance('Authflags', $authflags);
return $authflag;
});
});
Explanation:
instance Authflags contains group_id => permissionObject
Code explanation:
Get the Authflags array instance
If we already have the needed permissionObject return it
Else generate/calculate/request the permissionObject
Update the Authflags instance
Return the created permissionObject
But whatever I try I keep getting the ReflectionException in Container.php line 776: Class Authflag does not exist.
I tried to create a contract and a service and set a binding inside the AppServiceProvider. But I'm pretty sure I was doing a completely wrong/different thing.
I tried to just copy this code with some modifications inside the AppServiceProvder. But It just seemed wrong and didn't work.
(Come to think of it the whole code should have probably been inside the start/global.php)
How can I port this code to Laravel 5.0?
You have to use a middleware "encapsulation". Here is an example, that will show where you would have to put your custom before and after parts of your app.
use Closure;
class ChangeCookieLifetime {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//anything put here will be run BEFORE your app
$response = $next($request);
//anything put here will be run AFTER your app
return $response
}
}
In your particular case iw dould like this:
use Closure;
class ChangeCookieLifetime {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
App::instance('Authflags', array());
App::bind('Authflag', function($app, $param) {
$authflags = App::make('Authflags');
if(isset($authflags[$param]))
{
return $authflags[$param];
}
// Calculate generate flag value
$authflags[$param] = $authflag;
App::instance('Authflags', $authflags);
return $authflag;
});
$response = $next($request);
//anything put here will be run AFTER your app
return $response
}
}
Although I can't promise that the parts I inserted will work, this is the direct "translation" from Laravel 4.2 to Laravel 5

Resources