Azis Hapidin
Membuat Website Multi Language dengan Laravel

Ketika kita membuat sebuah website yang akan banyak diakses oleh pengguna dari berbagai negara. Maka salah satu fitur yang wajib ada adalah fitur multi language atau multi bahasa, fitur ini mungkin bisa kita skip jika kita membuat sebuah aplikasi dalam bahasa Inggris, tapi ketika kita ingin lebih spesifik menargetkan user dari negara-negara tertentu (Misal: Indonesia, Arab atau China) maka saya rasa fitur ini sudah sangat wajib sekali untuk ada.

Di Laravel, untuk membuat fitur multi language ini kita bisa menggunakan fitur bawaan Laravel bernama Localization.

Contoh kasus kali ini kita akan membuat satu halaman seperti dibawah, abaikan tampilannya yang terlalu polos, kita fokus ke Localization-nya saja 😀 Walaupun pada contoh kasus kita hanya akan mencoba di 1 halaman, jika kita faham maka untuk implementasi di halaman lain tidak akan sulit.

Oh iya, jika teman-teman ingin cek source code yang sudah jadi, saya share juga disini.

Persiapan

Pertama, siapkan project laravel seperti biasa dengan menjalankan perintah dibawah pada Terminal:

composer create-project laravel/laravel multilanguage

Pada contoh ini saya menggunakan Laravel 5.8, jadi jika suatu saat nanti Laravel sudah update Major (Apa itu Major? Silahkan baca-baca Mengenal Semantic Versioning) dan tutorial ini jadi tidak jalan. Silahkan kabari saya untuk saya update artikelnya.

Oh iya saya asumsikan teman-teman sudah faham basic Laravel ya mulai dari Controller, Route, Middleware, View, dsb.

Membuat Halaman Depan

Setelah selesai inisiasi project-nya, selanjutnya kita akan membuat/mengubah halaman depan dengan mengubah file menjadi seperti ini:

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
 
<head>
    <title>{{ config('app.name') }}</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
 
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light container">
        <a class="navbar-brand" href="#">{{ config('app.name') }}</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
 
        <div class="navbar-collapse collapse w-100 order-3 dual-collapse2">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                        data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        {{ __('home.switch_language') }}
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                        {{-- Disini nanti navigasi --}}
                    </div>
                </li>
            </ul>
        </div>
    </nav>
    <div class="container pt-5">
        <h1>{{ __('home.title') }}</h1>
        <p>{{ __('home.description') }}</p> 
    </div>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
 
</html>

Coba kita perhatikan baris 32, disitu kita memanggil __('home.title') , itu adalah helper untuk memanggil teks yang ada di file resources/lang/{locale-code}/home.php dengan key title.

Jika sekarang kita buka halamannya maka hanya akan tampil seperti ini:

Selanjutnya adalah kita harus membuat file resources/lang/en/home.php dengan isi sebagai berikut:

<?php 
 
return [
 
    /*
    |--------------------------------------------------------------------------
    | Home Page Language Lines
    |--------------------------------------------------------------------------
    |
    */
    
    'switch_language' => 'Switch Language',
    'title' => 'Welcome',
    'description' => 'This is example implementation of Laravel Localization.',
];

Jika kita refresh halaman tadi, maka sekarang akan menjadi seperti ini:

Menyiapkan Bahasa baru

Mungkin akan muncul pertanyaan:

Kenapa direktorinya mengarah ke resources/lang/en/namafile.php, kenapa harus en?

Jawabannya adalah karena konfigurasi default locale di fileconfig/app.php adalah en.

Maka untuk menambahkan bahasa baru, kita cukup membuat direktori untuk bahasa baru yang akan kita tambahkan. Karena pada contoh tutorial kali ini kita akan menambahkan Bahasa Indonesia, maka tinggal copy saja folder en tadi dengan nama folder id.

Kemudian ubah file resources/lang/id/home.php menjadi seperti ini:

<?php 
 
return [
 
    /*
    |--------------------------------------------------------------------------
    | Home Page Language Lines
    |--------------------------------------------------------------------------
    |
    */
    
    'switch_language' => 'Pindah Bahasa',
    'title' => 'Selamat Datang',
    'description' => 'Ini adalah contoh implementasi Laravel Localization.',
];

Kemudian ubah nilai locale di file config/app.php tadi menjadi id.

Sampai sini silahkan coba refresh halaman tadi, jika tidak ada masalah maka akan berubah menjadi Bahasa Indonesia seperti ini.

Membuat Fitur Switch Language

