Laravel langsys/langsys-php-laravel
langsys/langsys-php 위에 얹은 얇은 Laravel 바인딩으로, @t Blade 지시문, t() 헬퍼, 로케일 미들웨어를 제공합니다. 코드에 작성한 문구가 조회 키이자 기본 언어 기본값 역할을 하므로 키 파일도, 추출 단계도 필요 없습니다. 번역은 서버에서 이루어지므로 페이지가 이미 현지화된 상태로 전달됩니다.
백엔드 SDK이므로 이 페이지에는 브라우저 내 플레이그라운드가 없습니다. 브라우저에서는 PHP를 실행할 수 없기 때문입니다. 데모 앱은 아래 모든 예제를 직접 실행해 볼 수 있는 라이브 버전입니다. 클론한 뒤 php artisan serve를 실행하거나, 설치부터 서비스까지 알아서 처리해 주는 실제 PHP 컨테이너인 Codespace에서 열어 보세요. 자동 페이지 번역과 Inertia 시딩을 포함한 전체 패키지 레퍼런스는 Laravel SDK 문서에서 확인할 수 있습니다.
AI 코딩 에이전트를 사용 중이신가요? 이 프롬프트를 전달해 보세요
Add Langsys translation to this Laravel app.
1. Read https://docs.langsys.dev/llms.txt, then follow
https://docs.langsys.dev/learn/sdk/laravel/ for the install and setup.
2. The English text in the code is the translation key. Wrap user-facing
strings as they are: no keys file, no extraction step, and no
hand-written plural or gender branches (Langsys generates those).
3. Read the Langsys project id and API key from environment variables.
The write key is for development and servers only; anything shipped
to the browser gets the read-only key.
4. Keep brand names and user-generated content out of translation. 설치
composer require langsys/langsys-php-laravel
php artisan vendor:publish --tag=langsys-config # The server can hold a WRITE key — unlike a browser app, it's never
# shipped to visitors. A write key is what lets new phrases register.
LANGSYS_API_KEY=your-api-key
LANGSYS_PROJECT_ID=your-project-id 아직 프로젝트나 키가 없으신가요? 빠른 시작으로 2분이면 둘 다 준비할 수 있습니다.
미들웨어
두 개의 미들웨어가 프레임워크 관련 작업을 처리합니다. DetectLocale은 방문자의 로케일(쿼리 매개변수, 쿠키, 세션, 그다음 Accept-Language)을 판별하고 선택 내용을 유지하며, FlushPendingRegistrations는 응답이 전송된 후에 새로 발견된 문구를 Langsys로 보내므로 등록 작업이 페이지 속도를 늦추지 않습니다.
// bootstrap/app.php (Laravel 11/12)
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
// Resolves ?locale= / cookie / session / Accept-Language,
// then persists the visitor's choice.
\Langsys\Laravel\Http\Middleware\DetectLocale::class,
// After the response is sent, registers any phrases
// rendered for the first time.
\Langsys\Laravel\Http\Middleware\FlushPendingRegistrations::class,
]);
}) Blade에서 번역하기
디렉티브는 하나뿐입니다: @t(phrase, category?, params?, locale?). 매개변수는 {name} 마커로 삽입되며, 숫자와 날짜는 로케일에 맞게 서식이 적용되고 출력은 HTML 이스케이프 처리됩니다.
<h1>@t('Welcome to our store', 'Home')</h1>
<p>@t('Hello, {name}! You have {count} new messages.', 'Greetings',
['name' => $name, 'count' => $count])</p> PHP의 어디에서나
@t는 이스케이프 처리가 추가된 t() 헬퍼일 뿐이며, 헬퍼 자체는 컨트롤러, Livewire 컴포넌트, 잡, 메일, 유효성 검사 메시지 등 어디에서나 사용할 수 있습니다.
// Controllers, Livewire components, jobs, mail — anywhere:
$title = t('Order confirmed', 'Checkout');
$body = t('Your order {id} ships on {date}.', 'Checkout', [
'id' => (string) $order->number, // strings skip number formatting
'date' => $order->ships_at, // DateTime → locale-formatted
]); 복수형
문장은 단순하게 작성하세요. Langsys는 번역 과정에서 기준 로케일을 포함한 각 로케일의 복수형을 생성하며, SDK는 개수에 맞는 분기를 렌더링합니다(ext-intl를 통한 전체 ICU 지원). 모든 SDK에서 동일하므로 백엔드와 프론트엔드 간에 문구를 그대로 재사용할 수 있습니다.
// Written flat. Langsys generates each locale's plural forms during
// translation (the base locale included) and the SDK picks the branch.
t('You have {count} items in your cart', 'Cart', ['count' => $count]); Langsys가 생성하는 복수형은 langsys/langsys-php 1.3.2부터 PHP에 적용됩니다. 이전 버전에서는 1을 포함한 모든 수량에 복수형이 표시됩니다.
성 일치
스페인어, 프랑스어, 러시아어는 {username} has been invited을(를) 대상 인물에 맞춰 활용합니다. Langsys는 복수형을 생성하는 것과 같은 방식으로 번역 중에 이러한 분기를 생성하며, 인수 이름은 변수 이름 뒤에 _gender를 붙인 형태이고 값은 male, female, other 중 하나입니다. 알고 있다면 항상 전달하세요. 작동 방식과 이 값이 필요한 문구를 찾는 방법 →
{{-- Pass the agreement argument alongside the value it inflects. --}}
@t('{username} has been invited', 'Team', [
'username' => $post->author->name,
'username_gender' => $post->author->gender, // 'male' | 'female' | 'other'
]) 성별을 모르시나요? 'other'를 명시적으로 전달하세요. 중립 분기입니다. 전달하지 않더라도 기본 SDK가 자동으로 other 분기를 사용하므로(langsys/langsys-php 1.3.1 이상, ext-intl 유무와 관계없음) 문장이 올바르게 표시됩니다.
카테고리
카테고리가 문구의 범위를 정하므로, 같은 문장이라도 맥락에 따라 다르게 번역될 수 있습니다.
{{-- Same word, two meanings — the category disambiguates. --}}
<strong>@t('Home', 'Main Menu')</strong> {{-- "Inicio" --}}
<strong>@t('Home', 'Home repairs')</strong> {{-- "Casa" --}} 마커 스타일은 하나입니다: {name}. JS SDK에서는 중괄호 하나가 JSX 및 Vue 템플릿 구문과 충돌하기 때문에 markup 매개변수에 %name%을 사용합니다. Blade에서는 이런 충돌이 없으므로 PHP 환경에서는 어디서나 표준 형식인 {name}을 사용합니다. 이는 모든 SDK에서 t()가 사용하는 형식과 같습니다.
어떤 것을 사용해야 하나요?
| 번역 중입니다… | 사용 | 이유 |
|---|---|---|
| Blade 템플릿의 텍스트입니다. | @t(...) | t() 헬퍼에 HTML 이스케이프가 더해져 템플릿에 바로 출력해도 안전합니다. |
| 컨트롤러, Livewire, 잡, 메일 등 그 외 어느 곳에 있는 문자열이든 가능합니다. | t() | 매개변수가 삽입되고 ICU 복수형이 처리된 일반 문자열을 반환합니다. |
| 절대 번역되면 안 되는 내용 — 브랜드명, 코드, ID. | 감싸지 않고 그대로 두기 | 적용 범위는 명시적입니다. 사용자가 감싼 문자열만 번역되며, 태그되지 않은 출력은 그대로 전달됩니다. |
| 이미 문자열로 가지고 있는 전체 HTML 문서. | Langsys::client()->translatePage() | 원시 PHP SDK의 전체 페이지 파이프라인으로 전환하여 제목, 메타, 본문 텍스트를 한 번의 호출로 처리합니다. |
기본 원칙: Blade → @t · PHP → t() · 건드릴 수 없는 것 → 감싸지 마세요.
서버에서 토큰 탐색
Langsys가 아직 본 적 없는 문구를 렌더링하면 대기열에 추가되었다가 응답이 종료된 후 등록됩니다. 방문자에게는 기본 언어 텍스트가 즉시 표시되고, 해당 문구는 번역할 준비가 된 상태로 대시보드에 나타납니다. 이 기능에는 쓰기 키가 필요하며, 읽기 전용 키에서는 대기열 등록이 조용히 건너뛰어집니다. 카탈로그가 변경되어서는 안 되는 환경에서는 바로 이 동작이 필요합니다.
JS SDK와 함께 사용하기
Inertia나 하이브리드 앱을 사용하시나요? 서버가 이미 가져온 카탈로그를 JS SDK에 전달하면 클라이언트가 다시 가져오지 않아도 됩니다. 프런트엔드 SDK 페이지에서 설명하는 initialTranslations 전달 방식과 동일합니다.
// app/Http/Middleware/HandleInertiaRequests.php
use Langsys\Laravel\Support\InertiaSsrProps;
public function share(Request $request): array
{
return [...parent::share($request), ...InertiaSsrProps::share()];
} // resources/js — Vue shown; same shape for React/Svelte
import { LangsysApp, useLocaleStore } from 'langsys-js-vue';
const { store } = useLocaleStore(props.langsys.initialTranslationsLocale);
LangsysApp.init({
projectid: import.meta.env.VITE_LANGSYS_PROJECT_ID,
key: import.meta.env.VITE_LANGSYS_API_KEY, // read-only key on the client
UserLocaleStore: store,
initialTranslations: props.langsys.initialTranslations,
initialTranslationsLocale: props.langsys.initialTranslationsLocale,
}); 파사드와 원시 클라이언트
Langsys 파사드는 t()를 그대로 반영하며, Langsys::client()는 문구 조회 이외의 모든 작업(카탈로그 읽기, 캐시 제어, 콘텐츠 블록)을 위해 내부의 langsys/langsys-php 클라이언트를 제공합니다.
use Langsys\Laravel\Facades\Langsys;
Langsys::translate('Save', 'UI'); // same seam as t()
Langsys::client()->getTranslations('es-es'); // the vanilla langsys/langsys-php client
Langsys::client()->clearCache('es-es'); // pick up dashboard edits before the TTL