codezero-be / laravel-localized-routes

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

Advanced Scoped Options - Multi-site (domain localization & slug localization) #105

Open cdo9 opened 8 months ago

cdo9 commented 8 months ago

I have a requirement for a website I am building. Like #21 but not exactly the same. I am building a "multi-site", some of the sites use domain localization, others use slugs).

I wanted to use Scoped Options to do something like this :

url locale
firstwebsite.test/en en
firstwebsite.test/fr fr
firstwebsite.test/pt pt
secondwebsite.test en
deuxiemesite.test fr
segundosite.test pt
Route::domain('firstwebsite.test')->group(function () {
        Route::localized(function () {
                Route::get('/', [\App\Http\Controllers\HomeController::class, 'index']);
        }, ['supported_locales' => ['en', 'fr', 'pt',]]);
});
Route::pattern('secondwebsite', 'secondwebsite.test|deuxiemesite.test|segundosite.test');
Route::domain('{secondwebsite}')->group(function () {
        Route::localized(function () {
            // Home
            Route::get('/', [\App\Http\Controllers\HomeController::class, 'index']);
        }, ['supported_locales' => [
                'en' => 'secondwebsite.test',
                'fr' => 'deuxiemesite.test',
                'pt' => 'segundosite.test',
           ]]);
});

Do you think it will be possible to update the Scoped Options to make it support the domains in "supported_locales" ? In my use case config will never be used, only Scoped Options.

I would love to build this for this package and make a PR. If you are ok with that I would love to have some hints/indications on the way you see this.

cdo9 commented 8 months ago

I added a $locales parameter to the LocaleConfig::hasCustomDomains() function and the LocaleConfig::getSupportedLocales().

Here are the updated functions :

    public function hasCustomDomains($locales = null): bool
    {
        $firstValue = array_values($this->getSupportedLocales($locales))[0] ?? '';
        $containsDot =  strpos($firstValue, '.') !== false;

        return $containsDot;
    }
    public function getSupportedLocales($locales = null): array
    {
        return $locales ?: $this->supportedLocales;
    }

Updated the register function line 28 : $usingDomains = LocaleConfig::hasCustomDomains($locales);

And for now, I can access all my urls from my table above. Do you think I might have broken something ? I will keep testing and give you updates accordingly.

ivanvermeyen commented 8 months ago

Hello,

A PR is always welcome.

When I was looking through my code for your question, I actually just discovered the bug with hasCustomDomains() that you fixed above. The same is true for hasCustomSlugs().

The whole scoped config feature needs more testing and probably needs to be tweaked here and there. It would be nice if it could work fluently with the main config. But that is more complex than it seams I think.

One problem you should double check is if your routes have duplicate names, because you use duplicate locales.

I can give this some deeper thought later today.

cdo9 commented 8 months ago

Thanks for your reply, I will continue working on this in the next days/weeks :)

I am now trying to have this urls working :

url locale
firstwebsite.test/en/category/{translatedSlug} en
firstwebsite.test/fr/categorie/{translatedSlug} fr
firstwebsite.test/pt/categoria/{translatedSlug} pt
secondwebsite.test/category/{translatedSlug} en
deuxiemesite.test/categorie/{translatedSlug} fr
segundosite.test/categoria/{translatedSlug} pt

I added this two routes to my web.php file :

Route::get(Lang::uri('firstwebsite/shop/category/{$productCategory}'),
[\App\Http\Controllers\Shop\CategoryController::class, 'show'])->name('firstwebsite.shop.category');
Route::get(Lang::uri('secondwebsite/shop/category/{$productCategory}'),
[\App\Http\Controllers\Shop\CategoryController::class, 'show'])->name('secondwebsite.shop.category');

Translation is working well, I have done a foreach of my categories and urls are ok but I have a 404 when accessing my URLs, I need to figure out why this is happening

EDIT 1 :

When I was looking through my code for your question, I actually just discovered the bug with hasCustomDomains() that you fixed above. The same is true for hasCustomSlugs().

Yes you are right for hasCustomSlugs. Will update this has well.

One problem you should double check is if your routes have duplicate names, because you use duplicate locales.

I think with my route naming i am ok ? firstwebsite.shop.category & secondwebsite.shop.category

ivanvermeyen commented 8 months ago

Could you show me a more complete example of your route registration? And perhaps a screenshot of the php artisan route:list command? Trying to understand the flow of your routes.

cdo9 commented 8 months ago

EDIT : my bad... i removed the $ sign and everything is working well!! Here are the example :

web.php

    Route::domain('firstwebsite.test')->group(function () {
        Route::localized(function () {
        // Home
        Route::get('/', [\App\Http\Controllers\HomeController::class, 'index'])->name('firstwebsite.home');
        // Shop
        Route::get(Lang::uri('firstwebsite/shop/category/{productCategory}'), [\App\Http\Controllers\Shop\CategoryController::class, 'show'])->name('firstwebsite.shop.category');
        }, ['supported_locales' => ['en', 'fr', 'pt']]
        );
    });

    Route::pattern('secondwebsite', 'secondwebsite.test|deuxiemesite.test|segundosite.test');
    Route::domain('{secondwebsite}')->group(function () {
        Route::localized(function () {
            // Home
            Route::get('/', [\App\Http\Controllers\HomeController::class, 'index'])->name('secondwebsite.home');
            // Shop
            Route::get(Lang::uri('secondwebsite/shop/category/{productCategory}'), [\App\Http\Controllers\Shop\CategoryController::class, 'show'])->name('secondwebsite.shop.category');
        }, ['supported_locales' => ['en' => 'secondwebsite.test', 'fr' => 'deuxiemesite.test', 'pt' => 'segundosite.test']]
        );
    });

php artisan route:list

GET|HEAD   secondwebsite.test/ en.secondwebsite.home › HomeController@index
GET|HEAD   deuxiemesite.test/ fr.secondwebsite.home › HomeController@index
GET|HEAD   segundosite.test/ pt.secondwebsite.home › HomeController@index
GET|HEAD   segundosite.test/categoria/{productCategory} pt.secondwebsite.shop.category › Shop\CategoryController@show
GET|HEAD   deuxiemesite.test/categorie/{productCategory} fr.secondwebsite.shop.category › Shop\CategoryController@show
GET|HEAD   secondwebsite.test/category/{productCategory} en.secondwebsite.shop.category › Shop\CategoryController@show
GET|HEAD   firstwebsite.test/en en.firstwebsite.home › HomeController@index
GET|HEAD   firstwebsite.test/en/category/{productCategory} en.firstwebsite.shop.category › Shop\CategoryController@show
GET|HEAD   firstwebsite.test/fr fr.firstwebsite.home › HomeController@index
GET|HEAD   firstwebsite.test/fr/categorie/{productCategory} fr.firstwebsite.shop.category › Shop\CategoryController@show
GET|HEAD   firstwebsite.test/pt pt.firstwebsite.home › HomeController@index
GET|HEAD   firstwebsite.test/pt/categoria/{productCategory} pt.firstwebsite.shop.category › Shop\CategoryController@show
cdo9 commented 7 months ago

Hello @ivanvermeyen

I was waiting Laravel 11 to start this new website, so I will update this issue according to my finds.

There is an error on the README for Laravel 11 configuration : Target class [CodeZero\Localizer\Middleware\SetLocale] does not exist. The class is : \CodeZero\LocalizedRoutes\Middleware\SetLocale::class,

ivanvermeyen commented 7 months ago

Woops, that's what I get for copy-pasting :) Fixed it now. Thanks for catching that!