diff --git a/frontend/src/app/setting/general.tsx b/frontend/src/app/setting/general.tsx index 217f37bd..3644d5e0 100644 --- a/frontend/src/app/setting/general.tsx +++ b/frontend/src/app/setting/general.tsx @@ -108,6 +108,9 @@ export default function GeneralPage() { {t("general.language.options.ja")} + + {t("general.language.options.ko")} + diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts index 1e7047ed..3024ba4b 100644 --- a/frontend/src/i18n/index.ts +++ b/frontend/src/i18n/index.ts @@ -3,6 +3,7 @@ import { initReactI18next } from "react-i18next"; import en from "@/i18n/locales/en.json"; import ja from "@/i18n/locales/ja.json"; +import ko from "@/i18n/locales/ko.json"; import zhCN from "@/i18n/locales/zh_CN.json"; import zhTW from "@/i18n/locales/zh_TW.json"; import { DEFAULT_LANGUAGE, useSettingsStore } from "@/store/settings-store"; @@ -11,6 +12,7 @@ const resources = Object.fromEntries( [ ["en", en], ["ja", ja], + ["ko", ko], ["zh_CN", zhCN], ["zh_TW", zhTW], ].map(([locale, translation]) => [locale, { translation }]), diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 3eaf87c7..566e6543 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -15,7 +15,8 @@ "en": "English (United States)", "zh_CN": "简体中文", "zh_TW": "繁體中文", - "ja": "日本語" + "ja": "日本語", + "ko": "한국어" } }, "theme": { diff --git a/frontend/src/i18n/locales/ja.json b/frontend/src/i18n/locales/ja.json index b09f3649..9c5b254a 100644 --- a/frontend/src/i18n/locales/ja.json +++ b/frontend/src/i18n/locales/ja.json @@ -15,7 +15,8 @@ "en": "English (United States)", "zh_CN": "简体中文", "zh_TW": "繁體中文", - "ja": "日本語" + "ja": "日本語", + "ko": "한국어" } }, "theme": { diff --git a/frontend/src/i18n/locales/ko.json b/frontend/src/i18n/locales/ko.json new file mode 100644 index 00000000..bb612ac5 --- /dev/null +++ b/frontend/src/i18n/locales/ko.json @@ -0,0 +1,435 @@ +{ + "general": { + "title": "일반", + "description": "환경설정과 앱 설정을 관리하세요.", + "account": { + "title": "계정", + "signInDesc": "Valuecell AI 기능을 시작하려면 로그인하세요.", + "signOut": "로그아웃", + "signIn": "로그인" + }, + "language": { + "title": "언어 및 지역", + "description": "앱에서 사용할 언어와 지역 형식을 선택하세요.", + "options": { + "en": "English (United States)", + "zh_CN": "简体中文", + "zh_TW": "繁體中文", + "ja": "日本語", + "ko": "한국어" + } + }, + "theme": { + "title": "테마", + "description": "밝은 테마, 어두운 테마 또는 시스템 설정을 따르도록 선택하세요.", + "options": { + "system": "시스템 설정", + "light": "밝게", + "dark": "어둡게" + } + }, + "quotesColor": { + "title": "시세 색상", + "description": "주식 시세 등락을 표시할 색상을 선택하세요.", + "greenUpRedDown": "상승 초록 / 하락 빨강", + "redUpGreenDown": "상승 빨강 / 하락 초록" + }, + "updates": { + "title": "앱 업데이트", + "check": "업데이트 확인" + } + }, + "auth": { + "login": { + "title": "로그인", + "tagline": "최초의 오픈소스 금융 에이전트 플랫폼.", + "providers": { + "google": "Google", + "apple": "Apple" + }, + "actions": { + "continueWith": "{{provider}}(으)로 계속하기" + }, + "errors": { + "timeout": { + "title": "로그인 시간이 초과되었습니다", + "description": "다시 시도해 주세요." + }, + "failed": { + "title": "{{provider}}(으)로 로그인하지 못했습니다", + "description": "정보: {{info}}" + } + } + } + }, + "settings": { + "title": "설정", + "nav": { + "models": "모델", + "general": "일반", + "memory": "메모리" + }, + "models": { + "title": "모델 제공업체", + "noProviders": "사용 가능한 제공업체가 없습니다.", + "loading": "제공업체 정보를 불러오는 중...", + "defaultProvider": "기본 제공업체", + "apiKey": "API 키", + "enterApiKey": "API 키 입력", + "getApiKey": "여기를 클릭해 API 키 받기", + "apiHost": "API 호스트", + "models": "모델", + "add": "추가", + "addModel": "모델 추가", + "modelId": "모델 ID", + "enterModelId": "모델 ID 입력", + "modelName": "모델 이름", + "enterModelName": "모델 이름 입력", + "cancel": "취소", + "confirm": "확인", + "noModels": "이 제공업체에 설정된 모델이 없습니다.", + "hidePassword": "비밀번호 숨기기", + "showPassword": "비밀번호 표시", + "waitingForCheck": "확인 대기 중", + "checkAvailability": "사용 가능 여부 확인", + "available": "사용 가능", + "unavailable": "사용 불가" + }, + "memory": { + "title": "저장된 메모리", + "description": "대화 속 유용한 정보를 기억하고 자동으로 관리하여 답변의 개인화와 관련성을 높입니다.", + "loading": "불러오는 중...", + "noMemories": "아직 저장된 메모리가 없습니다", + "delete": "삭제" + } + }, + "common": { + "back": "뒤로", + "loading": "불러오는 중", + "settingUpEnvironment": "환경을 설정하는 중..." + }, + "nav": { + "home": "홈", + "strategy": "전략", + "ranking": "랭킹", + "market": "마켓", + "setting": "설정" + }, + "updates": { + "toast": { + "checking": "업데이트를 확인하는 중...", + "latest": "이미 최신 버전을 사용하고 있습니다", + "availableTitle": "업데이트가 있습니다", + "availableDesc": "새 버전({{version}})을 사용할 수 있습니다. 지금 설치하시겠습니까?", + "install": "설치", + "later": "나중에", + "downloading": "업데이트를 다운로드하는 중... {{percentage}}%", + "installedTitle": "업데이트가 성공적으로 설치되었습니다!", + "installedDesc": "업데이트를 적용하려면 앱을 다시 시작해야 합니다.", + "relaunch": "다시 시작", + "downloadFailed": "업데이트 다운로드 실패: {{error}}", + "checkFailed": "업데이트 확인 실패: {{error}}" + } + }, + "market": { + "title": "에이전트 마켓" + }, + "agent": { + "welcome": "{{name}}에 오신 것을 환영합니다!", + "unknown": "알 수 없는 에이전트", + "status": { + "running": "실행 중" + }, + "action": { + "view": "보기" + }, + "config": { + "disable": "비활성화", + "chat": "채팅", + "collectAndChat": "저장하고 채팅하기" + } + }, + "chat": { + "input": { + "placeholder": "메시지를 입력하세요..." + }, + "newConversation": "새 대화", + "settings": "설정", + "conversationList": { + "title": "대화 목록", + "loading": "불러오는 중...", + "empty": "아직 대화가 없습니다" + }, + "action": { + "delete": "삭제" + } + }, + "strategy": { + "types": { + "PromptBasedStrategy": "프롬프트 기반 전략", + "GridStrategy": "그리드 전략" + }, + "providers": { + "azure": "Azure OpenAI", + "dashscope": "알리바바 클라우드", + "deepseek": "딥시크", + "google": "Google Cloud", + "openai": "OpenAI", + "openai-compatible": "OpenAI 호환 API", + "openrouter": "OpenRouter", + "siliconflow": "SiliconFlow" + }, + "title": "트레이딩 전략", + "add": "트레이딩 전략 추가", + "noStrategies": "트레이딩 전략이 없습니다", + "createFirst": "첫 전략을 만들어 트레이딩을 시작하세요", + "status": { + "running": "실행 중", + "stopped": "중지됨", + "live": "실전", + "virtual": "모의" + }, + "action": { + "stop": "트레이딩 전략을 중지할까요?", + "stopDesc": "전략 \"{{name}}\"을(를) 중지하면 즉시 멈추고 강제 청산이 실행됩니다. 계속하시겠습니까?", + "confirmStop": "중지 확인", + "delete": "삭제", + "deleteTitle": "전략을 삭제할까요?", + "deleteDesc": "전략 \"{{name}}\"을(를) 삭제하면 즉시 멈추고 강제 청산이 실행됩니다. 계속하시겠습니까?", + "confirmDelete": "삭제 확인", + "details": "상세 정보", + "duplicate": "복제", + "cancel": "취소", + "back": "뒤로", + "next": "다음", + "confirm": "확인", + "publish": "게시", + "shareToSocial": "소셜에 공유", + "shareToRanking": "랭킹에 공유" + }, + "portfolio": { + "title": "포트폴리오 가치 추이", + "totalEquity": "총 자산", + "availableBalance": "사용 가능 잔액", + "totalPnl": "총 손익", + "noData": "포트폴리오 가치 데이터가 없습니다", + "noDataDesc": "트레이딩이 시작되면 포트폴리오 가치 차트가 표시됩니다" + }, + "positions": { + "title": "포지션", + "symbol": "종목", + "type": "유형", + "leverage": "레버리지", + "quantity": "수량", + "pnl": "손익", + "noOpen": "보유 중인 포지션이 없습니다", + "noOpenDesc": "포지션을 진입하면 여기에 표시됩니다" + }, + "create": { + "title": "트레이딩 전략 추가", + "steps": { + "aiModels": "AI 모델", + "exchanges": "거래소", + "tradingStrategy": "트레이딩 전략" + }, + "error": "전략 생성 오류" + }, + "copy": { + "title": "트레이딩 전략 복제", + "error": "전략 복제 오류" + }, + "toast": { + "published": "전략이 성공적으로 게시되었습니다" + }, + "form": { + "strategyType": { + "label": "전략 유형", + "promptBased": "프롬프트 기반 전략", + "grid": "그리드 전략" + }, + "strategyName": { + "label": "전략 이름", + "placeholder": "전략 이름 입력" + }, + "initialCapital": { + "label": "초기 자본금", + "placeholder": "초기 자본금 입력" + }, + "maxLeverage": { + "label": "최대 레버리지", + "placeholder": "최대 레버리지" + }, + "decideInterval": { + "label": "판단 주기 (초)", + "placeholder": "예: 300" + }, + "tradingSymbols": { + "label": "거래 종목", + "placeholder": "거래 종목 선택...", + "searchPlaceholder": "종목 검색 또는 추가...", + "emptyText": "종목을 찾을 수 없습니다." + }, + "promptTemplate": { + "label": "시스템 프롬프트 템플릿", + "new": "새 프롬프트", + "view": "전략 보기" + }, + "aiModels": { + "platform": "모델 플랫폼", + "model": "모델 선택", + "noModels": "사용 가능한 모델이 없습니다", + "apiKey": { + "label": "API 키", + "placeholder": "API 키 입력" + } + }, + "exchanges": { + "transactionType": "거래 유형", + "liveTrading": "실전 매매", + "virtualTrading": "모의 매매", + "selectExchange": "거래소 선택", + "walletAddress": "지갑 주소", + "privateKey": "프라이빗 키", + "apiKey": "API Key", + "secretKey": "Secret Key", + "passphrase": "Passphrase", + "testConnection": "연결 테스트", + "test": { + "success": "연결 성공!", + "failed": "연결에 실패했습니다. API Key, Secret Key 또는 Passphrase를 확인해 주세요." + }, + "placeholder": { + "binance": { + "apiKey": "API Key 입력 (64자)", + "secretKey": "Secret Key 입력 (64자)" + }, + "okx": { + "apiKey": "API Key 입력 (형식: xxxxxxxx-xxxx-...)", + "secretKey": "Secret Key 입력 (32자리 대문자와 숫자)", + "passphrase": "Passphrase 입력 (API 생성 시 설정)" + }, + "gate": { + "apiKey": "API Key 입력 ('key_'로 시작)", + "secretKey": "Secret Key 입력 (64자)" + }, + "hyperliquid": { + "walletAddress": "지갑 주소 입력 ('0x'로 시작)", + "privateKey": "프라이빗 키 입력 (64자)" + }, + "blockchain": { + "apiKey": "API Key 입력 (형식: xxxxxxxx-xxxx-...)", + "secretKey": "Secret Key 입력" + }, + "coinbase": { + "apiKey": "API Key 입력 (또는 Key Name)", + "secretKey": "API Secret 입력 (또는 Private Key)", + "passphrase": "Passphrase 입력 (Legacy Pro API 필요 시)" + }, + "mexc": { + "apiKey": "Access Key 입력 ('mx0'로 시작)", + "secretKey": "Secret Key 입력 (보통 32자)" + }, + "default": { + "apiKey": "여기에 API Key를 붙여넣으세요", + "secretKey": "여기에 Secret Key를 붙여넣으세요", + "passphrase": "Passphrase 입력", + "walletAddress": "지갑 주소 입력", + "privateKey": "프라이빗 키 입력" + } + } + } + }, + "prompt": { + "delete": { + "title": "전략 프롬프트 삭제", + "description": "이 전략 프롬프트를 삭제하시겠습니까? 이 작업은 되돌릴 수 없으며 시스템에서 프롬프트가 영구적으로 삭제됩니다." + } + }, + "detail": { + "title": "전략 상세 정보", + "loading": "상세 정보를 불러오는 중...", + "returnRate": "수익률", + "strategyType": "전략 유형", + "modelProvider": "모델 제공업체", + "modelId": "모델 ID", + "initialCapital": "초기 자본금", + "maxLeverage": "최대 레버리지", + "tradingSymbols": "거래 종목", + "prompt": "프롬프트" + }, + "history": { + "title": "거래 내역", + "live": "실전 매매", + "virtual": "모의 매매", + "cycle": "사이클 #{{index}}", + "aiReasoning": "AI 추론 로직", + "operation": "실행한 작업", + "empty": { + "title": "거래 내역이 없습니다", + "desc": "완료된 거래가 여기에 표시됩니다" + }, + "details": { + "time": "시간", + "price": "가격", + "quantity": "수량", + "holdingTime": "보유 시간", + "tradingFee": "거래 수수료", + "reasoning": "추론" + } + } + }, + "rank": { + "title": "수익 랭킹", + "table": { + "rank": "순위", + "user": "사용자", + "pnl": "손익", + "strategy": "전략", + "exchange": "거래소", + "model": "모델", + "details": "상세 정보", + "loading": "불러오는 중..." + } + }, + "home": { + "hello": "👋 안녕하세요, 투자자님!", + "welcome": "👋 ValueCell에 오신 것을 환영합니다!", + "watchlist": "내 관심 종목", + "stock": { + "loading": "주식 데이터를 불러오는 중...", + "error": "주식 데이터 로딩 실패: {{message}}", + "remove": "제거", + "removing": "제거하는 중...", + "add": "종목 추가", + "about": "소개", + "sector": "섹터:", + "industry": "산업:", + "website": "웹사이트:" + }, + "search": { + "title": "종목 검색", + "placeholder": "종목명 또는 코드로 검색", + "searching": "검색하는 중...", + "noResults": "관련 종목을 찾을 수 없습니다", + "action": { + "watch": "관심 종목", + "watching": "추가하는 중...", + "watched": "관심 종목에 추가됨" + } + }, + "suggestions": { + "research": { + "title": "심층 리서치", + "description": "SEC 공시 자료를 분석해 심층 주식 분석 리포트를 생성합니다." + }, + "strategy": { + "title": "자동 매매", + "description": "다중 전략 스마트 트레이딩으로 나만의 전략을 자동 실행합니다." + }, + "news": { + "title": "뉴스 알림", + "description": "맞춤 일정에 따라 개인화된 뉴스를 전달합니다." + } + } + } +} diff --git a/frontend/src/i18n/locales/zh_CN.json b/frontend/src/i18n/locales/zh_CN.json index 36b478ab..dee716c7 100644 --- a/frontend/src/i18n/locales/zh_CN.json +++ b/frontend/src/i18n/locales/zh_CN.json @@ -15,7 +15,8 @@ "en": "English (United States)", "zh_CN": "简体中文", "zh_TW": "繁體中文", - "ja": "日本語" + "ja": "日本語", + "ko": "한국어" } }, "theme": { diff --git a/frontend/src/i18n/locales/zh_TW.json b/frontend/src/i18n/locales/zh_TW.json index 32247aba..9c329aa8 100644 --- a/frontend/src/i18n/locales/zh_TW.json +++ b/frontend/src/i18n/locales/zh_TW.json @@ -15,7 +15,8 @@ "en": "English (United States)", "zh_CN": "简体中文", "zh_TW": "繁體中文", - "ja": "日本語" + "ja": "日本語", + "ko": "한국어" } }, "theme": { diff --git a/frontend/src/root.tsx b/frontend/src/root.tsx index df49a2b4..4f745410 100644 --- a/frontend/src/root.tsx +++ b/frontend/src/root.tsx @@ -17,6 +17,7 @@ export function Layout({ children }: { children: React.ReactNode }) { zh_CN: "zh-CN", zh_TW: "zh-TW", ja: "ja", + ko: "ko", }[language] ?? "en"; return ( diff --git a/frontend/src/store/settings-store.ts b/frontend/src/store/settings-store.ts index 200934a2..53033402 100644 --- a/frontend/src/store/settings-store.ts +++ b/frontend/src/store/settings-store.ts @@ -16,7 +16,7 @@ import i18n from "@/i18n"; import type { StockChangeType } from "@/types/stock"; export type StockColorMode = "GREEN_UP_RED_DOWN" | "RED_UP_GREEN_DOWN"; -export type LanguageCode = "en" | "zh_CN" | "zh_TW" | "ja"; +export type LanguageCode = "en" | "zh_CN" | "zh_TW" | "ja" | "ko"; export const DEFAULT_LANGUAGE = "en"; interface SettingsStoreState { @@ -34,6 +34,7 @@ const getLanguage = () => { "zh-Hans": "zh_CN", "zh-Hant": "zh_TW", "ja-JP": "ja", + "ko-KR": "ko", }; return map[navigator.language] ?? DEFAULT_LANGUAGE; };