Payload CMS

업데이트일: 3주 전 · 7분 소요

Payload CMS를 로컬라이제이션 엔진에 연결하고 번역할 collection과 global을 선택하면, Lingo.dev가 해당 localized field를 대상 로캘로 번역한 뒤 각 로캘 아래의 Payload에 다시 써 넣습니다.

로컬라이제이션이 활성화되어 있고 Lexical 리치 텍스트 편집기를 사용하는 Payload 3 프로젝트에서 사용할 수 있습니다. 기존 Slate 편집기는 지원되지 않습니다. 로컬라이즈된 text, textarea, richText 필드가 번역되며, 문서의 나머지 내용은 그대로 유지됩니다.

Payload CMS는 Enterprise 플랜에서 사용할 수 있습니다. Connect 페이지에 Payload CMS is not on your plan이라고 표시되면 문의해 주세요. 바로 도와드리겠습니다.

시작하기 전에#

필요한 것은 세 가지입니다:

  • 로컬라이제이션이 설정된 Payload 3. 소스 로캘과 대상 로캘이 Payload 설정에 있는 로캘과 일치하는지 확인하세요.
  • API 키가 있는 서비스 사용자. auth collection(보통 useAPIKey: true)에서 users을 설정하고, Lingo.dev용 사용자를 만든 뒤 Payload 관리자에서 해당 사용자의 API 키를 생성하세요. 이 사용자에게는 번역하려는 모든 collection과 global에 대한 읽기 및 업데이트 권한이 필요합니다.
  • 로컬라이제이션 엔진. 이 엔진의 glossary, 브랜드 보이스, 규칙이 번역 결과를 좌우합니다.

로캘 코드는 Payload 설정과 정확히 일치해야 합니다

Lingo.dev에서 선택하는 로캘은 localization.locales 아래의 코드와 정확히 일치해야 합니다. Payload에 en와 de가 있다면 **English (United States)**가 아니라 English와 German을 선택하세요. en-US와 en는 서로 다른 로캘입니다. 플러그인이 변경 사항을 감지하는 로캘이므로 Payload의 defaultLocale를 소스 로캘로 사용하세요.

Payload 인스턴스 연결하기#

1

연동 열기

Studio -> All integrations로 이동한 다음, Payload CMS 카드에서 Connect를 클릭하세요.

2

인스턴스 정보 입력

필드입력 내용
주소인스턴스의 루트 URL입니다. 예: https://cms.example.com. HTTPS만 지원합니다
인증 컬렉션서비스 API 키가 속한 컬렉션입니다. 보통 users입니다
API 키서비스 사용자의 API 키
Custom headers선택 사항입니다. 인스턴스로 보내는 모든 요청에 함께 전송됩니다. 항목마다 Add header를 클릭하거나 Name: value 줄을 붙여 넣어 행을 채우세요

Verify instance를 클릭하세요. Lingo.dev가 다음 단계로 넘어가기 전에 이 키가 인스턴스와 일치하는지 확인합니다.

3

번역할 항목 선택하기

설정설명
이름이 연결을 구분할 수 있도록 Production 또는 Staging처럼 인스턴스를 식별할 이름입니다
Collections and Globals번역할 항목을 클릭하세요. 서비스 사용자가 읽기와 업데이트를 할 수 없는 항목은 취소선으로 표시되며, 접근 권한을 얻기 전까지는 선택할 수 없습니다
엔진이 번역에 적용되는 용어집, 규칙, 브랜드 보이스를 사용하는 엔진
소스 로캘편집자가 작성하는 로캘입니다. Payload의 defaultLocale를 사용하세요
대상 로캘번역할 대상 로캘
모드Publish는 게시된 변경 사항만 번역하고 번역도 바로 게시합니다. Draft는 초안 저장도 번역하고 번역을 초안으로 작성합니다. 자세한 내용은 아래의 Drafts와 Published 비교를 참고하세요

Connect를 클릭하세요.

4

플러그인 설치하기

마지막 단계에서 Webhook URL이 표시됩니다. 지금 복사하세요. 한 번만 표시됩니다. Payload 환경에서 이를 LINGO_WEBHOOK_URL로 저장한 다음, 플러그인을 설치하고 구성에 추가하세요:

