August 9, 2020

PHP MVC - Laravel Views / Blade Templates / Localization

Title: PHP Laravel - 뷰 / 블레이드 템플릿 / 다국어
Author: DongDongE
Tags: Programming
Release: 2020.08.09


[Views - 뷰]


Creating Views - 뷰 생성하기


뷰에는 애플리케이션에서 제공하는 HTML로 포함되며 컨트롤러 / 애플리케이션 로직을 프레젠테이션 로직과 분리합니다.
View는 "resources/views" 디렉터리에 저장됩니다. 간단한 View 예제는 아래와 같습니다.


<!-- View stored in resources/views/greeting.blade.php -->

<html>
    <body>
        <h1>Hello, {{ $name }}</h1>
    </body>
</html>

해당 View는 "resources/views/greeting.blade.php"에 저장되므로 다음과 같이 전역 "view" 도우미(helper)를 사용하여 반환할 수 있습니다.


Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});

보이는 바와 같이 도우미에 전달된 첫 번째 인수는 "resources/views" 디렉터리의 view 파일 이름에 해당합니다. Ex) "resources/views/greeting.blade.php"
두 번째 인수는 view에서 사용할 수 있는 데이터의 배열입니다. 이 경우 "Blade(블레이드)" 구문을 사용하여 View에 표시되는 "name" 변수를 전달합니다. Python Flask의 Jinja 문법처럼 PHP Laravel에는 Blade 문법이 존재합니다.

물론, View는 "resources/view" 디렉터리의 서브 디렉터리내에 중첩될 수 있습니다. "Dot"(점) 표기법을 사용하여 중첩된 view를 참조할 수 있습니다. 예를 들어 "resources/views/admin/profile.blade.php"에 저장되어 있는 경우 아래와 같이 이를 참조할 수 있습니다.


return view('admin.profile', $data);



Determining If A View Exists - View가 존재하는지 확인하기


View 파일이 존재하는지 확인해야하는 경우 View Facade(파사드)를 사용할 수 있습니다. View가 존재하는 경우 "exists" 메소드에서 "true"를 반환합니다.


use Illuminate\Support\Facades\View;

if (View::exists('emails.customer')) {
    //
}



Passing Data To Views - View에 데이터 전달하기


이전 예제에서 확인하였듯이, 뷰에 데이터 배열을 전달할 수 있습니다.


return view('greetings', ['name' => 'Victoria']);

이러한 방식으로 정보를 전달할 때, $data는 키/값 쌍으로 구성된 배열로 전달되어야합니다. View내에서 <?php echo $key; ?> 와 같이 각각의 키에 해당하는 값에 액세스할 수 있습니다. view 도우미 함수에 전체 데이터 배열을 전달하는 대신 "with" 메소드를 사용하여 개별 데이터 조각을 view에 추가할 수 있습니다.


return view('greeting')->with('name', 'Victoria');



Sharing Data With All Views - 모든 뷰에서 데이터 공유하기


경우에 따라 애플리케이션에서 렌더링하는 모든 뷰와 데이터를 공유해야할 수 있습니다. 뷰 파사드의 "share" 메소드를 사용하면 됩니다. 일반적으로 서비스 프로바이더의 "boot" 메소드에 구성해 놓아야 합니다. "AppServiceProvider"에 추가하거나 별도의 서비스 공급자를 생성하여 저장할 수 있습니다.


<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        View::share('key', 'value');
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}



View Composers - 뷰 컴포저


뷰 컴포저는 뷰가 렌더링될 때 호출되는 콜백 또는 클래스 메소드입니다. 뷰가 렌더링될 때 마다 뷰에 바인딩(전달)하려는 데이터가 있는 경우 뷰 컴포저가 해당 로직을 단일 위치로 구성하는데 도와줄 수 있습니다.

예를 들어, 서비스 프로바이더내에 뷰 컴포저를 등록해보도록 하겠습니다. View 파사드를 사용하여 기본 "Illuminate\Contracts\View\Factory" contract 구현체에 액세스하기 위해 "View" 파사드를 사용할 것입니다. 라라벨은 뷰 컴포저를 위한 기본 디렉터리를 포함하지 않습니다. 원하는대로 구성할 수 있으며, "App\Http\ViewComposers" 디렉터리를 만들 수 있습니다.


