메인 콘텐츠로 건너뛰기

설정

Rosetta는 설정 없이(zero-config) 작동해요. 프로젝트에서 로케일 파일, 형식, 대상 언어를 자동으로 감지하거든요. 더 세밀하게 제어하려면 프로젝트 루트에 i18n-rosetta.config.json 파일을 만들거나 다음 명령을 실행하세요:

npx i18n-rosetta init

전체 설정 참조

i18n-rosetta.config.json
{
"version": 3,
"inputLocale": "en",
"localesDir": "./locales",
"contentDir": null,
"translatableFields": null,
"format": "auto",
"model": "google/gemini-3.5-flash",
"defaultMethod": "llm",
"batchSize": 80,
"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 타입 생성은 아직 구현되지 않았어요. 이는 향후 추가될 기능을 위한 자리 표시자(placeholder)예요. 이 값들을 설정해도 아무런 효과가 없어요. :::

필드

필드타입기본값설명
versionnumber3설정 스키마 버전이에요. 항상 3을 사용해요.
inputLocalestring"en"소스 언어 코드예요 (BCP 47).
localesDirstring"./locales"로케일 파일 경로예요. Rosetta가 이 디렉터리를 스캔해요.
contentDirstringnullHugo 콘텐츠 디렉터리예요. Markdown 본문 번역을 활성화해요.
translatableFieldsstring[]null콘텐츠 번역 시 번역 가능한 기본 frontmatter 필드를 재정의해요. null은 내장된 기본값(title, description, summary)을 사용해요.
formatstring"auto"파일 형식이에요: json, toml, yaml, 또는 auto (확장자에서 감지해요).
modelstring"google/gemini-3.5-flash"LLM 메서드의 기본 모델이에요. 형식은 메서드에 따라 달라요: OpenRouter는 provider/model를 사용하고(예: google/gemini-3.5-flash), 직접 제공자는 기본 이름만 사용해요(예: gpt-4o, gemini-2.5-flash).
defaultMethodstring"llm"기본 번역 메서드예요: llm, llm-coached, google-translate, deepl, microsoft-translator, libretranslate, openai, anthropic, gemini, api. --method CLI 플래그로 재정의할 수 있어요.
batchSizenumber80번역 배치당 키 개수예요. 높을수록 API 호출 횟수는 줄어들지만 프롬프트 크기가 커져요.
jsonConcurrencynumber200JSON 키 동기화를 위한 최대 병렬 로케일 번역 수예요. --json-concurrency CLI 플래그로 재정의할 수 있어요.
contentConcurrencynumber48콘텐츠(Markdown/MDX) 번역을 위한 최대 병렬 API 호출 수예요. --content-concurrency CLI 플래그로 재정의할 수 있어요.
fallbackPrefixstring"[EN] "auditverify이 이전 실행에서 번역되지 않은 레거시 값을 감지하는 데 사용하는 마커 접두사예요. Rosetta는 이 접두사를 쓰지 않고 감지를 위해 읽기만 해요.
apiKeyEnvVarstring"OPENROUTER_API_KEY"API 키의 환경 변수 이름이에요. 사용자 지정 환경 변수 이름을 사용하려면 재정의하세요.
baseUrlstring""SEO 아티팩트 생성(hreflang, sitemaps, JSON-LD)을 위한 기본 URL이에요.
pairsobject{}쌍(pair)별 메서드, 모델, 품질 재정의예요. 쌍 설정(Pair Configuration)을 참고하세요.
languagesobject{}언어별 재정의예요. 언어 설정(Language Configuration)을 참고하세요.
lint.srcDirstringnull린트 스캔을 위한 소스 디렉터리예요. null = 프레임워크에서 자동 감지해요.
lint.ignorestring[]["node_modules", ...]린트에서 제외할 Glob 패턴이에요.
lint.minLengthnumber2하드코딩된 것으로 표시할 최소 문자열 길이예요.
seo.urlPatternstring"/:locale/:path"hreflang 태그 생성을 위한 URL 패턴 템플릿이에요.
seo.pagesstring[]nullSEO를 위한 명시적 페이지 목록이에요. null = 로케일 키에서 자동 감지해요.
typegen.outputstringnull생성된 TypeScript 타입의 출력 경로예요. null = 비활성화돼요.
typegen.autoGeneratebooleanfalse각 동기화 후 타입을 자동으로 다시 생성해요.

쌍 설정 (Pair Configuration)

각 소스→대상 쌍은 독립적으로 설정할 수 있어요:

{
"pairs": {
"en:fr": {
"method": "google-translate",
"qualityTier": "high"
},
"en:ja": {
"method": "llm",
"model": "google/gemini-2.5-pro"
},
"en:crk": {
"methodPlugin": "crk-coached-v1"
}
}
}

쌍 필드

필드타입설명
methodstring번역 메서드예요: llm, llm-coached, google-translate, deepl, microsoft-translator, libretranslate, openai, anthropic, gemini, api
methodPluginstring설치된 플러그인 이름이에요 (.rosetta/methods/에서 가져옴)
modelstring이 쌍의 기본 모델을 재정의해요
endpointstring원격 API 엔드포인트 URL이에요. methodapi일 때 필수예요.
qualityTierstring표시 티어예요: standard, high, research, verified

언어 설정

언어는 세 가지 형식을 허용해요:

코드 배열 (가장 간단함)

{
"languages": ["fr", "de", "ja"]
}

각 언어는 내장된 레지스터 테이블에서 기본 레지스터(register)를 가져와요. 기본값이 없는 언어는 "Professional register."을 사용해요.

레지스터 문자열이 있는 객체

값은 언어 카드의 **프리셋 키(preset key)**이거나 사용자 지정 레지스터 텍스트일 수 있어요:

{
"languages": {
"fr": "casual-tu",
"ko": "formal-hapsyo",
"ja": "Custom: Polite Japanese for a gaming app."
}
}

Rosetta는 문자열이 언어 카드의 프리셋 키와 일치하는지 확인해요. 일치하면 카드의 전체 레지스터 프롬프트를 사용해요. 그렇지 않으면 문자열을 그대로 사용해요. 사용 가능한 프리셋은 지원되는 언어(Supported Languages)를 참고하세요.

전체 설정이 있는 객체

{
"languages": {
"crk": {
"name": "Plains Cree",
"register": "SRO syllabics with grammatical precision.",
"model": "google/gemini-2.5-pro",
"batchSize": 5,
"maxRetries": 5,
"script": "cans"
}
}
}

동일한 블록 내에서 약식과 전체 객체를 섞어서 사용할 수 있어요.

언어 필드

필드타입설명
registerstring스타일/어조 지침이에요. 프리셋 키(예: casual-tu, formal-hapsyo) 또는 사용자 지정 텍스트일 수 있어요. 언어 카드(Language Cards)를 참고하세요.
namestring사람이 읽을 수 있는 언어 이름이에요 (상태 표시용)
modelstring기본 모델을 재정의해요
batchSizenumber기본 배치 크기를 재정의해요
maxRetriesnumber실패한 배치에 대한 최대 재시도 횟수예요 (기본값: 3)
scriptstringISO 15924 스크립트 코드예요. 품질 게이트(quality gate)에서 스크립트 유효성 검사를 트리거해요.

:::info 상속 체인 설정은 다음 순서로 확인돼요 (먼저 적용된 것이 우선):

쌍(pair) 수준언어 수준전역 설정기본값

예를 들어, pairs["en:fr"]에서 model을 설정하면, 언어 수준과 전역 model 값을 모두 재정의해요. :::

영어가 아닌 소스

소스 언어가 영어가 아닌 경우:

# CLI flag (one-time)
npx i18n-rosetta sync --source fr
i18n-rosetta.config.json (permanent)
{
"inputLocale": "fr"
}

잠금 파일 (Lock File)

Rosetta는 번역된 소스 값의 SHA-256 해시를 추적하기 위해 .i18n-rosetta.lock 파일을 생성해요. 모든 개발자가 동일한 번역 기준선을 공유할 수 있도록 이 파일을 커밋해 주세요.

소스 값이 변경되면 해시가 더 이상 일치하지 않으며, Rosetta는 다음 동기화 시 해당 키를 다시 번역해요.

.rosettaignore

lint 스캔에서 파일을 제외하려면 프로젝트 루트에 .rosettaignore 파일을 만드세요. .gitignore과 같은 glob 패턴을 사용해요:

.rosettaignore
src/components/legacy/**
src/utils/constants.js
**/*.test.js

.rosetta/ 디렉터리

Rosetta는 내부 상태를 위해 프로젝트 루트에 .rosetta/ 디렉터리를 생성해요. 이는 프로젝트 소스가 아닌 로컬 최적화이므로, 일반적으로 .gitignore에 추가해야 해요:

.rosetta/
파일목적커밋 여부
tm.json번역 메모리 캐시 — 소스 텍스트 + 로케일 + 메서드를 키로 사용하여 이전 번역을 저장해요아니요 (로컬 캐시)
xliff/*.xliff전문 번역가 검토를 위한 XLIFF 내보내기 파일이에요아니요 (임시 파일)
methods/설치된 메서드 플러그인 매니페스트예요예 (공유 설정)
backups/래핑 전 백업이에요 (wrap --undo에 의해 생성됨)아니요 (안전망)

tm.json에 대한 자세한 내용과 API 비용을 절감하는 방법은 번역 메모리(Translation Memory)를 참고하세요.


프로그래밍 방식 API

빌드 스크립트 및 사용자 지정 통합을 위해 패키지에서 직접 가져오세요:

import { GeminiMethod, runSync, resolveConfig } from 'i18n-rosetta';

// 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' }

사용 가능한 내보내기(Exports)

내보내기기능
TranslationMethod모든 메서드의 기본 클래스예요
LLMMethodLLM 메서드(OpenRouter)의 기본 클래스예요
DirectLLMMethod직접 LLM 제공자(OpenAI, Anthropic, Gemini)의 기본 클래스예요
OpenAIMethod, AnthropicMethod, GeminiMethod직접 LLM 제공자 클래스예요
DeepLMethod, MicrosoftTranslatorMethod, LibreTranslateMethod전통적인 기계 번역(MT) 클래스예요
GoogleTranslateMethodGoogle Cloud Translation이에요
LLMCoachedMethod코칭된 LLM(OpenRouter + 코칭 데이터)이에요
APIMethod원격 API 클라이언트예요
runSync, runContentSync전체 동기화 파이프라인이에요
resolveConfig, resolvePairs설정 확인(resolution)이에요
validateTranslations품질 게이트(Quality gate)예요
loadCoachingData, findDictionaryMatches코칭 유틸리티예요

사용자 지정 제공자 확장

DirectLLMMethod를 확장하여 약 40줄의 코드로 새로운 LLM 제공자를 추가할 수 있어요:

import { DirectLLMMethod } from 'i18n-rosetta';

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.'];
}
}

번역, 코칭, 재시도 루프, 모델 유효성 검사, 품질 티어 및 설정 도움말이 기본으로 제공돼요. HTTP 요청 형태만 제공자에 따라 달라요. 원시 fetch()를 사용하는 비 LLM 어댑터의 경우, 자체 재시도 루프를 작성하는 대신 lib/methods/fetch-with-retry.js의 공유 fetchWithRetry() 헬퍼를 사용하세요.


참고 항목