GitLab CI에서 Lingo.dev를 실행하면 소스 문자열을 추가하거나 변경한 모든 머지 리퀘스트에 번역이 이미 채워진 상태로 돌아옵니다. 파이프라인은 lingo push를 실행하고, 로컬라이제이션 엔진은 새로 추가되었거나 변경된 키만 번역한 뒤, 결과를 MR 브랜치에 바로 커밋합니다 — 번역은 MR diff에 표시되고 사람이 머지하기 전에 검토됩니다. 아무것도 눈에 띄지 않게 기본 브랜치에 반영되지 않습니다.
실행 예제
완전히 실행 가능한 전체 설정은 gitlab.com/lingo.dev/gitlab-cicd-example에서 확인할 수 있습니다.
사전 준비 사항#
Lingo.dev 조직과 엔진, 그리고 service API 키가 필요합니다(Dashboard → API Keys → create, type service).
Lingo.dev용으로 설정된 프로젝트가 필요합니다. 다음 명령으로 한 번만 생성하면 됩니다:
bashnpx @lingo.dev/cli@latest init # scaffolds .lingo/config.json npx @lingo.dev/cli@latest link # connects the project to your org + engine.lingo/config.json에는 소스/대상 로캘과 소스 glob 패턴이 선언됩니다:json{ "sourceLocale": "en", "targetLocales": ["es", "fr", "de", "zh"], "files": [{ "pattern": "locales/en.json" }], "orgId": "org_...", "engineId": "eng_..." }커밋된 기준 상태도 필요합니다. 처음 한 번은 전체를 번역해 커밋해 두어야 CI가 비교할 lockfile이 생깁니다:
bashnpx @lingo.dev/cli@latest push --backfill-missing --wait git add locales .lingo && git commit -m "chore(i18n): baseline translations"
액세스 토큰#
Settings → CI/CD → Variables 아래에 masked CI/CD 변수를 두 개 추가하세요:
LINGO_API_KEY— Lingo.dev service 키(lingo_sk_...)입니다. CLI가 이 값을 자동으로 읽어 인증합니다.GITLAB_PUSH_TOKEN—write_repository범위를 가진 Project Access Token(역할 Developer)입니다. 이 토큰으로 CI가 번역을 MR 브랜치에 다시 커밋할 수 있습니다.
Settings → Access tokens에서 Project Access Token을 생성하세요. CI_JOB_TOKEN은 커밋을 푸시할 수 없기 때문에, 커밋을 다시 반영하는 단계에는 전용 토큰이 필요합니다. Project access token을 사용하려면 유료 GitLab 플랜이 필요합니다.
파이프라인#
다음 .gitlab-ci.yml을 커밋하세요. 이 설정은 기본 브랜치를 대상으로 하는 머지 리퀘스트에서 실행되며, 번역을 MR의 소스 브랜치로 다시 푸시합니다:
stages:
- localize
localize:
stage: localize
image: node:22-alpine
rules:
# Only on merge requests that target the default branch.
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
before_script:
- apk add --no-cache git
script:
# Pin the CLI version — never @latest; bump deliberately after testing.
# --wait blocks until the engine finishes and writes files: since 1.6.0
# `push` is async by default (it submits the run and exits), so CI must
# wait to have something to commit.
- npx -y @lingo.dev/cli@1.6.0 push --wait
- |
if [ -z "$(git status --porcelain)" ]; then
echo "Translations already up to date — nothing to commit."
exit 0
fi
git config user.name "lingo-bot"
git config user.email "bot@lingo.dev"
git add locales .lingo/lock.json
# [skip ci] keeps the bot's own commit from re-triggering this pipeline.
git commit -m "chore(i18n): sync translations [skip ci]"
git push "https://oauth2:${GITLAB_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "HEAD:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"직접 해보기#
git checkout -b feat/new-strings
# add or change a key in locales/en.json
git commit -am "feat: add strings" && git push -u origin feat/new-strings
# open an MR feat/new-strings -> main (UI, or: glab mr create --fill --target-branch main)MR 파이프라인은 lingo push --wait를 실행하고, locales/{...}.json와 업데이트된 .lingo/lock.json를 MR 브랜치에 커밋합니다. 그러면 번역이 diff에 나타나고, 검토자는 필요한 값을 수정한 뒤 머지하면 됩니다.
사람이 수정한 내용이 유지되는 방식#
lingo push은 수동 편집을 키별로 보존합니다:
- 대상 문자열을 수정하고(영문 소스는 그대로인 경우) → 해당 문자열은 유지되고, 나머지 모든 키는 계속 번역됩니다.
- 수정된 키의 영문 소스가 바뀌면 → 그 키에 대해서는 새 번역이 생성됩니다(의미가 달라졌기 때문입니다).
- 새 소스 키가 추가되면 → 수동 편집이 들어 있는 파일이라도 번역되어 함께 추가됩니다.
즉, MR에서 검토자가 수정한 내용은 이후 파이프라인이 다시 실행돼도 유지되고, 새 키와 변경된 키는 자동으로 계속 반영됩니다.
푸시 모드#
lingo push— 증분 방식이며 CI의 기본값입니다. 새 키와 변경된 키만 번역하고 나머지는 그대로 유지합니다. 출력이 기록될 때까지 대기하도록 CI에서는--wait를 추가하세요(1.6.0+부터는 기본적으로 비동기입니다).lingo push --backfill-missing— 첫 푸시 / 새 로캘 초기 구성용입니다. 아직 존재하지 않는 대상 파일을 채웁니다. 지속적으로 변경되는 작업에는 적합하지 않습니다.lingo push --force --yes— 모든 것을 처음부터 다시 번역합니다(수동 편집은 덮어씁니다). 드물게만 사용합니다.
맞춤 설정#
- MR 대신 기본 브랜치에 자동 커밋:
$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH에서 트리거하고$CI_DEFAULT_BRANCH로 다시 푸시하세요. 더 단순하지만 AI 출력이 검토 없이 기본 브랜치에 바로 반영됩니다. - 특정 문자열 고정:
.lingo/config.json에서preservedKeys/lockedKeys를 사용하면 소스가 바뀌어도 선택한 키를 고정할 수 있습니다. - Self-hosted GitLab: 별도 변경 없이 그대로 동작합니다. gitlab.com에서는 새 계정이 공유 러너로 CI 작업을 실행하기 전에 신원 확인을 완료해야 합니다.
