167 lines
5.1 KiB
TypeScript
167 lines
5.1 KiB
TypeScript
import { DEFAULT_LOCALE_CODE, DEFAULT_COVERAGES } 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
|
|
}
|
|
|
|
export const getFinalLanguage = (path = '', defaultLocale: string, coverages: string[]) => {
|
|
// const nuxtApp = useNuxtApp()
|
|
let finalLocale = ''
|
|
let requestedLocale
|
|
let acceptLanguage: string
|
|
let defaultLang = 'en'
|
|
let defaultLangEn: string
|
|
if (defaultLocale) {
|
|
defaultLangEn = defaultLocale
|
|
} else {
|
|
defaultLangEn = 'en'
|
|
}
|
|
|
|
requestedLocale = path?.split('/')[1]?.toLowerCase() ?? 'undefined'
|
|
|
|
if (import.meta.server) {
|
|
const headers = useRequestHeaders(['accept-language'])
|
|
acceptLanguage = headers['accept-language'] || defaultLangEn
|
|
|
|
defaultLang =
|
|
coverages.find((locale: string) => getPreferredLanguage(acceptLanguage)?.startsWith(locale)) || defaultLangEn
|
|
}
|
|
|
|
// const DEFAULT_COVERAGES = i18n.locales.map((locale) => locale.code)
|
|
const DEFAULT_COVERAGES = coverages
|
|
const requestedPage = path?.split('/')[2]?.toLowerCase() ?? undefined
|
|
|
|
const localeMap: Record<string, string> = {
|
|
'zh-tw': 'zh-TW',
|
|
'zh-cn': 'zh-CN'
|
|
}
|
|
|
|
if (localeMap[requestedLocale]) {
|
|
requestedLocale = localeMap[requestedLocale]
|
|
}
|
|
|
|
if (requestedLocale !== undefined && DEFAULT_COVERAGES.includes(requestedLocale)) {
|
|
finalLocale = requestedLocale
|
|
} else if (
|
|
requestedLocale === undefined ||
|
|
requestedLocale === '' ||
|
|
path !== '' ||
|
|
(requestedLocale !== undefined && !DEFAULT_COVERAGES.includes(requestedLocale) && requestedPage !== undefined)
|
|
) {
|
|
// 요청된 언어가 없을 때 or 잘못된 언어코드로 요청 시 브라우저 언어로 설정
|
|
finalLocale = defaultLang
|
|
} else {
|
|
// 그 외의 경우 기본 언어로 설정 (중국어 번체)
|
|
finalLocale = defaultLangEn
|
|
}
|
|
|
|
return finalLocale.toLowerCase()
|
|
}
|
|
|
|
/**
|
|
* 우선순위에 따른 언어 조회 (CSR)
|
|
*
|
|
* @param {string} path - 현재 URL 경로
|
|
*/
|
|
export const csrGetFinalLocale = (path = '') => {
|
|
let finalLocale = DEFAULT_LOCALE_CODE // 기본값 설정
|
|
const localeMap: Record<string, string> = {
|
|
'zh-tw': 'zh-TW',
|
|
'zh-cn': 'zh-CN'
|
|
}
|
|
|
|
// 1. URL 패스에 포함된 언어
|
|
if (path && path !== '' && path.split('/').length > 1) {
|
|
const pathLocal = path.split('/')[1]
|
|
|
|
// URL 패스에 포함된 언어가 지원하는 언어인지 체크
|
|
if (pathLocal && pathLocal !== '' && DEFAULT_COVERAGES.includes(pathLocal)) {
|
|
finalLocale = pathLocal // .toLowerCase()
|
|
|
|
if (localeMap[pathLocal]) {
|
|
finalLocale = localeMap[pathLocal]
|
|
}
|
|
}
|
|
return finalLocale
|
|
}
|
|
|
|
// 2. 브라우저 언어
|
|
const browserLanguage = navigator.language || navigator.languages[0]
|
|
if (browserLanguage && browserLanguage !== '' && DEFAULT_COVERAGES.includes(browserLanguage)) {
|
|
finalLocale = browserLanguage // .toLowerCase()
|
|
if (localeMap[browserLanguage]) {
|
|
finalLocale = localeMap[browserLanguage]
|
|
}
|
|
return finalLocale
|
|
}
|
|
|
|
// 3. 서비스 기본 언어
|
|
finalLocale = DEFAULT_LOCALE_CODE
|
|
|
|
return finalLocale
|
|
}
|
|
|
|
/**
|
|
* 우선순위에 따른 언어 조회 (SSR)
|
|
*
|
|
* @param {string} path - 현재 URL 경로
|
|
* @param {any} headers - 요청 헤더
|
|
*/
|
|
export const ssrGetFinalLocale = (path = '', headers: any) => {
|
|
let finalLocale = DEFAULT_LOCALE_CODE // 기본값 설정
|
|
|
|
|
|
try {
|
|
// 1. URL path에 포함된 언어 정보
|
|
if (path && path !== '' && path.split('/').length > 1) {
|
|
const pathLocale = path.split('/')[1]
|
|
|
|
// URL path에 포함된 언어 정보가 지원하는 언어인지 체크
|
|
if (pathLocale && pathLocale !== '' && DEFAULT_COVERAGES.includes(pathLocale)) {
|
|
finalLocale = pathLocale // .toLowerCase()
|
|
|
|
return finalLocale
|
|
}
|
|
}
|
|
|
|
// 2. 요청 헤더의 브라우저 언어 (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 = DEFAULT_COVERAGES.find((locale: string) =>
|
|
preferredLocale.toLowerCase().startsWith(locale.toLowerCase())
|
|
)
|
|
if (matchedLocale) {
|
|
finalLocale = matchedLocale
|
|
// return matchedLocale.toLowerCase()
|
|
|
|
return finalLocale
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 서비스 기본 언어
|
|
finalLocale = DEFAULT_LOCALE_CODE
|
|
} catch (e) {
|
|
console.error('[Exception] localeUtil.ssrGetFinalLocale: ', e)
|
|
finalLocale = DEFAULT_LOCALE_CODE
|
|
}
|
|
return finalLocale
|
|
}
|