CLI는 모노레포를 기본적으로 지원합니다. 루트에 재귀 ** glob을 사용하는 단일 i18n.json을 두어 패키지를 자동으로 찾게 할 수도 있고, 패키지별 경로를 명시한 단일 루트 구성을 쓸 수도 있습니다. 또는 각 패키지에 별도의 i18n.json 파일을 두고 matrix-strategy GitHub Action과 조합해 사용할 수도 있습니다.
각 패턴은 언제 쓰면 좋을까요?#
| 시나리오 | 패턴 | 구성 파일 | GitHub Action |
|---|---|---|---|
| 모든 패키지가 동일한 레이아웃과 로캘을 공유하고, 새 패키지도 자동으로 포함되길 원하는 경우 | 재귀 단일 구성 | 루트에 ** glob이 포함된 i18n.json 하나 | 기본 working-directory로 단일 스텝 |
| 모든 패키지가 소스 및 대상 로캘을 공유하는 경우 | 단일 구성 | 루트에 i18n.json 하나 | 기본 working-directory로 단일 스텝 |
| 패키지마다 대상 로캘이 다른 경우 | 패키지별 구성 | 패키지마다 i18n.json 하나 | working-directory을 사용하는 매트릭스 전략 |
| 패키지마다 서로 다른 엔진(용어집, 브랜드 보이스)이 필요한 경우 | 패키지별 구성 + 별도 엔진 | 패키지마다 i18n.json 하나씩, 각각 자체 engineId 포함 | working-directory을 사용하는 매트릭스 전략 |
패턴 1: 재귀 단일 구성#
모든 패키지가 동일한 레이아웃(예: apps/<name>/locales/[locale].json)을 따른다면, 루트의 단일 i18n.json에서 재귀 ** glob을 사용하세요. 새 패키지도 같은 레이아웃만 따르면 자동으로 포함됩니다:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": ["apps/**/locales/[locale].json"]
}
}
}CLI는 기본적으로 node_modules, .git, dist, build, .next, .turbo를 무시하므로, 재귀 패턴이 vendored 트리나 빌드 트리 아래로 내려가지 않습니다. 그 밖에 제외하고 싶은 항목이 있다면 exclude 항목을 직접 추가하세요.
GitHub Action은 아래 패턴 2와 동일합니다 — 단일 스텝에 기본 working directory를 사용합니다.
모든 패키지가 동일한 소스 로캘, 대상 로캘, 레이아웃, 로컬라이제이션 엔진을 공유하고, 패키지를 추가할 때마다 i18n.json을 수정하고 싶지 않다면 이 방식을 사용하세요.
패턴 2: 단일 구성, 공유 로캘#
저장소 루트에 i18n.json 하나만 두면 됩니다. 버킷 경로로 각 패키지 내부 경로를 명시적으로 지정합니다:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": [
"apps/web/locales/[locale].json",
"apps/dashboard/locales/[locale].json"
]
},
"markdown": {
"include": ["packages/docs/content/[locale]/*.md"]
}
}
}GitHub Action — 표준 단일 스텝:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
pull-request: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}모든 패키지가 동일한 소스 로캘, 대상 로캘, 로컬라이제이션 엔진을 공유하지만 레이아웃 차이가 커서 재귀 glob이 너무 넓게 잡힐 때 이 방식을 사용하세요.
패턴 3: 패키지별 구성, 서로 다른 로캘#
각 패키지는 대상 로캘을 독립적으로 설정한 자체 i18n.json을 가집니다:
apps/web/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja", "ko", "zh-Hans"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
}
}
}apps/marketing/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
},
"markdown": {
"include": ["content/[locale]/*.md"]
}
}
}GitHub Action — working-directory을 사용하는 매트릭스 전략:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
translate:
runs-on: ubuntu-latest
strategy:
matrix:
package: [apps/web, apps/marketing]
steps:
- uses: actions/checkout@v4
- uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
working-directory: ${{ matrix.package }}
pull-request: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}각 매트릭스 항목은 해당 패키지의 i18n.json 범위에서 CLI를 실행합니다. 따라서 action은 그 패키지에서 선언한 파일만 번역합니다.
패턴 4: 패키지별 구성, 별도 엔진#
구조는 패턴 3과 같지만, 각 패키지가 서로 다른 로컬라이제이션 엔진에 연결됩니다. 이렇게 하면 각 패키지마다 자체 용어집, 브랜드 보이스, 모델 구성을 따로 설정할 수 있습니다.
apps/product/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
}
},
"engineId": "eng_ProductApp123"
}apps/docs/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr"]
},
"buckets": {
"markdown": {
"include": ["content/[locale]/*.md"]
}
},
"engineId": "eng_DocsEngine456"
}GitHub Action YAML은 패턴 3과 동일합니다 — 각 i18n.json에 있는 engineId이 번역을 올바른 엔진으로 자동 라우팅합니다.
lockfile은 어떻게 동작하나요?#
각 i18n.json 위치마다 같은 디렉터리에 자체 i18n.lock 파일이 생성됩니다. lockfile은 어떤 소스 콘텐츠가 번역되었는지 추적해 증분 업데이트를 가능하게 합니다. 패턴 1과 2에서는 루트에 lockfile이 하나 있고, 패턴 3과 4에서는 각 패키지마다 lockfile이 하나씩 있습니다.
FAQ#
새 패키지도 자동으로 포함되나요?
패턴 1(재귀 **)에서만 가능합니다. 패턴 3과 4에서는 패키지를 추가할 때 워크플로의 matrix.package 목록에 새 항목도 함께 추가해야 합니다.
패키지마다 다른 로캘을 사용할 수 있나요?
네. 패턴 3 또는 4를 사용하세요. 각 패키지의 i18n.json에서 자체 locale.targets 배열을 독립적으로 선언할 수 있습니다.
워크플로 파일은 하나면 되나요, 아니면 여러 개가 필요한가요?
매트릭스 전략을 사용하는 워크플로 파일 하나로 모든 패키지를 처리할 수 있습니다. 각 매트릭스 항목은 서로 다른 working-directory을 기준으로 실행되므로, CLI 범위가 해당 패키지의 구성으로 제한됩니다.
패키지들이 용어집은 공유하면서 로캘은 다르게 설정할 수 있나요?
네. 두 패키지가 같은 engineId을 가리키도록 하고, 각 i18n.json에서 서로 다른 locale.targets을 설정하세요. 그러면 엔진의 용어집이 요청된 로캘 쌍에 맞춰 적용됩니다.