Nah selanjutnya adalah kita membuat fitur switch language atau pindah bahasa. Inti pada bagian ini adalah kita harus mengubah value locale yang ada di config/app.php tadi menjadi sesuai dengan locale/bahasa yang dipilih. Dan nilai locale yang dipilih user akan kita simpan di session.

Pertama kita harus membuat code untuk menyimpan nilai locale yang dipilih oleh user ke session.

Buat controller dengan menjalankan perintah dibawah pada Terminal:

php artisan make:controller LocalizationController

Kemudian tambahkan method untuk switch language seperti dibawah:

<?php
 
namespace App\Http\Controllers;
 
use App;
use Illuminate\Http\Request;
 
class LocalizationController extends Controller
{
    /**
     * Switch Language.
     *
     * @param string $language Language code.
     * 
     * @return Response
     */
    public function switch($language = '')
    {
        // Simpan locale ke session.
        request()->session()->put('locale', $language);
 
        // Arahkan ke halaman sebelumnya.
        return redirect()->back();
    }
}

Jangan lupa tambahkan juga di Route:

<?php
 
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
 
Route::get('/', function () {
    return view('welcome');
});
 
Route::get('lang/{language}', 'LocalizationController@switch')->name('localization.switch');

Selanjutnya adalah kita harus membuat Middleware untuk set nilai locale yang ada di config tadi.

Jalankan perintah dibawah di Terminal:

php artisan make:middleware LocalizationMiddleware

Kemudian kita ubah file app/Http/Middleware/LocalizationMiddleware.php menjadi seperti ini:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
 
class LocalizationMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // Cek apakah session 'locale' ada?
        if ($request->session()->has('locale')) {
            // Jika ada, maka set App Locale sesuai nilai yang ada di session 'locale'.
            \App::setLocale($request->session()->get('locale'));
        }
        
        // Lanjutkan request.
        return $next($request);
    }
}

Kita registrasi Middleware diatas dan 1 Middleware lain ke Global Middleware di app/Http/Kernel.php (perhatikan baris 22 dan 23).

<?php
 
namespace App\Http;
 
use Illuminate\Foundation\Http\Kernel as HttpKernel;
 
class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Session\Middleware\StartSession::class, // Karena kita menggunakan Session, maka tambahkan Middleware ini
        \App\Http\Middleware\LocalizationMiddleware::class, // Middleware untuk Cek Bahasa
    ];
 
    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
 
        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];
 
    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
 
    /**
     * The priority-sorted list of middleware.
     *
     * This forces non-global middleware to always be in the given order.
     *
     * @var array
     */
    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\Authenticate::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];
}

Selanjutnya kita tambahkan link/menu untuk switch language tadi, terserah teman-teman ingin menyimpannya dimana. Pada contoh disini kita akan menambahkan pada navbar di bagian kanan atas. Silahkan ubah file welcome.blade.php menjadi seperti ini (perhatikan baris 25 dan 26):

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
 
<head>
    <title>{{ config('app.name') }}</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
 
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light container">
        <a class="navbar-brand" href="#">{{ config('app.name') }}</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
 
        <div class="navbar-collapse collapse w-100 order-3 dual-collapse2">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                        data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        {{ __('home.switch_language') }}
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <a class="dropdown-item {{ app()->getLocale() == 'en' ? 'active' : '' }}" href="{{ route('localization.switch', 'en') }}">English</a>
                        <a class="dropdown-item {{ app()->getLocale() == 'id' ? 'active' : '' }}" href="{{ route('localization.switch', 'id') }}">Bahasa Indonesia</a>
                    </div>
                </li>
            </ul>
        </div>
    </nav>
    <div class="container pt-5">
        <h1>{{ __('home.title') }}</h1>
        <p>{{ __('home.description') }}</p> 
    </div>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
 
</html>

Fungsi app()->getLocale() diatas adalah untuk mendapatkan locale yang sedang aktif.

Testing

Jika tidak ada masalah, harusnya semua berjalan seperti pada gambar dibawah:

Selanjutnya Apa?

Selanjutnya adalah silahkan implementasi di halaman lain, oh iya pada folder tadi kita lihat juga ada banyak file lain seperti auth.php, pagination.php, passwords.php dan validation.php. Silahkan ubah isinya sesuai dengan yang diinginkan.

Jika ingin menambahkan bahasa lain, silakan untuk lakukan hal yang sama lagi seperti diatas.

Penutup

Sekian artikel kali ini, mohon maaf jika ada kekurangan. Bila ada yang kurang jelas silahkan untuk berkomentar pada kolom komentar dibawah.

Terima kasih 🙂