mcamara / laravel-localization

Easy localization for Laravel
MIT License
3.32k stars 507 forks source link

Route Trans Caching is broken with Livewire 3 #880

Open relaypilot opened 11 months ago

relaypilot commented 11 months ago

Describe the bug When using Livewire 3, it is not possible to cache the localized routes with php artisan route:trans:cache. Livewire 2 automatically preserved the URL prefix when making component updates via https://example.com/en/livewire/update Livewire 3 has stopped supporting this behavior automatically. See official Livewire documentation mentioning Laravel Localization: https://livewire.laravel.com/docs/upgrading#localization

To Reproduce Steps to reproduce the behavior:

  1. Require Livewire 3 and update the Livewire update route (as recommended in the official Livewire documentation)
  2. Cache localized routes using: php artisan route:trans:cache
  3. Browse your website using a Laravel Localization locale (EN in my example)
  4. Open the browser console and click on a Livewire button (or any Livewire action)
  5. Console logs a call to /livewire/update instead of /en/livewire/update and returns a 404

Expected behavior When browing the FR locale (or any other locales), you would expect Livewire to call /en/livewire/update instead of the non-localized route /livewire/update This only fails when php artisan route:trans:cache has been run previously. If you run php artisan route:trans:clear, it works correctly. So something is broken in caching the route.

More info:

ArtMin96 commented 10 months ago

Having the same issue

greggh commented 10 months ago

I am having this issue without the route:trans:cache. I can clear it and still get the error. It is posting to /livewire/update instead of /en/livewire/update

dennisvandalen commented 10 months ago

Same here. Cache is broken.

I does work without caching while adding the new setUpdateRoute method to the route group.

Route::group(['prefix' => LaravelLocalization::setLocale()], function ()
{
    // Your other localized routes...

    Livewire::setUpdateRoute(function ($handle) {
        return Route::post('/livewire/update', $handle);
    });
});
mperezsc commented 10 months ago

Experiencing the same. In my case it works after clearing cache, but once cached, it fails.

core45 commented 10 months ago

In my case no Livewire 3 component placed on localized route works properly when it comes to update. Routes cached or not.

The solution mentioned by dennisvandalen helped though. Still it should be mentioned in the documentation at least, or better, dealt with

dennisvandalen commented 10 months ago

I guess someone needs to review the caching meganism of this package. But I’m not sure how actively maintained it is, looking at the PRs that haven’t been merged or commented on.

@mcamara are you still actively maintaining this package?

RikoDEV commented 10 months ago

It looks like a livewire problem, when I manually edited the https://github.com/livewire/livewire/blob/daa88b5a6203c0e60f0a9bf8a8b5ac1394708ddc/src/Mechanisms/HandleRequests/HandleRequests.php#L29C12-L29C12 line by adding before $this->updateRoute->uri the current language the update request was executed correctly.

LaravelLocalization correctly registers the route with the prefix, but livewire tries to send the request to the route without prefix.

Working code inside HandleRequests:

    function getUpdateUri()
    {
        return (string) str(app()->getLocale() . "/{$this->updateRoute->uri}")->start('/');
    }

or more universal:

    function getUpdateUri()
    {
        return (string) str(route('livewire.update', null, false))->start('/');
    }
core45 commented 10 months ago

Whatever the culprit is both Livewire 3 and LaravelLocalization are quite popular packages. But I'd say it's easier to fix LaravelLocalization. Or at least put the info in the docs how fix it for now.

poldixd commented 9 months ago

Did anybody found a workaround?

ArtMin96 commented 9 months ago

Did anybody found a workaround?

https://github.com/mcamara/laravel-localization/issues/880#issuecomment-1703773314

core45 commented 9 months ago

The workaround is on the top of this thread.

Route::group(['prefix' => LaravelLocalization::setLocale()], function () { // Your other localized routes...

Livewire::setUpdateRoute(function ($handle) {
    return Route::post('/livewire/update', $handle);
});

});

