i18n 문서로 돌아가기
Translation Loaders
설정
@hua-labs/i18n-loaders
번역 로딩 전략 가이드: API, 정적, 커스텀 로더의 사용 사례와 SSR 지원 여부.
설치
Terminalbash
npm install @hua-labs/i18n-loadersImporttsx
import { Translation Loaders } from '@hua-labs/i18n-loaders';개요
Translation Loaders는 API 엔드포인트, 정적 파일 또는 커스텀 소스에서 번역 파일을 로드하는 유연한 전략을 제공합니다.
로더 유형
API 로더
SSR
API 엔드포인트에서 번역을 로드, 서버 렌더링 앱에 적합
정적 로더
Client
정적 JSON 파일에서 번역을 로드, 클라이언트 사이드 앱에 적합
커스텀 로더
Flexible
CMS 또는 데이터베이스 기반 번역을 위한 커스텀 로딩 전략 구현
API 레퍼런스
옵션
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| translationApiPath | string | "/api/translations" | docs:i18n.translation-loaders.options.translationApiPath |
| baseUrl | string | - | docs:i18n.translation-loaders.options.baseUrl |
| cacheTtlMs | number | 300000 | docs:i18n.translation-loaders.options.cacheTtlMs |
| disableCache | boolean | false | docs:i18n.translation-loaders.options.disableCache |
| retryCount | number | 0 | docs:i18n.translation-loaders.options.retryCount |
| retryDelay | number | 1000 | docs:i18n.translation-loaders.options.retryDelay |
| autoInvalidateInDev | boolean | true | docs:i18n.translation-loaders.options.autoInvalidateInDev |
| fetcher | (url: RequestInfo | URL, init?: RequestInit) => Promise<Response> | fetch | docs:i18n.translation-loaders.options.fetcher |
| localFallbackBaseUrl | string | "http://localhost:3000" | docs:i18n.translation-loaders.options.localFallbackBaseUrl |
| requestInit | RequestInit | ((lang: string, ns: string) => RequestInit) | - | docs:i18n.translation-loaders.options.requestInit |
| logger | Pick<Console, 'log' | 'warn' | 'error'> | console | docs:i18n.translation-loaders.options.logger |
반환값
| 이름 | 타입 | 설명 |
|---|---|---|
| loader | (language: string, namespace: string) => Promise<TranslationRecord> | docs:i18n.translation-loaders.returns.loader |
| invalidate | (language?: string, namespace?: string) => void | docs:i18n.translation-loaders.returns.invalidate |
| clear | () => void | docs:i18n.translation-loaders.returns.clear |
코드 예시
docs:i18n.translation-loaders.examples.i18nexamplesproductionloader
tsx
import { createApiTranslationLoader } from '@hua-labs/i18n-loaders';
import { createCoreI18n } from '@hua-labs/i18n-core';
// Production-ready loader with caching, retry, and dev auto-invalidation
// Returns TranslationLoader function with .invalidate() and .clear() methods
const loader = createApiTranslationLoader({
translationApiPath: '/api/translations',
baseUrl: process.env.NEXT_PUBLIC_BASE_URL,
retryCount: 2,
retryDelay: 1000,
cacheTtlMs: 5 * 60 * 1000, // 5 minutes
autoInvalidateInDev: true,
});
// Pass to createCoreI18n
const I18nProvider = createCoreI18n({
defaultLanguage: 'ko',
supportedLanguages: [
{ code: 'ko', name: 'Korean', nativeName: '한국어' },
{ code: 'en', name: 'English', nativeName: 'English' },
],
namespaces: ['common', 'navigation'],
translationLoader: 'custom',
loadTranslations: loader,
});
// Cache management via attached methods
loader.invalidate('ko', 'common'); // Invalidate specific
loader.invalidate('ko'); // Invalidate all for language
loader.clear(); // Clear all cachedocs:i18n.translation-loaders.examples.i18nexamplespreloadandwarm
tsx
import { preloadNamespaces, warmFallbackLanguages } from '@hua-labs/i18n-loaders';
// Preload critical namespaces at app startup
// preloadNamespaces(language, namespaces, loader, options?)
await preloadNamespaces('ko', ['common', 'navigation'], loader, { suppressErrors: true });
await preloadNamespaces('en', ['common', 'navigation'], loader);
// Warm fallback language cache for instant switching
// warmFallbackLanguages(currentLanguage, languages, namespaces, loader, options?)
await warmFallbackLanguages('ko', ['ko', 'en', 'ja'], ['common'], loader);docs:i18n.translation-loaders.examples.i18nexamplesloadercomparison
tsx
/**
* Translation Loader Comparison
* 번역 로더 비교
*
* | Loader | Location | SSR Support | Use Case |
* |----------|---------------------|-------------|-----------------------------|
* | api | lib/translations/ | ✅ Yes | Production apps, SSR |
* | static | public/translations/| ❌ No | Simple apps, prototypes |
* | custom | Any | ✅ Possible | CMS, external APIs |
*/docs:i18n.translation-loaders.examples.i18nexamplesapiloader
tsx
// hua.config.ts - API Loader (Recommended for SSR)
import { defineConfig } from '@hua-labs/hua/framework';
export default defineConfig({
i18n: {
defaultLanguage: 'ko',
supportedLanguages: ['ko', 'en', 'ja'],
namespaces: ['common', 'navigation'],
translationLoader: 'api', // Load from lib/translations/
translationApiPath: '/api/translations',
},
});
// File structure:
// your-app/
// ├── lib/
// │ └── translations/
// │ ├── ko/
// │ │ ├── common.json
// │ │ └── navigation.json
// │ └── en/
// │ ├── common.json
// │ └── navigation.jsondocs:i18n.translation-loaders.examples.i18nexamplesstaticloader
tsx
// hua.config.ts - Static Loader (No SSR)
import { defineConfig } from '@hua-labs/hua/framework';
export default defineConfig({
i18n: {
defaultLanguage: 'ko',
supportedLanguages: ['ko', 'en'],
namespaces: ['common'],
translationLoader: 'static', // Load from public/translations/
},
});
// File structure:
// your-app/
// └── public/
// └── translations/
// ├── ko/
// │ └── common.json
// └── en/
// └── common.json
// ⚠️ Warning: Static loader causes language flickering on SSR
// because translations are fetched client-side after hydration.docs:i18n.translation-loaders.examples.i18nexamplescustomloader
tsx
// hua.config.ts - Custom Loader
import { defineConfig } from '@hua-labs/hua/framework';
export default defineConfig({
i18n: {
defaultLanguage: 'ko',
supportedLanguages: ['ko', 'en'],
namespaces: ['common'],
translationLoader: 'custom',
customLoader: async (language: string, namespace: string) => {
// Load from CMS, external API, or any source
const response = await fetch(
`https://cms.example.com/translations/${language}/${namespace}`
);
return response.json();
},
},
});docs:i18n.translation-loaders.examples.i18nexamplesapiroute
tsx
// app/api/translations/[language]/[namespace]/route.ts
import { NextResponse } from "next/server";
import fs from "fs";
import path from "path";
export async function GET(
request: Request,
{ params }: { params: Promise<{ language: string; namespace: string }> }
) {
const { language, namespace } = await params;
// API loader reads from lib/translations/ (not public/)
const filePath = path.join(
process.cwd(),
"lib/translations", // ← Server-side only, supports SSR
language,
`${namespace}.json`
);
try {
const content = fs.readFileSync(filePath, "utf-8");
return NextResponse.json(JSON.parse(content));
} catch {
return NextResponse.json({}, { status: 404 });
}
}사용 사례
SSR 앱
올바른 언어로 서버사이드 렌더링이 필요한 프로덕션 앱
정적 사이트
SSR이 필요 없는 간단한 사이트
CMS 연동
외부 CMS 또는 API에서 번역 로드