fix. 다국어 적용

This commit is contained in:
clkim
2025-11-06 22:03:07 +09:00
parent c5aee0902f
commit 91da285fce
4 changed files with 77 additions and 73 deletions

View File

@@ -40,7 +40,7 @@ const DUP_IMAGE_MAP: Record<Platform, string> = {
} as const
const componentTag = computed(() => {
if (props.platform === 'stove') {
if (props.type !== 'duplication' && props.platform === 'stove') {
return 'a'
}
return 'button'

View File

@@ -1,17 +1,38 @@
<script setup lang="ts">
interface Props {
preregistCode?: string
tm?: any // i18n translate message function
}
const props = defineProps<Props>()
const { locale, tm } = useI18n()
const modalStore = useModalStore()
const { gameData } = useGameDataStore()
const { handleTokenValidation } = useTokenValidation()
const { getPreregist, setPreregist } = usePreregist()
const { isNorthAmerica, countryCode } = useGds()
// Multilingual
const { locale } = useI18n()
// Props로 전달받은 tm 또는 전역 i18n의 tm 사용
const t = (key: string) => {
if (props.tm) {
return props.tm(key)
}
return key
}
// 게임명 치환 헬퍼
const tWithGameName = (key: string) => {
const text = t(key)
if (typeof text === 'string' && text.includes('%게임명%')) {
const gameName = gameData?.game_name ?? ''
return text.replace(/%게임명%/g, gameName)
}
return text
}
// State
const isOpen = ref(false)
const step = ref<1 | 2>(1)
@@ -85,11 +106,11 @@ const toggleExpand = (key: keyof typeof expanded.value, event: Event) => {
// 에러 코드 매핑
const ERROR_MESSAGES: Record<number, string> = {
'-90002': '사전 등록 기간이 아닙니다.',
'-90018': '생년월일을 입력해주세요.',
'-90022': '사전 등록 가능한 연령이 아닙니다.',
'-90000': '필수 약관을 모두 선택해 주세요.',
'-90023': '이미 사전 등록을 완료한 계정입니다',
'-90002': t('Preregist_Alert_Date'),
'-90018': t('Preregist_Alert_Birth'),
'-90022': t('Preregist_Alert_Age'),
'-90000': t('Preregist_Alert_Agree'),
'-90023': t('Preregist_Alert_Already'),
}
const showErrorModal = (code: number) => {
@@ -104,8 +125,8 @@ const showErrorModal = (code: number) => {
// 기타 오류
modalStore.handleOpenConfirm({
contentText: tm('Alert_Error'),
confirmButtonText: tm('Text_Customer'),
contentText: t('Alert_Error'),
confirmButtonText: t('Text_Customer'),
confirmButtonEvent: () => {
window.open('aa', '_blank')
},
@@ -263,9 +284,7 @@ defineExpose({
<h2
class="flex-1 text-xl font-bold leading-[30px] tracking-[-0.6px] text-[#ebebeb] md:text-2xl md:leading-[34px] md:tracking-[-0.72px]"
>
사전 등록 이용 약관에
<br />
동의해주세요
{{ t('Preregist_Modal_Title01') }}
</h2>
<div class="flex h-[30px] items-center gap-1 md:h-[34px]">
<span
@@ -306,7 +325,7 @@ defineExpose({
<span
class="flex-1 text-base font-bold leading-6 tracking-[-0.48px] text-[#ebebeb] md:text-lg md:leading-[26px] md:tracking-[-0.54px]"
>
아래 내용에 모두 동의 합니다.
{{ t('Preregist_Agree_All') }}
</span>
</div>
<div class="mt-4">
@@ -324,7 +343,7 @@ defineExpose({
<span
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
>
[필수] 18 이상입니다.
{{ t('Preregist_Agree_Age') }}
</span>
</div>
</div>
@@ -340,7 +359,7 @@ defineExpose({
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
@click="handleCheck('privacy')"
>
[필수] 개인정보 수집 이용동의
{{ t('Preregist_Agree_Privacy') }}
</span>
<button
type="button"
@@ -355,28 +374,12 @@ defineExpose({
<!-- Privacy Detail Content -->
<div
v-if="expanded.privacy"
class="mt-4 h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
class="mt-4 max-h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
>
<p
v-dompurify-html="t('Preregist_Agree_Privacy_Info')"
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#b2b2b2]"
>
약관은 [게임명] (이하 "회사") 제공하는 사전등록 서비스와
관련하여 회사와 이용자 간의 권리, 의무 책임사항, 서비스
이용조건 절차 기본적인 사항을 규정함을 목적으로 합니다.
<br />
<br />
회사는 이용자의 개인정보를 중요시하며, 개인정보 보호법,
정보통신망 이용촉진 정보보호 등에 관한 법률 준수하고
있습니다.
<br />
<br />
수집하는 개인정보 항목: 이메일 주소, 휴대전화번호, 게임 계정
정보
<br />
개인정보 수집 목적: 사전등록 확인, 게임 출시 안내, 마케팅 활용
<br />
개인정보 보유 이용기간: 회원 탈퇴 시까지
</p>
></p>
</div>
</div>
<!-- Marketing Check with Accordion -->
@@ -391,7 +394,7 @@ defineExpose({
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
@click="handleCheck('marketing')"
>
[필수] 게임 서비스의 유용한 소식 받기
{{ t('Preregist_Agree_News') }}
</span>
<button
type="button"
@@ -406,31 +409,12 @@ defineExpose({
<!-- Marketing Detail Content -->
<div
v-if="expanded.marketing"
class="mt-4 h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
class="mt-4 max-h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
>
<p
v-dompurify-html="tWithGameName('Preregist_Agree_News_Info')"
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#b2b2b2]"
>
회사는 다음의 목적으로 광고성 정보를 전송합니다:
<br />
<br />
게임 출시 안내 업데이트 정보
<br />
이벤트, 프로모션 등의 마케팅 정보
<br />
게임 혜택 쿠폰 제공
<br />
신규 콘텐츠 패치 정보
<br />
<br />
전송방법: 이메일, SMS, 푸시 알림, 알림
<br />
<br />
이용자는 언제든지 수신 동의를 철회할 있으며, 수신 거부
시에도 서비스 이용에는 제한이 없습니다. , 거래 관련 정보,
고객문의 답변 의무적으로 안내되어야 하는 정보는 수신동의
여부와 무관하게 제공됩니다.
</p>
></p>
</div>
</div>
@@ -447,7 +431,7 @@ defineExpose({
<p
class="text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
>
[필수] 생년월일을 입력해주세요
{{ t('Preregist_Agree_Birth') }}
</p>
<div class="flex gap-2">
@@ -515,7 +499,7 @@ defineExpose({
:disabled="!canSubmit || isSubmitting"
@click="handleSubmit"
>
사전 등록하기
{{ t('Preregist_Btn_Preegist') }}
</AtomsButton>
</div>
</div>
@@ -526,7 +510,7 @@ defineExpose({
<p
class="flex-1 text-xl font-bold leading-[30px] tracking-[-0.6px] text-[#ebebeb] md:text-2xl md:leading-[34px] md:tracking-[-0.72px]"
>
사전 등록이 완료되었습니다.
{{ t('Preregist_Modal_Title02') }}
</p>
<div class="flex h-[30px] items-center gap-1 md:h-[34px]">
<span
@@ -565,7 +549,7 @@ defineExpose({
<p
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#ebebeb] md:text-[15px] md:leading-6 md:tracking-[-0.45px]"
>
광고성 정보 수신에 동의하였습니다.
{{ t('Preregist_Agree_News_Complete') }}
</p>
</div>
@@ -574,7 +558,7 @@ defineExpose({
<p
class="text-left text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-center md:text-base md:leading-[26px] md:tracking-[-0.48px]"
>
STOVE APP 다운로드 하고 정식 런칭 소식 알림 받기!
{{ t('Preregist_Stove_Download') }}
</p>
<div class="flex items-center gap-3">
<div

View File

@@ -3,13 +3,12 @@ import { usePageDataStore } from '#layers/stores/usePageDataStore'
import { useGetGameDomain } from '#layers/composables/useGetGameDomain'
import { usePathResolver } from '#layers/composables/usePathResolver'
import type { PageDataResponse } from '#layers/types/api/pageData'
import type {
GameDataValue,
} from '#layers/types/api/gameData'
import type { GameDataValue } from '#layers/types/api/gameData'
export default defineNuxtRouteMiddleware(async (to, _from) => {
// [TODO] 하이드레이션 에러 처리
if (!import.meta.client) return
const config = useRuntimeConfig()
const stoveApiBaseUrl = config.public.stoveApiUrl
const apiUrl = `${stoveApiBaseUrl}/pub-comm/v2.0/template/page`
@@ -21,7 +20,12 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
const gameDataStore = useGameDataStore()
const gameData = gameDataStore.gameData as GameDataValue
const langCode = ssrGetFinalLocale(to.path, headers, gameData?.lang_codes, gameData?.default_lang_code)
const langCode = ssrGetFinalLocale(
to.path,
headers,
gameData?.lang_codes,
gameData?.default_lang_code
)
try {
if (to.path.includes('inspection')) {
@@ -48,7 +52,6 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
loading: true,
})) as PageDataResponse | null
console.log('🚀 ~ response?.code:', response?.code)
// if(response?.code === 91003) {
// throw createError({
// statusCode: 404,

View File

@@ -12,7 +12,21 @@ interface Props {
const props = defineProps<Props>()
const { locale } = useI18n()
// Configuration
const runtimeConfig = useRuntimeConfig()
const dataResourcesUrl = runtimeConfig.public.dataResourcesUrl as string
const multilingualFileName = 'STOVE_PUBTEMPLATE_homepage_brand_preregist.json'
// Multilingual
const resultGetMultilingual = await useGetMultilingual({
baseApiUrl: dataResourcesUrl,
fileName: multilingualFileName,
})
const { tm, locale }: any = useI18n({
useScope: 'local',
messages: Object(resultGetMultilingual?.value?.multilingual),
})
const { getOperateResourcesData } = useResourcesData()
const { gameData } = storeToRefs(useGameDataStore())
const { pageData } = storeToRefs(usePageDataStore())
@@ -25,11 +39,13 @@ const OS_TYPE_MAP: Record<string, Platform[]> = {
'3': ['google_play', 'app_store'],
}
const preregistModalRef = ref<{ handlePreregist: () => void } | null>(null)
const preregistModalRef = ref<{ handlePreregist: () => Promise<void> } | null>(
null
)
// Preregist Section
const preregistCode = computed(
() => getComponentGroup(props.components, 'preregistCode')?.display?.text
() => getComponentGroup(props.components, 'eventKey')?.display?.text
)
const prdBackgroundData = computed(() =>
getComponentGroup(props.components, 'background')
@@ -261,7 +277,7 @@ const handlePreregistClick = () => {
:text-color="buttonColors.textColor"
@click="handlePreregistClick"
>
사전 등록 하기
{{ tm('Preregist_Btn_Preegist') }}
</AtomsButtonLauncher>
<AtomsButtonLauncher
v-for="platform in platformButtons"
@@ -271,7 +287,7 @@ const handlePreregistClick = () => {
:background-color="buttonColors.backgroundColor"
:text-color="buttonColors.textColor"
>
사전 등록 하기
{{ tm('Preregist_Btn_Preegist') }}
</AtomsButtonLauncher>
</div>
<WidgetsDescription
@@ -360,6 +376,7 @@ const handlePreregistClick = () => {
<WidgetsModalPreregist
ref="preregistModalRef"
:tm="tm"
:preregist-code="preregistCode"
/>
</div>