메인 콘텐츠로 건너뛰기

로컬라이제이션이란

Laravel의 로컬라이제이션 기능은 여러 언어로 번역 문자열을 취득하는 편리한 구조를 제공합니다. 애플리케이션 내에서 여러 언어를 지원하기 위해 사용합니다. 번역 문자열의 관리 방법은 2종류가 있습니다.
방법특징
PHP 파일 형식lang/ja/messages.php와 같은 키·값 배열. 밸리데이션 에러 등 기능별로 정리하고 싶은 경우에 적합
JSON 형식lang/ja.json에 번역 문자열을 그대로 키로 정의. 번역 대상이 많은 애플리케이션에 권장
기본 Laravel 애플리케이션에는 lang 디렉터리가 포함되어 있지 않습니다. 커스터마이즈하려면 lang:publish Artisan 명령어로 공개합니다.
php artisan lang:publish

로케일의 설정

기본 로케일

애플리케이션의 기본 언어는 config/app.phplocale로 설정합니다. 일반적으로는 .env 파일의 APP_LOCALE 환경 변수를 사용합니다.
// config/app.php
'locale' => env('APP_LOCALE', 'en'),
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
# .env
APP_LOCALE=ja
APP_FALLBACK_LOCALE=en
fallback_locale은 지정한 언어에 번역 문자열이 존재하지 않는 경우의 폴백 언어입니다.

실행 시의 로케일 변경

App 파사드의 setLocale() 메서드로 요청 단위로 로케일을 변경할 수 있습니다.
use Illuminate\Support\Facades\App;

Route::get('/greeting/{locale}', function (string $locale) {
    if (! in_array($locale, ['en', 'ja', 'fr'])) {
        abort(400);
    }

    App::setLocale($locale);

    // ...
});

현재의 로케일 확인

use Illuminate\Support\Facades\App;

$locale = App::currentLocale();

if (App::isLocale('ja')) {
    // 일본어의 경우의 처리
}

언어 파일의 작성

PHP 파일 형식

lang/{언어 코드}/ 디렉터리에 PHP 파일을 작성합니다. 키·값 형식의 배열을 반환합니다.
/lang
    /en
        messages.php
    /ja
        messages.php
<?php

// lang/ja/messages.php

return [
    'welcome' => '애플리케이션에 오신 것을 환영합니다!',
    'goodbye' => '또 만나요!',
];
지역 차이가 있는 언어는 ISO 15897에 따라 디렉터리 이름을 붙입니다. 예를 들어 영국 영어는 en-gb가 아닌 en_GB입니다.

JSON 형식

번역할 문자열이 많은 경우 JSON 형식이 권장됩니다. lang/ 디렉터리에 언어 코드 이름의 JSON 파일을 작성합니다.
/lang
    en.json
    ja.json
기본 번역 문자열(영어)을 키로 정의합니다.
{
    "Welcome to our application!": "애플리케이션에 오신 것을 환영합니다!",
    "I love programming.": "프로그래밍을 정말 좋아합니다.",
    "Logout": "로그아웃",
    "Dashboard": "대시보드"
}
JSON 형식에서는 영어 문장 그 자체가 키가 되기 때문에 영어의 기본 표시가 자동으로 기능합니다. 번역 파일이 없는 언어에서는 키(영어 원문)가 그대로 표시됩니다.

PHP 파일 형식과 JSON 형식의 사용 구분

  • 밸리데이션 에러 메시지 등 기능별로 정리하고 싶은 경우
  • Laravel의 내장 번역(validation.php, auth.php 등)을 덮어쓰는 경우
  • 계층적인 키 관리가 필요한 경우
// lang/ja/validation.php
return [
    'required' => ':attribute은(는) 필수입니다.',
    'email' => ':attribute은(는) 유효한 이메일 주소여야 합니다.',
];
  • UI의 문구가 많고 키를 생각하는 것이 번거로운 경우
  • 템플릿에 영어를 그대로 써 두고, 다른 언어는 번역 파일로 대응하는 경우
  • 국제화 대응이 나중에 추가된 애플리케이션
{{-- Blade 템플릿에 영어를 그대로 씀 --}}
{{ __('Welcome to our application!') }}

