부가서비스 페이지 및 컴포넌트 다국어화 완료

- 부가서비스 메인 페이지 다국어화
  * 헤더 타이틀, 사용중인 서비스/신청 가능한 서비스 섹션
  * 비활성 서비스 안내 메시지
- 부가서비스 공통 컴포넌트 다국어화
  * list-item: 11개 서비스의 상태 라벨 (성공, 실패, 요청, 재발송)
  * title-info-wrap: 서비스 정보 표시
- 정산대행 페이지 다국어화 (5개 페이지)
  * 관리, 입금, 회원, 상세 페이지 헤더
  * 상세 페이지: 입금 확인, 정산 정보, 수수료 정보 등 17개 필드
  * 상태 변경 이력: 출금 실패, 동의 완료, 동의 만료 등
- 서비스별 상세 페이지 통화 표기 개선 (4개 페이지)
  * ARS, 펀드계좌(이체/결과), 페이아웃 상세 페이지
- 전체 통화 표기 통일 (11개 인스턴스)
  * 한국어: 100,000원 (suffix)
  * 영어: ₩100,000 (prefix)
- 번역 키 추가: additionalService 네임스페이스 51+ 키
  * 공통 상태 라벨, 11개 서비스명 및 설명
  * 정산대행 전용 21개 키
- 지원 서비스: SMS결제, ARS결제, KEY-IN결제, 계좌조회/인증,
  페이아웃, 정산대행, 링크결제, 펀드계좌, 알림톡, 안면인증

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jay Sheen
2025-10-29 18:22:09 +09:00
parent 3f0ab49a3d
commit f0a157b2c3
13 changed files with 217 additions and 60 deletions

View File

