로케일 전환
사용자가 선호하는 로케일을 변경할 수 있도록 언어 전환기를 구현하세요.
기본 구현
useLingoContext 훅을 사용하여 현재 로케일과 변경 함수를 가져옵니다:
"use client"; // For Next.js
import { useLingoContext } from "@lingo.dev/compiler/react";
export function LanguageSwitcher() {
const { locale, setLocale } = useLingoContext();
return (
<select value={locale} onChange={(e) => setLocale(e.target.value)}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="de">Deutsch</option>
<option value="fr">Français</option>
</select>
);
}
setLocale()가 호출되면:
- 새 로케일이 저장됩니다(사용자 정의 리졸버 또는 기본 쿠키를 통해)
- 새 로케일을 적용하기 위해 페이지가 새로고침됩니다
사용자 정의 UI
플래그가 있는 드롭다운
"use client";
import { useLingoContext } from "@lingo.dev/compiler/react";
const locales = [
{ code: "en", name: "English", flag: "🇺🇸" },
{ code: "es", name: "Español", flag: "🇪🇸" },
{ code: "de", name: "Deutsch", flag: "🇩🇪" },
{ code: "fr", name: "Français", flag: "🇫🇷" },
];
export function LanguageSwitcher() {
const { locale: currentLocale, setLocale } = useLingoContext();
return (
<div className="relative">
<select
value={currentLocale}
onChange={(e) => setLocale(e.target.value)}
className="px-4 py-2 border rounded-md"
>
{locales.map((locale) => (
<option key={locale.code} value={locale.code}>
{locale.flag} {locale.name}
</option>
))}
</select>
</div>
);
}
버튼 그룹
"use client";
import { useLingoContext } from "@lingo.dev/compiler/react";
export function LanguageSwitcher() {
const { locale, setLocale } = useLingoContext();
const locales = ["en", "es", "de", "fr"];
return (
<div className="flex gap-2">
{locales.map((loc) => (
<button
key={loc}
onClick={() => setLocale(loc)}
className={`px-3 py-1 rounded ${
locale === loc ? "bg-blue-500 text-white" : "bg-gray-200"
}`}
>
{loc.toUpperCase()}
</button>
))}
</div>
);
}
드롭다운 메뉴
"use client";
import { useState } from "react";
import { useLingoContext } from "@lingo.dev/compiler/react";
export function LanguageSwitcher() {
const { locale, setLocale } = useLingoContext();
const [isOpen, setIsOpen] = useState(false);
const locales = [
{ code: "en", name: "English" },
{ code: "es", name: "Español" },
{ code: "de", name: "Deutsch" },
{ code: "fr", name: "Français" },
];
const currentLocaleName = locales.find((l) => l.code === locale)?.name;
return (
<div className="relative">
<button
onClick={() => setIsOpen(!isOpen)}
className="px-4 py-2 border rounded-md flex items-center gap-2"
>
<span>{currentLocaleName}</span>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>
{isOpen && (
<div className="absolute top-full mt-2 bg-white border rounded-md shadow-lg">
{locales.map((loc) => (
<button
key={loc.code}
onClick={() => {
setLocale(loc.code);
setIsOpen(false);
}}
className={`block w-full text-left px-4 py-2 hover:bg-gray-100 ${
locale === loc.code ? "bg-blue-50" : ""
}`}
>
{loc.name}
</button>
))}
</div>
)}
</div>
);
}
지속성
기본적으로 setLocale()는 구성된 로케일 지속성(기본값은 쿠키)을 사용합니다.
사용자 정의 지속성
사용자 정의 로케일 리졸버를 통해 사용자 정의 지속성을 구현하세요:
// .lingo/locale-resolver.client.ts
export function persistLocale(locale: string): void {
// Custom logic: localStorage, URL params, API call, etc.
localStorage.setItem("locale", locale);
window.location.reload();
}
setLocale()는 자동으로 persistLocale() 함수를 호출합니다.
페이지 새로고침 방지
기본적으로 setLocale()는 새 로케일을 적용하기 위해 페이지를 새로고침합니다. 새로고침을 방지하려면:
- 클라이언트 측 상태 관리를 사용하세요
- 모든 로케일에 대한 번역을 미리 로드하세요
- 페이지 새로고침 없이 번역을 전환하세요
참고: 이는 사용자 정의 구현이 필요합니다. 컴파일러의 기본 동작은 단순성을 위해 페이지를 새로고침합니다.
URL 기반 로케일 전환
URL 기반 로케일 라우팅(/en/about, /es/about)의 경우:
"use client";
import { useRouter, usePathname } from "next/navigation";
export function LanguageSwitcher() {
const router = useRouter();
const pathname = usePathname();
// Extract current locale from path: /es/about → es
const currentLocale = pathname.split("/")[1];
function switchLocale(newLocale: string) {
// Replace locale in path: /es/about → /de/about
const newPath = pathname.replace(`/${currentLocale}`, `/${newLocale}`);
router.push(newPath);
}
return (
<select value={currentLocale} onChange={(e) => switchLocale(e.target.value)}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="de">Deutsch</option>
</select>
);
}
서브도메인 기반 전환
서브도메인 기반 라우팅의 경우 (es.example.com):
"use client";
export function LanguageSwitcher() {
const currentLocale = window.location.hostname.split(".")[0];
function switchLocale(newLocale: string) {
const host = window.location.hostname;
const domain = host.split(".").slice(1).join(".");
const newHost = `${newLocale}.${domain}`;
window.location.href = `${window.location.protocol}//${newHost}${window.location.pathname}`;
}
return (
<select value={currentLocale} onChange={(e) => switchLocale(e.target.value)}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="de">Deutsch</option>
</select>
);
}
원어 언어명
더 나은 사용자 경험을 위해 언어명을 원어로 표시하세요:
const locales = [
{ code: "en", name: "English" },
{ code: "es", name: "Español" },
{ code: "de", name: "Deutsch" },
{ code: "fr", name: "Français" },
{ code: "ja", name: "日本語" },
{ code: "zh", name: "中文" },
{ code: "ar", name: "العربية" },
{ code: "ru", name: "Русский" },
];
접근성
언어 전환기를 접근 가능하게 만드세요:
const { locale, setLocale } = useLingoContext();
<div role="group" aria-label="Language selector">
<label htmlFor="language-select" className="sr-only">
Choose language
</label>
<select
id="language-select"
value={locale}
onChange={(e) => setLocale(e.target.value)}
aria-label="Select language"
>
{locales.map((loc) => (
<option key={loc.code} value={loc.code}>
{loc.name}
</option>
))}
</select>
</div>
일반적인 패턴
내비게이션 바 통합
export function Navbar() {
return (
<nav className="flex items-center justify-between p-4">
<Logo />
<div className="flex items-center gap-4">
<NavLinks />
<LanguageSwitcher />
</div>
</nav>
);
}
푸터 통합
export function Footer() {
return (
<footer className="p-4 border-t">
<div className="flex justify-between items-center">
<p>© 2024 Your Company</p>
<LanguageSwitcher />
</div>
</footer>
);
}
모바일 메뉴
export function MobileMenu() {
return (
<div className="mobile-menu">
<NavLinks />
<div className="border-t pt-4 mt-4">
<p className="text-sm text-gray-500 mb-2">Language</p>
<LanguageSwitcher />
</div>
</div>
);
}
테스트
개발 환경에서 로케일 전환을 테스트하세요:
- 언어 전환기 컴포넌트 추가
- 개발 서버 실행
- 클릭하여 로케일 전환
- 새 로케일로 페이지가 다시 로드되는지 확인
- 번역이 업데이트되는지 확인
pseudotranslator가 활성화되면 가짜 번역이 즉시 표시됩니다.
자주 묻는 질문
페이지가 다시 로드되는 이유는 무엇인가요? 컴파일러가 새 로케일을 적용하기 위해 페이지를 다시 로드합니다. 이를 통해 모든 서버 컴포넌트와 메타데이터가 올바르게 업데이트됩니다.
다시 로드를 피할 수 있나요? 가능하지만 커스텀 구현이 필요합니다. 모든 번역을 미리 로드하고 클라이언트 측 상태를 수동으로 관리해야 합니다.
LanguageSwitcher를 Suspense로 래핑해야 하나요?
아니요. useLingoContext는 동기식이므로 suspense가 필요하지 않습니다.
사용자의 브라우저 언어를 자동으로 감지할 수 있나요? 예. 사용자 정의 로케일 리졸버에서 구현하세요:
export function getClientLocale(): string {
return navigator.language.split("-")[0] || "en";
}
지원되는 모든 로케일을 표시해야 하나요, 아니면 일부만 표시해야 하나요? 드롭다운에 모두 표시하세요. 로케일이 많은 경우 지역별로 그룹화하거나 검색/필터 UI를 사용하세요.
다음 단계
- 사용자 정의 로케일 리졸버 — 지속성 사용자 정의
- 프레임워크 통합 — 프레임워크별 라우팅 패턴
- 모범 사례 — 언어 전환을 위한 UX 권장 사항