번역 문자열의 취득

__() 헬퍼

가장 자주 사용하는 방법입니다. PHP 파일 형식에서는 “파일명.키” 형식으로 지정합니다.
// PHP 파일 형식: lang/ja/messages.php 의 'welcome' 키
echo __('messages.welcome');
// => 애플리케이션에 오신 것을 환영합니다!

// JSON 형식: 키에 번역 원본의 문자열을 그대로 지정
echo __('I love programming.');
// => 프로그래밍을 정말 좋아합니다.
번역 문자열이 존재하지 않는 경우, 지정한 키가 그대로 반환됩니다.
echo __('messages.not_exists');
// => messages.not_exists(키가 그대로 반환됨)

Blade 템플릿에서의 사용

Blade 템플릿에서는 {{ __() }}를 사용합니다.
{{-- PHP 파일 형식 --}}
<h1>{{ __('messages.welcome') }}</h1>

{{-- JSON 형식 --}}
<button>{{ __('Logout') }}</button>

{{-- @lang 디렉티브(비권장·후방 호환을 위해 남아 있음) --}}
@lang('messages.welcome')
@lang 디렉티브는 비권장입니다. 현재는 {{ __() }}를 사용하는 것이 권장됩니다.

플레이스홀더

번역 문자열에 :이름 형식의 플레이스홀더를 매입할 수 있습니다.
// lang/ja/messages.php
return [
    'welcome' => '어서오세요, :name님!',
    'greet'   => '안녕하세요, :Name님!',  // 최초의 문자를 대문자로
    'shout'   => 'HEY :NAME!',              // 전부 대문자로
];
__()의 두 번째 인수에 치환값의 배열을 전달합니다.
echo __('messages.welcome', ['name' => '田中']);
// => 어서오세요, 田中님!

echo __('messages.greet', ['name' => 'taro']);
// => 안녕하세요, Taro님!(Name 은 선두 대문자)

echo __('messages.shout', ['name' => 'taro']);
// => HEY TARO!(NAME 은 전부 대문자)
Blade 템플릿에서도 동일하게 사용할 수 있습니다.
<p>{{ __('messages.welcome', ['name' => $user->name]) }}</p>

복수형

언어에 따라 복수형의 룰이 다릅니다. Laravel은 | 기호로 단수형과 복수형을 전환할 수 있습니다.

기본적인 복수형

// lang/ja/messages.php
return [
    'apples' => '사과가 1개 있습니다|사과가 여러 개 있습니다',
];
JSON 형식에서도 동일하게 정의할 수 있습니다.
{
    "There is one apple|There are many apples": "사과가 1개 있습니다|사과가 여러 개 있습니다"
}
trans_choice() 함수에 수량을 전달해 취득합니다.
echo trans_choice('messages.apples', 1);
// => 사과가 1개 있습니다

echo trans_choice('messages.apples', 5);
// => 사과가 여러 개 있습니다

범위를 지정한 복수형

보다 상세한 범위 지정이 가능합니다.
'apples' => '{0} 사과가 없습니다|[1,19] 몇 개의 사과가 있습니다|[20,*] 많은 사과가 있습니다',
echo trans_choice('messages.apples', 0);
// => 사과가 없습니다

echo trans_choice('messages.apples', 10);
// => 몇 개의 사과가 있습니다

echo trans_choice('messages.apples', 50);
// => 많은 사과가 있습니다

복수형에서의 플레이스홀더

:count로 수량을 표시할 수 있습니다. 세 번째 인수로 추가의 치환값을 전달할 수 있습니다.
// lang/ja/messages.php
return [
    'minutes_ago' => '{1} :value분 전|[2,*] :value분 전',
    'items'       => ':count건의 아이템이 있습니다',
];
echo trans_choice('messages.minutes_ago', 5, ['value' => 5]);
// => 5분 전

echo trans_choice('messages.items', 3);
// => 3건의 아이템이 있습니다

패키지의 언어 파일을 오버라이드

