2016-12-21 74 views
7

Używam list rozwijanych dla języków, składających się z angielskiego i holenderskiego.Zmiana ustawień regionalnych Laravel

<form class="" action="{{url('/locale')}}" method="post"> 
      Locale: 
       <select class="" name="locale" onchange="this.form.submit()"> 

       <option value="en" >English</option> 
       <option value="du" >Dutch</option> 
       </select> 
      </form> 

Wtedy to mój routes.php,

Route::post('/locale', function(){ 

    \App::setLocale(Request::Input('locale')); 

    return redirect()->back(); 
}); 

I to nie działa.

W moim projekcie, ścieżka jest jak ten

resources/ 
/du 
    navigation.php 
/en 
    /navigation.php 

z holenderskiej (du) 'navigation.php'

<?php 
return [ 
    "home" => 'Home-test-dutch', 
]; 

i na English (en) '' navigation.php

<?php 
return [ 
    "home" => 'Home', 
]; 
+0

setLocale nie jest trwały, więc zmiana go, a następnie przekierowanie pozostawi domyślną. Skorzystaj z sesji (lub bazy danych) i oprogramowania pośredniego, aby ta zmiana stała się stała dla użytkownika. Powinienem zauważyć, że jeśli jest to strona internetowa z widokiem publicznym, powinieneś używać różnych adresów URL dla różnych języków. – Devon

Odpowiedz

1

App::setLocale() nie jest trwałe. miałem podobny problem przed więc stworzyłem middleware:

<?php 

namespace App\Http\Middleware; 

use Closure; 

class SetLocale 
{ 
    /** 
     * Handle an incoming request. 
     * 
     * @param \Illuminate\Http\Request $request 
     * @param \Closure $next 
     * @return mixed 
     */ 
    public function handle($request, Closure $next) 
    { 
     if (strpos($request->getHttpHost(), 'fr.') === 0) { 
      \App::setLocale('fr'); 
     } else { 
      \App::setLocale('en'); 
     } 
     return $next($request); 
    } 
} 

I zarejestrował middleware w app\Http\Kernel:

protected $middlewareGroups = [ 
    'web' => [ 
     // ... 
     \App\Http\Middleware\SetLocale::class, 
     // ... 
    ] 
]; 

Skrypt ten działa dla dwóch domen: http://example.org (PL) i http://fr.example.org (fr). Jako oprogramowanie pośrednie jest wywoływane przy każdym żądaniu, więc ustawienia narodowe są zawsze ustawiane jako właściwe ustawienia narodowe zgodnie z adresem URL.

Moje trasy wyglądało:

Route::group(['domain' => 'fr.' . config('app.root-domain')], function() { 
    Route::get('a-propos', '[email protected]'); 
    // ... 
} 
Route::group(['domain' => config('app.root-domain')], function() { 
    Route::get('about', '[email protected]'); 
    // ... 
} 

Więc to odpowiada właściwej lokalizacji do:

I korzystają z tego samego kontrolera i same widok, tylko 2 różne trasy + globalne oprogramowanie pośrednie.

Mam nadzieję, że pomoże, nie wiem, czy to najlepsze rozwiązanie. To rozwiązanie działa bezsesyjnie, pasuje do domeny i/lub tras. To ma pewne zalety w stosunku do rozwiązań opartych na sesji:

  • żadne ewentualne błędy wynikające z użycia sesji („magia” zmienić język)
  • Można przepisać swoje trasy. Francuski użytkownik może chcieć zobaczyć "/ mon-panier" i angielskiego użytkownika "/ my-cart" w swoim adresie URL.
  • Lepsze indeksowanie w google (SEO), ponieważ możesz mieć prawdziwy indeks według kraju z odpowiednią treścią.
  • Używam go w produkcji!

To może mieć również swoje wady.

+0

To rozwiązanie działa tylko w wielu domenach. – Froxz

+1

@Froxz, tak, ale dla celów SEO, nie chcesz wyświetlać różnych języków z tego samego adresu URL dla witryn publicznych. Niekoniecznie potrzebujesz różnych subdomen, innego prefiksu lub czegoś, co może również zadziałać. – Devon

+0

@Froxz Można go łatwo dostosować do prostych tras bez subdomeny, wystarczy zmienić logikę oprogramowania pośredniego. –

8

App::setLocale() nie jest trwały, ustawia ustawienia regionalne tylko dla bieżącego żądania. Co można zrobić, to:

Route::post('/locale', function(){ 

    session(['my_locale' => Request::Input('locale')]); 

    return redirect()->back(); 
}); 

Spowoduje to ustawienie session key dla bieżącego użytkownika Po będziemy potrzebować Middleware wykryć locale

<?php namespace App\Http\Middleware; 

use Closure; 
use Illuminate\Http\Request; 
use Illuminate\Foundation\Application; 

class Language { 

    public function __construct(Application $app, Request $request) { 
     $this->app = $app; 
     $this->request = $request; 
    } 

    /** 
    * Handle an incoming request. 
    * 
    * @param \Illuminate\Http\Request $request 
    * @param \Closure $next 
    * @return mixed 
    */ 
    public function handle($request, Closure $next) 
    { 
     $this->app->setLocale(session('my_locale', config('app.locale'))); 

     return $next($request); 
    } 

} 

To będzie sesję, a jeśli jest pusty to przywróci domyślne ustawienia regionalne ustawione w konfiguracji aplikacji.

Otwarte app\Http\Kernel.php i dodać tę linię:

protected $middleware = [ 
    \App\Http\Middleware\Language::class, 
]; 

jak globalne middlware lub po prostu dla sieci web. nadzieję, że to pomogło i masz pomysł jak to działa

Scenariusz №2 Załóż array ze wszystkich dostępnych lokalizacjach na swojej stronie wewnątrz app config

'available_locale' => ['fr', 'gr', 'ja'], 

Wewnątrz Middleware będziemy sprawdzać URL pierwszy segment en fr gr cy jeżeli ten segment jest w available_locales_array możemy ustawić locale

public function handle($request, Closure $next) 
{ 
     if(in_array($request->segment(1), config('app.available_locales_array'))){ 
      $this->app->setLocale($request->segment(1)); 
     }else{ 
      $this->app->setLocale(config('app.locale')); 
     } 

     return $next($request); 
} 

będziesz nee d zmodyfikuj app\Providers\RouteServiceProvider, aby ustawić prefiks dla wszystkich twoich tras. dzięki czemu można uzyskać do nich dostęp domain.com lub domain.com/fr/ z French language znajdują się: mapWebRoutes i dodać do niego:

if(in_array($request->segment(1), config('app.available_locales_array'))){ 
    $locale = $request->segment(1); 
}else{ 
    $locale = null; 
} 
Route::group([ 
    'middleware' => 'web', 
    'namespace' => $this->namespace, 
    'prefix' => $locale 
], function ($router) { 
    require base_path('routes/web.php'); 
}); 

To będzie poprzedzić wszystkie swoje trasy na literę kraj jak „fr gr cy” z wyjątkiem pl dla non-duplikaty , więc lepiej nie dodawać do available_locales_array