I'm trying to translate views which some of them are loaded via Ajax, so the problem is that even the locale is I get always the text of the default locale, to be clear, this how my files looks :
app/config/app.php :
//...
'languages' => array('fr', 'en'),
'locale' => 'fr',
//...
routes.php
if(!Request::ajax()) {
// Set locale
$locale = Request::segment(1);
if(in_array($locale, Config::get('app.languages'))) {
App::setLocale($locale);
Session::put('locale', $locale);
} else {
$locale = null;
Session::put('locale', $locale);
}
$locale = Session::get('locale') or null;
}
// Group by locale
Route::group(
array( 'prefix' => $locale ), function () {
// Home controller
Route::get('/' . Config::get('app.lcoale'), array( 'uses' => 'HomeController#getIndex', 'as' => '/' ));
//...
The ajax routes are out of the group prefixed by the locale :
Route::group(
array( 'prefix' => 'ajax', 'namespace' => 'Ajax', 'before' => 'ajax' ), function () {
//...
When I check the current locale after sending ajax request Config::get('app.locale'): It show me the correct locale, but the rendered text in the view is of the default locale (fr).
It makes a sense for you ?, Please help.
Thank you
Resolved for me.
Route::filter('ajax', function(){
if(! Request::ajax())
{
App::abort(404);
}
// Set again the locale
if(Session::has('locale'))
App::setLocale(Session::get('locale'));
});
Related
I have a group route like this
PHP LARAVEL 9
/**
* ACCOMODATIONS
*/
Route::controller(AccomodationsController::class)->group(function () {
Route::prefix('accomodations')->group(function () {
Route::GET('/', 'index');
Route::GET('/italy', 'index');
Route::GET('/greece', 'index');
});
});
In the controller side I want to obtain the accomodations part and the italy greece part without slashes. I'm doing like this
PHP LARAVEL 9
class AccomodationsController extends Controller
{
public function index(request $request){
$listType = [
'type' => trim($request->route()->getPrefix(), '/'),
'route' => request()->segment(count(request()->segments()))
];
dd($listType);
);
}
/*
http://example.com/accomodations outputs
array [
"type" => "accomodations"
"route" => ""
]
/*
/*
http://example.com/accomodations/italy outputs
array [
"type" => "accomodations"
"route" => "italy"
]
*/
/*
http://example.com/accomodations/greece outputs
array [
"type" => "accomodations"
"route" => "greece"
]
*/
This works but the way I'm manipulating the request in $listType seems a little bloated to me, is there a cleaner way in laravel?
Use parameterized route for same method.
Routes
Route::controller(AccomodationsController::class)->group(function () {
Route::prefix('accomodations')->group(function () {
Route::GET('/{destination}', 'index');
});
});
Controller
public function index(Request $request, $destination){
$listType = [
'type' => trim($request->route()->getPrefix(), '/'),
'route' => $destination
];
dd($listType);
);
If your destination is optional you can use optional parameter
Edit 1:
Route with Optional Parameter
Route::controller(AccomodationsController::class)->group(function () {
Route::prefix('accomodations')->group(function () {
Route::GET('/{destination?}', 'index');
});
});
Controller with Optional parameter
public function index(Request $request, $destination=''){
$listType = [
'type' => trim($request->route()->getPrefix(), '/'),
'route' => $destination
];
dd($listType);
);
you can assign any value (null, string, int, etc.) to the destination variable just like the default function argument in PHP.
I'm trying to have access to {module} inside my function, but it returns me the following error :
Too few arguments to function {closure}(), 1 passed in /Users/Bernard/PROJECTS/myproject/vendor/laravel/lumen-framework/src/Routing/Router.php on line 62 and exactly 2 expected
Here's my code :
$app->router->group([
'namespace' => 'App\Http\Controllers',
], function ($router) {
$router->group([
'namespace' => $version,
'prefix' => "api/$version/{contest}/{module}",
'middleware' => 'App\Http\Middleware\COMMON\DefineContest',
], function ($request, $module) use ($router) {
dd($module);
require __DIR__ . "/../routes/v1/{module}.routes.php";
});
});
In Laravel, it would be as simple as calling Illuminate\Support\Facades\Route::parameter(paramname) but since it is apparently not available in Lumen(looking at Lumen Router there are no methods or parameters for this use case), this is an imperative answer that does get the job done:
$version = 1;
$router->group([
'namespace' => 'App\Http\Controllers',
], function ($router) use ($version) {
$router->group([
'namespace' => $version,
'prefix' => "api/$version/{contest}/{module}",
'middleware' => 'App\Http\Middleware\COMMON\DefineContest'
], function ($router) use ($version) {
$url = $_SERVER['REQUEST_URI'];
if (preg_match("/api\/$version\/(?<contest>\w+)\/(?<module>\w+)/", $url, $output)) {
$module = $output['module'];
dd($module);
}
});
});
I should point out that this code results in an extra step for every route which I don't think matters since it's not that heavy but something to note of.
I have an url like /locations/name-of-the-location.ID
My route is:
Route::get('locations/{slug}.{location}', ['as' => 'locations.show', 'uses' => 'LocationsController#show'])->where([
'location' => '[0-9]+',
'slug' => '[a-z0-9-]+'
]);
Now I want to check if the slug provided is the same that is saved in the database column 'slug' with my model (because the slug may have changed). If not, then I want to redirect to the correct path.
Where is the best place to do that? I thought of \App\Providers\RouteServiceProvider- but when I try to use Route::currentRouteName() there, I get NULL, maybe because it is 'too early' for that method in the boot() method of RouteServiceProvider.
What I could do, is to work with the path(), but that seems a bit dirty to me, because I work with route prefixes in an other language.
Here's what I tried (I am using a little helper class RouteSlug) - of course it does not work:
public function boot()
{
parent::boot();
if (strstr(Route::currentRouteName(), '.', true) == 'locations')
{
Route::bind('location', function ($location) {
$location = \App\Location::withTrashed()->find($location);
$parameters = Route::getCurrentRoute()->parameters();
$slug = $parameters['slug'];
if ($redirect = \RouteSlug::checkRedirect(Route::getCurrentRoute()->getName(), $location->id, $location->slug, $slug))
{
return redirect($redirect);
}
else
{
return $location;
}
});
}
}
Your route should look like this:
Route::get('locations/{id}/{slug}', ['as' => 'locations.show', 'uses' => 'LocationsController#show'])->where([
'id' => '[0-9]+',
'slug' => '[a-z0-9-]+'
]);
And LocationsController#show should look like this:
public function show($id, $slug)
{
// Add 'use App\Location' to the top of this controller
$location = Location::find($id);
// I'm not sure what you were doing with the soft deleted items
// but you might want to restore them if you are using them
if ($location->trashed()) $location->restore();
if ($slug != $location->slug) {
return redirect()->route('locations.show', ['id' => $id, 'slug' => $location->slug]);
}
// Return the view
}
So finally I came up with a Middleware:
App\Http\Middleware\CheckSlug
public function handle($request, Closure $next)
{
if ($redirect = RouteSlug::checkRedirect(Route::currentRouteName(), $request->location->id, $request->location->slug, $request->slug))
{
return redirect($redirect);
}
return $next($request);
}
My route look like this:
Route::get('locations/{slug}.{location}', ['as' => 'locations.show', 'uses' => 'LocationsController#show'])->where([
'location' => '[0-9]+',
'slug' => '[a-z0-9-]+'
])->middleware(App\Http\Middleware\CheckSlug::class);
"You may also change the active language at runtime using the setLocale method on the App facade:"
https://laravel.com/docs/5.3/localization#introduction
Route::get('welcome/{locale}', function ($locale) {
App::setLocale($locale);
//
});
How do we do that with $locale if we have something like this:
Route::group(['prefix' => 'admin/{id}/{locale}', 'namespace' => 'Admin'], function( $locale ) {
// this does not work.
App::setLocale( $locale );
// this does work.
App::setLocale( Request::segment( 3 ) );
Route::resource('product', 'ProductController', ['except' => [
'show'
]]);
});
The issue is with route parameters not with localization
Since you expect two params for the route you should pass two params for the closure.
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
});
In your example
Route::group(['prefix' => 'admin/{id}/{locale}', 'namespace' => 'Admin'], function( $id, $locale ) {
// this does not work.
App::setLocale( $locale );
// this does work.
App::setLocale( Request::segment( 3 ) );
Route::resource('product', 'ProductController', ['except' => [ 'show' ]]);
});
Refer route parameters for more info
Please note - Route::group callback executes on any request (even not for your prefix!). Route::group is not similar to Route::get/post/match, it is like a helper for internal get/post/match calls.
App::setLocale( $locale ); does not work because Laravel passes only instance of Illuminate\Routing\Router into group's callback. On this stage locale prefix has not been extracted and even URL has not been processed.
App::setLocale( Request::segment( 3 ) ); will be executed for 'one/two/three' with 'three' as a locale.
Your example should be:
Route::group(['prefix' => 'admin/{id}/{locale}', 'namespace' => 'Admin'], function() {
// test a locale
Route::get('test', function($locale){ echo $locale; });
// ProductController::index($locale)
Route::resource('product', 'ProductController', ['except' => [
'show'
]]);
});
So, just update your ProductController and add $locale as a parameter.
Alternative: if you want setLocale in one place update your routes:
// set locale for '/admin/anything/[en|fr|ru|jp]/anything' only
if (Request::segment(1) === 'admin' && in_array(Request::segment(3), ['en', 'fr', 'ru', 'jp'])) {
App::setLocale(Request::segment(3));
} else {
// set default / fallback locale
App::setLocale('en');
}
Route::group(['prefix' => 'admin/{id}/{locale}', 'namespace' => 'Admin'], function() {
Route::resource('product', 'ProductController', ['except' => [
'show'
]]);
});
I have a problem with my advanced template when I try to change page using internationalization.
I try to explain. To use the internationalization on my site I have follow this steps:
In params.php, I have added this:
<?php
return [
'adminEmail' => 'admin#example.com',
'languages' => [
'en' => 'English',
'it' => 'Italian',
],
];
I have added this in my frontend\views\layouts\main.php to call on my website the languages insert above:
<?php
foreach(Yii::$app->params['languages'] as $key => $language){
echo '<span class="language" id ="'.$key.'">'.$language.' | </span>';
}
?>
after I have created a new file named main.js. To permit to yii2 to see the main.js file I added this in the AppAsset.php (is it correct?). In this file I insert this:
$(function(){
$(document).on('click','.language', function(){
var lang = $(this).attr('id');
$.post('index.php?r=site/language', {'lang':lang},function(data){
location.reload();
});
});
$(document).on('click','.fc-day', function(){
var date = $(this).attr('data-date');
$get('index.php?r=event/create',{'date':date},function(data){
$('#modal').modal(show)
.find('#modalContent')
.html(data);
});
});
$('#modalButton').click(function(){
$('#modal').modal(show)
.find('#modalContent')
.load($(this).attr('value'));
});
});
after that in the sitecontroller.php I have added this:
public function actionLanguage()
{
if(isset($_POST['lang'])){
Yii::$app->language = $_POST['lang'];
$cookie = new Yii\web\cookie([
'name'=>'lang',
'value'=>$_POST['lang']
]);
Yii::$app->getResponse()->getCookies()->add($cookie);
}
}
after in config\main.php I have added this in components:
'components' => [
'i18n' => [
'translations' => [
'app' => [
'class' => 'yii\i18n\PhpMessageSource',
//'basepath' => #app/messages,
'sourceLanguage' => 'it',
'fileMap' => [
'app' => 'app.php',
'app/error' => 'error.php',
],
],
],
],
finally i have create on the root a folder called messages\it and messages\en and inside two files (one per folder) called app.php I have insert this text:
<?php
return [
'Benvenuto' => 'Welcome'
];
that's all...but after load my home page (correctly) when i click on one of the languages (Italian or English) I see the following messages:
jquery.js?ver=1.11.3:4 POST http://localhost/mdf/frontend/web/index.php?r=site/language 400 (Bad Request)
And If I try to paste directly this url, I obtain only a blank page:
http://localhost/mdf/frontend/web/index.php?r=site/language
This is only a partial response to your question
The blank page when you invoke using browser could be related to the fact that you don't render nothings in this case.
try manage the ajax this way
public function actionLanguage()
{
if (Yii::$app->request->isAjax) {
$data = Yii::$app->request->post();
if(isset($data['lang'])) {
Yii::$app->language = $data['lang'];
$cookie = new Yii\web\cookie([
'name'=>'lang',
'value'=>$_POST['lang']
]);
Yii::$app->getResponse()->getCookies()->add($cookie);
return;
}
} else {
return $this->render('index', []);
}
}