Skip to main content

Laravel i18n: 국제화 및 현지화 완벽 가이드

첫 로케일 파일부터 프로덕션까지, Laravel 번역 시스템을 설정하고 복수형을 처리하며 JSON 폴백 버그를 해결하고 지역 변형을 위한 스마트 로케일 폴백 체인을 추가해 보세요.

1

Laravel 번역 시스템 이해

Laravel에는 PHP 배열과 JSON이라는 두 파일 형식을 지원하는 번역 시스템이 내장되어 있어요. PHP 파일은 기능별로 구성된 중첩 키(auth.failed, validation.required)를 사용해요. JSON 파일은 원본 문자열을 키로 사용하므로 더 간단하지만 중첩은 지원하지 않아요.

Terminal
composer create-project laravel/laravel my-app
cd my-app

# Laravel includes i18n out of the box
# No extra packages needed for basic usage
Laravel 번역 시스템은 lang/ 디렉터리(Laravel 9 이상) 또는 resources/lang/ 디렉터리(Laravel 8 이하)에 있어요. 프레임워크가 디렉터리를 자동으로 감지해요. 둘 다 있으면 lang/이 우선해요.
2

로케일 설정 구성

config/app.php에서 애플리케이션의 기본 로케일과 폴백 로케일을 설정하세요. 활성 로케일에 번역 키가 없으면 폴백 로케일을 사용해요. 애플리케이션이 지원하는 로케일을 구성하고 사용자가 선호하는 로케일을 감지해 설정하는 미들웨어를 추가하세요.

config/app.php
// config/app.php
return [
    'locale' => 'en',            // Default locale
    'fallback_locale' => 'en',   // Fallback when key is missing
    'faker_locale' => 'en_US',

    // Available locales (for your language switcher)
    'available_locales' => ['en', 'de', 'ja', 'es', 'fr', 'pt-BR'],
];
app/Http/Middleware/SetLocale.php
// app/Http/Middleware/SetLocale.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class SetLocale
{
    public function handle(Request $request, Closure $next)
    {
        $locale = $request->segment(1); // e.g. /de/about

        if (in_array($locale, config('app.available_locales'))) {
            app()->setLocale($locale);
        }

        return $next($request);
    }
}
3

번역 함수 사용

Laravel은 문자열을 번역하는 세 가지 방법을 제공해요. __() 도우미 함수(권장), trans() 함수, @lang Blade 지시어예요. 세 방식 모두 번역 키와 선택적 대체 매개변수를 받아요. PHP 코드와 Blade 템플릿에서는 __() 도우미를 사용하고 HTML을 이스케이프할 필요가 없는 Blade에서는 @lang을 사용하세요.

lang/en/messages.php
// lang/en/messages.php
return [
    'welcome' => 'Welcome to our application',
    'greeting' => 'Hello, :name!',
    'nav' => [
        'home' => 'Home',
        'about' => 'About',
        'settings' => 'Settings',
    ],
];

// lang/de/messages.php
return [
    'welcome' => 'Willkommen in unserer Anwendung',
    'greeting' => 'Hallo, :name!',
    'nav' => [
        'home' => 'Startseite',
        'about' => 'Über uns',
        'settings' => 'Einstellungen',
    ],
];
새 코드에서는 trans()보다 __() 도우미를 우선 사용하세요. __() 도우미는 PHP와 JSON 번역 파일을 모두 지원하지만 trans()는 PHP 파일만 지원해요. @lang 지시어는 Blade 템플릿의 {'{ __() }'}과 같지만 구문이 조금 더 간결해요.
4

복수형 처리

Laravel은 파이프로 구분한 복수형 구문을 사용해요. 가장 간단한 형식은 'apples' => 'There is one apple|There are many apples'예요. 명시적 범위에는 'apples' => '{0} No apples|{1} One apple|[2,*] :count apples'를 사용하세요. trans_choice() 도우미 또는 Str::plural()이 개수에 따라 올바른 형식을 선택해요.

lang/en.json
// lang/en.json
{
    "Welcome back!": "Welcome back!",
    "You have :count new notifications": "You have :count new notifications",
    "Copyright :year :company": "Copyright :year :company"
}

