ステップバイステップの Laravel ローカリゼーション [ガイド]

ステップバイステップの Laravel ローカリゼーション [ガイド]
目次

Laravelローカリゼーションは、開発者が多言語 Web サイトを作成できるようにする強力な機能です。 LaravelにWeb ローカリゼーションを実装すると、さまざまな言語的背景を持つ訪問者にパーソナライズされたユーザー エクスペリエンスを提供でき、最終的にリーチが拡大し、ユーザー エンゲージメントが向上します。

Laravel アプリケーションにローカリゼーションを実装する手順を説明し、ローカリゼーションの取り組みを簡素化および強化できるツールを紹介します。

Laravel Web サイトをローカライズする必要があるのはなぜですか?

ステップバイステップの Laravel ローカリゼーション [ガイド]

Laravel Web サイトをローカライズする必要がある重要な理由をいくつか紹介します。

  • 世界中の視聴者にリーチする: Laravel をローカライズすることで、アプリのリーチを世界中の視聴者に広げることができます。これにより、さまざまな国や言語背景のユーザーがコンテンツを理解し、操作できるようになります。
  • ユーザー エクスペリエンスの向上:ローカリゼーションにより、ユーザーは母国語でアプリを操作できるようになり、ユーザー エクスペリエンスが大幅に向上します。これにより、エンゲージメント率が向上し、直帰率が低下し、コンバージョンが増加します。
  • 競争上の優位性:競争の激しい世界市場では、複数の言語でアプリを提供することで、競合他社に対して大きな優位性を得ることができます。これは国際市場への取り組みを示し、新しい市場へのより効果的な参入に役立ちます。
  • SEO の向上:適切にローカライズされた Web サイトは、特定の言語での検索において検索エンジンでのランクが向上する傾向があります。ブログのトラフィックとさまざまな市場でのオンラインでの認知度を高めることができます。

多言語 Laravel ローカリゼーションの要件

ステップバイステップの Laravel ローカリゼーション [ガイド]

Laravelで多言語ローカリゼーションを実装する際には、考慮すべき要件と手順がいくつかあります。

  • 最新のローカリゼーション機能を入手するには、 Laravel の最新バージョン (バージョン 10.x など) を使用していることを確認してください。
  • PHP と Laravel フレームワークの基本を理解していると、実装プロセスに役立ちます。
  • Web サーバーやデータベースなど、 Laravelサポートするローカル開発環境またはサーバーをセットアップします。
  • アプリケーションがサポートする言語を最初から決定します。

簡単な Laravel 翻訳

ステップバイステップの Laravel ローカリゼーション [ガイド]

Laravel アプリケーションまたは Web を翻訳する前に満たす必要がある要件を理解した後、 Laravel 簡単に翻訳するためのいくつかの手順を示します。