What is needed is a permanent solution and a bit of attention by the package owner.

poldixd commented 9 months ago

Maybe I found a solution inspired by this file.

Remove this block from the web.php

Livewire::setUpdateRoute(function ($handle) {
    return Route::post('/livewire/update', $handle);
});

… and put it in the RouteServiceProvider.php. Don't forget the middleware() and prefix() method.

use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Livewire\Livewire;

// ...

/**
 * Define your route model bindings, pattern filters, and other route configuration.
 *
 * @return void
 */
public function boot()
{
    Livewire::setUpdateRoute(function ($handle) {
        return Route::post('/livewire/update', $handle)
            ->middleware('web')
            ->prefix(LaravelLocalization::setLocale());
    });

    // ...
}

Now Livewire::setUpdateRoute will not be cached if you run php artisan route:trans:cache.

dennisvandalen commented 9 months ago

Maybe I found a solution inspired by this file.

Remove this block from the web.php

Livewire::setUpdateRoute(function ($handle) {
    return Route::post('/livewire/update', $handle);
});

… and put it in the RouteServiceProvider.php. Don't forget the middleware() and prefix() method.

use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Livewire\Livewire;

// ...

/**
 * Define your route model bindings, pattern filters, and other route configuration.
 *
 * @return void
 */
public function boot()
{
    Livewire::setUpdateRoute(function ($handle) {
        return Route::post('/livewire/update', $handle)
            ->middleware('web')
            ->prefix(LaravelLocalization::setLocale());
    });

    // ...
}

Now Livewire::setUpdateRoute will not be cached if you run php artisan route:trans:cache.

Awesome, this works perfectly!

mperezsc commented 9 months ago

Maybe I found a solution inspired by this file.

Remove this block from the web.php

Livewire::setUpdateRoute(function ($handle) {
    return Route::post('/livewire/update', $handle);
});

… and put it in the RouteServiceProvider.php. Don't forget the middleware() and prefix() method.

use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Livewire\Livewire;

// ...

/**
 * Define your route model bindings, pattern filters, and other route configuration.
 *
 * @return void
 */
public function boot()
{
    Livewire::setUpdateRoute(function ($handle) {
        return Route::post('/livewire/update', $handle)
            ->middleware('web')
            ->prefix(LaravelLocalization::setLocale());
    });

    // ...
}

Now Livewire::setUpdateRoute will not be cached if you run php artisan route:trans:cache.

Do you consider this a defenitive solution, or should this be temporary until either livewire or this package updates something? Thanks a lot, I really appreciate it.

BarionTechnology commented 6 months ago

Maybe I found a solution inspired by this file. Remove this block from the web.php

Livewire::setUpdateRoute(function ($handle) {
    return Route::post('/livewire/update', $handle);
});

… and put it in the RouteServiceProvider.php. Don't forget the middleware() and prefix() method.

use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Livewire\Livewire;

// ...

/**
 * Define your route model bindings, pattern filters, and other route configuration.
 *
 * @return void
 */
public function boot()
{
    Livewire::setUpdateRoute(function ($handle) {
        return Route::post('/livewire/update', $handle)
            ->middleware('web')
            ->prefix(LaravelLocalization::setLocale());
    });

    // ...
}

Now Livewire::setUpdateRoute will not be cached if you run php artisan route:trans:cache.

Awesome, this works perfectly!

This works perfect to me, I have a different error on my website. When I make a searching by wire:model.live, my website redirects to my login. But this solved my issue

kevinaswind commented 4 months ago

Thank you so much! You saved my day!

inalto commented 2 months ago

genius, thankyou it saves to put the hands in livewire.

//Livewire\Mechanisms\PersistentMiddleware\PersistentMiddleware::getRouteFromRequest($request) 

$route = app('router')->getRoutes()->match($request);

the getRoutes function was failing to find the route in livewire even if i put livewire/update in the ignore list.

your solution is simple and elegant (after you know how :)