bash
pnpm add @lingo.dev/payloadcms
ts
import { buildConfig } from "payload";
import { lingo } from "@lingo.dev/payloadcms";

export default buildConfig({
  // ...your collections, globals, and localization config
  plugins: [
    lingo({
      webhookUrl: process.env.LINGO_WEBHOOK_URL,
    }),
  ],
});

Done을 클릭한 다음 Payload를 다시 배포하세요. 이제부터 소스 로캘에서 게시되는 모든 변경 사항이 번역을 위해 Lingo.dev로 전송됩니다.

플러그인이 하는 일

Lingo.dev에 어떤 field가 localized text인지 알려주는 GET /api/lingo/schema 엔드포인트와, document 또는 global이 변경될 때 Lingo.dev에 신호를 보내는 hook이 추가됩니다. 범위, 로캘, 엔진은 대시보드에서 관리하므로 재배포 없이 바꿀 수 있습니다. hook을 건너뛰고 모든 번역을 대시보드에서 직접 시작하려면 webhookUrl를 생략하세요.

번역 대상 선택하기#

연결 페이지에는 Collections, Globals, Workflow runs, Settings의 네 개 탭이 있습니다.

범위는 컬렉션과 글로벌별로 각각 설정됩니다. Collections 탭과 Globals 탭에는 인스턴스에서 제공하는 모든 항목이 한 줄씩 표시되며, 마지막 동기화 시점도 함께 나옵니다. 각 행에는 Sync 스위치가 있습니다. 이 스위치를 켜면 그 시점부터 해당 컬렉션의 모든 문서 또는 해당 글로벌이 범위에 포함됩니다. 변경 사항은 스위치를 전환하는 즉시 저장되며, 다시 배포하지 않아도 다음 실행에 적용됩니다. 표 헤더의 스위치로 목록의 모든 항목에 대해 Sync를 한꺼번에 켜거나 끌 수 있습니다.

no read + update로 표시된 행은 잠겨 있습니다. 서비스 사용자가 읽기와 업데이트를 할 수 없어서 번역할 수 없습니다. not localized yet로 표시된 행은 Sync가 꺼져 있다는 뜻입니다.

로캘, 엔진, 모드는 Settings 탭에서 변경합니다.

문서 안에서는 Payload 필드 설정에 따라 번역 대상이 결정됩니다:

필드번역 여부
text로 표시된 textarea, richText, localized: true 필드예
로컬라이즈된 group, array, blocks, 또는 tabs 안에 있는 동일한 필드 유형예
리치 텍스트에 포함된 블록 및 인라인 블록예, 해당 텍스트 field도 같은 규칙으로 번역됩니다
select, radio, checkbox, number, date, relationship, upload, json, code, email, point아니요
로컬라이즈되지 않았고 로컬라이즈된 상위 필드도 없는 필드아니요
id, blockType, blockName아니요

리치 텍스트는 Lexical 트리 형태로 번역됩니다. 서식, 링크, 업로드, 블록 구조는 그대로 유지되고, 내부 텍스트만 바뀝니다. 굵은 텍스트나 링크 때문에 문장이 나뉘어 있어도 하나의 문장으로 번역됩니다.

field를 범위에 포함하려면 Payload에서 해당 field를 localized: true로 표시한 뒤 다시 배포하세요. 다음 실행부터 반영됩니다.

동기화 및 재번역#

자동 실행. 플러그인에 webhookUrl이 설정되어 있으면 소스 로캘의 문서나 글로벌이 저장될 때마다 Lingo.dev에 알림이 전송됩니다. 짧은 시간 안에 발생한 저장은 디바운스되어 하나의 실행으로 묶입니다. 다른 로캘에서의 저장, 초안 저장(연결이 Draft 모드가 아닌 경우), 그리고 범위 밖 콘텐츠는 무시됩니다.

수동 실행. 버튼은 두 개이며, 각각 하는 일이 다릅니다:

