ARCANEDEV / Localization

:globe_with_meridians: Localization package for Laravel
MIT License
185 stars 37 forks source link

Problem with language selector with parameters #144

Closed perffy closed 5 years ago

perffy commented 5 years ago

Description:

The language selector on each page is not working with getLocalizedURL(), when it have more arguments and i pass them through $_SERVER['QUERY_STRING']. In my Sitemap Controller when i pass the locale, route and the parameters to getLocalizedURL() it is working fine.

Steps To Reproduce:

de/routes.php:

<?php

    return [
        'standings' => [
            'country'   => 'tabellen/{country}.html',
            'show'      => 'tabellen/{country}/{type}/{name}-{id}.html',
            'overall'   => 'tabellen/{country}/{name}-{id}.html',
        ],
        'predictions' => [
            'index'     => 'prognosen/{country?}/{date?}',
            'show'      => 'prognose/{id}/{name}/{date}/{livestream?}',
        ],
    ];

?>

en/routes.php:

<?php

    return [

        'standings' => [
            'country'   => 'standings/{country}.html',
            'show'      => 'standings/{country}/{type}/{name}-{id}.html',
            'overall'   => 'standings/{country}/{name}-{id}.html',
        ],
        'predictions' => [
            'index'     => 'predictions/{country?}/{date?}',
            'show'      => 'prediction/{id}/{name}/{date}/{livestream?}',
        ],
    ];

?>

routes/frontend/home.php

Route::group([
    'prefix'     => Localization::setLocale(),
    'middleware' => [
        'localization-session-redirect',
        'localization-redirect',
    ],
], function() {

    Route::transGet('routes.predictions.index', 'HomeController@index')->name('index');
    Route::transGet('routes.predictions.show', 'HomeController@show')->name('show');

    Route::transGet('routes.standings.country', 'StandingController@country')->name('standings.country');
    Route::transGet('routes.standings.show', 'StandingController@show')->name('standings.show');
    Route::transGet('routes.standings.overall', 'StandingController@overall')->name('standings.overall');

});

Language selector:

@foreach(Localization::getSupportedLocales() as $localeCode => $locale)
    <li>
        <a rel="alternate" hreflang="{{ $localeCode }}" href="{{ Localization::getLocalizedURL($localeCode, url()->current()) }}{{ $_SERVER['QUERY_STRING'] ? '?' . $_SERVER['QUERY_STRING'] : '' }}">
            <span class="flag-icon flag-icon-{{ $localeCode  }}"></span>
        </a>
    </li>
@endforeach

When i call: http://soccerbets:7070/prediction/371915/montenegro-vs-hungary/2019-09-05/0

The german link looks like this: http://soccerbets:7070/de/prediction/371915/montenegro-vs-hungary/2019-09-05/0

Instead of: http://soccerbets:7070/de/prognose/371915/montenegro-vs-hungary/2019-09-05/0

BUT

When i call: http://soccerbets:7070/Predictions/2019-09-05

The german link looks like this: http://soccerbets:7070/de/Prognosen/2019-09-05

Which is fine, but i don't understand, why with this URL is working, but with other not.

Thanks in advance !

arcanedev-maroc commented 5 years ago

Check this issue: #139

perffy commented 5 years ago

I saw all similar issues, but didn't find any solution. How i need to implement the language selector, so it works on every page, without explicit to pass the route parameters ? I have tried with this, but doesn't work:

<a rel="alternate" hreflang="{{ $localeCode }}" href="{{ Localization::getLocalizedURL($localeCode, url()->current()) }}{{ $_SERVER['QUERY_STRING'] ? '?' . $_SERVER['QUERY_STRING'] : '' }}">

arcanedev-maroc commented 5 years ago

What i've mentioned in the previous issue is the use the of method localization()->getUrlFromRouteName() to solve your issue.

It's little bit tricky but you need to specify your routes and translations with a specific name convention.

Try this:

Config

<?php

/* -----------------------------------------------------------------
 |  Settings
 | -----------------------------------------------------------------
 */

'supported-locales'      => ['en', 'de'],

'accept-language-header' => true,

'hide-default-in-url'    => false,

'redirection-code'       => 302,

