Code Monkey home page Code Monkey logo

Comments (11)

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024 1

After a lot of thinking and tinkering, I've come up with a working prototype that handles the Livewire requests always being the ajax endpoint instead of the expected original URL.

I could run my current test suite on it by using the current URL for now, instead of the Livewire::originalUrl().
Mind the lines that are commented out.

I pushed a few changes beforehand, to inject the Request instance in my classes' constructor, and used that instead of the Request and Route facades.

In the SetLocale middleware (temporarily?) I can now check if it's a Livewire request, and then rebind my classes with the recreated Request. The main Laravel Request en current Route stays untouched.

You can see in the middleware that I had to jump through some hoops to make everything work.
I'm not overly excited about the complexity, but at least for now, it works.

https://github.com/codezero-be/laravel-localized-routes/pull/93/files

If @gwleuverink or anyone would like to review, I'm open for any feedback.
The middleware changes are on the support-livewire branch:

https://github.com/codezero-be/laravel-localized-routes/tree/support-livewire

from laravel-localized-routes.

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024

Hi,

It's really hard to tell what's going on.
I also have no experience with Livewire.

from laravel-localized-routes.

gwleuverink avatar gwleuverink commented on June 9, 2024

Not sure if this is the problem, but I'm also experiencing some difficulties.

Livewire makes under the hood requests to the backend, to a dedicated /livewire/message endpoint. Because of this it seems like request()->route()->getAction('localized-routes-locale') doesn't return the locale of the route the request originated from.

from laravel-localized-routes.

mgussekloo avatar mgussekloo commented on June 9, 2024

I have the same issue. After an update, {{ \Route::localizedUrl('nl') }} results in "http://site.test/livewire/message/slideshow" (where slideshow is the name of the Livewire component). I hope this gets fixed! Seems this is a known issue with Livewire, and a number of packages exist to deal with it, such as this one. I guess it would be nice if Localized Routes was aware of Livewire, or could be made aware of it in a way.

from laravel-localized-routes.

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024

Hello,

It seems you can configure the middleware in the Livewire config.
By default it applies the web middleware group.

If you add the SetLocale middleware to the web group (right after the session middleware), does it then apply the expected locale? In theory it should find the locale in the session.

You can not use the option omit_url_prefix_for_locale though, since no prefix means default locale then.

Some additional findings...

The /livewire/message path is hardcoded.
https://github.com/livewire/livewire/blob/e117c78f9a4b19edb294b5b576138fd1f896925a/js/connection/index.js#L41

The part that comes before that is the app_url, which is ultimately set in the Livewire config file.
https://github.com/livewire/livewire/blob/65d311c63d2d1092ad5891fd0c1c1bdbed272cee/src/LivewireManager.php#L228
https://github.com/livewire/livewire/blob/65d311c63d2d1092ad5891fd0c1c1bdbed272cee/src/LivewireManager.php#L298

Unfortunately, you can not detect the locale in a config file.
Perhaps you can update the window.livewire_app_url JS variable on runtime, to include the locale?

from laravel-localized-routes.

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024

Hi,

Sorry for the late followup.
I did some testing, but I don't understand what's going on with the locale in Livewire.
This doesn't seem to be documented.

I created a fresh Laravel test app with this package and Livewire included.
If you like, you can download it at https://github.com/ivanvermeyen/test-app-localized-routes-livewire.
The commits will show what I changed.

Locale Problem

For some reason, Livewire's locale is always set to the last locale in my supported_locales config.
I have no clue why.

Initial page load:

Scherm­afbeelding 2023-04-05 om 12 49 32

When I click the button to update the Component:

Scherm­afbeelding 2023-04-05 om 12 49 52

Livewire requests should go through the web middleware by default, so the SetLocale middleware should run too.

Current Route / Request Problem

As mentioned before, Livewire makes ajax calls to a /livewire/message endpoint.
Therefor, the current route and request doesn't match the "expected" original URL, which makes sense.
Code that uses the current route or request won't work properly, like the Route::localizedUrl() macro.

