Laravel default locale not in url - laravel

Suppose I have 3 (or more languages) on site. English, Italian, French. English being the default.
I want the homepage url to be:
mysite.com/ - for english
mysite.com/it - for italian
mysite.com/fr - for french
My route is currently
Route::get('/{locale}', 'HomeController#index')->name('home');
This works for French, Italian but obviously not for English being just mysite.com/
I dont want another route like
Route::get('/', 'HomeController#index')
Because then I wouldn be able to simply call home in any language as
{{ route('home', $locale) }}
Whats the best solution?

One of my old solutions but still should work:
In the beginning of routes.php
$locale = Request::segment(1);
if(in_array($locale, ['en','fr','it'])){
app()->setLocale($locale);
}else{
app()->setLocale('en');
$locale = '';
}
Then
Route::group([
'prefix' => $locale
], function(){
Route::get('/demo', 'TestController#demo')->name('demo');
...
})
Important: You should always use named routes in this scenario. The generated URLs will then be for the current locale:
route('demo') will return /demo when app locale is english, and /it/demo when app locale is italian!

Laravel allows optional parameters in route definition, so you can set local route parameter as optional for your usage :
Route::get('/{locale?}', 'HomeController#index')->name('home');
And in your HomeController, check the parameter to know if locale is present
public function index(Request $request, $locale = null) {
if (empty($locale)) {
$locale = 'en'; // english by default
}
...
}
Hope it's helps you :)

Related

Laravel edit function UrlGenerator locale

I am making a multilingual site on Laravel 9, I have multilingual routes
ru.home
uk.home
en.home
Based on them, the correct locale is displayed, everything works.
But, instead of writing in each template
{{ route(app()->getLocale().'home') }}
I need to change or override the behavior of a function route() (Illuminate\Routing\UrlGenerator)
To be able to transfer locale into a function like this:
route($name, $parameters = [], $absolute = true, $locale = null)
Как правильно это сделать?

Laravel 8 route() does not localize strings

EDIT: found the answer to all my questions: https://github.com/codezero-be/laravel-localized-routes (and, of course, 42).
I'm working on a multi-language website where the URL's contain localized strings. For instance:
https://site/en/members/john-doe
https://site/nl/leden/john-doe
(and so for every language)
In web.php, I prefixed my routes. Via middleware, I set the current language (retrieved from the first URL-segment). This works fine for everything (both in controllers and in blade)... except for the URLs generated by route(). They are always in the default language. Even though everything else is correctly localized. If I dump app()->getLocale() in a controller of blade it shows the correct language. Only the URLs generated by the route()-function are always in the default fallback language.
I've tried moving my middleware-class higher up in the middleware-groups list. That didn't make a difference.
web.php
Route::prefix('{lang}')->group(function() {
Route::get(trans('routes.members') . '/{username}/', 'MembersController#profile')
->name('members.show');
}
SetLanguage middleware
...
public function handle(Request $request, Closure $next)
{
$lang = $request->segment(1) ?? app()->getLocale();
//set app language
app()->setLocale($lang);
//set default url parameter
URL::defaults(['lang' => $lang]);
return $next($request);
}
...
App\Http\Kernel.php
...
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Laravel\Jetstream\Http\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\SetLanguage::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\UserLastSeenAt::class,
],
...
Got it (with a little help from a friend)
In the AppServiceProvider's boot function I've added
public function boot(Request $request)
{
//set app language
app()->setLocale($request->segment(1) ?? app()->getLocale());
}
& the SetLanguage-middleware now only contains
public function handle(Request $request, Closure $next)
{
//set default url parameter
URL::defaults(['lang' => app()->getLocale()]);
return $next($request);
}
That did the trick!
Great! I've done the same as you, but i have a problem when i chose to change the lang from switcher.
The switcher in blade:
<a class="ml-1 underline ml-2 mr-2" href="{{ route('change-lang')}}">
<span>{{ $locale_name }}</span>
</a>
The target route:
Route::get('/lang', [LangController::class, 'changeLang'])->name('change-lang');
The function in LangController:
public function changeLang($locale){
App::setLocale($locale);
session()->put('locale', $locale);
return redirect()->back();
}
Let me Exaplain:
If i navigate, for example, in about section and my url is "webname/it/azienda" and i switch language in EN my url becomes "webname/it/en";
I don't have issues if i change language if I have "webname/azienda" or "/" for home page.
I cannot change only the parameters LOCALE without adding it.

Laravel Redirect url from {id} to {id}/{name}

I am new in laravel framework now I'm working fully developed website using Laravel. I have changed blog url form {id} to {id}/{name} like www.example.com/news/203 to www.example.com/news/203/title. It's working fine. but i need to redirect if old url enter into current url opened from cache or something else.
Route::get('{id}/{name}', 'EventController#show')
->name('events-detail')
->where([
"id" => "[0-9]+"
]);
You can define another route in which you will find the model by id and use its title to redirect the user to the new route:
Route::get('{id}', function ($id) {
$model = Model::findOrFail($id);
return redirect()->route('events-detail', ['id' => $id, 'name' => $model->name]);
});
Note that you have to change Model with the class you use for this route.
Create 2 routes and add below code.
Route::get('{id}/{name}', function () {
//new URL as you want
return redirect()->route({id}/{name});
});
Route::get('{id}', function () {
//as you want for simple URL
});
I'm assuming the name portion is not really used at all, except for SEO/friendlier urls. If this is the case, just make the name parameter optional, and there will be no need for a redirect:
Route::get('{id}/{name?}', 'EventController#show')
->name('events-detail')
->where([
"id" => "[0-9]+"
]);
This route will match /203 and /203/news-title.