서드파티 패키지가 독자적인 언어 파일을 가지고 있는 경우, lang/vendor/{패키지명}/{언어 코드}/에 같은 이름의 파일을 놓음으로써 덮어쓸 수 있습니다. 예를 들어 skyrim/hearthfire 패키지의 영어 메시지를 커스터마이즈하려면.
lang/
└── vendor/
    └── hearthfire/
        └── en/
            └── messages.php
// lang/vendor/hearthfire/en/messages.php
return [
    'welcome' => '커스터마이즈한 메시지',
    // 덮어쓰고 싶은 키만 정의. 다른 키는 원래 파일에서 읽어 들여짐
];

실전 예시: 한영 전환 미들웨어

URL 경로나 세션, 사용자 설정에 기반해 로케일을 자동 전환하는 미들웨어의 구현 예시입니다.
1

미들웨어 작성

php artisan make:middleware SetLocale
2

미들웨어 구현

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Symfony\Component\HttpFoundation\Response;

class SetLocale
{
    public function handle(Request $request, Closure $next): Response
    {
        // 지원할 로케일 목록
        $supportedLocales = ['ja', 'en'];

        // 세션에 로케일이 저장되어 있다면 그것을 사용
        $locale = $request->session()->get('locale');

        // 세션에 없다면 브라우저의 Accept-Language 를 참조
        if (! $locale) {
            $browserLocale = substr($request->getPreferredLanguage($supportedLocales) ?? 'ja', 0, 2);
            $locale = in_array($browserLocale, $supportedLocales) ? $browserLocale : 'ja';
        }

        App::setLocale($locale);

        return $next($request);
    }
}
3

미들웨어 등록

bootstrap/app.php에서 미들웨어를 등록합니다.
use App\Http\Middleware\SetLocale;

->withMiddleware(function (Middleware $middleware) {
    $middleware->append(SetLocale::class);
})
4

로케일 전환 라우트 추가

// routes/web.php
Route::post('/locale/{locale}', function (string $locale) {
    if (! in_array($locale, ['ja', 'en'])) {
        abort(400);
    }

    session(['locale' => $locale]);

    return back();
})->name('locale.switch');
5

Blade 템플릿에 전환 버튼 추가

<div>
    <form method="POST" action="{{ route('locale.switch', 'ja') }}">
        @csrf
        <button type="submit">일본어</button>
    </form>

    <form method="POST" action="{{ route('locale.switch', 'en') }}">
        @csrf
        <button type="submit">English</button>
    </form>
</div>

번역 파일의 구성 예시

lang/
├── ja.json          # JSON 형식(UI 문구)
├── en.json
├── ja/
│   └── validation.php   # PHP 파일 형식(밸리데이션)
└── en/
    └── validation.php
// lang/ja.json
{
    "Dashboard": "대시보드",
    "Login": "로그인",
    "Logout": "로그아웃",
    "Welcome, :name!": "어서오세요, :name님!",
    "Save": "저장",
    "Cancel": "취소",
    "Are you sure?": "정말 괜찮으십니까?"
}
{{-- resources/views/layouts/app.blade.php --}}
<nav>
    <a href="{{ route('dashboard') }}">{{ __('Dashboard') }}</a>
    <span>{{ __('Welcome, :name!', ['name' => auth()->user()->name]) }}</span>

    <form method="POST" action="{{ route('logout') }}">
        @csrf
        <button type="submit">{{ __('Logout') }}</button>
    </form>
</nav>

정리

방법파일 경로키의 예시취득 방법
PHP 파일lang/ja/messages.php'welcome' => '...'__('messages.welcome')
JSONlang/ja.json"Welcome": "..."__('Welcome')
함수·메서드용도
__('key')번역 문자열을 취득하는 헬퍼
trans('key')__() 와 동등한 헬퍼
trans_choice('key', $count)복수형 대응의 번역 문자열을 취득
App::setLocale('ja')요청 단위로 로케일을 변경
App::currentLocale()현재의 로케일을 취득
App::isLocale('ja')현재의 로케일을 확인
{{-- 기본 --}}
{{ __('messages.welcome') }}

{{-- 플레이스홀더 있음 --}}
{{ __('messages.welcome', ['name' => $user->name]) }}

{{-- 복수형 --}}
{{ trans_choice('messages.apples', $count) }}
마지막 수정일 2026년 7월 13일