選択した言語に応じて多くの翻訳されたルートを持つアプリケーションを作成したいと思います。 多言語WebサイトでURLを作成する3つの方法 で説明しました。
この場合、前述のトピックの最初のメソッドでなければなりません。
デフォルトの言語pl
と2つの他の言語en
とfr
を設定したと仮定しましょう。メインページ、連絡先ページ、アバウトページの3ページしかありません。
サイトのURLは次のようになります。
/
/[about]
/[contact]
/en
/en/[about]
/en/[contact]
/fr
/fr/[about]
/fr/[contact]
一方、[about]
および[contact]
は、選択した言語に従って翻訳する必要があります。たとえば、英語ではcontact
のままにしますが、ポーランド語ではkontakt
などにします。
どうすればできるだけ簡単にできますか?
最初のステップ:
app/lang
ディレクトリに移動し、ここで各言語のルートの翻訳を作成します。 3つのroutes.php
ファイルを作成する必要があります-それぞれ3つの言語を使用するため、それぞれ別個の言語ディレクトリ(pl/en/fr)にあります
ポーランド語の場合:
<?php
// app/lang/pl/routes.php
return array(
'contact' => 'kontakt',
'about' => 'o-nas'
);
英語の場合:
<?php
// app/lang/en/routes.php
return array(
'contact' => 'contact',
'about' => 'about-us'
);
フランス語の場合:
<?php
// app/lang/fr/routes.php
return array(
'contact' => 'contact-fr',
'about' => 'about-fr'
);
2番目のステップ:
app/config/app.php
ファイルに移動します。
行を見つける必要があります。
'locale' => 'en',
それをあなたの主要なサイト言語(あなたの場合はポーランド語)にすべき言語に変更します:
'locale' => 'pl',
また、このファイルに次の行を追加する必要があります。
/**
* List of alternative languages (not including the one specified as 'locale')
*/
'alt_langs' => array ('en', 'fr'),
/**
* Prefix of selected locale - leave empty (set in runtime)
*/
'locale_prefix' => '',
alt_langs
configでは、代替言語(あなたの場合はen
およびfr
)を設定します-これらは、翻訳を含むファイルを作成した最初のステップのファイル名と同じである必要があります。
_locale_prefix
はロケールのプレフィックスです。デフォルトのロケールにはプレフィックスが必要ないため、空の文字列に設定されます。デフォルト以外の言語が選択される場合、この設定は実行時に変更されます。
番目のステップ
app/routes.php
ファイルに移動して、そのコンテンツを配置します(これがapp/routes.php
ファイルのコンテンツ全体です)。
<?php
// app/routes.php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/
/*
* Set up locale and locale_prefix if other language is selected
*/
if (in_array(Request::segment(1), Config::get('app.alt_langs'))) {
App::setLocale(Request::segment(1));
Config::set('app.locale_prefix', Request::segment(1));
}
/*
* Set up route patterns - patterns will have to be the same as in translated route for current language
*/
foreach(Lang::get('routes') as $k => $v) {
Route::pattern($k, $v);
}
Route::group(array('prefix' => Config::get('app.locale_prefix')), function()
{
Route::get(
'/',
function () {
return "main page - ".App::getLocale();
}
);
Route::get(
'/{contact}/',
function () {
return "contact page ".App::getLocale();
}
);
Route::get(
'/{about}/',
function () {
return "about page ".App::getLocale();
}
);
});
最初に表示されるように、urlの最初のセグメントが言語の名前と一致するかどうかを確認します。一致する場合は、ロケールと現在の言語プレフィックスを変更します。
次に、小さなループで、すべてのルート名の要件を設定します(URLでabout
とcontact
を翻訳する必要があると述べました)。現在の言語用。
最後に、言語と同じプレフィックスを持つルートグループを作成し(既定の言語では空になります)、グループ内で単にパスを作成しますが、これらのパラメーターはabout
およびcontact
を扱いますvariables
として、routes.php
および{about}
構文を使用します。
その場合、現在の言語の最初のステップで定義したものと同じであれば、すべてのルートの{contact}
がチェックされることを覚えておく必要があります。この効果が望ましくなく、whereを使用して各ルートに手動でルートを設定する場合、ループごとにcontact
とabout
を個別に設定するループなしの代替{contact}
ファイルがあります。
app\routes.php
4番目のステップ:
あなたはそれについて言及していませんが、あなたが考慮することができる1つの余分なものがあります。誰かがsomething
が正しいルートでないURL <?php
// app/routes.php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/
/*
* Set up locale and locale_prefix if other language is selected
*/
if (in_array(Request::segment(1), Config::get('app.alt_langs'))) {
App::setLocale(Request::segment(1));
Config::set('app.locale_prefix', Request::segment(1));
}
Route::group(array('prefix' => Config::get('app.locale_prefix')), function()
{
Route::get(
'/',
function () {
return "main page - ".App::getLocale();
}
);
Route::get(
'/{contact}/',
function () {
return "contact page ".App::getLocale();
}
)->where('contact', Lang::get('routes.contact'));
Route::get(
'/{about}/',
function () {
return "about page ".App::getLocale();
}
)->where('about', Lang::get('routes.about'));
});
を使用する場合、リダイレクトを行うための最良の解決策だと思います。ただし、/en/something
はデフォルト言語であるため、/
ではなく、/en
にリダイレクトする必要があります。
したがって、app/start/global.php
ファイルを開いて、不明なURLの301リダイレクトをここで作成できます。
// app/start/global.php
App::missing(function()
{
return Redirect::to(Config::get('app.locale_prefix'),301);
});
MarcinNabiałek が最初の回答で提供してくれたのは、ルートのローカリゼーションの問題に対する確実な解決策です。
マイナーバグベア:
彼のソリューションの唯一の本当の欠点は、キャッシュされたルートを使用できないことです。これは、_Laravel's
_ docs :
アプリケーションがコントローラーベースのルートのみを使用している場合は、Laravelのルートキャッシュを利用する必要があります。ルートキャッシュを使用すると、アプリケーションのすべてのルートを登録するのにかかる時間が大幅に短縮されます。場合によっては、ルート登録の速度が最大100倍になることもあります。ルートキャッシュを生成するには、_
route:cache
_ Artisanコマンドを実行するだけです。
ルートをキャッシュできないのはなぜですか?
MarcinNabiałek's メソッドは_locale_prefix
_に基づいて新しいルートを動的に生成するため、それらをキャッシュすると_404
_変数に格納されていないプレフィックスにアクセスすると_locale_prefix
_エラーが発生しますキャッシング時。
何を保持しますか?
基盤は本当にしっかりしているようで、そのほとんどを維持できます!
さまざまなローカライズ固有のルートファイルを確実に保持できます。
_<?php
// app/lang/pl/routes.php
return array(
'contact' => 'kontakt',
'about' => 'o-nas'
);
_
すべての_app/config/app.php
_変数を保持することもできます。
_/**
* Default locale
*/
'locale' => 'pl'
/**
* List of alternative languages (not including the one specified as 'locale')
*/
'alt_langs' => array ('en', 'fr'),
/**
* Prefix of selected locale - leave empty (set in runtime)
*/
'locale_prefix' => '',
/**
* Let's also add a all_langs array
*/
'all_langs' => array ('en', 'fr', 'pl'),
_
また、ルートセグメントをチェックするコードも必要です。しかし、これのポイントはキャッシュを利用することなので、それを_routes.php
_ファイルの外に移動する必要があります。ルートをキャッシュすると、その1つは使用されなくなります。とりあえず、_app/Providers/AppServiceProver.php
_に移動します:
_public function boot(){
/*
* Set up locale and locale_prefix if other language is selected
*/
if (in_array(Request::segment(1), config('app.alt_langs'))) {
App::setLocale(Request::segment(1));
config([ 'app.locale_prefix' => Request::segment(1) ]);
}
}
_
忘れないでください:
_use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\App;
_
ルートのセットアップ:
_app/Http/routes.php
_ファイル内でいくつかの変更が発生します。
最初に、すべての_alt_langs
_およびデフォルトの_locale_prefix
_を含む新しい配列を作成する必要があります。デフォルトの_''
_は、ほとんどの場合_$all_langs = config('app.all_langs');
_です。
_*** Laravel aside 1: ***
_
変換されたルートパラメータでさまざまなlangプレフィックスをすべてキャッシュできるようにするには、それらをすべて登録する必要があります。どうすればそれができますか?
_public static function get($key, $replace = array(), $locale = null, $fallback = true){
return \Illuminate\Translation\Translator::get($key, $replace, $locale, $fallback);
}
_
Lang::get(..)
の定義を見てみましょう:
_$locale
_
その関数の3番目のパラメーターは_$all_langs
_変数です!素晴らしい-確かにそれを有利に使うことができます!この関数では、実際に翻訳を取得するロケールを選択できます!
次に行うことは、_404
_配列を反復処理し、各言語プレフィックスに対して新しいRoute
グループを作成することです。それだけでなく、以前必要だったwhere
チェーンとpatterns
も削除し、適切な翻訳でルートを登録するだけです(他の人は__(SOMECODE)をスローします) __もう確認する必要はありません):
_/**
* Iterate over each language prefix
*/
foreach( $all_langs as $prefix ){
if ($prefix == 'pl') $prefix = '';
/**
* Register new route group with current prefix
*/
Route::group(['prefix' => $prefix], function() use ($prefix) {
// Now we need to make sure the default prefix points to default lang folder.
if ($prefix == '') $prefix = 'pl';
/**
* The following line will register:
*
* example.com/
* example.com/en/
*/
Route::get('/', 'MainController@getHome')->name('home');
/**
* The following line will register:
*
* example.com/kontakt
* example.com/en/contact
*/
Route::get(Lang::get('routes.contact',[], $prefix) , 'MainController@getContact')->name('contact');
/**
* “In another moment down went Alice after it, never once
* considering how in the world she was to get out again.”
*/
Route::group(['prefix' => 'admin', 'middleware' => 'admin'], function () use ($prefix){
/**
* The following line will register:
*
* example.com/admin/uzivatelia
* example.com/en/admin/users
*/
Route::get(Lang::get('routes.admin.users',[], $prefix), 'AdminController@getUsers')
->name('admin-users');
});
});
}
/**
* There might be routes that we want to exclude from our language setup.
* For example these pesky ajax routes! Well let's just move them out of the `foreach` loop.
* I will get back to this later.
*/
Route::group(['middleware' => 'ajax', 'prefix' => 'api'], function () {
/**
* This will only register example.com/api/login
*/
Route::post('login', 'AjaxController@login')->name('ajax-login');
});
_
ヒューストン、問題があります!
あなたが見ることができるように、私は名前付きルートを使用することを好みます(ほとんどの人はおそらくそうします):
_Route::get('/', 'MainController@getHome')->name('home');
_
ブレードテンプレート内で非常に簡単に使用できます。
_{{route('home')}}
_
しかし、これまでの私のソリューションには問題があります。ルート名は互いにオーバーライドします。上記のforeach
ループは、最後にプレフィックスが付けられたルートのみを名前で登録します。
言い換えると、_example.com/
_が_locale_perfix
_配列の最後の項目であったため、_$all_langs
_のみがhome
ルートにバインドされます。
ルート名の前に言語_$prefix
_を付けることでこれを回避できます。例えば:
_Route::get('/', 'MainController@getHome')->name($prefix.'_home');
_
ループ内の各ルートに対してこれを行う必要があります。これは別の小さな障害を作成します。
しかし、私の大規模なプロジェクトはほぼ終了しました!
おそらくご想像のとおり、すべてのファイルに戻り、各route
ヘルパー関数呼び出しにapp
構成から読み込まれた現在の_locale_prefix
_をプレフィックスとして追加する必要があります。
あなたがそうしないことを除いて!
_*** Laravel aside 2: ***
_
Laravel=がroute
ヘルパーメソッドを実装する方法を見てみましょう。
_if (! function_exists('route')) {
/**
* Generate a URL to a named route.
*
* @param string $name
* @param array $parameters
* @param bool $absolute
* @return string
*/
function route($name, $parameters = [], $absolute = true)
{
return app('url')->route($name, $parameters, $absolute);
}
}
_
ご覧のとおり、Laravelは最初にroute
関数が存在するかどうかを確認します。別の関数がまだ存在しない場合にのみroute
関数を登録します!
つまり、route
テンプレートでこれまでに行われたBlade
呼び出しをすべて書き換える必要なく、問題を非常に簡単に回避できます。
_app/helpers.php
_ファイルを実際にすばやく作成しましょう。
_helpers.php
_に次の行を入力して、_bootstrap/autoload.php
_をロードする前にLaravelがファイルをロードすることを確認しましょう
_//Put this line here
require __DIR__ . '/../app/helpers.php';
//Right before this original line
require __DIR__.'/../vendor/autoload.php';
_
あとは、_app/helpers.php
_ファイル内に独自のroute
関数を作成するだけです。元の実装を基礎として使用します。
_<?php
//Same parameters and a new $lang parameter
use Illuminate\Support\Str;
function route($name, $parameters = [], $absolute = true, $lang = null)
{
/*
* Remember the ajax routes we wanted to exclude from our lang system?
* Check if the name provided to the function is the one you want to
* exclude. If it is we will just use the original implementation.
**/
if (Str::contains($name, ['ajax', 'autocomplete'])){
return app('url')->route($name, $parameters, $absolute);
}
//Check if $lang is valid and make a route to chosen lang
if ( $lang && in_array($lang, config('app.alt_langs')) ){
return app('url')->route($lang . '_' . $name, $parameters, $absolute);
}
/**
* For all other routes get the current locale_prefix and prefix the name.
*/
$locale_prefix = config('app.locale_prefix');
if ($locale_prefix == '') $locale_prefix = 'pl';
return app('url')->route($locale_prefix . '_' . $name, $parameters, $absolute);
}
_
それだけです!
したがって、基本的に行ったことは、使用可能なすべてのプレフィックスグループを登録することです。翻訳された各ルートを作成し、その名前にも接頭辞を付けました。そして、sort ofLaravel route
関数をオーバーライドして、すべてのルート名(一部を除く)に現在の_locale_prefix
_これにより、毎回config('app.locale_prefix')
と入力することなく、ブレードテンプレートに適切なURLが作成されます。
そうそう:
_php artisan route:cache
_
ルートをキャッシュするのは、開発中にプロジェクトを混乱させる可能性が高いため、プロジェクトを展開した後にのみ行う必要があります。ただし、キャッシュはいつでもクリアできます。
_php artisan route:clear
_
MarcinNabiałek の元の回答に感謝します。本当に助かりました。
同じ結果をよりシンプルなアプローチで適用できます。完璧ではありませんが、迅速で簡単なソリューションを提供します。ただし、そのシナリオでは、各ルートを作成する必要があるため、大規模なWebサイトに対してはそうしない可能性があります。
Route::get('/contact-us', function () {
return view('contactus');
})->name('rte_contact'); // DEFAULT
Route::get('/contactez-nous', function () {
return view('contactus');
})->name('rte_contact_fr');
ローカライズファイルでルート名を次のように定義するだけです。
# app/resources/lang/en.json
{ "rte_contact": "rte_contact" } //DEFAULT
// app/resources/lang/fr.json
{ "rte_contact": "rte_contact_fr" }
その後、次のような生成されたロケール変数を使用して、ブレードテンプレートでそれらを使用できます。
<a class="nav-link" href="{{ route(__('rte_contact')) }}"> {{ __('nav_contact') }}</a>