これを行うには、ローカライズするビュー ファイル (resources/views/welcome.blade.php など) を開きます。次に、body タグを次のコードに置き換えます。

				
					<body class="antialiased">
    <div class="relative flex items-top justify-center min-h-screen bg-gray-100 sm:items-center py-4 sm:pt-0">
        <div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
            <div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
                Welcome to Linguise website!
            </div>
        </div>
    </div> <script data-no-optimize="1">!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function i(t){return e({},it,t)}function o(t,e){var n,a="LazyLoad::Initialized",i=new t(e);try{n=new CustomEvent(a,{detail:{instance:i}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(a,!1,!1,{instance:i})}window.dispatchEvent(n)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,bt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,bt,e)}function r(t){return s(t,null),0}function u(t){return null===c(t)}function d(t){return c(t)===vt}function f(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function _(t,e){nt?t.classList.add(e):t.className+=(t.className?" ":"")+e}function v(t,e){nt?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function b(t,e){!e||(e=e._observer)&&e.unobserve(t)}function p(t,e){t&&(t.loadingCount+=e)}function h(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function m(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function E(t){return!!t[st]}function I(t){return t[st]}function y(t){return delete t[st]}function A(e,t){var n;E(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[st]=n)}function k(a,t){var i;E(a)&&(i=I(a),t.forEach(function(t){var e,n;e=a,(t=i[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function L(t,e,n){_(t,e.class_loading),s(t,ut),n&&(p(n,1),f(e.callback_loading,t,n))}function w(t,e,n){n&&t.setAttribute(e,n)}function x(t,e){w(t,ct,l(t,e.data_sizes)),w(t,rt,l(t,e.data_srcset)),w(t,ot,l(t,e.data_src))}function O(t,e,n){var a=l(t,e.data_bg_multi),i=l(t,e.data_bg_multi_hidpi);(a=at&&i?i:a)&&(t.style.backgroundImage=a,n=n,_(t=t,(e=e).class_applied),s(t,ft),n&&(e.unobserve_completed&&b(t,e),f(e.callback_applied,t,n)))}function N(t,e){!e||0<e.loadingCount||0<e.toLoadCount||f(t.callback_finish,e)}function C(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function M(t){return!!t.llEvLisnrs}function z(t){if(M(t)){var e,n,a=t.llEvLisnrs;for(e in a){var i=a[e];n=e,i=i,t.removeEventListener(n,i)}delete t.llEvLisnrs}}function R(t,e,n){var a;delete t.llTempImage,p(n,-1),(a=n)&&--a.toLoadCount,v(t,e.class_loading),e.unobserve_completed&&b(t,n)}function T(o,r,c){var l=g(o)||o;M(l)||function(t,e,n){M(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";C(t,a,e),C(t,"error",n)}(l,function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_loaded),s(e,dt),f(n.callback_loaded,e,a),i||N(n,a),z(l)},function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_error),s(e,_t),f(n.callback_error,e,a),i||N(n,a),z(l)})}function G(t,e,n){var a,i,o,r,c;t.llTempImage=document.createElement("IMG"),T(t,e,n),E(c=t)||(c[st]={backgroundImage:c.style.backgroundImage}),o=n,r=l(a=t,(i=e).data_bg),c=l(a,i.data_bg_hidpi),(r=at&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),L(a,i,o)),O(t,e,n)}function D(t,e,n){var a;T(t,e,n),a=e,e=n,(t=It[(n=t).tagName])&&(t(n,a),L(n,a,e))}function V(t,e,n){var a;a=t,(-1<yt.indexOf(a.tagName)?D:G)(t,e,n)}function F(t,e,n){var a;t.setAttribute("loading","lazy"),T(t,e,n),a=e,(e=It[(n=t).tagName])&&e(n,a),s(t,vt)}function j(t){t.removeAttribute(ot),t.removeAttribute(rt),t.removeAttribute(ct)}function P(t){m(t,function(t){k(t,Et)}),k(t,Et)}function S(t){var e;(e=At[t.tagName])?e(t):E(e=t)&&(t=I(e),e.style.backgroundImage=t.backgroundImage)}function U(t,e){var n;S(t),n=e,u(e=t)||d(e)||(v(e,n.class_entered),v(e,n.class_exited),v(e,n.class_applied),v(e,n.class_loading),v(e,n.class_loaded),v(e,n.class_error)),r(t),y(t)}function $(t,e,n,a){var i;n.cancel_on_exit&&(c(t)!==ut||"IMG"===t.tagName&&(z(t),m(i=t,function(t){j(t)}),j(i),P(t),v(t,n.class_loading),p(a,-1),r(t),f(n.callback_cancel,t,e,a)))}function q(t,e,n,a){var i,o,r=(o=t,0<=pt.indexOf(c(o)));s(t,"entered"),_(t,n.class_entered),v(t,n.class_exited),i=t,o=a,n.unobserve_entered&&b(i,o),f(n.callback_enter,t,e,a),r||V(t,n,a)}function H(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function B(t,i,o){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?q(t.target,t,i,o):(e=t.target,n=t,a=i,t=o,void(u(e)||(_(e,a.class_exited),$(e,n,a,t),f(a.callback_exit,e,n,t))));var e,n,a})}function J(e,n){var t;et&&!H(e)&&(n._observer=new IntersectionObserver(function(t){B(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function K(t){return Array.prototype.slice.call(t)}function Q(t){return t.container.querySelectorAll(t.elements_selector)}function W(t){return c(t)===_t}function X(t,e){return e=t||Q(e),K(e).filter(u)}function Y(e,t){var n;(n=Q(e),K(n).filter(W)).forEach(function(t){v(t,e.class_error),r(t)}),t.update()}function t(t,e){var n,a,t=i(t);this._settings=t,this.loadingCount=0,J(t,this),n=t,a=this,Z&&window.addEventListener("online",function(){Y(n,a)}),this.update(e)}var Z="undefined"!=typeof window,tt=Z&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),et=Z&&"IntersectionObserver"in window,nt=Z&&"classList"in document.createElement("p"),at=Z&&1<window.devicePixelRatio,it={elements_selector:".lazy",container:tt||Z?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",rt="srcset",ct="sizes",lt="poster",st="llOriginalAttrs",ut="loading",dt="loaded",ft="applied",_t="error",vt="native",gt="data-",bt="ll-status",pt=[ut,dt,ft,_t],ht=[ot],mt=[ot,lt],Et=[ot,rt,ct],It={IMG:function(t,e){m(t,function(t){A(t,Et),x(t,e)}),A(t,Et),x(t,e)},IFRAME:function(t,e){A(t,ht),w(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){A(t,ht),w(t,ot,l(t,e.data_src))}),A(t,mt),w(t,lt,l(t,e.data_poster)),w(t,ot,l(t,e.data_src)),t.load()}},yt=["IMG","IFRAME","VIDEO"],At={IMG:P,IFRAME:function(t){k(t,ht)},VIDEO:function(t){a(t,function(t){k(t,ht)}),k(t,mt),t.load()}},kt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,i=this._settings,o=X(t,i);{if(h(this,o.length),!tt&&et)return H(i)?(e=i,n=this,o.forEach(function(t){-1!==kt.indexOf(t.tagName)&&F(t,e,n)}),void h(n,0)):(t=this._observer,i=o,t.disconnect(),a=t,void i.forEach(function(t){a.observe(t)}));this.loadAll(o)}},destroy:function(){this._observer&&this._observer.disconnect(),Q(this._settings).forEach(function(t){y(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;X(t,n).forEach(function(t){b(t,e),V(t,n,e)})},restoreAll:function(){var e=this._settings;Q(e).forEach(function(t){U(t,e)})}},t.load=function(t,e){e=i(e);V(t,e)},t.resetStatus=function(t){r(t)},Z&&function(t,e){if(e)if(e.length)for(var n,a=0;n=e[a];a+=1)o(t,n);else o(t,e)}(t,window.lazyLoadOptions),t});!function(e,t){"use strict";function a(){t.body.classList.add("litespeed_lazyloaded")}function n(){console.log("[LiteSpeed] Start Lazy Load Images"),d=new LazyLoad({elements_selector:"[data-lazyloaded]",callback_finish:a}),o=function(){d.update()},e.MutationObserver&&new MutationObserver(o).observe(t.documentElement,{childList:!0,subtree:!0,attributes:!0})}var d,o;e.addEventListener?e.addEventListener("load",n,!1):e.attachEvent("onload",n)}(window,document);</script><script data-no-optimize="1">var litespeed_vary=document.cookie.replace(/(?:(?:^|.*;\s*)_lscache_vary\s*\=\s*([^;]*).*$)|^.*$/,"");litespeed_vary||fetch("/wp-content/plugins/litespeed-cache/guest.vary.php",{method:"POST",cache:"no-cache",redirect:"follow"}).then(e=>e.json()).then(e=>{console.log(e),e.hasOwnProperty("reload")&&"yes"==e.reload&&(sessionStorage.setItem("litespeed_docref",document.referrer),window.location.reload(!0))});</script><script data-optimized="1" type="litespeed/javascript" data-src="https://www.linguise.com/wp-content/litespeed/js/435d0eaada3b593adf726e5cdfb5dd43.js?ver=0e199"></script><script>const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script></body>
				
			

ご覧のとおり、上記のテキストは現在コードに直接書き込まれています。 Web サイトを別の言語に翻訳する(国際化)ことが困難になります

上記のテキストをより柔軟にして、さまざまな言語に簡単に適応できるようにします。 Laravel これに非常に役立つ機能を提供します。ローカリゼーション システム。最初のステップとして、既存のテキストを次のコードに置き換えます。

				
					{{ __('Welcome to Linguise website!') }}
				
			

Laravel デフォルトで上記のテキストを表示し、ユーザーが英語以外の言語を選択した場合は翻訳を検索します。この場合、英語がアプリケーションのデフォルト言語として使用されます。

Laravel 多言語 Web でのロケールのセットアップ

ステップバイステップの Laravel ローカリゼーション [ガイド]

しかし、 Laravel どのようにして現在の言語を判断したり、アプリケーションで利用可能な言語を認識したりするのでしょうか? config/app.php ファイル内のロケール設定をチェックします。このファイルを開いて、次の 2 つのキーを探します。

				
					/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/

'locale' => 'en',

/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/

'fallback_locale' => 'en',

				
			

キーの上の説明は明確である必要があります。要約すると、ロケール キーはアプリケーションのデフォルトのロケールを保持します (コード内で他のロケールが指定されていない場合)。 fallback_locale は、アプリケーションで存在しないロケールが要求された場合にアクティブ化されます。

次に、このファイルに新しいキーを追加して、サポートされているすべてのロケールのリストを提供しましょう。

				
					/*
|--------------------------------------------------------------------------
| Available locales
|--------------------------------------------------------------------------
|
| List all locales that your application works with
|
*/

'available_locales' => [
  'English' => 'en',
  'Italian' => 'it',
  'French' => 'fr',
],


				
			

現時点では、 Laravel Web で英語、イタリア語、フランス語の 3 つの言語をサポートすることを試しました。

Laravel 翻訳ファイルの概要

ステップバイステップの Laravel ローカリゼーション [ガイド]

Laravelでは、他の多くのフレームワークと同様に、さまざまな言語の翻訳が別のファイルに保存されます。これらの翻訳ファイルを整理するには 2 つの方法が使用されます。

古い方法では、ファイルは resource/lang/{en,fr,it}/{myfile.php} の構造に保存されます。新しい方法では、resources/lang/{fr.json, it.json} などの JSON ファイルを使用します。この記事では新しい方法に焦点を当てますが、変換キーの名前とアクセス方法の違いを除けば、原則は古い方法でも同様です。

地域によって異なる言語の場合は、ISO 15897 標準に従って言語ディレクトリまたはファイルに名前を付ける必要があります。たとえば、イギリス英語には、en-gb ではなく en_GB という名前が付けられます。

一般情報

Laravelでは、多くのフレームワークと同様に、さまざまな言語の翻訳が別のファイルに保存されます。 Laravel 翻訳ファイルを整理するには、主に 2 つの方法があります。

  1. 従来のアプローチでは、ファイルをパス resource/lang/{en,fr,it}/{myfile.php} に保存します。
  2. 最新のアプローチでは、resources/lang/{fr.json, it.json} ファイルを利用します。

この記事では 2 番目の方法に焦点を当てますが、原則は両方に適用できます (変換キーの名前とアクセス方法は異なります)。

地域によって異なる言語の場合は、ISO 15897 標準に従って言語ディレクトリ/ファイルに名前を付けることをお勧めします。たとえば、イギリス英語は en-gb ではなく en_GB と表記されます。

Laravel 翻訳ファイルの作成

アプリケーションのロケールを構成したら、デフォルトのウェルカム メッセージの翻訳に進むことができます。

まず、resources/lang ディレクトリ内に JSON 形式で新しいローカリゼーション ファイルを作成します。まず、resources/lang/it.json ファイルを作成し、適切な翻訳を入力します。

				
					{
  "Welcome to Linguise website!": "Benvenuti nel sito web di Linguise!"
}

				
			

次に、resources/lang/fr.json ファイルを追加します。

				
					{
 "Welcome to Linguise website!": "Bienvenue sur le site de Linguise"
}

				
			

ご覧のとおり、welcome.blade.php ファイルのデフォルト メッセージ ({{ __(' Linguise Web サイトへようこそ!') }}) を一貫して参照しています。 Laravel デフォルトのメッセージが英語であることを自動的に認識するため、en.json ファイルを作成する必要はありません。

Laravel 多言語アプリで言語スイッチャーを設定する

ステップバイステップの Laravel ローカリゼーション [ガイド]

さらに、 Laravel ローカル言語をオーバーライドするようにまだ設定されていないため、現時点ではルート内で直接翻訳を処理します。 Routes/web.php ファイル内のデフォルトの welcome ルートを次のように変更します。

				
					Route::get('/{locale?}', function ($locale = null) {
    if (isset($locale) && in_array($locale, config('app.available_locales'))) {
        app()->setLocale($locale);
    }
    
    return view('welcome');
});
				
			

この場合、オプションのロケール GET パラメーターを取得し、それに基づいて現在のロケールを設定します (要求されたロケールがサポートされている場合)。

これで、Web サイトにアクセスし、サポートされている言語のいずれかを URL の最初のセグメントとして含めることができます。たとえば、localhost/it または localhost/fr に移動すると、ローカライズされたコンテンツが表示されます。ロケールを指定しない場合、またはサポートされていないロケールを選択した場合、 Laravel デフォルトで英語 (en) に設定されます。

Laravelのローカリゼーション ミドルウェア

すべての URL にロケールを含めることは理想的ではなく、サイトの視覚的な魅力を損なう可能性があります。これに対処するために、言語スイッチャーをセットアップし、ユーザー セッションを利用して翻訳されたコンテンツを表示します。新しいミドルウェアを app/Http/Middleware/Localization.php ファイルに作成することも、artisan make:middleware Localization コマンドを実行して生成することもできます。

次に、その中に次のコードを追加します。

				
					<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;

class Localization
{
    /**
    * Handle an incoming request.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @return mixed
    */
    public function handle(Request $request, Closure $next)
    {
        if (Session::has('locale')) {
            App::setLocale(Session::get('locale'));
        }
        return $next($request);
    }
}


				
			

このオプションがセッションに存在する場合、このミドルウェアは、ユーザーが選択した場所を使用するように Laravel 指示します。

この操作はすべてのリクエストで実行する必要があるため、Web ミドルウェア グループの app/Http/Kernel.php にあるデフォルトのミドルウェア スタックに追加します。

				
					/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
  'web' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \App\Http\Middleware\VerifyCsrfToken::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \App\Http\Middleware\Localization::class, // <--- add this
],


				
			

ルートの変更

次に、routes/web.php ファイルでロケールを変更するためのルートを定義します。ここではクロージャー ルートを使用していますが、必要に応じて同じコードをコントローラー内に配置することもできます。

				
					Route::get('language/{locale}', function ($locale) {
   app()->setLocale($locale);
   session()->put('locale', $locale);
   return redirect()->back();
});

				
			

さらに、以前にデフォルトのウェルカム ルートに追加されていたロケールの切り替えを削除します。ルート ルートは次のようになります。

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

				
			

これが完了すると、ユーザーは localhost/ language/{locale} にアクセスすることによってのみアクティブな言語を切り替えることができます。選択したロケールはセッションに保存され、ユーザーは前のページにリダイレクトされます (ローカリゼーション ミドルウェアによって処理されます)。 

これをテストするには、localhost/ language/it に移動します (ブラウザーでセッション Cookie がアクティブであると仮定します)。翻訳されたコンテンツが表示されるはずです。サイト内を移動したり、ページを更新したりしても、選択した言語は有効なままになります。

言語スイッチャーの実装

URL にロケール コードを手動で入力することをユーザーに要求するのではなく、言語スイッチャーLaravel Web を変更するためのクリック可能なオプションをユーザーに提供する必要がありますこれを実現するには、単純な言語スイッチャーを作成します。 resource/views/partials/ language_switcher.blade.php に新しいファイルを追加し、次のコードを挿入します。

				
					<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
    @foreach($available_locales as $locale_name => $available_locale)
        @if($available_locale === $current_locale)
            <span class="ml-2 mr-2 text-gray-700">{{ $locale_name }}</span>
        @else
            <a class="ml-1 underline ml-2 mr-2" href="language/{{ $available_locale }}">
                <span>{{ $locale_name }}</span>
            </a>
        @endif
    @endforeach
</div>


				
			

新しく作成した言語スイッチャーを「ようこそ」ビューに含めるには、スイッチャーを表示したい welcome.blade.php ファイルに次の行を追加します。

				
					<body class="antialiased">
    <div class="relative flex items-top justify-center min-h-screen bg-gray-100 sm:items-center py-4 sm:pt-0">
        <div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
            @include('partials/language_switcher')

            <div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
                {{ __('Welcome to our website!') }}
            </div>
        </div>
    </div> <script data-no-optimize="1">!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function i(t){return e({},it,t)}function o(t,e){var n,a="LazyLoad::Initialized",i=new t(e);try{n=new CustomEvent(a,{detail:{instance:i}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(a,!1,!1,{instance:i})}window.dispatchEvent(n)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,bt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,bt,e)}function r(t){return s(t,null),0}function u(t){return null===c(t)}function d(t){return c(t)===vt}function f(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function _(t,e){nt?t.classList.add(e):t.className+=(t.className?" ":"")+e}function v(t,e){nt?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function b(t,e){!e||(e=e._observer)&&e.unobserve(t)}function p(t,e){t&&(t.loadingCount+=e)}function h(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function m(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function E(t){return!!t[st]}function I(t){return t[st]}function y(t){return delete t[st]}function A(e,t){var n;E(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[st]=n)}function k(a,t){var i;E(a)&&(i=I(a),t.forEach(function(t){var e,n;e=a,(t=i[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function L(t,e,n){_(t,e.class_loading),s(t,ut),n&&(p(n,1),f(e.callback_loading,t,n))}function w(t,e,n){n&&t.setAttribute(e,n)}function x(t,e){w(t,ct,l(t,e.data_sizes)),w(t,rt,l(t,e.data_srcset)),w(t,ot,l(t,e.data_src))}function O(t,e,n){var a=l(t,e.data_bg_multi),i=l(t,e.data_bg_multi_hidpi);(a=at&&i?i:a)&&(t.style.backgroundImage=a,n=n,_(t=t,(e=e).class_applied),s(t,ft),n&&(e.unobserve_completed&&b(t,e),f(e.callback_applied,t,n)))}function N(t,e){!e||0<e.loadingCount||0<e.toLoadCount||f(t.callback_finish,e)}function C(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function M(t){return!!t.llEvLisnrs}function z(t){if(M(t)){var e,n,a=t.llEvLisnrs;for(e in a){var i=a[e];n=e,i=i,t.removeEventListener(n,i)}delete t.llEvLisnrs}}function R(t,e,n){var a;delete t.llTempImage,p(n,-1),(a=n)&&--a.toLoadCount,v(t,e.class_loading),e.unobserve_completed&&b(t,n)}function T(o,r,c){var l=g(o)||o;M(l)||function(t,e,n){M(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";C(t,a,e),C(t,"error",n)}(l,function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_loaded),s(e,dt),f(n.callback_loaded,e,a),i||N(n,a),z(l)},function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_error),s(e,_t),f(n.callback_error,e,a),i||N(n,a),z(l)})}function G(t,e,n){var a,i,o,r,c;t.llTempImage=document.createElement("IMG"),T(t,e,n),E(c=t)||(c[st]={backgroundImage:c.style.backgroundImage}),o=n,r=l(a=t,(i=e).data_bg),c=l(a,i.data_bg_hidpi),(r=at&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),L(a,i,o)),O(t,e,n)}function D(t,e,n){var a;T(t,e,n),a=e,e=n,(t=It[(n=t).tagName])&&(t(n,a),L(n,a,e))}function V(t,e,n){var a;a=t,(-1<yt.indexOf(a.tagName)?D:G)(t,e,n)}function F(t,e,n){var a;t.setAttribute("loading","lazy"),T(t,e,n),a=e,(e=It[(n=t).tagName])&&e(n,a),s(t,vt)}function j(t){t.removeAttribute(ot),t.removeAttribute(rt),t.removeAttribute(ct)}function P(t){m(t,function(t){k(t,Et)}),k(t,Et)}function S(t){var e;(e=At[t.tagName])?e(t):E(e=t)&&(t=I(e),e.style.backgroundImage=t.backgroundImage)}function U(t,e){var n;S(t),n=e,u(e=t)||d(e)||(v(e,n.class_entered),v(e,n.class_exited),v(e,n.class_applied),v(e,n.class_loading),v(e,n.class_loaded),v(e,n.class_error)),r(t),y(t)}function $(t,e,n,a){var i;n.cancel_on_exit&&(c(t)!==ut||"IMG"===t.tagName&&(z(t),m(i=t,function(t){j(t)}),j(i),P(t),v(t,n.class_loading),p(a,-1),r(t),f(n.callback_cancel,t,e,a)))}function q(t,e,n,a){var i,o,r=(o=t,0<=pt.indexOf(c(o)));s(t,"entered"),_(t,n.class_entered),v(t,n.class_exited),i=t,o=a,n.unobserve_entered&&b(i,o),f(n.callback_enter,t,e,a),r||V(t,n,a)}function H(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function B(t,i,o){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?q(t.target,t,i,o):(e=t.target,n=t,a=i,t=o,void(u(e)||(_(e,a.class_exited),$(e,n,a,t),f(a.callback_exit,e,n,t))));var e,n,a})}function J(e,n){var t;et&&!H(e)&&(n._observer=new IntersectionObserver(function(t){B(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function K(t){return Array.prototype.slice.call(t)}function Q(t){return t.container.querySelectorAll(t.elements_selector)}function W(t){return c(t)===_t}function X(t,e){return e=t||Q(e),K(e).filter(u)}function Y(e,t){var n;(n=Q(e),K(n).filter(W)).forEach(function(t){v(t,e.class_error),r(t)}),t.update()}function t(t,e){var n,a,t=i(t);this._settings=t,this.loadingCount=0,J(t,this),n=t,a=this,Z&&window.addEventListener("online",function(){Y(n,a)}),this.update(e)}var Z="undefined"!=typeof window,tt=Z&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),et=Z&&"IntersectionObserver"in window,nt=Z&&"classList"in document.createElement("p"),at=Z&&1<window.devicePixelRatio,it={elements_selector:".lazy",container:tt||Z?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",rt="srcset",ct="sizes",lt="poster",st="llOriginalAttrs",ut="loading",dt="loaded",ft="applied",_t="error",vt="native",gt="data-",bt="ll-status",pt=[ut,dt,ft,_t],ht=[ot],mt=[ot,lt],Et=[ot,rt,ct],It={IMG:function(t,e){m(t,function(t){A(t,Et),x(t,e)}),A(t,Et),x(t,e)},IFRAME:function(t,e){A(t,ht),w(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){A(t,ht),w(t,ot,l(t,e.data_src))}),A(t,mt),w(t,lt,l(t,e.data_poster)),w(t,ot,l(t,e.data_src)),t.load()}},yt=["IMG","IFRAME","VIDEO"],At={IMG:P,IFRAME:function(t){k(t,ht)},VIDEO:function(t){a(t,function(t){k(t,ht)}),k(t,mt),t.load()}},kt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,i=this._settings,o=X(t,i);{if(h(this,o.length),!tt&&et)return H(i)?(e=i,n=this,o.forEach(function(t){-1!==kt.indexOf(t.tagName)&&F(t,e,n)}),void h(n,0)):(t=this._observer,i=o,t.disconnect(),a=t,void i.forEach(function(t){a.observe(t)}));this.loadAll(o)}},destroy:function(){this._observer&&this._observer.disconnect(),Q(this._settings).forEach(function(t){y(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;X(t,n).forEach(function(t){b(t,e),V(t,n,e)})},restoreAll:function(){var e=this._settings;Q(e).forEach(function(t){U(t,e)})}},t.load=function(t,e){e=i(e);V(t,e)},t.resetStatus=function(t){r(t)},Z&&function(t,e){if(e)if(e.length)for(var n,a=0;n=e[a];a+=1)o(t,n);else o(t,e)}(t,window.lazyLoadOptions),t});!function(e,t){"use strict";function a(){t.body.classList.add("litespeed_lazyloaded")}function n(){console.log("[LiteSpeed] Start Lazy Load Images"),d=new LazyLoad({elements_selector:"[data-lazyloaded]",callback_finish:a}),o=function(){d.update()},e.MutationObserver&&new MutationObserver(o).observe(t.documentElement,{childList:!0,subtree:!0,attributes:!0})}var d,o;e.addEventListener?e.addEventListener("load",n,!1):e.attachEvent("onload",n)}(window,document);</script><script data-optimized="1" type="litespeed/javascript" data-src="https://www.linguise.com/wp-content/litespeed/js/435d0eaada3b593adf726e5cdfb5dd43.js?ver=0e199"></script><script>const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script></body>


				
			

app/Providers/AppServiceProvider.php ファイルを開き、boot() メソッドに次のコードを追加して、言語スイッチャーの使用時に現在のロケールをすべてのビューで共有します。

				
					* Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    view()->composer('partials.language_switcher', function ($view) {
        $view->with('current_locale', app()->getLocale());
        $view->with('available_locales', config('app.available_locales'));
    });
}


				
			

Laravel PHP の高度な翻訳機能

ステップバイステップの Laravel ローカリゼーション [ガイド]

この説明では、他のローカリゼーション コンポーネント、つまり日付、数値、通貨を扱います。手順は次のとおりです。

Laravelのローカライズされた日付

日付と時刻の処理は、ローカリゼーション プロセスにおいて非常に重要です。 Laravel Carbon を使用して日付と時刻を管理します。 Carbon を使用してローカライズされた日付を表示する方法は次のとおりです。

				
					<?php
Route::get('/', function () {
    $today = \Carbon\Carbon::now()
        ->settings(
            [
                'locale' => app()->getLocale(),
            ]
        );

    // LL is macro placeholder for MMMM D, YYYY (you could write same as dddd, MMMM D, YYYY)
    $dateMessage = $today->isoFormat('dddd, LL');

    return view('welcome', [
        'date_message' => $dateMessage
    ]);
});


				
			

このコードは、アプリケーションの現在のロケールに基づいて Carbon ロケールを設定し、それに応じて日付をフォーマットします。

ローカライズされた日付をビューに表示するには:

				
					{{ __('Welcome to our website, :Name', ['name' => ‘Johb’]) }}
<br>
{{ trans_choice('{0} There :form :count apples|{1} There :form just :count apple|[2,19] There :form :count apples', 1, ['form' => 'is']) }}
<br>
{{ $date_message }}


				
			

数値と通貨の書式設定

国が異なれば、数値のフォーマット方法も異なります。例えば。

  • フランス → 123 123,12
  • ドイツ → 123.123,12
  • 日本 → 123,123

Laravel アプリケーションでこれらのバリエーションに対応するには、NumberFormatter を使用できます。

				
					<?php
$num = NumberFormatter::create('en_US', NumberFormatter::DECIMAL);

$num2 = NumberFormatter::create('fr', NumberFormatter::DECIMAL);
				
			

特定の言語で数字をスペルアウトすることもできます。

				
					<?php
$num = NumberFormatter::create('en_US', NumberFormatter::SPELLOUT);

$num2 = NumberFormatter::create('it', NumberFormatter::SPELLOUT);
				
			

通貨は次のとおりです。フランス語ロケール (`fr`) の場合、通貨はユーロ (€) で表示され、米国ロケール (`en_US`) の場合は米ドル ($) で表示されます。

				
					<?php
$currency1 = NumberFormatter::create('it', NumberFormatter::CURRENCY);

$currency2 = NumberFormatter::create('en_US', NumberFormatter::CURRENCY);
				
			
言語の壁を打ち破る
言葉の壁に別れを告げて、無限の成長を楽しみましょう! 今すぐ自動翻訳サービスをお試しください。

代替ソリューション Linguiseを使用した Laravel ローカリゼーション

ステップバイステップの Laravel ローカリゼーション [ガイド]

この記事で説明されているように Laravel ローカリゼーションの手順を理解した後、このプロセスには多くの手順が含まれており、ユーザーは Laravel プログラム コードを深く理解する必要があります。

このため、アプリケーションをローカライズしたい初心者ユーザーにとっては確かに困難になる可能性があります。したがって、高速翻訳が可能で、ローカリゼーションをサポートし、実装に必要な手順が簡単な、より革新的なソリューションが必要です。

有望なソリューションの 1 つは Linguiseです。 Linguise 深いコーディング知識を必要とせずに、 Laravel ローカリゼーションへのより簡単で効率的なアプローチを提供します。 Linguise の主な機能は次のとおりです。

  • Laravelとの簡単な統合
  • コーディングなしで言語スイッチャーをカスタマイズ
  • 画像翻訳
  • ローカルコンテキストに合わせて翻訳をカスタマイズするライブエディター
  • 動的に生成されたコンテンツの動的翻訳
  • 多言語バージョンの SEO 最適化

Laravel Web サイトLinguiseインストールする手順も簡単に実行できます。ここで簡単に説明します。

  1. Linguise アカウントを作成します (30 日間の無料トライアルを無料で使用します)
  2. Laravel Web ドメインを登録し、いくつかの情報を入力します。 APIキーを取得します。
  3. 取得した Laravel フォルダーに Linguise 翻訳スクリプトをアップロードして接続します。
  4. htaccess ファイルに言語 URL を設定します。
  5. 言語スイッチャー スクリプトを HTML の先頭に挿入します。
  6. 必要に応じて言語スイッチャーをカスタマイズします
  7. 言語スイッチャーが Laravel Web 上に表示され、コンテンツを自動的に翻訳できます。

どうやって? Linguise使用すると、登録してアクティブ化するだけで、言語スイッチャーが表示されます。その後は、ライブ エディターを使用してローカライズしたり、メディアや画像などを翻訳したりすることができます。

新しい市場を開拓する準備はできていますか? 1 か月間リスクなしのトライアルで、自動翻訳サービスを無料でお試しください。 クレジットカードは必要ありません!

結論

Laravel ローカリゼーションは、開発者が多言語の Web サイトやアプリケーションを作成できるようにする強力な機能です。これまで見てきたように、組み込みの Laravel ローカリゼーション プロセスには複数のステップが含まれており、フレームワークをよく理解する必要があります。初心者や、より迅速な解決策を探している人にとっては、難しいかもしれません。

Linguiseのようなツールは、より合理化されたアプローチを求める人にとって革新的な代替手段を提供します。これらのソリューションは、迅速な翻訳機能、簡単な統合、カスタマイズ可能な言語スイッチャーや画像翻訳などのユーザーフレンドリーな機能を提供します。さあ、 Linguiseアカウントを作成して Laravelローカライズする機能をお楽しみください。

あなたも読むことに興味があるかもしれません

お見逃しなく!
ニュースレターを購読する

ウェブサイトの自動翻訳、国際SEOなどのニュースを受け取る!

Invalid email address
試してみる。 月に1回、いつでも退会できます。

メールを共有せずに終了しないでください。

宝くじに当たるという保証はできませんが、翻訳に関する興味深い情報ニュースや、時折割引を受けることはお約束できます。

お見逃しなく!
Invalid email address