Files
web-temp/layers/utils/localeUtil.ts

168 lines
4.6 KiB
TypeScript

// 사용자 선호 언어 조회
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[],
defaultLocale: string
) => {
const runtimeConfig = useRuntimeConfig()
const baseDomain = `${runtimeConfig.public.baseDomain}`
let finalLocale = defaultLocale // 기본값 설정
// 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 !== '' &&
coveragesLocales.includes(pathLocale)
) {
finalLocale = pathLocale
return finalLocale
}
return finalLocale
}
// 2. LOCALE 쿠키 언어
const cookieLanguage =
`${useCookie('LOCALE', { domain: baseDomain }).value}`.toLowerCase()
if (
cookieLanguage &&
cookieLanguage !== '' &&
coveragesLocales.includes(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. 서비스 기본 언어
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
}
}
}
}
// 4. 서비스 기본 언어
finalLocale = defaultLocale
} catch (e) {
finalLocale = defaultLocale
}
return finalLocale
}