Localization in laravel

I designed a site with Laravel. now I want add new language to it.I read laravel document . It was good but I have a problem.suppose I have a page that show detail of products so I have a route like mysite.com/product/id that get product's id and show it.also I have a method in controller like
public function showProduct($id){
...
}
If I add new Language , the route will change to this: mysite/en/product/id
now I must change my method because now two parameter send my method.something like this :
public function showProduct($lang,$id){
...
}
So two problems arise:
I must change all method in my site which is time consuming
I do not need language parameter in methods because I set $locan via middleware
pay attention that I do not want remove for example en from my URL (because of SEO)
Open your RouteServiceProvider and say that language parameter actually is not a parameter, it's a global prefix.
protected function mapWebRoutes()
{
Route::group([
'middleware' => 'web',
'namespace' => $this->namespace,
'prefix' => Request::segment(1) // but also you need a middleware about that for making controls..
], function ($router) {
require base_path('routes/web.php');
});
}
here is sample language middleware, but it's need to be improve
public function handle($request, Closure $next)
{
$langSegment = $request->segment(1);
// no need for admin side right ?
if ($langSegment === "admin")
return $next($request);
// if it's home page, get language but if it's not supported, then fallback locale gonna run
if (is_null($langSegment)) {
app()->setLocale($request->getPreferredLanguage((config("app.locales"))));
return $next($request);
}
// if first segment is language parameter then go on
if (strlen($langSegment) == 2)
return $next($request);
else
// if it's not, then you may want to add locale language parameter or you may want to abort 404
return redirect(url(config("app.locale") . "/" . implode($request->segments())));
}
So in your controller, or in your routes. you don't have deal with language parameter
Something like
Route::group(['prefix' => 'en'], function () {
App::setLocale('en');
//Same routes pointing to the same methods...
});
Or
Route::group(['prefix' => 'en', 'middleware' => 'yourMiddleware'], function () {
//Same routes pointing to the same methods...
});

route() helper function in a different locale

I'm trying to create a language switcher, so that you can easily change language on the fly (without being redirected to the home page).
The thing I can't seem to accomplish is getting a url from a route name in a different locale.
Imagine your on mydomain.com/events (or mydomain.com/en/events since these are the same) and I want to get url in french (mydomain.com/fr/evenements)...
In my routes.php I have:
$locale = Request::segment(1);
if ( !array_key_exists($locale, Config::get('translatable.languages'))) {
$locale = null;
App::setlocale(Config::get('translatable.fallback_locale'));
}else{
App::setLocale($locale);
}
Route::group(array('prefix' => $locale), function(){
Route::get(Lang::get('routes.events'), array('as' => 'events.index', 'uses' => 'EventController#index'));
});
I have tried
setting the application locale right before calling the route($route_name) helper function
Setting a session variable with the requested locale (in this example 'fr'), then calling the route($route_name) function. For this I also added at the top of routes.php:
if( Session::has('requested_locale') ){
$locale = Session::pull('requested_locale');
}
I have no idea's left on how to handle this...
I know there is a package Laravel Localization that can do this, but I need it to work without that package (if possible)...
My solution on Laravel 5.1 was...
Defined locales in the config/app.php to create routes using the language files
'locale' => 'en',
'locales' => [
'en'=>'English',
'fr'=>'Français'
],
I've defined my routes in the resources/lang/ directory ('en/routes.php' and 'fr/routes.php' in my case)
return [
'about' => 'a-propos',
];
Defined routes using the language keys, example:
Route::get(trans('routes.about'), ['as' => 'about', function () {
return view('pages.'.App::getLocale().'.about');
}]);
Then I've created dummy route that would be used only for switching to another locale, ONLY after the current route has been matched to request
`
Route::matched(function($route) {
$route = Route::current();
$route_name = $route->getName();
$route_uri = $route->uri();
$locales = Config::get('app.locales');
foreach ($locales as $locale_code => $locale_name) {
if ($locale_code == App::getLocale()) {
continue;
}
if (Lang::has('routes.'.$route_name, $locale_code)) {
$route_uri = $locale_code . '/' . Lang::get('routes.'.$route_name, [], $locale_code);
}
else {
$route_uri = $locale_code . '/' . substr($route_uri, 3);
}
Route::get($route_uri, ['as' => 'change_locale_to_'.$locale_code, function(){
}]);
}
});
`
Finally, I use the dummy route in the view I want. $locale_toggle is a Locale eloquent Model that I'm setting in a Middleware for handling the language with a language code route prefix.
<a href="{{ route('change_locale_to_'.$locale_toggle->code, Route::current()->parameters()) }}" class="dropdown-toggle">

Resources