Lingo.dev CLI는 설정된 .strings로컬라이제이션 엔진을 통해 Xcode , Android XML, Flutter ARB, React Native JSON 등 네이티브 모바일 리소스 파일을 번역합니다. 파일 확장자만으로 형식을 자동 감지하고, 구조는 그대로 유지하며, 복수형도 기본 지원합니다.
플랫폼 개요#
| 플랫폼 | 네이티브 형식 | 일반적인 소스 파일 경로 |
|---|---|---|
| iOS (Xcode) | .strings | en.lproj/Localizable.strings |
| iOS (Xcode) | .stringsdict | en.lproj/Localizable.stringsdict |
| iOS (Xcode) | .xcstrings | Localizable.xcstrings |
| Android | strings.xml | app/src/main/res/values/strings.xml |
| Flutter | .arb | lib/l10n/app_en.arb |
| React Native | .json | src/locales/en.json |
사전 준비#
모든 CLI 실행 시 콘텐츠는 로컬라이제이션 엔진을 거칩니다. 어떤 LLM 모델, 용어집, 브랜드 보이스, 규칙을 적용할지 정하는 설정이죠. Lingo.dev 대시보드에서 만들어 보세요.
CLI(Node.js 22+)를 설치한 뒤 인증하세요:
npm install -g @lingo.dev/cli
lingo loginlingo login을 실행하면 일회용 코드로 로그인할 수 있습니다. CI에서는 대화형 로그인을 건너뛰고 --api-key를 전달하거나 LINGO_API_KEY를 설정하세요.
플랫폼 설정하기#
lingo init을 실행해 .lingo/config.json(소스/타깃 로캘과 파일 패턴 포함)을 만들고, 이어서 lingo link을 실행해 orgId와 engineId를 연결하세요. .lingo/config.json은 저장소에 커밋하면 됩니다. 아래 예시에서는 각 플랫폼별로 완성된 config를 보여줍니다.
패턴은 항상 소스 파일을 가리키며, CLI는 이를 기준으로 각 타깃 경로를 계산합니다. 보통은 경로에서 찾은 로캘만 바꾸면 됩니다(en.lproj → de.lproj, app_en.arb → app_de.arb). 다만 두 플랫폼은 예외인데, 이 역시 모두 자동으로 처리됩니다. String Catalog는 모든 로캘을 하나의 파일에 담기 때문에 타깃 경로가 소스 경로와 같고, Android는 경로에 로캘이 전혀 없는 한정자 없는 values/에 기본 문자열을 두기 때문에 CLI가 여기에 타깃 한정자를 붙입니다(values/ → values-de/).
Xcode는 세 가지 로컬라이제이션 형식을 지원합니다. 프로젝트 설정에 맞는 형식을 선택하세요.
String Catalogs (.xcstrings) — Xcode 15에서 도입된 최신 Xcode 포맷입니다. 하나의 JSON 파일에 모든 로캘이 들어 있으며, 새 문자열을 추가하면 Xcode가 자동으로 업데이트합니다. CLI는 이 파일을 제자리에서 수정하므로 패턴은 로캘 세그먼트 없이 해당 단일 카탈로그만 가리키면 됩니다.
{
"orgId": "org_...",
"engineId": "eng_...",
"sourceLocale": "en",
"targetLocales": ["es", "fr", "de", "ja"],
"files": [{ "pattern": "MyApp/Localizable.xcstrings" }]
}레거시 .strings 파일 — [code].lproj/ 디렉터리마다 로캘별 파일 하나씩 사용하는 방식입니다. 소스 로캘은 경로(en.lproj)에 포함되고, CLI는 각 타깃을 해당 .lproj 디렉터리에 각각 기록합니다. 프로젝트에서 복수형용 .stringsdict도 함께 쓴다면 files 항목을 하나 더 추가하세요.
{
"orgId": "org_...",
"engineId": "eng_...",
"sourceLocale": "en",
"targetLocales": ["es", "fr", "de", "ja"],
"files": [
{ "pattern": "MyApp/en.lproj/Localizable.strings" },
{ "pattern": "MyApp/en.lproj/Localizable.stringsdict" }
]
}개발 언어 번들이 Base.lproj이 아니라 en.lproj인 프로젝트도 문제없이 동작하며, CLI는 Base.lproj을 소스 로캘로 인식합니다.
Xcode의 i18n 인프라를 설정하려면 Apple의 로컬라이제이션 문서를 참고하세요.
번역 실행#
명령 하나로 모든 리소스 파일을 번역할 수 있습니다:
lingo pushCLI는 소스 로캘 파일을 읽고, 저장소에 커밋하는 lockfile(.lingo/lock.json)을 기준으로 지난 실행 이후 무엇이 바뀌었는지 계산한 뒤, 변경된 부분만 번역해 타깃 로캘 파일에 기록합니다.
처음 실행할 때나 새 타깃 로캘을 추가했을 때는 전체를 처음부터 번역하세요:
lingo push --backfill-missing프로젝트에 여러 리소스 유형이 섞여 있다면 glob을 전달해 특정 플랫폼만 지정하세요(--bucket 또는 --target-locale 플래그는 없습니다). 패턴은 소스 경로를 기준으로 매칭되므로, 타깃이 아니라 소스 파일 기준으로 범위를 좁혀야 합니다.
lingo push "app/src/main/res/values/strings.xml"
lingo push "MyApp/Localizable.xcstrings"다른 환경(예: 다른 머신)에서 최신 번역을 가져오려면 lingo pull을 실행하세요. 변경 사항을 기록하지 않고 번역이 최신 상태인지 확인하려면 — 배포 게이트로 쓰기 좋습니다 — lingo check를 실행하세요.
복수형과 플랫폼 규칙#
모바일 플랫폼마다 복수형 처리 방식은 다릅니다. iOS는 .stringsdict 또는 String Catalog 규칙을 사용하고, Android는 <plurals> XML 요소를 사용하며, Flutter는 ARB 파일에서 ICU MessageFormat을 사용합니다. CLI는 번역 과정에서 각 플랫폼의 네이티브 복수형 구조를 유지하고, 각 대상 로캘에 맞는 올바른 복수형 범주를 생성합니다.
CI 자동화#
번역을 항상 최신 상태로 유지하는 가장 권장되는 방법은 Lingo.dev GitHub App입니다. 서버 측에서 실행되며, 커밋된 .lingo/config.json와 engineId를 읽어 번역 업데이트를 자동으로 생성합니다. 즉, 러너나 시크릿, lockfile을 직접 관리할 필요가 없습니다. 자체 파이프라인에서 번역을 실행하고 싶다면 CI 러너에서 lingo push를 실행한 뒤 결과를 커밋하세요.
