codezero-be / laravel-localized-routes

⭐️ A convenient way to set up and use localized routes in a Laravel app.
MIT License
491 stars 45 forks source link

Switcher if route is missing translation #111

Open martin-ro opened 3 months ago

martin-ro commented 3 months ago

Assume we have a page that has only one or two translations out of 3 available locales the switcher would with break with.

Missing required parameter for [Route: en.page.show] [URI: {page}] [Missing parameter: page].

I see there was a discussion to implement some checks but was last active 2021.

Am I missing something here or?

Thanks

ivanvermeyen commented 3 months ago

Hi,

Thanks for reporting this. At first glance, I think there should be an additional condiition in the swtcher to check if the current route exists in a given locale. There is a Route::hasLocalized('name', 'locale') but it needs the "base" route name. without the locale prefix.

I will try and rework the helper method to accept the current route name with or without the locale prefix. Then you could do something like this:

@if (Route::isLocalized() || Route::isFallback())
    <ul>
        @foreach(LocaleConfig::getLocales() as $locale)
            @if ( ! App::isLocale($locale) && Route::hasLocalized(Route::currentRouteName(), $locale))
                <li>
                    <a href="{{ Route::localizedUrl($locale) }}">
                        {{ strtoupper($locale) }}
                    </a>
                </li>
            @endif
        @endforeach
    </ul>
@endif
martin-ro commented 3 months ago

Just started using this package today. I assume page.show is the "base" name? Not en.page.show for example?

Tried a little hack to test that

@if (Route::isLocalized() || Route::isFallback())
    <ul>
        @foreach(LocaleConfig::getLocales() as $locale)
            @if ( ! App::isLocale($locale) && Route::hasLocalized(Str::after(Route::currentRouteName(), '.'), $locale))
                <li>
                    <a href="{{ Route::localizedUrl($locale) }}">
                        {{ strtoupper($locale) }}
                    </a>
                </li>
            @endif
        @endforeach
    </ul>
@endif

Same result.

ivanvermeyen commented 3 months ago

Your solutions looks like it should be working... I'm trying to write some tests for the macro, but for some reason the Route::has() macro can't be tested easily...

This basic test fails while it should 100% work. If I run the macro inside the route closure then it works, but it harder to run a bunch of assertions...

namespace CodeZero\LocalizedRoutes\Tests\Feature\Macros\Route;

use PHPUnit\Framework\Attributes\Test;
use CodeZero\LocalizedRoutes\Tests\TestCase;
use Illuminate\Support\Facades\Route;

final class HasLocalizedMacroTest extends TestCase
{
    #[Test]
    public function it_checks_if_the_given_route_exists_in_the_given_locale(): void
    {
        $this->withoutExceptionHandling();
        $this->setSupportedLocales(['en', 'nl']);

        Route::localized(function () {
            Route::get('localized-route', function () {})
                ->name('localized-route')
                ->middleware(['web']);
        });

        Route::get('non-localized-route', function () {})
            ->name('non-localized-route')
            ->middleware(['web']);

        $this->assertTrue(Route::hasLocalized('localized-route', 'nl'));
        $this->assertFalse(Route::hasLocalized('non-localized-route', 'nl'));
    }
}

I'll look for a decent way to test this so I can assure its working properly.

ivanvermeyen commented 3 months ago

Reading your original post again: you're missing a parameter value for {page}. I don't know how I missed that.

Missing required parameter for [Route: en.page.show] [URI: {page}] [Missing parameter: page].

Can you show me what the route looks like and how it is translated (there are a few strategies for parameters).