Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translatable route parameters isn't work when wich language ? #885

Open
ducvu91 opened this issue Nov 20, 2023 · 8 comments
Open

Translatable route parameters isn't work when wich language ? #885

ducvu91 opened this issue Nov 20, 2023 · 8 comments

Comments

@ducvu91
Copy link

ducvu91 commented Nov 20, 2023

Describe the bug
Translatable route parameters
http://url/en/article/important-change
http://url/es/articulo/cambio-importante
I setup like example, when access directly from url it ok. But when use button change language (also like example Creating a language selector). it show url 404. if not have parameters, it ok.

To Reproduce
Steps to reproduce the behavior:

  1. Go to http://url/en/article/important-change
  2. Click on change language es button.
  3. auto redirect to http://url/es/article/important-change
  4. 404 & See error

Expected behavior
when change language ES, it redirect to http://url/es/articulo/cambio-importante

More info:

  • Version of Laravel : 10
  • Version of the Laravel-localization package : 1.8
  • Which middleware is used in Route::groups : 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath'
  • Copy of the config file ( or at least setting of supportedLocales : all, useAcceptLanguageHeader : false and hideDefaultLocaleInURL:true).

it seems code in button change language have issue, it not generate to url belong to this language

@ducvu91 ducvu91 changed the title Translatable route parameters is work when wich language ? Translatable route parameters isn't work when wich language ? Nov 20, 2023
@mlayah
Copy link

mlayah commented Dec 1, 2023

Did you get a fix for this, i am currently experiencing the same issue.

@StefanoTesla
Copy link

I had the same problem in the past, you didn't paste your controller middlware setting to go deeper in this problem

@kichetof
Copy link

kichetof commented Dec 8, 2023

Hi!

Same issue here, only the locale change in the url, nothing else.
Language selector couldn't redirect to the translated route, only on index or without non dynamic text.

Example code:

Route::group([
    'prefix' => LaravelLocalization::setLocale(),
    'middleware' => ['localize', 'localizationRedirect', 'localeSessionRedirect'],
], function () {
    Route::get(LaravelLocalization::transRoute(__('/{user}/wish/{wish}')), WishIndexController::class);
});

fr.json

{
"/{user}/wish/{wish}": "/{user}/souhait/{wish}",
}

Selector EN: en/username/wish/my-x-mas-idea
Selector FR: fr/username/wish/my-x-mas-idea ❌
‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎^

Should be: Selector FR: fr/username/souhait/my-x-mas-idea ✅
‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ^

Hopefully a fix or a workaround? 🤞🏻

@StefanoTesla
Copy link

I found the way to make it work finally!

I will write how on monday

@StefanoTesla
Copy link

StefanoTesla commented Dec 9, 2023

So here I am.

Routes EN:

<?php

return [
    "prodotti_singoli"    =>  "products/{slug}",
];

Routes IT:

<?php

return [
    "prodotti_singoli"    =>  "prodotti/{slug}",
];

Web.php:

Route::get(LaravelLocalization::transRoute('routes.prodotti_singoli'),[ProductsController::class, 'show']);

Model Products:

<?php

namespace App\Models\Products;

class Product extends Model implements \Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable
{

 /* some methods */


    public function getLocalizedRouteKey($locale)
    {
        return $this->getTranslation('slug',$locale); <-methods to get other languages slug
    }

    public function resolveRouteBinding($value,  $field = null) <-methods to get the model by slug! (in the doc $filed is missing)
    {

        $field = $field ?? 'slug';
        $currentLocale = App()->getLocale();
        return $this->where("slug->{$currentLocale}", $value)->first() ?? abort(404);

    }

ProductController:


    public function show(Product $slug)
    {
        return view('product', compact('slug'));

    }

view:

<x-layouts.baselayout>
    <a rel="alternate" href="{{ LaravelLocalization::getLocalizedURL('en') }}">ENG</a>
    <a rel="alternate" href="{{ LaravelLocalization::getLocalizedURL('it') }}">ITA</a>
    <p>Nome: {{ $slug->name }}</p>
</x-layouts.baselayout>

Advisor:
I'm using Mcamara to translate routes and spatie/laravle-translatable to get my site multilanguages.

My problem was find the way to overwrite the way as Laravel resolve the model url, and get the right "alternate" link.

First thing we need to care is the model shoud implement \Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable

❌❌❌❌❌❌ Worng way ❌❌❌❌❌❌

use \Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable;

class MyModel extend Model
   use LocalizedUrlRoutable

❌❌❌❌❌❌ Worng way ❌❌❌❌❌❌
You will get a fatal error where LocalizedUrlRoutable is not a trait. @mcamara we can do something?

✅✅✅✅✅ Correct Way ✅✅✅✅✅✅✅

class MyModel extend Model implement \Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable;
{

In the model we need olso two more methods, one is getLocalizedRouteKey

    public function getLocalizedRouteKey($locale)
    {
        return $this->getTranslation('slug',$locale);
    }

This metods is called when we call LaravelLocalization::getLocalizedURL('en') or any others locale, in my example is the way how I can get the translated version of the slug using spatie/laravel-translatable feel free to write your correct way.

And the laravel provided method resolveRouteBinding()

Always in the method we need to add this:

    public function resolveRouteBinding($value,  $field = null)
    {
        $field = $field ?? 'slug';
        $currentLocale = App()->getLocale();
        return $this->where("slug->{$currentLocale}", $value)->first() ?? abort(404);

    }

This method will be called from the controller to get the right model,

<?php

namespace App\Http\Controllers;

use App\Models\Products\Product;

class ProductsController extends Controller
{
    public function show(Product $slug)
    {
        return view('product', compact('slug'));
    }

But we need to do some consideration before, The controller method should have the the Model as input parameter, the variable should be named as the model column we want to find.

You can put a dd() inside the resolveRouteBinding to ensure that is fired.

@StefanoTesla
Copy link

The problem noy is how to get two nested dynamics url :(

@fxcjahid
Copy link

I see

class ProductsController extends Controller {

        public function show(Product $slug)
        {
            return view('product', compact('slug'));
        }
        
 }

if we can't use it like this then the transable file is not translated

well, In case it is resolved. But, I am looking for like this :

        public function show($slug)
        {
            return Product::findBySlug($slug);
        }

Anyone can give me a solution how can I solve this?

@fxcjahid
Copy link

@mcamara Pls feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants