CLI는 18가지 파일 형식을 번역합니다. 형식은 파일 확장자로 자동 판별되며, 이를 덮어쓰려면 format 항목에 files[]을 설정하세요. 또는 항상 이 설정이 필요한 세 가지 형식(yaml-openapi, yaml-root-key, android)에도 지정해야 합니다.
| 형식 | 확장자 | format 값 | 참고 |
|---|---|---|---|
| JSON | .json | json | 키/값 형식. key controls를 지원합니다. |
| JSONC | .jsonc | jsonc | 주석이 포함된 JSON. 주석은 유지되며 translator notes 역할도 합니다. |
| YAML | .yaml, .yml | yaml | 일반 YAML입니다. 모든 문자열 값이 번역되고 키와 구조는 그대로 유지됩니다. |
| OpenAPI YAML | .yaml, .yml | yaml-openapi | OpenAPI 스펙입니다. format을 명시적으로 설정하세요. 일반 .yaml는 자동 감지 시 yaml로 처리됩니다. |
| 로캘 루트 키 YAML | .yaml, .yml | yaml-root-key | 로캘은 YAML의 루트 키입니다(Rails config/locales). 루트 키는 대상 로캘로 다시 작성됩니다. format를 명시적으로 설정하세요. |
| Markdown | .md | md | 본문은 번역되며, frontmatter는 opt-in입니다. |
| MDX | .mdx | mdx | Markdown + JSX. 컴포넌트 props는 opt-in입니다. |
| Markdoc | .mdoc | markdoc | Markdown + 태그. frontmatter와 태그 속성을 지원합니다. |
| TypeScript | .ts, .mts, .cts | typescript | 로캘 모듈(export default { … })입니다. 문자열 리터럴은 번역되고 코드는 유지됩니다. |
| Gettext PO | .po | po | msgstr는 번역되며, msgid, 주석, 헤더는 유지됩니다. |
| Flutter ARB | .arb | flutter | 문자열 값은 번역되며 @ 메타데이터와 {placeholders}는 유지됩니다. |
| Android | .xml | android | strings.xml 형식입니다. format를 명시적으로 설정하세요. .xml는 자동 감지되지 않습니다. |
| Xcode strings | .strings | xcode-strings | 값은 번역되고 키는 유지됩니다. |
| Xcode String Catalog | .xcstrings | xcode-xcstrings | 하나의 파일에 모든 로캘이 들어 있습니다. 타깃은 같은 파일에 다시 기록됩니다(아래 참고). |
| Xcode stringsdict | .stringsdict | xcode-stringsdict | 복수형 문자열은 번역되고 형식 제어 키는 유지됩니다. |
| XLIFF | .xlf, .xliff | xliff | <source>는 유지되고, <target>는 유닛별로 기록됩니다. 버전 1.2와 2.0을 지원합니다. |
| SubRip | .srt | srt | 자막 텍스트는 번역되며 인덱스와 타임코드는 그대로 유지됩니다. |
| PHP | .php | php | Laravel return [ … ] 형식입니다. 문자열 값은 번역되고 키, 숫자, 구조는 유지됩니다. |
처음부터 끝까지 살펴보기
데모 프로젝트는 문서 및 데이터 형식(JSON, JSONC, Markdown, MDX, Markdoc, OpenAPI YAML)과 각 형식에 꼭 필요한 설정만 담아둔 작은 Sandbox입니다. npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo로 복제한 뒤 push를 실행하세요. 앱 및 프레임워크 형식은 여기에는 포함되어 있지 않습니다. 해당 형식은 Example projects에서 프레임워크별 전체 저장소를 제공하며, 아래 형식별 스니펫에서 관련 설정을 확인할 수 있습니다.
npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo
cd my-lingo-demoJSON 및 JSONC#
기본적인 키/값 번역입니다. key control로 따로 지정하지 않는 한 모든 문자열 값이 번역됩니다.
{ "pattern": "content/en/app.json", "lockedKeys": ["meta.version"] }JSONC는 주석도 함께 보존하며, 엔진은 이를 문맥 정보로 활용합니다. 자세한 내용은 translator notes를 참고하세요.
{ "pattern": "content/en/settings.jsonc", "preservedKeys": ["featureFlags"] }Markdown, MDX, Markdoc#
본문은 기본적으로 번역됩니다. frontmatter와 임베드된 컴포넌트는 직접 opt-in하지 않으면 번역되지 않습니다.
Frontmatter#
번역할 frontmatter 필드는 translateFrontmatterFields에 나열하세요:
{
"pattern": "content/en/guide.md",
"translateFrontmatterFields": ["title", "description"]
}MDX 컴포넌트 props#
MDX에서는 translateComponentProps를 사용해 특정 컴포넌트의 특정 props만 번역할 수 있습니다:
{
"pattern": "content/en/landing.mdx",
"translateFrontmatterFields": ["title"],
"translateComponentProps": [{ "component": ["Hero", "Callout"], "props": ["title", "body"] }]
}이렇게 하면 title와 body의 <Hero> 및 <Callout> props만 번역되고, 나머지 props는 모두 그대로 유지됩니다.
Markdoc#
Markdoc는 Markdown과 비슷하게 동작하며, frontmatter와 태그 속성은 유지됩니다:
{
"pattern": "content/en/changelog.mdoc",
"translateFrontmatterFields": ["title"]
}YAML#
일반 YAML은 .yaml/.yml 확장자로 자동 감지됩니다. 모든 문자열 값이 번역되고 키와 구조는 유지됩니다:
{ "pattern": "content/en/strings.yaml" }OpenAPI 스펙은 예외입니다. .yaml 확장자를 함께 쓰지만, 엔진이 사용자에게 노출되는 필드(요약, 설명)만 번역하고 스키마 키, 경로, operation ID는 그대로 두려면 format를 명시적으로 지정해야 합니다:
{ "pattern": "content/en/api.yaml", "format": "yaml-openapi" }Rails 스타일 로캘 파일은 또 다른 예외입니다. 로캘이 YAML의 루트 키(en:)이며, 대상 파일도 대상 로캘(es:)을 루트로 가져야 합니다. 이 경우에도 format를 명시적으로 설정하세요:
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }앱 및 프레임워크 형식#
PO, Flutter ARB, Xcode .strings, Xcode .stringsdict, TypeScript 로캘 모듈, XLIFF, SubRip, PHP는 모두 같은 원칙을 따릅니다. 번역 가능한 텍스트만 번역하고, 구조적 요소는 모두 유지합니다(키, ID, 메타데이터, 플레이스홀더, 타임코드, 코드, 서식). 각 형식은 확장자로 자동 감지되므로 소스 파일을 가리키는 패턴만 지정하면 됩니다:
{ "pattern": "lib/l10n/app_en.arb" }
{ "pattern": "locales/en.po" }
{ "pattern": "Localizable.strings" }
{ "pattern": "l10n/en.xlf" }다만 확장자가 너무 모호해 자동 감지할 수 없는 형식이 하나 있어, 이 경우에는 format를 명시적으로 지정해야 합니다:
{ "pattern": "res/values/strings.xml", "format": "android" }Xcode String Catalogs#
.xcstrings(String Catalog) 파일은 모든 로캘을 하나의 파일에 담습니다. 로캘별 출력 경로는 없으며, CLI가 소스 로캘을 읽은 뒤 모든 타깃을 같은 파일에 다시 기록합니다:
{ "pattern": "Localizable.xcstrings" }카탈로그에서 "shouldTranslate": false로 표시된 문자열은 건너뜁니다 — CLI는 해당 문자열을 번역하지 않고 손대지 않은 채로 둡니다.
출력 경로#
이 패턴은 소스 파일의 이름을 기준으로 하며, 모든 대상 경로는 여기서 파생됩니다. 다음 네 가지 규칙이 순서대로 적용됩니다:
- 경로 세그먼트 전체 또는 파일명 자체가 로캘인 경우 — 가장 일반적인 케이스입니다.
content/en/app.json→content/de/app.json,locales/en.json→locales/de.json. - 세그먼트나 파일명 끝에 로캘이 붙는 경우 — Android, Xcode
.strings/.stringsdict, Flutter,yaml-root-key처럼 이런 형식을 쓰는 레이아웃에 해당합니다.res/values-en/→res/values-de/,app_en.arb→app_de.arb,devise.en.yml→devise.de.yml. - 경로에 로캘이 전혀 없고, 플랫폼이 기본 언어에 예약해 둔 이름을 쓰는 경우입니다. Android의 기본
res/values/는res/values-de/가 되고, Xcode의Base.lproj는de.lproj가 됩니다. - String Catalog의 경우, 하나의 파일에 모든 로캘이 들어 있으므로 대상 경로는 소스 경로와 동일합니다.
대상 경로가 BCP 47을 따르지 않는 플랫폼은 Android뿐입니다. CLI는 Android가 실제로 읽는 리소스 한정자를 기록하므로, pt-BR는 values-pt-rBR/로, zh-Hans는 values-b+zh+Hans/로 들어갑니다.
어느 규칙에도 맞지 않아 소스 로캘이 경로 어디에도 나타나지 않으면, CLI는 대체 동작으로 파일 옆에 <locale>/ 디렉터리를 만들어 넣고, lingo push를 통해 추측한 결과임을 알려줍니다. 이 경고는 패턴이 잘못되었다는 신호로 받아들이세요. Configuration을 참고하세요.
레거시 CLI를 사용 중이신가요?#
레거시 CLI의 주요 형식 대부분은 이제 현재 CLI에서도 지원됩니다(PO, XLIFF, Android/Xcode strings, Flutter ARB 등 — 위 표 참고). 다만 비교적 덜 쓰이는 일부 형식(예: CSV, HTML, MJML, .properties)은 아직 지원되지 않습니다. 해당 형식이 추가되기 전까지는 legacy CLI docs를 참고하세요.