@@ -1,7 +1,8 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { useTranslation } from 'react-i18next';
import { HeaderType } from '@/entities/common/model/types';
import {
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -25,6 +26,7 @@ import { useExtensionArsResendMutation } from '@/entities/additional-service/api
import { getArsOrderStatusName, getArsPaymentStatusName } from '@/entities/additional-service/model/ars/constant';
export const ArsDetailPage = () => {
const { t, i18n } = useTranslation();
const { navigate } = useNavigate();
const location = useLocation();
@@ -85,10 +87,11 @@ export const ArsDetailPage = () => {
<div className="num-amount">
<span className="amount">
<NumericFormat
value={ detail?.amount }
value={ detail?.amount }
thousandSeparator
displayType="text"
suffix='원'
prefix={i18n.language === 'en' ? t('home.currencySymbol') : ''}
suffix={i18n.language === 'en' ? '' : t('home.currencyWon')}
></NumericFormat>
</span>
</div>

View File

@@ -1,5 +1,6 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { useTranslation } from 'react-i18next';
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
@@ -22,6 +23,7 @@ import { useExtensionFundAccountDownloadReceiptMutation } from '@/entities/addit
import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
export const FundAccountResultDetailPage = () => {
const { t, i18n } = useTranslation();
const { navigate } = useNavigate();
const location = useLocation();
@@ -88,7 +90,8 @@ export const FundAccountResultDetailPage = () => {
value={detail?.amount}
thousandSeparator
displayType="text"
suffix='원'
prefix={i18n.language === 'en' ? t('home.currencySymbol') : ''}
suffix={i18n.language === 'en' ? '' : t('home.currencyWon')}
></NumericFormat>
</span>
</div>

View File

@@ -1,5 +1,6 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { useTranslation } from 'react-i18next';
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
@@ -18,6 +19,7 @@ import { snackBar } from '@/shared/lib';
import { useExtensionFundAccountTransferRequestMutation } from '@/entities/additional-service/api/fund-account/use-extension-fund-account-transfer-request-mutation';
export const FundAccountTransferDetailPage = () => {
const { t, i18n } = useTranslation();
const { navigate } = useNavigate();
const location = useLocation();
@@ -81,7 +83,8 @@ export const FundAccountTransferDetailPage = () => {
value={detail?.amount}
thousandSeparator
displayType="text"
suffix='원'
prefix={i18n.language === 'en' ? t('home.currencySymbol') : ''}
suffix={i18n.language === 'en' ? '' : t('home.currencyWon')}
></NumericFormat>
</span>
</div>

View File

@@ -1,4 +1,5 @@
import { ChangeEvent, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { HeaderType } from '@/entities/common/model/types';
@@ -14,6 +15,7 @@ import { useStore } from '@/shared/model/store';
import { Dialog } from '@/shared/ui/dialogs/dialog';
export const ListPage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate();
const midOptions = useStore.getState().UserStore.selectOptionsMids;
const userMid = useStore.getState().UserStore.mid;
@@ -25,7 +27,7 @@ export const ListPage = () => {
const { mutateAsync: extensionList } = useExtensionListMutation();
useSetHeaderTitle('부가서비스 소개');
useSetHeaderTitle(t('additionalService.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {
@@ -115,9 +117,9 @@ export const ListPage = () => {
}
</select>
</div>
<h3 className="ing-title"> </h3>
<h3 className="ing-title">{t('additionalService.activeServices')}</h3>
{getActiveExtensionList()}
<h3 className="ing-title"> </h3>
<h3 className="ing-title">{t('additionalService.availableServices')}</h3>
{getAvailableExtensionList()}
</div>
</div>
@@ -128,11 +130,11 @@ export const ListPage = () => {
onClose={() => setDialogOpen(false)}
message={
<>
.<br />
.
{t('additionalService.notActiveServiceMessage')}<br />
{t('additionalService.contactSalesMessage')}
</>
}
buttonLabel={['확인']}
buttonLabel={[t('common.confirm')]}
onConfirmClick={() => setDialogOpen(false)}
afterLeave={() => { }}
/>

View File

@@ -1,7 +1,8 @@
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { useTranslation } from 'react-i18next';
import { HeaderType } from '@/entities/common/model/types';
import {
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -18,6 +19,7 @@ import { EmailBottomSheet } from '@/entities/common/ui/email-bottom-sheet';
import { DownloadTypeBottomSheet } from '@/entities/common/ui/download-type-bottom-sheet';
export const PayoutDetailPage = () => {
const { t, i18n } = useTranslation();
const { navigate } = useNavigate();
const location = useLocation();
@@ -107,10 +109,11 @@ export const PayoutDetailPage = () => {
<div className="num-amount">
<span className="amount">
<NumericFormat
value={ detail?.disbursementAmount }
value={ detail?.disbursementAmount }
thousandSeparator
displayType="text"
suffix='원'
prefix={i18n.language === 'en' ? t('home.currencySymbol') : ''}
suffix={i18n.language === 'en' ? '' : t('home.currencyWon')}
></NumericFormat>
</span>
</div>

View File

@@ -1,11 +1,12 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { SettlementAgencyTab } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-tab';
import { SettlementAgencyTab } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-tab';
import { SettlementAgencyDepositWrap } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-deposit-wrap';
import { SettlementAgencyTabKeys } from '@/entities/additional-service/model/types';
import { HeaderType } from '@/entities/common/model/types';
import {
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -13,11 +14,12 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
export const SettlementAgencyDepositPage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState<SettlementAgencyTabKeys>(SettlementAgencyTabKeys.Deposit);
useSetHeaderTitle('정산대행');
useSetHeaderTitle(t('additionalService.settlementAgency.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {

View File

@@ -1,10 +1,11 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { IMAGE_ROOT } from '@/shared/constants/common';
import { SettlementAgencyBottomAgree } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-bottom-agree';
import { HeaderType } from '@/entities/common/model/types';
import {
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -12,11 +13,12 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
export const SettlementAgencyDetailPage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate();
const [bottomAgreeOn, setBottomAgreeOn] = useState<boolean>(false);
useSetHeaderTitle('정산대행');
useSetHeaderTitle(t('additionalService.settlementAgency.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {
@@ -40,7 +42,7 @@ export const SettlementAgencyDetailPage = () => {
<div className="receipt-row">
<button type="button" className="receipt-btn">
<span className="icon-24 download"></span>
<span></span>
<span>{t('additionalService.settlementAgency.depositConfirmation')}</span>
</button>
</div>
</div>
@@ -48,84 +50,84 @@ export const SettlementAgencyDetailPage = () => {
<div className="detail-divider"></div>
<div className="pay-detail">
<div className="detail-title"> </div>
<div className="detail-title">{t('additionalService.settlementAgency.settlementInfo')}</div>
<ul className="kv-list">
<li className="kv-row">
<span className="k">ID</span>
<span className="k">{t('additionalService.settlementAgency.settlementId')}</span>
<span className="v">AB25061012</span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="k">{t('additionalService.settlementAgency.settlementDate')}</span>
<span className="v">2025.06.08</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="k">{t('additionalService.settlementAgency.settlementStatus')}</span>
<span className="v"></span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="k">{t('additionalService.settlementAgency.totalTransactionAmount')}</span>
<span className="v">105,000,000 </span>
</li>
<li className="kv-row bolder">
<span className="k"></span>
<span className="k">{t('additionalService.settlementAgency.settlementAmount')}</span>
<span className="v">100,000,000</span>
</li>
</ul>
<div className="detail-divider"></div>
<div className="detail-title"> </div>
<div className="detail-title">{t('additionalService.settlementAgency.settlementStoreInfo')}</div>
<ul className="kv-list">
<li className="kv-row">
<span className="k"> ID</span>
<span className="k">{t('additionalService.settlementAgency.settlementStoreId')}</span>
<span className="v">BACK01</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="k">{t('additionalService.settlementAgency.settlementStoreName')}</span>
<span className="v">3</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="k">{t('additionalService.settlementAgency.businessNumber')}</span>
<span className="v">123456789</span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="k">{t('additionalService.settlementAgency.feeInfo')}</span>
<span className="v">3%, </span>
</li>
<li className="kv-row">
<span className="k"> </span>
<span className="k">{t('additionalService.settlementAgency.taxStatus')}</span>
<span className="v">, </span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="k">{t('additionalService.settlementAgency.bank')}</span>
<span className="v"></span>
</li>
<li className="kv-row">
<span className="k"></span>
<span className="k">{t('additionalService.settlementAgency.accountNumber')}</span>
<span className="v">110-12-12-11111</span>
</li>
</ul>
<div className="detail-divider"></div>
<div className="detail-title summary-amount divTop">
<span className="amount-text states-17"> </span>
<span className="amount-text states-17"> {t('additionalService.settlementAgency.statusChangeHistory')}</span>
<button>
<img
<img
src={ IMAGE_ROOT + '/ico_divTop_arrow.svg' }
alt="화살표"
alt={t('settlement.arrow')}
/>
</button>
</div>
<div className="sd-history">
<div className="sd-history-item">
<div className="left">
<div className="name"></div>
<div className="name">{t('additionalService.settlementAgency.withdrawalFailed')}</div>
<div className="time">2025/04/15 10:00:00</div>
</div>
<div className="right">
<div className="reason">사유 : 지급 </div>
<div className="reason">{t('additionalService.settlementAgency.reason')} : {t('additionalService.settlementAgency.accountError')}</div>
</div>
</div>
<div className="sd-history-item">
<div className="left">
<div className="name"></div>
<div className="name">{t('additionalService.settlementAgency.agreementCompleted')}</div>
<div className="time">2025/04/10 10:00:00</div>
</div>
<div className="right">
@@ -134,7 +136,7 @@ export const SettlementAgencyDetailPage = () => {
</div>
<div className="sd-history-item">
<div className="left">
<div className="name"> </div>
<div className="name">{t('additionalService.settlementAgency.agreementExpired')}</div>
<div className="time">2025/04/06 10:00:00</div>
</div>
<div className="right">
@@ -143,10 +145,10 @@ export const SettlementAgencyDetailPage = () => {
</div>
</div>
<div className="apply-row">
<button
<button
className="btn-50 btn-blue flex-1"
onClick={ () => oncClickToOpenBottomAgree() }
> /</button>
>{t('additionalService.settlementAgency.agreeOrReject')}</button>
</div>
</div>
</div>

View File

@@ -1,11 +1,12 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { SettlementAgencyTab } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-tab';
import { SettlementAgencyTab } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-tab';
import { SettlementAgencyManageWrap } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-manage-wrap';
import { SettlementAgencyTabKeys } from '@/entities/additional-service/model/types';
import { HeaderType } from '@/entities/common/model/types';
import {
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -13,11 +14,12 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
export const SettlementAgencyManagePage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState<SettlementAgencyTabKeys>(SettlementAgencyTabKeys.Manage);
useSetHeaderTitle('정산대행');
useSetHeaderTitle(t('additionalService.settlementAgency.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {

View File

@@ -1,11 +1,12 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { SettlementAgencyTab } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-tab';
import { SettlementAgencyTab } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-tab';
import { SettlementAgencyMemberWrap } from '@/entities/additional-service/ui/settlement-agency/settlement-agency-member-wrap';
import { SettlementAgencyTabKeys } from '@/entities/additional-service/model/types';
import { HeaderType } from '@/entities/common/model/types';
import {
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
@@ -13,11 +14,12 @@ import {
} from '@/widgets/sub-layout/use-sub-layout';
export const SettlementAgencyMemberPage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState<SettlementAgencyTabKeys>(SettlementAgencyTabKeys.Member);
useSetHeaderTitle('정산대행');
useSetHeaderTitle(t('additionalService.settlementAgency.title'));
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(false);
useSetOnBack(() => {