// lang/de.json
{
    "Welcome back!": "Willkommen zurück!",
    "You have :count new notifications": "Sie haben :count neue Benachrichtigungen",
    "Copyright :year :company": "Copyright :year :company"
}
Laravel의 내장 복수형 처리는 대부분 언어에서 단순한 one/other 규칙만 올바르게 처리해요. 복잡한 복수형이 있는 언어는 필요한 CLDR 복수형 범주를 모두 정의해야 해요. 아랍어에는 6가지, 러시아어에는 4가지, 폴란드어에는 3가지 복수형이 있어요. 그렇지 않으면 사용자에게 문법적으로 잘못된 텍스트가 표시돼요.
5

로케일 폴백 체인 추가

Laravel의 내장 폴백는 활성 로케일에서 fallback_locale로 바로 이동할 뿐 중간 단계가 없어요. pt-BR 사용자는 키가 누락되면 정상적인 pt-PT 번역 대신 영어를 보게 돼요. laravel-locale-chain은 로드 시점에 설정 가능한 폴백 체인의 번역을 딥 머지해 이 문제를 해결해요.

resources/views/example.blade.php
{{-- Simple translation --}}
<h1>{{ __('messages.welcome') }}</h1>

{{-- With variables --}}
<p>{{ __('messages.greeting', ['name' => $user->name]) }}</p>

{{-- Using @lang directive --}}
<h2>@lang('messages.nav.home')</h2>

{{-- JSON translations (use the string itself as key) --}}
<p>{{ __('Welcome back!') }}</p>

{{-- Pluralization --}}
{{ trans_choice('{0} No items|{1} One item|[2,*] :count items', $count) }}

{{-- Inside Blade components --}}
<x-button>{{ __('messages.nav.settings') }}</x-button>
6

번역 자동화

Laravel i18n 설정이 끝나면 AI로 로케일 파일을 번역하세요. AI 어시스턴트에게 원본 로케일 파일의 번역을 요청하거나 CI/CD 파이프라인에서 i18n Agent CLI를 사용하세요. PHP와 JSON 번역 파일을 모두 지원해요.

config/locale-chain.php
// Install locale chain package
composer require i18n-agent/laravel-locale-chain

// config/locale-chain.php
return [
    'chains' => [
        'pt-BR' => ['pt-BR', 'pt', 'en'],
        'zh-Hant-TW' => ['zh-Hant-TW', 'zh-Hant', 'zh', 'en'],
        'es-419' => ['es-419', 'es', 'en'],
    ],
];

// In AppServiceProvider::boot()
use I18nAgent\LocaleChain\LocaleChainServiceProvider;

// The package automatically deep-merges translations
// across the chain: pt-BR -> pt -> en
점진적으로 번역하세요. 새 키를 추가하면 모든 파일을 다시 생성하지 말고 변경분만 번역하세요. 사람이 검토한 번역을 보존하고 불필요한 변경을 피할 수 있어요.

흔한 실수

하드코딩된 단수/복수 로직

trans_choice() 대신 $count == 1 ? 'item' : 'items'를 작성하면 0이 단수인 언어(프랑스어), 복수형이 3가지 이상인 언어(러시아어, 폴란드어), 6가지인 언어(아랍어)에서 동작하지 않아요. 항상 Laravel 복수형 구문을 사용하고 필요한 형식을 모두 정의하세요.

대체되지 않는 JSON 번역

Laravel의 fallback_locale은 PHP 번역 파일에서만 작동해요. JSON 번역은 원본 문자열을 키로 사용하므로 번역이 없으면 폴백 로케일을 찾지 않고 키 자체(영어 텍스트)를 반환해요. 즉 JSON 번역에는 진정한 로케일 폴백 기능이 없어요. laravel-locale-chain으로 해결하세요.

우선순위를 모른 채 PHP와 JSON 혼용

같은 키가 PHP와 JSON 파일에 모두 있으면 PHP가 우선해요. PHP 파일이 JSON 값을 가리기 때문에 JSON 파일을 업데이트해도 효과가 없는 혼란스러운 동작이 생길 수 있어요. 기능 네임스페이스마다 한 형식을 선택해 일관되게 사용하세요.

지금 i18n Agent 사용해 보기

번역 파일을 여기에 드롭

JSON, YAML, PO, XML, CSV, Markdown, Properties

또는 클릭하여 파일 선택

대상 언어

가입 불필요즉시 견적

Laravel i18n FAQ