Astrotomic / laravel-translatable

A Laravel package for multilingual models
https://docs.astrotomic.info/laravel-translatable/
MIT License
1.23k stars 156 forks source link

Integration with codezero-be/laravel-localized-routes #233

Closed sheinfeld closed 3 years ago

sheinfeld commented 3 years ago

Hey guys,

I've been trying to integrate this package with https://github.com/codezero-be/laravel-localized-routes.

I'm having troubles routeBinding translated slugs.

Anyone managed to do this?

rucky96 commented 3 years ago

I have the same issue!

The route parameter is 'product:slug'. I have tried to include public function resolveRouteBinding($value, $field = null) { // Perform the logic to find the given slug in the database... return self::whereTranslation($field, $value) ->firstOrFail(); } But it returns 404 every time. All this despite the fact that it goes into function resolveRouteBinding($value, $field = null) and returns the item from the DB correctly (¿?). I don't understand where the mistake is, it's puzzling. But the 404 must come from before the call to the resolveRouteBinding function.

sheinfeld commented 3 years ago

Good News @rucky96!

I managed to do it like this in a Model:

...Model.... {
    public function getRouteKeyName(): string
    {
        return 'slug';
    }

    public function getRouteKey()
    {
        return $this->{'slug:' . app()->getLocale()};
    }

    public function resolveRouteBinding($value, $field = null)
    {
        return $this->whereTranslation($field ?? $this->getRouteKeyName() . '->' . app()->getLocale(), $value)
                 ->firstOrFail() ?? abort(404);
    }
}

And I've added a custom method to the RouteServiceProvider:

    public function boot()
    {
        Route::macro('currentLocalizedUrl', function ($locale = null, $parameters = null, $absolute = true) {
            $locale = $locale ?? app()->getLocale();
            $parameters = $parameters ?: Route::current()->parameters();
            $currentLocale = app()->getLocale();
            app()->setLocale($locale);
            foreach ($parameters as $attribute => $value) {
                if ($value instanceof Model) {
                    $parameters[$attribute] = $value->getRouteKey();
                }
            }
            app()->setLocale($currentLocale);

            return route(Route::current()->getName(), $parameters, $absolute, $locale);
        });

        parent::boot();
    }

routes/web.php:

Route::get(Lang::uri('article/{article:slug}'), 'ArticleController@show')->name('article.show');

resources/lang/en/routes.php:

return [
    'article' => 'article',
    'category' => 'category',
    'tag' => 'tag',

    'about-us' => 'about-us',
    'editorial-status' => 'editorial-status',
    'terms' => 'terms',
    'privacy' => 'privacy',
];

Working example:

<div class="dropdown-menu dropdown-menu-right" aria-labelledby="languageButton">
      @foreach (config('constants.locales') as $lang => $language)
          @if ($lang != app()->getLocale())
              <a class="dropdown-item" href="{{ Route::currentLocalizedUrl($lang) }}" hreflang="{{ $lang }}">
                  <span
                      class="flag-icon flag-icon-{{ $lang == "en" ? 'gb' : $lang }} mr-1"></span>{{$language}}
              </a>
          @endif
      @endforeach
  </div>

image

I hope it helps :)

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 21 days with no activity. Remove stale label or comment or this will be closed in 7 days