버튼설명사용 시점
Sync지난 실행 이후 변경된 내용만 번역합니다연결 후 기존 콘텐츠를 채우거나 실패 후 다시 시도할 때
Retranslate범위에 포함된 모든 항목을 처음부터 다시 번역합니다엔진의 glossary, 브랜드 보이스, 또는 규칙을 변경한 뒤

두 버튼 모두 페이지 헤더에 있으며, Sync가 켜진 모든 항목에 적용됩니다. 헤더의 Retranslate는 먼저 확인을 요청합니다. 일부 컬렉션이나 글로벌만 실행하려면 해당 행을 선택하세요. 그러면 **Queue sync (N)**와 **Queue retranslation (N)**이 나타나고, 선택한 행에만 적용됩니다. 행은 해당 Sync 스위치가 켜져 있어야만 선택할 수 있습니다.

연결만으로는 아무것도 번역되지 않습니다. 이미 있는 항목을 번역하려면 페이지 헤더에서 Sync를 클릭하세요. 나중에 대상 로캘을 추가할 때도 방식은 같습니다. 다음 Sync에서 해당 로캘이 채워집니다.

연결마다 동시에 진행 중인 실행은 하나뿐입니다. 추가 요청은 대기열에 들어가 순서대로 시작됩니다.

Retranslate는 수동 편집 내용을 덮어씁니다

Retranslate는 범위 안의 모든 번역된 field를 다시 생성하며, 여기에는 팀이 Payload에서 직접 수정한 번역도 포함됩니다. 반면 Sync는 소스 텍스트가 바뀐 field만 다시 생성하므로, 다른 곳의 수동 수정은 유지됩니다.

실행 모니터링#

Workflow runs 탭에는 모든 실행이 표시됩니다. 시작 시점, 실행을 트리거한 항목(Webhook 또는 Manual, 그리고 Sync 또는 Retranslate), 적용된 로캘, 소요 시간, 상태를 확인할 수 있습니다. 대기 중이거나 실행 중인 항목에는 Stop 버튼이 있습니다. 행을 열면 로캘별 결과를 볼 수 있습니다.

상태의미
Queued앞선 실행이 끝나기를 기다리는 중
Running진행 중
Completed모든 번역이 다시 기록되었습니다
Up to date지난 실행 이후 범위 안에서 변경된 내용이 없습니다. 실패는 아닙니다
Failed실행이 중지되었습니다. 이유는 해당 실행 행에 표시됩니다
Cancelled팀의 누군가가 중단했습니다

실행에 실패해도 이미 기록된 내용은 그대로 유지됩니다. 오류 메시지에는 기록되지 않은 문서가 표시되며, 다음 동기화에서 해당 문서들을 다시 시도합니다. 실행 도중 편집자가 저장한 문서는 건너뛰고, 다음 실행에서 다시 처리됩니다.

번역이 저장되는 위치#

각 번역은 Payload의 로컬라이제이션 모델에 따라 대상 로캘 아래의 동일한 문서 또는 글로벌에 기록됩니다. 번역된 필드만 기록되며, 나머지 필드는 그대로 유지됩니다. 다시 쓰기는 서비스 사용자로 실행되며 새 실행을 트리거하지 않습니다.

기존 번역은 유지됩니다. document를 처음 동기화할 때는 대상 로캘에 이미 있는 내용을 그대로 두고, 누락된 field만 번역합니다. 아직 Payload 기본값이 들어 있는 field는 누락된 것으로 간주됩니다. 기존 번역을 교체하려면 Retranslate를 사용하세요.

초안 vs 게시됨#

Publish 모드에서는 게시된 변경 사항만 실행을 시작하고, 번역은 작성되는 즉시 게시됩니다. Payload는 문서 전체를 게시하므로 해당 문서에 있는 게시되지 않은 초안 수정 내용도 번역과 함께 공개됩니다.

Draft 모드에서는 초안 저장도 실행을 시작합니다. Lingo.dev는 소스의 최신 초안을 읽고 각 번역을 초안으로 작성합니다. 누군가 Payload에서 번역을 게시하기 전까지는 독자에게 보이는 내용은 바뀌지 않습니다. 번역 품질을 평가하는 동안이나 번역이 검토를 거치는 경우에 이 모드를 사용하세요.

