SvelteKit i18n: 국제화 설정 가이드
처음부터 다국어 앱까지 ICU 메시지 형식, 로케일 기반 라우팅, 스마트 폴백 체인으로 SvelteKit 앱에 svelte-i18n을 설정하세요.
svelte-i18n 설치
svelte-i18n은 Svelte와 SvelteKit의 표준 국제화 라이브러리예요. 반응형 스토어, ICU MessageFormat 지원, 지연 로케일 로드를 기본으로 제공해요.
npm install svelte-i18nsvelte-i18n 구성
지연 로드 import 함수로 로케일을 등록하는 i18n 구성 파일을 만드세요. svelte-i18n은 해당 로케일이 활성화될 때만 메시지를 가져와요.
// src/lib/i18n.ts
import { register, init, getLocaleFromNavigator } from 'svelte-i18n';
// Register locale loaders (lazy-loaded)
register('en', () => import('../locales/en.json'));
register('de', () => import('../locales/de.json'));
register('ja', () => import('../locales/ja.json'));
register('es', () => import('../locales/es.json'));
init({
fallbackLocale: 'en',
initialLocale: getLocaleFromNavigator(), // Auto-detect browser language
});SvelteKit 레이아웃 통합
루트 레이아웃에서 i18n 구성을 가져오고 $isLoading 스토어로 렌더링을 제어하세요. 로케일 데이터를 비동기로 로드하는 동안 번역되지 않은 키가 잠깐 표시되는 현상을 막을 수 있어요.
<!-- src/routes/+layout.svelte -->
<script>
// Import i18n config — must run before any component renders
import '../lib/i18n';
import { isLoading } from 'svelte-i18n';
</script>
{#if $isLoading}
<p>Loading translations...</p>
{:else}
<slot />
{/if}SvelteKit의 로케일 기반 라우팅
/en/about, /de/about 같은 SEO 친화적 URL에는 [lang] 경로 매개변수를 사용하세요. URL 매개변수를 기준으로 레이아웃의 load 함수에서 svelte-i18n 로케일을 설정하세요.
// src/routes/[lang]/+layout.ts
import { locale } from 'svelte-i18n';
export function load({ params }) {
// Set the active locale from the URL parameter
locale.set(params.lang);
return {};
}
// src/routes/[lang]/+layout.svelte
<script>
import '../../lib/i18n';
import { isLoading } from 'svelte-i18n';
</script>
{#if $isLoading}
<p>Loading...</p>
{:else}
<slot />
{/if}번역 파일 형식
로케일마다 JSON 파일을 하나씩 만드세요. svelte-i18n은 복수형, 변수, select 표현식에 중첩 키와 ICU MessageFormat 구문을 지원해요.
// src/locales/en.json
{
"nav": {
"home": "Home",
"about": "About",
"settings": "Settings"
},
"greeting": "Hello, {name}!",
"cart": {
"itemCount": "{count, plural, one {# item} other {# items}}"
}
}
// src/locales/de.json
{
"nav": {
"home": "Startseite",
"about": "Uber uns",
"settings": "Einstellungen"
},
"greeting": "Hallo, {name}!",
"cart": {
"itemCount": "{count, plural, one {# Artikel} other {# Artikel}}"
}
}컴포넌트에서 번역 사용
svelte-i18n에서 $_ 스토어(또는 $format)를 가져와 Svelte 템플릿에서 사용하세요. 스토어는 반응형이므로 로케일이 바뀌면 번역된 모든 문자열이 자동으로 업데이트돼요.
<script>
import { _ } from 'svelte-i18n';
</script>
<h1>{$_('greeting', { values: { name: 'World' } })}</h1>
<nav>
<a href="/">{$_('nav.home')}</a>
<a href="/about">{$_('nav.about')}</a>
</nav><script>
import { _, date, number, time } from 'svelte-i18n';
</script>
<!-- Simple string -->
<p>{$_('greeting', { values: { name: userName } })}</p>
<!-- ICU plurals — handled automatically -->
<p>{$_('cart.itemCount', { values: { count: 3 } })}</p>
<!-- Date formatting -->
<p>{$date(new Date(), { format: 'long' })}</p>
<!-- Number formatting -->
<p>{$number(1999.99, { style: 'currency', currency: 'USD' })}</p>언어 전환
$locale 스토어에 바인딩되는 언어 선택기를 만드세요. 값이 바뀌면 svelte-i18n이 새 로케일의 메시지를 로드하고 번역된 모든 문자열을 반응형으로 업데이트해요.
<script>
import { locale, locales } from 'svelte-i18n';
const LANGUAGE_NAMES = {
en: 'English',
de: 'Deutsch',
ja: '日本語',
es: 'Espanol',
};
</script>
<select bind:value={$locale}>
{#each $locales as loc}
<option value={loc}>{LANGUAGE_NAMES[loc] ?? loc}</option>
{/each}
</select>ICU MessageFormat으로 복수형 처리
svelte-i18n은 모든 CLDR 복수형 범주를 처리하는 국제 표준인 ICU MessageFormat을 복수형 처리에 사용해요. 아랍어에는 6가지, 러시아어에는 4가지, 일본어에는 1가지 형식이 있어요. 대상 언어에 필요한 형식을 정의하면 svelte-i18n이 올바른 형식을 자동으로 선택해요.
// svelte-i18n uses ICU MessageFormat for plurals
// English:
{
"items": "{count, plural, one {# item} other {# items}}"
}
// Arabic (6 forms):
{
"items": "{count, plural, zero {no items} one {item} two {two items} few {# items} many {# items} other {# items}}"
}
// Japanese (1 form):
{
"items": "{count, plural, other {#個のアイテム}}"
}svelte-i18n-locale-chain을 활용한 스마트 로케일 폴백
svelte-i18n은 키가 없으면 중간 폴백 없이 fallbackLocale로 바로 폴백해요. 쓸 수 있는 pt-PT 번역이 있어도 pt-BR 사용자에게 영어가 표시돼요. svelte-i18n-locale-chain은 지역 변형의 메시지를 딥 머지하는 스마트 폴백 체인으로 이 문제를 해결해요.
npm install svelte-i18n-locale-chain svelte-i18n// src/lib/i18n.ts
import { initLocaleChain, setLocale } from 'svelte-i18n-locale-chain';
// Replace svelte-i18n's init + register with initLocaleChain
await initLocaleChain({
loadMessages: (locale) =>
import(`../locales/${locale}.json`).then(m => m.default),
defaultLocale: 'en',
initialLocale: 'pt-BR',
});
// Later, to change locale:
await setLocale('fr-CA');
// fr-CA user sees: fr-CA messages -> fr messages -> en messages
// No missing keys — deep-merged automatically번역 자동화
i18n 설정을 마쳤다면 AI로 로케일 파일을 번역하세요. IDE에서 AI 어시스턴트에게 원문 파일 번역을 요청하거나 CI/CD 파이프라인에서 i18n Agent CLI를 사용하세요.
# In your IDE, ask your AI assistant:
> Translate src/locales/en.json to German, Japanese, and Spanish
✓ de.json created (1.2s)
✓ ja.json created (1.5s)
✓ es.json created (1.1s)
# Or use the CLI in CI/CD:
npx i18n-agent translate src/locales/en.json --lang de,ja,es번역 품질 자동화
흔한 실수
SvelteKit의 SSR 로케일 누출
svelte-i18n-locale-chain과 register() 함께 사용
ICU 구문 오류의 무음 실패
번역되지 않은 콘텐츠 깜박임
권장 파일 구조
my-sveltekit-app/
├── src/
│ ├── lib/
│ │ └── i18n.ts # i18n configuration
│ ├── locales/
│ │ ├── en.json # Source language
│ │ ├── de.json # German
│ │ ├── ja.json # Japanese
│ │ └── es.json # Spanish
│ └── routes/
│ ├── +layout.svelte # Import i18n, guard isLoading
│ ├── +page.svelte
│ └── [lang]/ # Optional: locale-based routing
│ ├── +layout.ts # Set locale from URL param
│ ├── +layout.svelte
│ └── +page.svelte
├── svelte.config.js
└── package.json지금 i18n Agent 사용해 보기
번역 파일을 여기에 드롭
JSON, YAML, PO, XML, CSV, Markdown, Properties
또는 클릭하여 파일 선택
대상 언어
svelte-i18n-locale-chain을 활용한 로케일 폴백
pt-BR 같은 지역 로케일에 번역 키가 없으면 svelte-i18n은 상위 로케일 pt를 먼저 확인하지 않고 기본 로케일로 바로 이동해요.
npm install svelte-i18n-locale-chainimport { initLocaleChain } from 'svelte-i18n-locale-chain';
initLocaleChain({
fallbacks: {
'pt-BR': ['pt', 'en'],
'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
},
defaultLocale: 'en',
});지원 프레임워크와 내장 체인 75개의 전체 목록은 로케일 폴백 가이드에서 확인하세요. Learn more →