dimsav / laravel-translatable

[Deprecated] A Laravel package for multilingual models
MIT License
1.95k stars 320 forks source link

Prefix for default language #581

Closed emco83 closed 5 years ago

emco83 commented 5 years ago

I'm using this plugin for a long time using this tutorial: https://mydnic.be/post/how-to-build-an-efficient-and-seo-friendly-multilingual-architecture-for-your-laravel-application It's working fine, but I still haven't found a solution for removing the default language prefix.

Let's say I have two languages. German and English.

When the website has default set as German language , I got this URL: www.mywebsite.de/de

Please anybody help to remove the prefix /de for the default language. I've already checked the comments for this issue on the tutorial website, but still no solution for that.

Gummibeer commented 5 years ago

The routing part is pretty bad. 🤔 Using segments and a hard route prefix ties you so hard to a given structure. So you can't do admin/de and app/de for example.

It's better to use a route group with a named variable as prefix. I haven't tried but it should be possible to flag it as optional. In your middleware you only change the app local if it's present and matches a given one.

But this issue also doesn't belong to this package.

Gummibeer commented 5 years ago

This is my setup.

router:

Route::group([
    'middleware' => ['localized'],
    'prefix' => '{language}',
], function () {
    // all localized routes
});

middleware:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class Localized
{
    public function handle(Request $request, Closure $next)
    {
        $locale = $request->route('language');

        if (!in_array($locale, config('app.locales'))) {
            return redirect()->to(localized_route($request->route(), default_locale()));
        }

        app()->setLocale($locale);

        return $next($request);
    }
}
emco83 commented 5 years ago

Hi, Gummibeer.

Yes, I know this issue is not directly related with your plugin, but any help is useful.

So, your approach is to setup the Route group into routes/web.php and setup a new Localized middleware, right?

I've tried now by adding this route group into web.php.

Route::group([
    'middleware' => ['localized'],
    'prefix' => '{language}',
], function () {
    // all localized routes
});

I've created also your Localized middleware and setup in the Kernel.

I don't understand which routes should I set into?

..
function () {
    // all localized routes
});
emco83 commented 5 years ago

By the way if I set any route inside, I'm getting this error:

in_array() expects parameter 2 to be array, null given

and it's related with this line from the Localized class:

if (!in_array($locale, config('app.locales'))) {

EDIT: The error makes sense, because 'app.locales' doesn't exist. it should be 'translatable.locales', but even though I'm getting different error like that.

OK, I guess I have to give up from this idea, 'cos in the tutorial article there are many comments with this issue and nobody has solved this problem.

@Gummibeer

Your setup is different, I'm sure because you're using app.locales with different details..so without more details, it's impossible for me to solve the issue.

Gummibeer commented 5 years ago

Sorry, forgot the custom config - it's just a simple list of locales:

'locales' => [
    'de_de',
    'en_us',
],

And yes, the route group belongs into the routes/web.php and inside of the group function you put all your routes which should be localized. These functions are also custom ones localized_route($request->route(), default_locale()) you can replace them.

I also have an event listener for \Illuminate\Foundation\Events\LocaleUpdated:

namespace App\Listeners;

use Carbon\Carbon;
use Illuminate\Foundation\Events\LocaleUpdated;

class SetAppLocale
{
    public function handle(LocaleUpdated $event)
    {
        setlocale(LC_ALL, $event->locale);

        \URL::defaults([
            'language' => $event->locale,
        ]);

        Carbon::setLocale($event->locale);
    }
}

This custom listener sets the locale for all locale aware services which aren't set by laravel. The URL::defaults() allows to call any route/url generator without providing the current locale but get a localized url with the current locale.

At all I recommend to ask your questions in https://larachat.co , https://laracasts.com/discuss or any other general laravel help area. Because some of these things are always app specific - The major thing you have to get done is flag the locale url variable as optional.

emco83 commented 5 years ago

Thank you for your explanation! I hope I'll achieve this. :)