'facade'                 => 'Localization',

'utf-8-suffix'           => '.UTF-8',

/* -----------------------------------------------------------------
 |  Route
 | -----------------------------------------------------------------
 */

'route'                  => [
    'middleware' => [
        'localization-session-redirect' => true,
        'localization-cookie-redirect'  => false,
        'localization-redirect'         => true,
        'localized-routes'              => true,
        'translation-redirect'          => true,
    ],
],

//....

Routes

<?php

use Illuminate\Support\Facades\Route;

Route::localizedGroup(function () {
    Route::get('/', function () {
        return view('welcome');
    });

    // Predictions
    Route::transGet('routes.predictions.index', 'HomeController@index')
         ->name('predictions.index');
    Route::transGet('routes.predictions.show', 'HomeController@show')
         ->name('predictions.show');

    // Standings
    Route::transGet('routes.standings.country', 'StandingController@country')
         ->name('standings.country');
    Route::transGet('routes.standings.show', 'StandingController@show')
         ->name('standings.show');
    Route::transGet('routes.standings.overall', 'StandingController@overall')
         ->name('standings.overall');
});

Translations

EN

<?php

return [

    'standings' => [
        'country'   => 'standings/{country}.html',
        'show'      => 'standings/{country}/{type}/{name}-{id}.html',
        'overall'   => 'standings/{country}/{name}-{id}.html',
    ],

    'predictions' => [
        'index'     => 'predictions/{country?}/{date?}',
        'show'      => 'prediction/{id}/{name}/{date}/{livestream?}',
    ],

];

DE

<?php

return [

    'standings' => [
        'country'   => 'tabellen/{country}.html',
        'show'      => 'tabellen/{country}/{type}/{name}-{id}.html',
        'overall'   => 'tabellen/{country}/{name}-{id}.html',
    ],

    'predictions' => [
        'index'     => 'prognosen/{country?}/{date?}',
        'show'      => 'prognose/{id}/{name}/{date}/{livestream?}',
    ],

];

View - Nav language selector

@foreach(localization()->getSupportedLocales() as $key => $locale)
    <li>
        <?php
            $route = request()->route();
            $url = localization()->getUrlFromRouteName(
                $key, 'routes.'.$route->getName(), $route->parameters()
            );
        ?>
        <a rel="alternate" hreflang="{{ $key }}" href="{{ $url }}">
            <span class="flag-icon flag-icon-{{ $key }}"></span>
        </a>
    </li>
@endforeach

As you can see the route names is a little bit similar as the translation names, you need just to add the prefix routes. to access the translation value.

So the trick is this:

$route = request()->route(); // Get the current route

$url = localization()->getUrlFromRouteName(
    $key, // Locale key (en, de ...)
    "routes.{$route->getName()}", // Add the translation prefix 'routes.' to the route's name
    $route->parameters() // Get the current route's attributes
);
perffy commented 5 years ago

Unfortunately your code doesn't solve my case.

It produces: http://soccerbets:7070/prediction/371828/lommel-sk-vs-royale-union-saint-gilloise/2019-09-06/0 http://soccerbets:7070/de/

But i have found the solution for me:

@foreach(localization()->getSupportedLocales() as $localeCode => $locale)
    <li>
        <?php
            $route = request()->route();
            $url_route = Localization::getLocalizedURL($localeCode, route($route->getName(), $route->parameters()), $route->parameters(), false)
        ?>
        <a rel="alternate" hreflang="{{ $localeCode }}" href="{{ $url_route }}">
            <span class="flag-icon flag-icon-{{ $localeCode  }}"></span>
        </a>
    </li>
@endforeach

with that code it is working, but not fully :(

I have also another translation: bg

now if I am on page with locale = en and there are some parameters in the URL, it is translating the URL correct with bg and de locales, BUT if i am on a page where the locale = bg and the translated routes have Cyrillic letters it doesn't work, if i switch back to Latin letters it is working :(

The problem with the Cyrillic routes can be observed only on pages with some parameters in the URL and when the selected language is the Cyrillic language, otherwise it is working correct.

Chris-FXW commented 1 year ago

I have exactly same problem as @perffy. At the moment I use english words for Cyrillic pages unfortunately.