154 lines
4.7 KiB
TypeScript
154 lines
4.7 KiB
TypeScript
import { DEFAULT_LOCALE_CODE } from '../../i18n.config'
|
|
|
|
// 사용자 선호 언어 조회
|
|
export const getPreferredLanguage = (acceptLanguageHeader = '') => {
|
|
const languages = acceptLanguageHeader
|
|
.split(',')
|
|
.map(lang => {
|
|
const [code, priority = 'q=1'] = lang.trim().split(';q=')
|
|
return { code, priority: parseFloat(priority) }
|
|
})
|
|
.sort((a, b) => b.priority - a.priority)
|
|
|
|
return languages.length > 0 ? languages[0].code : null
|
|
}
|
|
|
|
// 쿠키 파싱 유틸리티 함수
|
|
const parseCookies = (cookieHeader: string) => {
|
|
const cookies: Record<string, string> = {}
|
|
if (cookieHeader) {
|
|
cookieHeader.split(';').forEach(cookie => {
|
|
const [name, value] = cookie.trim().split('=')
|
|
if (name && value) {
|
|
cookies[name] = decodeURIComponent(value)
|
|
}
|
|
})
|
|
}
|
|
return cookies
|
|
}
|
|
|
|
/**
|
|
* 우선순위에 따른 언어 조회 (CSR)
|
|
*
|
|
* @param {string} path - 현재 URL 경로
|
|
*/
|
|
export const csrGetFinalLocale = (path = '', coveragesLocales: string[]) => {
|
|
const runtimeConfig = useRuntimeConfig()
|
|
const baseDomain = `${runtimeConfig.public.baseDomain}`
|
|
|
|
let finalLocale = DEFAULT_LOCALE_CODE // 기본값 설정
|
|
|
|
// coveragesLocales가 빈 배열이거나 유효하지 않은 경우 기본 언어 반환
|
|
if (
|
|
!coveragesLocales ||
|
|
!Array.isArray(coveragesLocales) ||
|
|
coveragesLocales.length === 0
|
|
) {
|
|
return finalLocale
|
|
}
|
|
|
|
// 1. URL 패스에 포함된 언어
|
|
if (path && path !== '' && path.split('/').length > 1) {
|
|
// 쿼리스트링 제거한 순수 path 검사
|
|
if (path.includes('?')) {
|
|
path = path.split('?')[0]
|
|
}
|
|
const pathLocale = `${path.split('/')[1]}`.toLowerCase()
|
|
|
|
// URL 패스에 포함된 언어가 지원하는 언어인지 체크
|
|
if (pathLocale && pathLocale !== '') {
|
|
finalLocale = pathLocale
|
|
return finalLocale
|
|
}
|
|
return finalLocale
|
|
}
|
|
|
|
// 2. LOCALE 쿠키 언어
|
|
const cookieLanguage =
|
|
`${useCookie('LOCALE', { domain: baseDomain }).value}`.toLowerCase()
|
|
if (cookieLanguage && cookieLanguage !== '') {
|
|
finalLocale = cookieLanguage
|
|
return finalLocale
|
|
}
|
|
|
|
// 3. 브라우저 언어
|
|
const browserLanguage =
|
|
`${navigator.language || navigator.languages[0]}`.toLowerCase()
|
|
if (
|
|
browserLanguage &&
|
|
browserLanguage !== '' &&
|
|
coveragesLocales.includes(browserLanguage)
|
|
) {
|
|
finalLocale = browserLanguage
|
|
return finalLocale
|
|
}
|
|
|
|
// 3. 서비스 기본 언어
|
|
finalLocale = DEFAULT_LOCALE_CODE
|
|
|
|
return finalLocale
|
|
}
|
|
|
|
/**
|
|
* 우선순위에 따른 언어 조회 (SSR)
|
|
*
|
|
* @param {string} path - 현재 URL 경로
|
|
* @param {any} headers - 요청 헤더
|
|
*/
|
|
export const ssrGetFinalLocale = (path, headers: any, coveragesLocales: string[], defaultLocale: string) => {
|
|
let finalLocale = defaultLocale // 기본값 설정
|
|
|
|
try {
|
|
// 1. URL path에 포함된 언어 정보
|
|
if (path && path !== '' && path.split('/').length > 1) {
|
|
// 쿼리스트링 제거한 순수 path 검사
|
|
if (path.includes('?')) {
|
|
path = path.split('?')[0]
|
|
}
|
|
const pathLocalee = `${path.split('/')[1]}`.toLowerCase()
|
|
// URL path에 포함된 언어 정보가 지원하는 언어인지 체크
|
|
if (pathLocalee && pathLocalee !== '' && coveragesLocales.includes(pathLocalee)) {
|
|
finalLocale = pathLocalee
|
|
|
|
return finalLocale
|
|
}
|
|
}
|
|
|
|
// 2. LOCALE 쿠키 언어 (SSR에서는 headers에서 직접 파싱)
|
|
const cookieHeader = headers.cookie || ''
|
|
const cookies = parseCookies(cookieHeader)
|
|
const cookieLanguage = cookies.LOCALE ? `${cookies.LOCALE}`.toLowerCase() : ''
|
|
if (cookieLanguage && cookieLanguage !== '' && coveragesLocales.includes(cookieLanguage)) {
|
|
finalLocale = cookieLanguage
|
|
return finalLocale
|
|
}
|
|
|
|
// 3. 요청 헤더의 브라우저 언어 (accept-language)
|
|
if (headers && headers['accept-language']) {
|
|
const acceptLanguage = Array.isArray(headers['accept-language'])
|
|
? headers['accept-language'][0]
|
|
: headers['accept-language']
|
|
|
|
if (acceptLanguage && typeof acceptLanguage === 'string') {
|
|
const preferredLocale = getPreferredLanguage(acceptLanguage)
|
|
if (preferredLocale) {
|
|
// 선호 언어의 기본 코드와 일치하는 지원 로케일 찾기
|
|
const matchedLocale = coveragesLocales.find((locale: string) =>
|
|
preferredLocale.toLowerCase().startsWith(locale.toLowerCase())
|
|
)
|
|
if (matchedLocale) {
|
|
finalLocale = matchedLocale.toLowerCase()
|
|
return finalLocale
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 서비스 기본 언어
|
|
finalLocale = defaultLocale
|
|
} catch (e) {
|
|
finalLocale = defaultLocale
|
|
}
|
|
return finalLocale
|
|
}
|