Skip to content

언어 감지 미들웨어

언어 감지 미들웨어는 사용자의 선호 언어(로케일)를 다양한 소스에서 자동으로 식별하고 c.get('language')를 통해 제공한다. 쿼리 파라미터, 쿠키, 헤더, URL 경로 세그먼트 등 다양한 전략을 사용해 언어를 감지한다. 국제화(i18n)와 로케일별 콘텐츠 제공에 적합하다.

Import

ts
import { Hono } from 'hono'
import { languageDetector } from 'hono/language'

기본 사용법

쿼리 문자열, 쿠키, 헤더(기본 순서)에서 언어를 감지하고, 실패 시 영어로 대체하는 예제:

ts
const app = new Hono()

app.use(
  languageDetector({
    supportedLanguages: ['en', 'ar', 'ja'], // fallback 언어를 반드시 포함
    fallbackLanguage: 'en', // 필수
  })
)

app.get('/', (c) => {
  const lang = c.get('language')
  return c.text(`Hello! Your language is ${lang}`)
})

클라이언트 예제

sh
# 경로를 통한 방식
curl http://localhost:8787/ar/home

# 쿼리 파라미터를 통한 방식
curl http://localhost:8787/?lang=ar

# 쿠키를 통한 방식
curl -H 'Cookie: language=ja' http://localhost:8787/

# 헤더를 통한 방식
curl -H 'Accept-Language: ar,en;q=0.9' http://localhost:8787/

기본 설정

ts
export const DEFAULT_OPTIONS: DetectorOptions = {
  order: ['querystring', 'cookie', 'header'],
  lookupQueryString: 'lang',
  lookupCookie: 'language',
  lookupFromHeaderKey: 'accept-language',
  lookupFromPathIndex: 0,
  caches: ['cookie'],
  ignoreCase: true,
  fallbackLanguage: 'en',
  supportedLanguages: ['en'],
  cookieOptions: {
    sameSite: 'Strict',
    secure: true,
    maxAge: 365 * 24 * 60 * 60,
    httpOnly: true,
  },
  debug: false,
}

주요 동작

언어 감지 워크플로

  1. 순서: 기본적으로 다음 순서로 소스를 확인한다:

    • 쿼리 파라미터 (?lang=ar)
    • 쿠키 (language=ar)
    • Accept-Language 헤더
  2. 캐싱: 감지된 언어를 쿠키에 저장한다 (기본값 1년)

  3. 대체 언어: 유효한 감지 결과가 없으면 fallbackLanguage를 사용한다 (supportedLanguages 목록에 포함되어 있어야 함)

고급 설정

커스텀 감지 순서

URL 경로 감지를 우선시하는 예시 (/en/about):

ts
app.use(
  languageDetector({
    order: ['path', 'cookie', 'querystring', 'header'],
    lookupFromPathIndex: 0, // /en/profile → index 0 = 'en'
    supportedLanguages: ['en', 'ar'],
    fallbackLanguage: 'en',
  })
)

언어 코드 변환

복잡한 코드를 정규화한다 (예: en-US → en):

ts
app.use(
  languageDetector({
    convertDetectedLanguage: (lang) => lang.split('-')[0],
    supportedLanguages: ['en', 'ja'],
    fallbackLanguage: 'en',
  })
)

쿠키 설정

ts
app.use(
  languageDetector({
    lookupCookie: 'app_lang',
    caches: ['cookie'],
    cookieOptions: {
      path: '/', // 쿠키 경로
      sameSite: 'Lax', // 쿠키 same-site 정책
      secure: true, // HTTPS에서만 전송
      maxAge: 86400 * 365, // 1년 만료 기간
      httpOnly: true, // 자바스크립트로 접근 불가
      domain: '.example.com', // 선택 사항: 특정 도메인
    },
  })
)

쿠키 캐싱을 비활성화하려면:

ts
languageDetector({
  caches: false,
})

디버깅

로그 감지 단계:

ts
languageDetector({
  debug: true, // "쿼리 문자열에서 감지됨: ar"을 표시
})

옵션 참조

기본 옵션

옵션타입기본값필수 여부설명
supportedLanguagesstring[]['en']허용된 언어 코드
fallbackLanguagestring'en'기본 언어
orderDetectorType[]['querystring', 'cookie', 'header']아니오감지 순서
debugbooleanfalse아니오로깅 활성화

탐지 옵션

옵션타입기본값설명
lookupQueryStringstring'lang'쿼리 파라미터 이름
lookupCookiestring'language'쿠키 이름
lookupFromHeaderKeystring'accept-language'헤더 이름
lookupFromPathIndexnumber0경로 세그먼트 인덱스

쿠키 옵션

옵션타입기본값설명
cachesCacheType[] | false['cookie']캐시 설정
cookieOptions.pathstring'/'쿠키 경로
cookieOptions.sameSite'Strict' | 'Lax' | 'None''Strict'SameSite 정책
cookieOptions.securebooleantrueHTTPS 전용
cookieOptions.maxAgenumber31536000만료 시간 (초)
cookieOptions.httpOnlybooleantrueJS 접근 가능성
cookieOptions.domainstringundefined쿠키 도메인

고급 설정

옵션타입기본값설명
ignoreCasebooleantrue대소문자 구분 없이 매칭
convertDetectedLanguage(lang: string) => stringundefined언어 코드 변환 함수

유효성 검사 및 에러 처리

  • fallbackLanguagesupportedLanguages 목록에 포함되어야 한다 (설정 중 에러 발생)
  • lookupFromPathIndex 값은 0 이상이어야 한다
  • 잘못된 설정은 미들웨어 초기화 과정에서 에러를 발생시킨다
  • 언어 감지 실패 시 자동으로 fallbackLanguage를 사용한다

일반적인 활용 예제

경로 기반 라우팅

ts
app.get('/:lang/home', (c) => {
  const lang = c.get('language') // 'en', 'ar' 등
  return c.json({ message: getLocalizedContent(lang) })
})

다국어 지원

ts
languageDetector({
  supportedLanguages: ['en', 'en-GB', 'ar', 'ar-EG'],
  convertDetectedLanguage: (lang) => lang.replace('_', '-'), // 언어 코드 정규화
})

Released under the MIT License.