이 페이지에서 달성할 것
패키지의 메시지를 여러 언어로 배포하고, 이를 사용하는 애플리케이션이 필요한 문구만 변경할 수 있도록 합니다. 번역 키와 플레이스홀더를 공개 API로 다루고, 패키지 업데이트 시 커스터마이즈를 유지하는 방법까지 정리합니다. 로컬라이제이션은 애플리케이션에서의 기본 조작을, Laravel 패키지 개발은 등록과 공개의 기초를 다룹니다. 이 페이지에서는 Laravel 13의ServiceProvider, FileLoader, Translator 구현을 깊이 살펴봅니다.
loadTranslationsFrom()은 로드 위치의 등록이고, publishes()는 파일 복사 대상의 등록입니다. 번역을 사용하기 위해 사용자가 반드시 vendor:publish를 실행할 필요는 없습니다.PHP 번역을 네임스페이스와 함께 배포하기
패키지 전용 키를 갖고 싶다면 PHP 배열 형식과 네임스페이스를 사용합니다. 다음은Acme\Courier라는 패키지의 예입니다.
lang/ja/messages.php에 일본어 기본값을 준비합니다.
lang/en/messages.php에 폴백용 영어도 준비합니다.
boot()에서 로드와 선택적인 공개를 등록합니다.
ja를 사용합니다. 이 문서 사이트의 URL에 사용하는 jp와는 별개입니다.
courier는 loadTranslationsFrom()의 두 번째 인수입니다. Composer 패키지 이름에서 자동으로 결정되는 것이 아닙니다.
PHP 번역은 파일 전체를 대체하지 않는다
사용하는 애플리케이션에서는 표준 언어 디렉터리라면lang/vendor/courier/ja/messages.php에 변경할 키만 작성할 수 있습니다. 언어 디렉터리를 변경한 경우에도 $this->app->langPath('vendor/courier') 아래를 사용합니다.
queued만 바뀌고, failed는 패키지의 일본어 번역을 사용합니다.
FileLoader의 로드 순서
ServiceProvider::loadTranslationsFrom()은 Translator가 해결된 후에 네임스페이스를 등록합니다. 실제 파일 읽기는 번역이 요청될 때 이루어집니다.
FileLoader::loadNamespaced()는 등록된 패키지의 언어 파일을 읽고, 그 배열을 loadNamespaceOverrides()에 전달합니다. 여기서 로더의 각 언어 경로에 있는 vendor/{namespace}/{locale}/{group}.php를 읽어 array_replace_recursive()로 치환합니다.
표준 TranslationServiceProvider는 프레임워크의 언어 경로와 애플리케이션의 언어 경로를 이 순서로 로더에 전달합니다. 추가 경로를 등록하는 확장이 있는 경우에도, 나중에 읽는 덮어쓰기 배열이 같은 키에서 우선합니다.
JSON 번역은 패키지 전용 네임스페이스를 갖지 않는다
문장을 키로 사용하는 JSON 번역은 다음과 같이 디렉터리를 등록합니다. 이는 앞의 PHP 번역과는 별개의 선택지입니다.lang/ja.json 예입니다.
loadJsonTranslationsFrom()에는 네임스페이스 인수가 없습니다. 등록된 JSON 번역은 다른 패키지나 애플리케이션과 같은 키 공간을 공유합니다.
JSON의 덮어쓰기 위치는 애플리케이션의 ja.json
FileLoader::loadJsonPaths()는 등록된 JSON 경로를 먼저, 그 후에 일반 언어 경로를 읽어 array_merge()합니다. 표준 구성에서는 애플리케이션의 lang/ja.json에 있는 같은 문자열 키가 패키지의 값을 덮어씁니다.
- 패키지 간에 같은 문자열 키를 사용하면 나중에 읽는 JSON의 값이 우선합니다. 프로바이더 순서에 의존하는 설계는 피합니다.
lang/vendor/courier/ja.json은 표준 JSON 로더의 덮어쓰기 위치가 아닙니다. PHP용 공개 설정을 그대로 JSON에 재사용해도 이 위치는 자동으로 읽히지 않습니다.- 애플리케이션의
lang/ja.json으로 패키지의 JSON을publishes()해도 파일 내용은 병합되지 않습니다. 기존 번역을 깨뜨리지 않도록, 필요한 키만 사용자가 추가하는 절차를 안내합니다.
Translator::get()은 JSON의 완전 일치 키를 먼저 조사하므로, JSON에 courier::messages.delivery.queued 같은 키를 정의하면 PHP 측보다 우선합니다. 일반적으로 문장 키와 PHP 형식 키를 혼용하지 않는 방침으로 합니다.
공개된 번역을 깨뜨리지 않고 업데이트하기
PHP 번역을 일괄 공개하고 싶은 사용자에게는 대상을 좁힌 명령어를 안내할 수 있습니다.- 키와 네임스페이스를 유지한다 — 키의 삭제·이동은 사용자의
__()호출과 덮어쓰기 위치에 영향을 줍니다. 새 키를 추가하고 이전 키를 남겨 두는 이행 기간을 검토합니다. - 플레이스홀더를 유지한다 —
:name을:recipient로 바꾸면 호출 측의 치환 배열도 변경이 필요합니다. 번역 파일만의 수정으로 생각하지 않도록 합니다. - 공개된 파일의 차이를 확인한다 — 사용자의 덮어쓰기와 새 기본값을 비교합니다. 불필요해진 덮어쓰기 키를 삭제하면 패키지의 값으로 되돌릴 수 있습니다.
- 무조건적인 재공개를 피한다 —
--force에 의한 재공개는 사용자의 커스터마이즈를 덮어씁니다. JSON을 애플리케이션의 파일로 복사하는 설계에서는 다른 번역까지 잃을 가능성이 있습니다. - 상주 프로세스에서 확인한다 —
Translator::load()는 네임스페이스·그룹·언어별 배열을 인스턴스 내에 보관합니다. 이미 로드된 Translator가 남아 있는 프로세스에서는 파일 변경만으로 다시 로드된다고 단정할 수 없습니다. 운용에 따라 워커 등을 재시작합니다.
사용하는 애플리케이션에서 확인할 항목
서비스 프로바이더를 등록한 검증용 애플리케이션에서 다음 조합을 확인합니다. 패키지 내 테스트 환경 구축은 패키지 테스트를 참조하세요.
로드 후에 덮어쓰기 파일을 만드는 테스트에서는 Translator의 기존 로드 결과가 영향을 주지 않도록 합니다. 파일을 먼저 준비한 다음 가져오거나, 케이스마다 새 애플리케이션 인스턴스를 사용해 확인합니다.
참조한 1차 자료
공식 문서는 최신 기본 브랜치13.x, 내부 구현은 참조 시점의 최신 릴리스 v13.35.0을 확인했습니다.