구성
Champollion은 별도의 설정 없이 작동해요 — 프로젝트에서 로케일 파일, 형식, 대상 언어를 자동으로 감지해요. 더 세밀하게 제어하려면 프로젝트 루트에 champollion.config.json을 만들거나, 다음을 실행하세요:
npx champollion init
전체 구성 레퍼런스
{
"version": 3,
"inputLocale": "en",
"localesDir": "./locales",
"contentDir": null,
"translatableFields": null,
"format": "auto",
"model": "google/gemini-3.5-flash",
"temperature": 0.3,
"defaultMethod": "llm",
"batchSize": 80,
"coachingFile": null,
"promptContext": null,
"jsonConcurrency": 200,
"contentConcurrency": 48,
"fallbackPrefix": "[EN] ",
"apiKeyEnvVar": "OPENROUTER_API_KEY",
"baseUrl": "",
"pairs": {},
"languages": {},
"lint": {
"srcDir": null,
"ignore": ["node_modules", ".next", "dist"],
"minLength": 2
},
"seo": {
"urlPattern": "/:locale/:path",
"pages": null
},
"typegen": {
"output": null,
"autoGenerate": false
}
}
:::note typegen은 아직 구현되지 않았어요
typegen 구성 블록은 구성 로더에 의해 인식되고 보존되지만, TypeScript 타입 생성은 아직 구현되지 않았어요. 이것은 계획된 기능을 위한 플레이스홀더예요. 이 값들을 설정해도 아무런 효과가 없어요.
:::
필드
| 필드 | 타입 | 기본값 | 설명 |
|---|---|---|---|
version | number | 3 | 구성 스키마 버전. 항상 3. |
inputLocale | string | "en" | 소스 언어 코드 (BCP 47). |
localesDir | string | "./locales" | 로케일 파일 경로. Champollion이 이 디렉터리를 스캔해요. |
contentDir | string | null | Hugo 콘텐츠 디렉터리. Markdown 본문 번역을 활성화해요. |
translatableFields | string[] | null | 콘텐츠 번역을 위한 기본 번역 가능 frontmatter 필드를 재정의해요. null는 내장 기본값(title, description, summary)을 사용해요. |
format | string | "auto" | 파일 형식: json, toml, yaml, 또는 auto (확장자로부터 감지). |
model | string | "google/gemini-3.5-flash" | LLM 메서드의 기본 모델. 전체 OpenRouter 슬러그(provider/model) 또는 shared/model-aliases.json의 짧은 별칭(예: gemini-flash)을 허용해요. 직접 제공자는 단순 이름(예: gpt-4o)을 사용해요. |
temperature | number | 0.3 | LLM 온도 (0.0–2.0). 낮을수록 = 더 결정론적. |
defaultMethod | string | "llm" | 기본 번역 메서드: llm, llm-coached, google-translate, deepl, microsoft-translator, libretranslate, openai, anthropic, gemini, api. --method CLI 플래그로 재정의돼요. |
batchSize | number | 80 | 번역 배치당 키 수. 높을수록 = API 호출 감소, 단 프롬프트가 더 커져요. |
coachingFile | string | null | 자유 텍스트 코칭 프롬프트 파일의 경로 (프로젝트 루트 기준). 내용은 시작 시 읽혀 Coaching guidance: 블록으로 시스템 프롬프트에 주입돼요. |
promptContext | string | null | 시스템 프롬프트에 주입되는 애플리케이션 컨텍스트 문자열 (예: "E-commerce product descriptions"). 모델이 사용자 도메인에 맞게 번역을 조정하는 데 도움이 돼요. |
jsonConcurrency | number | 200 | JSON 키 동기화를 위한 최대 병렬 로케일 번역 수. --json-concurrency CLI 플래그로 재정의돼요. |
contentConcurrency | number | 48 | 콘텐츠(Markdown/MDX) 번역을 위한 최대 병렬 API 호출 수. --content-concurrency CLI 플래그로 재정의돼요. |
fallbackPrefix | string | "[EN] " | 이전 실행의 레거시 미번역 값을 감지하기 위해 audit와 verify가 사용하는 마커 접두사. Champollion은 이 접두사를 쓰지 않아요 — 감지를 위해 읽기만 해요. |
apiKeyEnvVar | string | "OPENROUTER_API_KEY" | API 키의 환경 변수 이름. 사용자 정의 환경 변수 이름을 위한 재정의. |
baseUrl | string | "" | SEO 아티팩트 생성(hreflang, sitemaps, JSON-LD)을 위한 기본 URL. |
pairs | object | {} | 페어별 메서드, 모델, 품질 재정의. 페어 구성을 참고하세요. |
languages | object | {} | 언어별 재정의. 언어 구성을 참고하세요. |
lint.srcDir | string | null | 린트 스캔을 위한 소스 디렉터리. null = 프레임워크로부터 자동 감지. |
lint.ignore | string[] | ["node_modules", ...] | 린트에서 제외할 glob 패턴. |
lint.minLength | number | 2 | 하드코딩으로 플래그할 최소 문자열 길이. |
seo.urlPattern | string | "/:locale/:path" | hreflang 태그 생성을 위한 URL 패턴 템플릿. |
seo.pages | string[] | null | SEO를 위한 명시적 페이지 목록. null = 로케일 키로부터 자동 감지. |
typegen.output | string | null | 생성된 TypeScript 타입의 출력 경로. null = 비활성화. |
typegen.autoGenerate | boolean | false | 각 동기화 후 타입을 자동으로 재생성. |
페어 구성
각 소스→대상 페어는 독립적으로 구성할 수 있어요:
{
"pairs": {
"en:fr": {
"method": "google-translate",
"qualityTier": "high"
},
"en:ja": {
"method": "llm",
"model": "google/gemini-2.5-pro"
},
"en:crk": {
"methodPlugin": "crk-coached-v1"
}
}
}
페어 필드
| 필드 | 타입 | 설명 |
|---|---|---|
method | string | 번역 메서드: llm, llm-coached, google-translate, deepl, microsoft-translator, libretranslate, openai, anthropic, gemini, api |
methodPlugin | string | 설치된 플러그인의 이름 (.champollion/methods/에서) |
model | string | 이 페어의 기본 모델을 재정의 |
temperature | number | 이 페어의 기본 온도를 재정의 |
batchSize | number | 이 페어의 기본 배치 크기를 재정의 |
register | string | 레지스터/톤 재정의 (프리셋 키 또는 자유 형식 텍스트) |
endpoint | string | 원격 API 엔드포인트 URL. method가 api일 때 필요해요. |
coachingFile | string | 이 페어를 위한 코칭 프롬프트 파일 경로 |
promptContext | string | 이 페어를 위한 애플리케이션 컨텍스트 |
qualityTier | string | 디스플레이 티어: standard, high, research, verified |
언어 구성
언어는 세 가지 형식을 허용해요:
코드 배열 (가장 간단함)
{
"languages": ["fr", "de", "ja"]
}
각 언어는 내장 레지스터 테이블에서 기본 레지스터를 가져와요. 기본값이 없는 언어는 "Professional register."을 가져와요.
레지스터 문자열을 가진 객체
값은 언어 카드의 프리셋 키이거나 사용자 정의 레지스터 텍스트일 수 있어요:
{
"languages": {
"fr": "casual-tu",
"ko": "formal-hapsyo",
"ja": "Custom: Polite Japanese for a gaming app."
}
}
Champollion은 문자열이 언어 카드의 프리셋 키와 일치하는지 확인해요. 일치하면 카드의 전체 레지스터 프롬프트가 사용돼요. 일치하지 않으면 문자열이 그대로 사용돼요. 사용 가능한 프리셋은 지원 언어를 참고하세요.
전체 구성을 가진 객체
{
"languages": {
"crk": {
"name": "Plains Cree",
"register": "SRO syllabics with grammatical precision.",
"model": "google/gemini-2.5-pro",
"batchSize": 5,
"maxRetries": 5,
"script": "cans"
}
}
}
같은 블록에서 단축 형식과 전체 객체를 혼합할 수 있어요.
언어 필드
| 필드 | 타입 | 설명 |
|---|---|---|
register | string | 스타일/톤 지침. 프리셋 키(예: casual-tu, formal-hapsyo)이거나 사용자 정의 텍스트일 수 있어요. 언어 카드를 참고하세요. |
name | string | 사람이 읽을 수 있는 언어 이름 (상태 표시용) |
model | string | 기본 모델을 재정의 |
temperature | number | 기본 온도를 재정의 |
batchSize | number | 기본 배치 크기를 재정의 |
coachingFile | string | 이 언어를 위한 코칭 프롬프트 파일 경로 |
promptContext | string | 이 언어를 위한 애플리케이션 컨텍스트 |
maxRetries | number | 실패한 배치의 최대 재시도 예산 (기본값: 3) |
script | string | ISO 15924 스크립트 코드. 품질 게이트에서 스크립트 검증을 트리거해요. |
:::info 상속 체인 설정은 다음 순서로 해결돼요 (먼저 나온 것이 우선):
페어 수준 → 언어 수준 → 전역 구성 → 기본값
예를 들어, pairs["en:fr"]가 model을 설정하면, 언어 수준과 전역 model 값을 모두 재정의해요.
:::
비영어 소스
소스 언어가 영어가 아닌 경우:
# CLI flag (one-time)
npx champollion sync --source fr
{
"inputLocale": "fr"
}
잠금 파일
Champollion은 번역된 소스 값의 SHA-256 해시를 추적하기 위해 .champollion.lock을 만들어요. 모든 개발자가 동일한 번역 베이스라인을 공유하도록 이 파일을 커밋하세요.
소스 값이 변경되면 해시가 더 이상 일치하지 않으며, champollion은 다음 동기화 시 해당 키를 다시 번역해요.
.champollionignore
lint 스캔에서 파일을 제외하려면 프로젝트 루트에 .champollionignore을 만드세요. .gitignore처럼 glob 패턴을 사용해요:
src/components/legacy/**
src/utils/constants.js
**/*.test.js
.champollion/ 디렉터리
Champollion은 내부 상태를 위해 프로젝트 루트에 .champollion/ 디렉터리를 만들어요. 일반적으로 이것을 .gitignore에 추가해야 해요 — 이것은 로컬 최적화이지, 프로젝트 소스가 아니에요:
.champollion/
| 파일 | 목적 | 커밋? |
|---|---|---|
tm.json | 번역 메모리 캐시 — 소스 텍스트 + 로케일 + 메서드를 키로 하여 이전 번역을 저장 | 아니요 (로컬 캐시) |
xliff/*.xliff | 전문 번역가 검토를 위한 XLIFF 내보내기 파일 | 아니요 (임시) |
methods/ | 설치된 메서드 플러그인 매니페스트 | 예 (공유 구성) |
backups/ | 래핑 전 백업 (wrap --undo에 의해 생성됨) | 아니요 (안전망) |
tm.json과 그것이 API 비용을 절감하는 방법에 대한 자세한 내용은 번역 메모리를 참고하세요.
프로그래밍 API
빌드 스크립트와 사용자 정의 통합의 경우, 패키지에서 직접 가져오세요:
import { GeminiMethod, runSync, resolveConfig } from 'champollion';
// Use a method class directly
const gemini = new GeminiMethod();
const result = await gemini.translate(
['greeting', 'farewell'],
{ greeting: 'Hello', farewell: 'Goodbye' },
{ target: 'fr', name: 'French', register: 'formal', model: 'gemini-2.5-flash' },
{ cwd: process.cwd() }
);
// result = { greeting: 'Bonjour', farewell: 'Au revoir' }
사용 가능한 내보내기
| 내보내기 | 기능 |
|---|---|
TranslationMethod | 모든 메서드의 베이스 클래스 |
LLMMethod | LLM 메서드의 베이스 클래스 (OpenRouter) |
DirectLLMMethod | 직접 LLM 제공자의 베이스 클래스 (OpenAI, Anthropic, Gemini) |
OpenAIMethod, AnthropicMethod, GeminiMethod | 직접 LLM 제공자 클래스 |
DeepLMethod, MicrosoftTranslatorMethod, LibreTranslateMethod | 전통적 MT 클래스 |
GoogleTranslateMethod | Google Cloud Translation |
LLMCoachedMethod | 코칭된 LLM (OpenRouter + 코칭 데이터) |
APIMethod | 원격 API 클라이언트 |
runSync, runContentSync | 전체 동기화 파이프라인 |
resolveConfig, resolvePairs | 구성 해결 |
validateTranslations | 품질 게이트 |
loadCoachingData, findDictionaryMatches | 코칭 유틸리티 |
사용자 정의 제공자 확장
새 LLM 제공자를 약 40줄로 추가하려면 DirectLLMMethod을 확장하세요:
import { DirectLLMMethod } from 'champollion';
class MistralMethod extends DirectLLMMethod {
constructor(options) {
super(options);
this.name = 'mistral';
}
_getApiKeyEnvVar() { return 'MISTRAL_API_KEY'; }
_getApiKeyOptionsKey() { return 'mistralApiKey'; }
_getDefaultModel() { return 'mistral-large-latest'; }
_getProviderLabel() { return 'Mistral'; }
_buildApiRequest({ prompt, systemMessage, apiKey, model, temperature }) {
return {
url: 'https://api.mistral.ai/v1/chat/completions',
headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
body: {
model,
messages: [
...(systemMessage ? [{ role: 'system', content: systemMessage }] : []),
{ role: 'user', content: prompt },
],
temperature,
},
};
}
_extractResponseText(json) {
return json.choices?.[0]?.message?.content;
}
// Optional but recommended: provider-specific setup help when translation fails
getSetupHelp() {
if (!process.env.MISTRAL_API_KEY) {
return [
'',
' ┌─ Missing API Key ─────────────────────────────────────────────┐',
' │ Mistral requires an API key from https://console.mistral.ai │',
' │ Run: export MISTRAL_API_KEY=... │',
' └────────────────────────────────────────────────────────────────┘',
];
}
return [' API key is set but translation failed. Check your Mistral dashboard.'];
}
}
translate, 코칭, 재시도 루프, 모델 검증, 품질 티어, 설정 도움말을 무료로 얻을 수 있어요. 제공자별로 다른 것은 HTTP 요청 형태뿐이에요. 원시 fetch()를 사용하는 비-LLM 어댑터의 경우, 직접 재시도 루프를 작성하는 대신 lib/methods/fetch-with-retry.js의 공유 fetchWithRetry() 헬퍼를 사용하세요.