I was able to fix this locally, but I don't know if this is a legit way.

First I need to inject the request (this is not on GitHub yet):

Scherm­afbeelding 2023-04-05 om 12 54 03

And then I inject a recreated version of the original request when we're in a Livewire requests, using a middleware.

public function handle(Request $request, Closure $next): Response
{
    if ($this->isLivewireRequest()) {
        $sessionRequest = Request::create(session('current-url'));

        $sessionRequest->setRouteResolver(function () use ($sessionRequest) {
            return Collection::make(Route::getRoutes())->first(function ($route) use ($sessionRequest) {
                return $route->matches($sessionRequest);
            });
        });

        app()->bind(LocalizedUrlGenerator::class, function () use ($sessionRequest) {
            return new LocalizedUrlGenerator($sessionRequest);
        });
    } else {
        session()->put('current-url', $request->fullUrl());
    }

    return $next($request);
}

protected function isLivewireRequest(): bool
{
    return class_exists(\Livewire\LivewireManager::class)
        && app(\Livewire\LivewireManager::class)->isLivewireRequest();
}

Now the macro works event when the Component gets updated:

Scherm­afbeelding 2023-04-05 om 13 55 27

I would need to do this for every class that uses the current route or request.

If anyone has a better understanding of how this all works, I'd love to hear it.

from laravel-localized-routes.

gwleuverink avatar gwleuverink commented on June 9, 2024

Hi @ivanvermeyen thanks for the comprehensive writeup.

I've since written a temporary workaround that just works ™️. By overriding the packages UrlGenerator, detecting a Livewire request & grabbing the correct locale from the request referrer.

This is hacky as hell though, so I'd love to see a more robust solution.

I vaguely remember Caleb (Livewire's creator) talking about supporting dynamic url's for Livewire update requests in V3, which will release soon (hopefully). It might be easier to integrate with in V3.

from laravel-localized-routes.

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024

The problem seems to be caused by temporarily updating the App locale when generating the URLs for alternative locales.
I do this to automatically fetch translated route parameters.

// Update the current locale if needed.
if ($locale !== null && $locale !== $currentLocale) {
App::setLocale($locale);
}
$url = parent::route($resolvedName, $parameters, $absolute);
// Restore the current locale if needed.
if ($locale !== null && $locale !== $currentLocale) {
App::setLocale($currentLocale);
}

If I comment out the 2 calls to App::setLocale(), the locale is correct in Livewire and the {locale}/livewire/message/{name} endpoint is used for the ajax calls.

Will try to find out why this issue is occurring.

from laravel-localized-routes.

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024

Finally discovered the source of all evil.

In the code of the Route::localizedUrl() macro, I try to generate a URL using URL::route().
If that fails, I catch any exception and resolve the URL manually.

try {
    return URL::route($this->route->getName(), $parameters, $absolute, $locale);
} catch (InvalidArgumentException $e) {
    return '';
}

By catching the exception, the locale that was temporarily changed in the underlying UrlGenerator code, never gets restored! So I need to update the code in the UrlGenerator:

if ($locale !== null && $locale !== $currentLocale) {
    App::setLocale($locale);
}

try {
    $url = parent::route($resolvedName, $parameters, $absolute);
} finally {
    if ($locale !== null && $locale !== $currentLocale) {
        App::setLocale($currentLocale);
    }
}

I'll fix his first and then figure out how to handle the Request issues.

from laravel-localized-routes.

gwleuverink avatar gwleuverink commented on June 9, 2024

Not sure if this helps, but you might need to add a persistent middleware to capture the locale url param

https://laravel-livewire.com/docs/2.x/security#persistent-middleware

Though it's been a while since first encountering this. If you need an extra set of eyes I'm happy to pair on it

from laravel-localized-routes.

ivanvermeyen avatar ivanvermeyen commented on June 9, 2024

@gwleuverink Thanks! I also came across the persistent middleware.
Although I think the web middleware group is automatically applied (locale is consistent now), people could potentially apply the middleware a different way for this package. So it's probably a good idea to use that.

from laravel-localized-routes.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.