<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function boot()
    {
        // Using class based composers...
        View::composer(
            'profile', 'App\Http\ViewComposers\ProfileComposer'
        );

        // Using Closure based composers...
        View::composer('dashboard', function ($view) {
            //
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

뷰 컴포저 등록을 포함할 새 서비스 프로바이더를 생성할 경우 "config/app.php" 설정 파일의 "providers" 배열에 이 서비스 프로바이더를 추가해야 합니다.


이제 view composer를 등록했다면 "profile" 뷰가 렌더링될 때 마다 "ProfileComposer@compose" 메소드가 실행될 것입니다. 이제 컴포저 클래스를 정의해봅시다.


<?php

namespace App\Http\ViewComposers;

use Illuminate\View\View;
use App\Repositories\UserRepository;

class ProfileComposer
{
    /**
     * The user repository implementation.
     *
     * @var UserRepository
     */
    protected $users;

    /**
     * Create a new profile composer.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        // Dependencies automatically resolved by service container...
        $this->users = $users;
    }

    /**
     * Bind data to the view.
     *
     * @param  View  $view
     * @return void
     */
    public function compose(View $view)
    {
        $view->with('count', $this->users->count());
    }
}

뷰가 렌더링되기 직전에 Composer의 compose 메소드가 "Illuminate\View\View" 인스턴스와 함께 호출됩니다. with 메소드를 사용하여 데이터를 뷰에 바인딩할 수 있습니다.

모든 뷰 컴포저는 "service container" 를 통해 해결되므로 컴포저의 생성자 내에서 필요한 중속성 유형 타입힌트할 수 있습니다.



Attaching A Composer To Multiple Views - 컴포저를 여러 뷰에 적용하기


"Composer" 메소드의 첫 번째 인수로 뷰 배열을 전달하여 한 번에 여러 뷰에 뷰 컴포저를 연결할 수 있습니다.


View::composer(
    ['profile', 'dashboard'],
    'App\Http\ViewComposers\MyViewComposer'
);

composer 메소드 또한 "*" 와일드 카드 문자를 허용하므로 컴포저를 모든 뷰에 연결할 수 있습니다.


View::composer('*', function ($view) {
    //
});



View Creators


뷰 크리에디터는 뷰 컴포저와 매우 유사합니다. 그러나 뷰가 렌더링될 때 까지 기다리지 않고 뷰가 인스턴스화된 직후에 실행됩니다. 뷰 크리에디터를 등록하려면 "view의 creator" 사용하면 됩니다.


View::creator('profile', 'App\Http\ViewCreators\ProfileCreator');




[Blade Templates - 블레이드 템플릿]


블레이드 템플릿이란?


Blade는 라라벨과 함께 제공되는 간단하면서도 강력한 템플릿 엔진입니다. 다른 인기있는 PHP 템플릿 엔진과 달리 "Blade"는 View에서 일반 PHP 코드를 사용하는 것을 허용합니다(제한하지 않습니다). 실제로 모든 Blade View는 일반 PHP 코드로 컴파일되고 수정될 때 까지 캐시됩니다. 즉, 블레이드는 기본적으로 애플리케이션에 오버 헤드(부담)가 전혀 없습니다. 블레이드 view 파일은 ".blade.php" 파일 확장자를 사용하며 일반적으로 "resurces/views" 디렉터리에 저장됩니다.



Template Inheritance - 템플릿 상속


Defining A Layout - 레이아웃 정의


Blade 사용의 두 가지 주요 이점은 "템플릿 상속"과 "섹션"입니다. 먼저 시작하기전 간단한 예를 살펴 보겠습니다. "마스터" 페이지 레이아웃을 살펴 보겠습니다. 대부분의 웹 애플리케이션은 다양한 페이지에서 동일한 일반 레이아웃을 유지하므로 해당 레이아웃을 단일 블레이드 view로 정의하는 것이 편리합니다.


<!-- Stored in resources/views/layouts/app.blade.php -->

<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

위 예제를 보면 일반적인 HTML 마크업 문법이 포함되어 있습니다. 그러나 "@section" 및 "@yield" 지시문에 유의해주십시오. 이름에서 알 수 있듯이 "@section" 지시문은 콘텐츠 섹션을 정의하고, "@yield" 지시문은 주어진 섹션의 콘텐츠를 표시하는데 사용됩니다.

이제 애플리케이션의 레이아웃을 정의 했으므로 레이아웃을 상속하는 자식 페이지를 정의해보도록 하겠습니다.



Extending A Layout - 레이아웃 확장


하위 뷰를 정의할 때 "Blade" "@extends" 지시어를 사용하여 하위 뷰가 "inherit(상속)" 받을지 명시할 수 있습니다. 블레이드 레이아웃을 확장하는 뷰는 "@section" 지시문을 사용하여 레이아웃의 섹션에 콘텐츠를 삽입할 수 있습니다. 위의 예제에서 볼 수 있듯이, 이러한 섹션의 내용은 "@yield"를 사용하여 레이아웃을 표시합니다.


<!-- Stored in resources/views/child.blade.php -->

@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

위 예제에서 "sidebar" 섹션은 "@parent" 지시문을 사용하여 레이아웃의 사이드 바에 컨텐츠를 추가 (덮어 쓰지 않고)합니다. "@parent" 지시문은 View가 렌더링될 때 레이아웃의 내용으로 대체됩니다.

글로벌 View 헬퍼를 사용하여 라우트에 블레이드 view를 반환할 수 있습니다.


Route::get('blade', function () {
    return view('child');
});



Displaying Data - 데이터 표시하기


전달되는 변수를 중괄호 "[", "]"로 묶어 블레이드 뷰에 전달된 데이터를 표시할 수 있습니다.
예를 들어 아래와 같은 라우트를 볼 수 있습니다.


Route::get('greeting', function () {
    return view('welcome', ['name' => 'Samantha']);
});

다음과 같이 "name" 변수의 내용을 표시할 수 있습니다.


Hello, {{ $name }}.

물론 뷰에 전달된 변수의 내용을 표시하는 데 제한되지 않습니다. PHP 함수의 결과를 출력할 수 있으며, 실제로 Blade 문법 안에서 원하는 모든 PHP 코드를 넣어 실행할 수 있습니다.


The current UNIX timestamp is {{ time() }}.

Blade "{{ }}" 문법은 XSS Attack을 방지하기 위해 자동으로 PHP의 "htmlentities" 함수를 거쳐 출력됩니다.



Echoing Data If It Exists - 데이터가 있는 경우 출력


때로는 변수를 출력하고 싶지만 변수가 존재하는지 정확히 알지 못하는 경우가 있습니다. 이를 다음과 같이 아래 PHP 코드를 통하여 표현할 수 있습니다.


/* $name 존재할 경우 $name 그대로 출력, 없을 경우 "Default" 출력 */
{{ isset($name) ? $name : 'Default' }}

그러나 삼항연산자를 작성하여 위의 블레이드 대신 삼항연산자로 컴파일되어 다음과 같이 편리하게 단축을 제공합니다.


/* $name 변수가 존재하지 않을 경우 "Default" 반환한다.  */
{{ $name or 'Default' }}

위 예에서 "$name" 변수가 존재시 그대로 $name 변수값이 표시되지만, 존재하지 않을 경우 "Default"로 표시됩니다.



Displaying Unescaped Data - 이스케이프 되지 않도록 데이터 표시하기


기본적으로 Blade 문법은 XSS 공격에 대응하기 위해 자동으로 PHP 함수의 "htmlentities"를 실행하여 반환값을 전달합니다. 하지만 데이터를 escape를 원치 않을 경우 다음과 같이 사용할 수 있습니다.


/* 전달된 $name 변수는 그대로 출력된다. */
Hello, {!! $name !!}.

특별한 경우를 제외하고는 애플리케이션이 사용자들로 부터 입력받아 출력(표시)될 때는 컨텐츠를 안전하게 escape(이스케이프)를 처리할 수 있도록 주의가 필요합니다.
만약 escape처리를 하지 않는 다면 XSS 취약점으로 세션 탈취 및 CSRF, SSRF 등 공격이 발생하게 됩니다.
안전을 위해서 항상 이스케이프 처리된 이중 중괄호 "{{ }}"을 사용하십시오.



Blade & JavaScript Frameworks - 블레이드 & 자바스크립트 프레임워크


많은 자바스크립트 프레임워크도 "중괄호"를 사용하여 지정된 표현식으로 브라우저에 표시되어야 함을 나타내므로 "@"기호를 사용하여 블레이드 렌더링 엔진에 표현식이 그대로 유지될 수 있습니다.


<h1>Laravel</h1>

Hello, @{{ name }}.

위 예제에서 "@" 기호는 Blade에 의해 제거됩니다. 하지만 "{{ name }}" 표현은 블레이드 엔진에 의해 영향을 받지 않으며 자바스크립트 프레임워크에 의해 렌더링될 수 있게 해줍니다.



The @verbatim Directive - @verbatim 지시어


템플릿의 많은 부분에 Javascript 변수를 표시하는 경우 "@verbatim" 지시어로 블레이드 출력문 앞에 "@" 기호를 쓸 필요가 없어집니다.


@verbatim
    <div class="container">
        Hello, {{ name }}.
    </div>
@endverbatim




[Control Structures - 제어 구조]

템플릿 상속 및 데이터 표시 외에도 Blade는 조건문 및 반복문과 같이 일반적인 PHP 제어 구조에 대한 편리한 기능을 제공합니다. 해당 방법들은 PHP 컨트롤러 구조를 이용할 수 있는 매우 깔끔하고 간결한 방법을 제공하는 동시에 PHP 코드에 익숙한 구조와 비슷하게 유지합니다.


if Statements - if문



"@if", "@elseif", "@else", "@endif" 지시문을 사용하여 if 조건문을 구성할 수 있습니다. 해당 지시문은 PHP 조건문과 동일하게 작동됩니다.


@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

보다 나은 편의를 위해 Blade에서는 "@unless" 문법도 제공합니다.


@unless (Auth::check())
    You are not signed in.
@endunless



Loops - 반복문


조건문 외에도 Blade는 PHP의 반복문을 위한 간단한 지시문을 제공합니다. 이러한 각 지시문은 기존 PHP 코드와 동일하게 작동합니다.


@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</p>
@endwhile

반복문을 사용할 때 반복문 변수를 사용하여 반복문의 첫 번째 또는 마지막 반복문에 대한 정보를 얻을 수 있습니다.


반복문을 사용할 때 반복문을 종료하거나 현재 반복 단계를 건너 뛸 수 있습니다. 즉, 기존 PHP 반복문 또는 조건문 그대로 사용이 가능합니다.


@foreach ($users as $user)
    @if ($user->type == 1)
        @continue
    @endif

    <li>{{ $user->name }}</li>

    @if ($user->number == 5)
        @break
    @endif
@endforeach

또한 반복문과 함께 조건식을 하나의 라인으로 표현할 수 있습니다.

@foreach ($users as $user)
    @continue($user->type == 1)

    <li>{{ $user->name }}</li>

    @break($user->number == 5)
@endforeach



The Loop Variable - 반복문 변수


반복문을 사용할 때 반복문 내에서 "$loop" 변수를 사용할 수 있습니다. 해당 변수는 현재 반복문의 인덱스 및 반복문이 첫 번째 또는 마지막 인지 알 수 있으며 이와 같은 유용한 정보에 대한 액세스를 제공합니다.


@foreach ($users as $user)
    @if ($loop->first)
        /* 첫 번째 루프에서 수행 */
        This is the first iteration.
    @endif

    @if ($loop->last)
        /* 마지막 루프에서 수행 */
        This is the last iteration.
    @endif

    <p>This is user {{ $user->id }}</p>
@endforeach

반복문이 중첩되어 있는 상위 반복문의 "$loop" 변수에 "parent" 속성을 통해서 액세스할 수 있습니다.


@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

"$loop" 변수는 다른 유용한 속성을 다양하게 포함하고 있습니다.


속성 설졍
$loop->index 현재 반복문의 인덱스 (0에서 부터 시작)
$loop->iteration 현재 반복문의 횟수 (1에서 부터 시작)
$loop->remaining 현재 반복문의 남은 횟수
$loop->count 반복되는 배열의 총 갯수
$loop->first 현재 반복문의 첫 번째 반복문 인지 확인
$loop->last 현재 반복문의 마지막 반복문인지 확인
$loop->depth 중첩된 반복문 확인
$loop->parent 중첩된 반복문 부모의 루프 변수



Comments - 주석


Blade를 사용하면 View에서 주석을 정의할 수 있습니다. 그러나 HTML 주석과 달리 블레이드 주석은 애플리케이션에서 반환하는 HTML에 포함되어 있지 않습니다.


{{-- This comment will not be present in the rendered HTML --}}



PHP


어떤 상황에서는 View에 PHP 코드를 포함하여 유용하게 사용할 수 있습니다. 블레이드의 "@php" 지시문을 사용하여 블레이드 템플릿내에서 PHP 블록에서 코드를 사용할 수 있습니다.


@php
    // php code
    phpinfo();
@endphp

블레이드는 위와 같이 기능을 제공하지만 이 기능을 너무 자주 사용하는 것은 템플릿에 로직이 너무 많이 포함됩니다.



Including Sub-Views - 하위 뷰 포함하기


블레이드의 "@include" 지시문을 사용하여 다른 뷰 내부에서 블레이드 뷰를 포함할 수 있습니다. 상위 뷰에서 사용할 수 있는 모든 변수는 포함된 뷰에서 사용할 수 있습니다.


<div>
    @include('shared.errors')

    <form>
        <!-- Form Contents -->
    </form>
</div>

하위에 포함하게될 뷰는 상위 뷰의 모든 데이터를 상속하게 되지만, 하위 뷰에는 추가 데이터 배열을 직접 전달할 수 있습니다.


@include('view.name', ['some' => 'data'])

물론 존재하지 않는 뷰를 "@include" 하려고하면 라라벨은 오류를 발생시킵니다. 존재하거나 존재하지 않을 수 있는 뷰를 포함하려면 "@includeIf" 지시문을 사용해야 합니다.


@includeIf('view.name', ['some' => 'data'])

블레이드 뷰에서 "__DIR__"와 "__FILE__"를 사용하지 않아야합니다. 사용시 컴파일된 캐시 뷰의 경로가 반환됩니다.



Rendering Views For Collections - 컬렉션을 뷰에서 렌더링


블레이드의 "@each" 지시어를 사용하면 반복문을 하나의 줄로 구성할 수 있습니다.


@each('view.name', $jobs, 'job')

첫 번째 인수는 배열 또는 집합의 각 요소에 대해 렌더링할 부분의 뷰 이름 입니다. 두 번째 인수는 반복하려는 배열 또는 컬렉션이고, 세 번째 인수는 뷰 내에서 현재 반복값에 할당 될 변수 이름입니다.
예를 들면 "jobs" 배열을 반복하려고 하면 보통 부분적 뷰에서 각 과제를 "job" 변수로 접근해야 하며, 현재 반복에서의 키 값은 부분적 뷰에서 "key" 변수로 접근할 수 있습니다.


또한 "@each" 지시어에 네 번째 인수를 전달할 수 있습니다. 해당 인자는 주어진 배열이 비었을 경우 렌더링될 뷰를 결정합니다.


@each('view.name', $jobs, 'job', 'view.empty')



Stacks - 스택


블레이드를 사용하면 다른 뷰 또는 레이아웃의 다른 곳에서 렌더링할 수 있는 이름이 지정된 스택으로 푸시할 수 있습니다. 이는 하위 뷰에 필요한 JavaScript 라이브러리를 지정하는데 유용할 수 있습니다.


@push('scripts')
    <script src="/example.js"></script>
@endpush

아래와 같이 필요한 만큼 여러번 스택으로 푸시할 수 있습니다. 전체 스택 콘텐츠를 렌더링하려면 스택이름을 "@stack" 지시문으로 전달하면 됩니다.


<head>
    <!-- Head Contents -->

    @stack('scripts')
</head>



Service Injection - 서비스 인잭션


"@inject" 지시문은 라라벨 서비스 컨테이너에서 서비스를 검색하는데 사용할 수 있습니다. "@inject"에 전달된 첫 번째 인수는 서비스가 배치될 변수의 이름이고, 두 번째 인자는 의존성을 해결하려는 서비스의 클래스 또는 인터페이스 이름입니다.


@inject('metrics', 'App\Services\MetricsService')

<div>
    Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>



Extending Blade - 블레이드 기능 확장


블레이드에서 "directive" 메소드를 사용하여 사용자 지정 지시문을 정의할 수 있습니다. 블레이드 컴파일러가 사용자 지정 지시어를 발견하면 해당 지시어에 정의된 콜백함수를 호출합니다.


다음의 예제는 전달된 "DateTime" 인스턴스의 "$var"의 포맷으로 변경하려는 "@datetime($var)" 지시어를 생성합니다.


<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

위와 같이 지시문에 전달되는 표현식에서 "format" 메소드를 연결합니다. 따라서 이 예제에서 지시문에 의해 생성된 최종 PHP 코드는 아래와 같습니다.


<?php echo ($var)->format('m/d/Y H:i'); ?>

블레이드 지시문의 로직을 수정한 이후에는 캐시된 모든 블레이드 뷰를 삭제해야합니다. 캐시된 블레이드 뷰는 "View:clear"으로 Artisan 아티즌 명령으로 제거할 수 있습니다.




[Localization - 다국어 지원]


Localization - 다국어 지원이란?


라라벨은 다국어 기능은 다양한 언어로 문자열로 편리하게 검색할 수 있으며, 애플리케이션내에서 여러 언어를 쉽게 지원할 수 있습니다. 언어 문자열은 "resources/lang" 디렉터리내 파일에 저장됩니다. 해당 디렉터리에는 애플리케이션에서 지원되는 각 언어에 대한 하위 디렉터리가 있어야 합니다.


/resources
    /lang
        /en
            messages.php
        /es
            messages.php

모든 언어 파일은 단순히 키가 있는 문자열의 배열로 아래와 같이 반환합니다


<?php

return [
    'welcome' => 'Welcome to our application'
];



Configuring The Locale - Locale 구성 변경하기


애플리케이션의 기본 언어는 "config/app.php" 설정파일에 저장됩니다. 물론 애플리케이션의 필요에 따라 해당 값을 변경할 수 있습니다. "App" 파사드의 "setLocale" 메소드를 사용하여 런타임에 활성화될 언어를 변경할 수 있습니다.


Route::get('welcome/{locale}', function ($locale) {
    App::setLocale($locale);

    //
});

지정되어 활성화된 언어 문자열이 존재하지 않을 경우 사용할 수 있는 "대체 언어"를 구성할 수 있습니다. 기본 언어와 마찬가지로 대체 언어도 "config/app.php" 설정파일에서 구성할 수 있습니다.


'fallback_locale' => 'en',



Determinig The Current Locale - 현재 로케일 설정


"App" 파사드에서 "getLocale" 및 "isLocale" 메소드를 사용하여 현재 로케일을 결정하거나 로케일이 주어진 값인지 확인할 수 있습니다.


$locale = App::getLocale();

if (App::isLocale('en')) {
    //
}



Retrieving Language Lines - 다국어 언어 가져오기


"trans" 도우미 헬퍼 함수를 사용하여 언어 파일에서 다국어파일을 검색할 수 있습니다.
"trans" 메소드는 첫 번째 인수로 언어 행의 파일과 키를 받습니다. 예를 들면 "resources/lang/messages.php" 언어 파일에서 "welcom"에 해당하는 다국어 언어 값을 찾을 수 있습니다.


echo trans('messages.welcome');

물론 블레이드 템플릿 엔진을 사용할 경우 "{{ }}" 구문을 사용하거나 "@lang" 지시문을 사용할 수 있습니다.


{{ trans('messages.welcome') }}

@lang('messages.welcome')

지정된 다국어 언어 행이 존재 하지 않으면 "trans" 함수는 단순히 다국어 키를 반환합니다. 따라서 위의 예를 사용하면 언어 행이 존재하지 않으면 "trans" 함수가 "messages.welcome"을 반환합니다.



Replacing Parameters In Language Lines - 다국어 언어 일부 교체하기


원하는 경우 다국어에 자리 표시자(place-holders)를 정의할 수 있습니다. 모든 자리 표시자 앞에 ":"가 붙습니다. 예를 들어 자리 표시자 이름으로 "welcome" 메시지를 정의할 수 있습니다.


'welcome' => 'Welcome, :name',

다국어를 검색할 때 자리 표시자를 대체하려면 "trans" 함수의 두 번째 인자로 대체 배열을 전달하면 됩니다.


echo trans('messages.welcome', ['name' => 'dayle']);

자리 표시자에 모두 대문자가 포함되어 있거나, 첫 글자만 대문자인 경우, 변환된 값은 그에 따라 대문자로 표시됩니다.


'welcome' => 'Welcome, :NAME', // Welcome, DAYLE
'goodbye' => 'Goodbye, :Name', // Goodbye, Dayle



Pluralization - 복수화


복수화는 여러 언어가 복수화에 대한 다양한 복잡한 규칙을 가지고 있기 때문에 복잡한 문제입니다.
"pipe" 문자를 사용하여 문자열의 단수형과 복수형을 구별할 수 있습니다.


'apples' => 'There is one apple|There are many apples',

복수화 옵션으로 언어행을 정의한 후 "trans_choice" 메소드를 사용하여 주어진 "count"에 대한 행을 표시할 수 있습니다. 예에서 개수가 1보다 크므로 복수 형식의 언어행이 반환됩니다.


echo trans_choice('messages.apples', 10);

라라벨 "Translator"는 "Symfony Translation" 구성 요소에 의해 구동되므로 여러 숫자 범위에 대한 언어 행을 지정하는 더 복잡한 복수화 규칙을 만들 수 있습니다.


'apples' => '{0} There are none|[1,19] There are some|[20,Inf] There are many',



Overriding Package Language Files - 패키지의 언어 파일 재정의


일부 패키지는 자체 언어 파일과 함께 제공될 수 있습니다. 패키지의 핵심 파일을 변경하여 이러한 줄을 조정하는 대신 "resources/lang/verdor/{package}/{locale}" 디렉터리에 파일을 배치하여 재정의할 수 있습니다.


예를 들어 "skyrim/hearthfire" 패키지의 영어 "messages.php" 다국어 메시지들을 변경할 필요가 있다면 "resources/lang/vendor/en/hearthfire/en/messages.php" 언어 파일을 추가하면 됩니다. 해당 파일에서 재정의하고자 하는 언어 라인을 지정하면 됩니다. 재정의하지 않은 다국어 메시지들은 패키지 언어 파일의 정의 그대로 따릅니다.




View 새로운 파일 생성하여 실습하기


Route::get('/', function () {
    return view('index_page', ['name' => 'DongDongE']);
});

routes/web.php


위 코드에서 웹 루트디렉터리에 접속시 "index_page"의 뷰 파일을 불러와 사용자 브라우저에 출력해보도록 하겠습니다.


<h1>index 페이지 입니다. <h1>
나의 이름은 {{ $name }} 입니다.

resources/views/index_page.blade.php


위 파일을 새로 생성하여 코드를 붙여 넣어 주십시오. 해당 코드는 라우트에서 뷰 파일로 "name" 변수에 "DongDongE" 인자를 배열에 담아 보내 View에서 해당 변수를 출력할 수 있는 로직입니다.


위와 같이 "view" 메소드에 배열로 인자를 담아 보내도 되지만 파트 "Passing Data To Views"와 같이 "with" 메소드로 배열 대신 개별 데이터를 전달할 수 있습니다.


Route::get('/', function () {
    return view('index_page')->with('name', 'DongD@ngE');
});

만약 여러개의 데이터일 경우는 배열로 넘겨주는 방식이 편합니다.




블레이드 실습해보기


이번 블레이드 실습은 위 파트 블레이드 부분에 자세히 설명되어 있어 설명을 기반으로 응용을 해보도록 하겠습니다.


Route::get('/', function () {
   $names = ['Scarlett Sipes', 'Leannon', 'Larkin', 'Alf Mohr', 'Keebler'];

   return view('index_page', ['names' => $names]);
});

routes/web.php


"$names" 변수에는 배열에 5명의 이름을 담아 view 메소드로 "names" 변수에 전달하였습니다. 전달된 인자를 view에서 사용자 브라우저로 출력할 수 있도록 해보겠습니다.


@foreach ($names as $name)
   {{ $name }} 
   <br>
@endforeach

resources/views/index_page.blade.php


전달되는 값은 배열이므로 "@for", "@white" 대신 "@foreach" 메소드로 하나씩 이름을 출력할 수 있도록 로직을 구현하였습니다. 블레이드 문법상 편하게 HTML 언어를 사용하고 PHP 문법은 "@로직명"으로 처리할 수 있습니다.

사용자 브라우저 아래와 같이 출력이 됩니다.


Scarlett Sipes
Leannon
Larkin
Alf Mohr
Keebler

또는 아래와 같이 "$loop" 변수의 도움을 받아 로직을 재미있게 처리할 수 있습니다. 위 블레이드 파트 부분에서 보다 자세하게 설명되여 구체적인 설명은 생략합니다.


@foreach ($names as $name)
    @if($loop->first)
        첫번째 - {{ $name }}<br>
        @continue;
    @endif
    
    @if($loop->last)
        마지막 - {{ $name }} <br>
        @continue;
    @endif
    
    {{ $name }} 
    <br>
@endforeach

출력 결과는 아래와 같습니다.


첫번째 - Scarlett Sipes
Leannon
Larkin
Alf Mohr
마지막 - Keebler

만약 부트스트랩 테마를 사용하여 템플릿 구간을 나누어(Head, Body, Footer) 사용시 유용합니다. 아래 예제로 설명을 드리겠습니다.


Route::get('/', function () {
    return view('index_page')->with('title', 'MyPages'); 
});

routes/web.php


웹 루트 디렉터리에 접근시 라우트는 "index_page.blade.php" 페이지의 뷰를 호출할 수 있도록 로직을 구현하였습니다. 그리고 "title" 변수에는 페이지 제목을 알리는 "MyPages" 값을 넣어 전달 하였습니다.


<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @yield("content")
    </body>
</html>

resources/views/index_template.balde.php


위 코드는 템플릿될 뼈대입니다. 예를 들어 "회원가입", "로그인" 페이지에서는 같은 헤더와 푸더를 사용하고 중간 "<body>" 부분만 다르게 표시함으로 위와 같이 중복되는 부분은 뼈대를 템플릿으로 만들어 설정할 수 있습니다.


@extends('index_template')

@section('title', $title)

@section('content')
    콘텐츠입니다.
@endsection

resources/views/index_page.balde.php


위 코드는 "index_template.balde.php" 템플릿을 "extends" 지시문으로 가져와 "section" 지시문을 통하여 각각 맞는 섹션에 값을 전달하여 표시 합니다.


<html>
    <head>
        <title>App Name - MyPages</title>
    </head>
    <body>
            콘텐츠입니다.
    </body>
</html>

위 코드와 같이 사용자 브라우저에 표시됩니다. 기존 MVC 패턴 라라벨을 이용하지 않고 PHP 코드로 사용한다면 대부분 부트스트랩 템플릿을 "include" 또는 "require_once" 메소드를 사용하여 해당 PHP 코드를 가져오게 됩니다.
그러면 오버헤드와 함께 PHP 엔진에서 실행 되지만 라라벨의 블레이드 엔진을 사용하여 PHP 코드 부분, 블레이드 문법 부분, HTMl 코드 부분 나누어 실행되므로 더 더욱 적은 오버헤드와 편리하게 관리할 수 있습니다.