나중에 Settings 탭에서 모드를 변경할 수 있습니다.

연결 관리#

설정#

Settings 탭에서는 연결이 읽는 인스턴스, Sync가 켜진 컬렉션과 글로벌, 그리고 연결 상태가 Working인지 Cannot be reached인지 확인할 수 있습니다. 여기서 이름, 소스 로캘, 대상 로캘, 엔진, 모드를 변경할 수 있습니다. 어떤 항목을 바꿔도 웹훅 URL은 유지되므로 다시 배포할 필요가 없습니다.

주소와 API 키는 연결을 만들 때 설정되며, 이후에는 변경할 수 없습니다. Lingo.dev가 다른 주소나 키를 사용하도록 하려면 연결을 끊은 뒤 다시 연결하세요.

연결 해제#

Settings 탭 하단의 Disconnect를 클릭하면 Lingo.dev가 해당 인스턴스를 읽고 쓰는 작업을 중지합니다. 이렇게 하면 연결, 실행 기록, 그리고 무엇이 번역되었는지에 대한 기록이 제거됩니다. 이미 Payload에 작성된 번역은 그대로 유지됩니다. 그다음 구성에서 LINGO_WEBHOOK_URL 또는 플러그인을 제거하세요.

다시 연결하면 webhook URL도 새로 발급됩니다

새 연결에는 새 webhook URL이 발급되므로, 자동 실행을 다시 사용하려면 먼저 LINGO_WEBHOOK_URL를 업데이트하고 다시 배포해야 합니다. 첫 번째 동기화에서는 범위 안의 모든 document를 다시 읽고, Payload에 이미 있는 번역은 유지한 채 비어 있는 부분만 채웁니다.

제한 사항#

제한세부 정보
Payload 버전로컬라이제이션이 설정된 Payload 3
필드 유형text로 표시된 textarea, richText, localized 필드(Lexical만 해당)
범위전체 컬렉션 및 글로벌. 필드별 선택은 지원하지 않음
연결조직당 여러 개 가능, Payload 인스턴스당 하나
동시 실행연결당 하나
주소HTTPS만 지원

문제 해결#

"Payload rejected the API key" 오류와 함께 연결에 실패합니다. 키, auth collection slug, 그리고 해당 collection에서 useAPIKey이 활성화되어 있는지 확인하세요.

컬렉션 또는 글로벌에 "no read + update"가 표시됩니다. 해당 컬렉션의 접근 구성에서 서비스 사용자에게 읽기와 업데이트 권한을 부여한 다음 연결 페이지를 새로고침하세요. 그러면 해당 행의 Sync 스위치 잠금이 해제됩니다.

첫 실행이 "The Lingo plugin isn't installed" 오류와 함께 실패합니다. Payload config의 @lingo.dev/payloadcms에 plugins를 추가하고 다시 배포하세요. 연결은 플러그인 없이도 가능하지만 동기화는 그렇지 않습니다.

Payload에서 게시해도 실행이 시작되지 않습니다. LINGO_WEBHOOK_URL이 설정되어 있는지, localization가 구성되어 있는지, 컬렉션 또는 글로벌이 범위에 포함되어 있는지, 저장이 소스 로캘에서 이루어졌는지, 그리고 연결이 Draft 모드가 아니라면 초안 저장이 아니라 게시였는지 확인하세요.

필드가 번역되지 않는 경우 해당 필드나 상위 항목에 localized: true이 없거나, text, textarea, richText 필드가 아니기 때문입니다.

Settings 탭에서 연결 상태가 Cannot be reached로 표시됩니다. 인스턴스가 실행 중인지, 키가 아직 유효한지, 게이트웨이 헤더가 계속 정상적으로 작동하는지 확인하세요. 기존 연결에서는 주소와 키를 수정할 수 없으므로 둘 중 하나라도 변경되었다면 연결을 끊고 다시 연결한 뒤 새 웹훅 URL로 LINGO_WEBHOOK_URL을 업데이트하세요.

다음 단계#