feat: add 6 new locales (ja, ko, fr, es, de, pt) and UI polish
- Add Japanese, Korean, French, Spanish, German, Portuguese translations - Improve session active state visibility in both themes - Static language labels in LanguageSwitch component - Dark theme: lighten chat input background for better contrast - Fix system theme listener not toggling back to light Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,449 @@
|
||||
export default {
|
||||
// 로그인
|
||||
login: {
|
||||
title: 'Hermes Web UI',
|
||||
description: '계속하려면 액세스 토큰을 입력하세요. 서버 시작 로그에서 확인할 수 있습니다.',
|
||||
placeholder: '액세스 토큰',
|
||||
submit: '로그인',
|
||||
tokenRequired: '액세스 토큰을 입력해 주세요',
|
||||
invalidToken: '유효하지 않은 토큰입니다',
|
||||
connectionFailed: '서버에 연결할 수 없습니다',
|
||||
},
|
||||
|
||||
// 공통
|
||||
common: {
|
||||
loading: '로딩 중...',
|
||||
cancel: '취소',
|
||||
delete: '삭제',
|
||||
edit: '편집',
|
||||
save: '저장',
|
||||
saved: '저장됨',
|
||||
update: '업데이트',
|
||||
create: '생성',
|
||||
saveFailed: '저장 실패',
|
||||
ok: '확인',
|
||||
copied: '복사됨',
|
||||
copy: '복사',
|
||||
noData: '데이터 없음',
|
||||
fetch: '가져오기',
|
||||
add: '추가',
|
||||
enable: '활성화',
|
||||
disable: '비활성화',
|
||||
configured: '구성됨',
|
||||
notConfigured: '미구성',
|
||||
confirm: '확인',
|
||||
expand: '펼치기',
|
||||
collapse: '접기',
|
||||
},
|
||||
|
||||
// 사이드바
|
||||
sidebar: {
|
||||
chat: '채팅',
|
||||
jobs: '예약 작업',
|
||||
models: '모델',
|
||||
profiles: '프로필',
|
||||
skills: '스킬',
|
||||
memory: '메모리',
|
||||
logs: '로그',
|
||||
usage: '사용량',
|
||||
channels: '채널',
|
||||
terminal: '터미널',
|
||||
settings: '설정',
|
||||
connected: '연결됨',
|
||||
disconnected: '연결 끊김',
|
||||
updateTip: '터미널에서 "hermes-web-ui update"를 실행하여 업데이트하세요',
|
||||
updateVersion: 'v{version}(으)로 업그레이드',
|
||||
updating: '업데이트 중...',
|
||||
updateSuccess: '업데이트 완료, 서버를 재시작해 주세요',
|
||||
updateFailed: '업데이트 실패',
|
||||
},
|
||||
|
||||
// 채팅
|
||||
chat: {
|
||||
emptyState: 'Hermes Agent와 대화를 시작하세요',
|
||||
inputPlaceholder: '메시지를 입력하세요... (Enter로 전송, Shift+Enter로 줄바꿈)',
|
||||
attachFiles: '파일 첨부',
|
||||
stop: '중지',
|
||||
send: '전송',
|
||||
contextUsed: '사용된 컨텍스트:',
|
||||
sessions: '세션',
|
||||
noSessions: '세션 없음',
|
||||
newChat: '새 채팅',
|
||||
deleteSession: '이 세션을 삭제하시겠습니까?',
|
||||
sessionDeleted: '세션이 삭제되었습니다',
|
||||
rename: '이름 변경',
|
||||
copySessionId: '세션 ID 복사',
|
||||
renamed: '이름이 변경되었습니다',
|
||||
renameFailed: '이름 변경 실패',
|
||||
renameSession: '세션 이름 변경',
|
||||
enterNewTitle: '새 제목을 입력하세요',
|
||||
other: '기타',
|
||||
runFailed: '실행 실패',
|
||||
error: '오류',
|
||||
tool: '도구',
|
||||
arguments: '인수',
|
||||
result: '결과',
|
||||
truncated: '... (잘림)',
|
||||
},
|
||||
|
||||
// 예약 작업
|
||||
jobs: {
|
||||
title: '예약 작업',
|
||||
createJob: '작업 생성',
|
||||
editJob: '작업 편집',
|
||||
noJobs: '예약된 작업이 없습니다. 새로 만들어 시작하세요.',
|
||||
name: '이름',
|
||||
namePlaceholder: '작업 이름',
|
||||
schedule: '스케줄 (Cron 표현식)',
|
||||
schedulePlaceholder: '예: 0 9 * * *',
|
||||
quickPresets: '빠른 프리셋',
|
||||
selectPreset: '프리셋 선택...',
|
||||
presetEveryMinute: '매 분',
|
||||
presetEvery5Min: '매 5분',
|
||||
presetEveryHour: '매 시간',
|
||||
presetEveryDay: '매일 00:00',
|
||||
presetEveryDay9: '매일 09:00',
|
||||
presetEveryMonday: '매주 월요일 09:00',
|
||||
presetEveryMonth: '매월 1일 09:00',
|
||||
prompt: '프롬프트',
|
||||
promptPlaceholder: '실행할 프롬프트',
|
||||
deliverTarget: '전송 대상',
|
||||
origin: '출처',
|
||||
local: '로컬',
|
||||
repeatCount: '반복 횟수 (선택)',
|
||||
repeatPlaceholder: '비워두면 무한 반복',
|
||||
jobCreated: '작업이 생성되었습니다',
|
||||
jobUpdated: '작업이 업데이트되었습니다',
|
||||
nameRequired: '이름을 입력해 주세요',
|
||||
scheduleRequired: '스케줄을 입력해 주세요',
|
||||
loadFailed: '작업을 불러오지 못했습니다',
|
||||
jobPaused: '작업이 일시 정지되었습니다',
|
||||
jobResumed: '작업이 재개되었습니다',
|
||||
jobTriggered: '작업이 실행되었습니다',
|
||||
jobDeleted: '작업이 삭제되었습니다',
|
||||
status: {
|
||||
running: '실행 중',
|
||||
paused: '일시 정지',
|
||||
disabled: '비활성화',
|
||||
scheduled: '예약됨',
|
||||
},
|
||||
info: {
|
||||
schedule: '스케줄',
|
||||
lastRun: '마지막 실행',
|
||||
nextRun: '다음 실행',
|
||||
deliver: '전송',
|
||||
repeat: '반복',
|
||||
},
|
||||
action: {
|
||||
pause: '일시 정지',
|
||||
pauseJob: '작업 일시 정지',
|
||||
resume: '재개',
|
||||
resumeJob: '작업 재개',
|
||||
runNow: '즉시 실행',
|
||||
triggerImmediately: '즉시 실행',
|
||||
},
|
||||
},
|
||||
|
||||
// 스킬
|
||||
skills: {
|
||||
title: '스킬',
|
||||
searchPlaceholder: '스킬 검색...',
|
||||
noMatch: '검색과 일치하는 스킬이 없습니다',
|
||||
noSkills: '스킬을 찾을 수 없습니다',
|
||||
backTo: '돌아가기',
|
||||
attachedFiles: '첨부 파일',
|
||||
loadFailed: '스킬을 불러오지 못했습니다',
|
||||
fileLoadFailed: '파일을 불러오지 못했습니다',
|
||||
toggleFailed: '스킬 상태를 전환하지 못했습니다',
|
||||
},
|
||||
|
||||
// 메모리
|
||||
memory: {
|
||||
title: '메모리',
|
||||
refresh: '새로고침',
|
||||
loadFailed: '메모리를 불러오지 못했습니다',
|
||||
myNotes: '내 메모',
|
||||
noNotes: '메모가 없습니다.',
|
||||
notesPlaceholder: '메모를 작성하세요...',
|
||||
userProfile: '사용자 프로필',
|
||||
noProfile: '프로필이 없습니다.',
|
||||
profilePlaceholder: '프로필을 작성하세요...',
|
||||
soul: '소울',
|
||||
noSoul: '소울 설정이 없습니다.',
|
||||
soulPlaceholder: '소울 설정을 작성하세요...',
|
||||
},
|
||||
|
||||
// 모델
|
||||
models: {
|
||||
title: '모델',
|
||||
addProvider: 'Provider 추가',
|
||||
providerType: 'Provider 유형',
|
||||
preset: '프리셋',
|
||||
custom: '사용자 지정',
|
||||
selectProvider: 'Provider 선택',
|
||||
chooseProvider: 'Provider를 선택하세요...',
|
||||
name: '이름',
|
||||
autoGeneratedName: 'Base URL에서 자동 생성',
|
||||
baseUrl: 'Base URL',
|
||||
baseUrlPlaceholder: '예: https://api.example.com/v1',
|
||||
apiKey: 'API Key',
|
||||
apiKeyPlaceholder: 'sk-...',
|
||||
defaultModel: '기본 모델',
|
||||
selectModel: '모델 선택...',
|
||||
providerAdded: 'Provider가 추가되었습니다',
|
||||
providerDeleted: 'Provider가 삭제되었습니다',
|
||||
deleteProvider: 'Provider 삭제',
|
||||
deleteConfirm: '"{name}"을(를) 삭제하시겠습니까?',
|
||||
noProviders: 'Provider가 없습니다. 사용자 지정 Provider를 추가하여 시작하세요.',
|
||||
builtIn: '내장',
|
||||
customType: '사용자 지정',
|
||||
provider: 'Provider',
|
||||
local: '로컬 ({host})',
|
||||
selectProviderRequired: 'Provider를 선택해 주세요',
|
||||
baseUrlRequired: 'Base URL을 입력해 주세요',
|
||||
apiKeyRequired: 'API Key를 입력해 주세요',
|
||||
modelRequired: '기본 모델을 선택해 주세요',
|
||||
enterBaseUrl: '먼저 Base URL을 입력해 주세요',
|
||||
unexpectedFormat: '예상치 못한 응답 형식입니다',
|
||||
foundModels: '{count}개의 모델을 찾았습니다',
|
||||
fetchFailed: '모델을 가져오지 못했습니다',
|
||||
},
|
||||
|
||||
// 프로필
|
||||
profiles: {
|
||||
title: '프로필',
|
||||
create: '프로필 생성',
|
||||
import: '가져오기',
|
||||
export: '내보내기',
|
||||
rename: '이름 변경',
|
||||
delete: '삭제',
|
||||
switchTo: '전환',
|
||||
switchConfirm: '프로필 "{name}"(으)로 전환하면 게이트웨이가 재시작됩니다. 계속하시겠습니까?',
|
||||
switchSuccess: '프로필 "{name}"(으)로 전환되었습니다',
|
||||
switchFailed: '프로필 전환 실패. 게이트웨이를 수동으로 재시작해야 할 수 있습니다.',
|
||||
createSuccess: '프로필 "{name}"이(가) 생성되었습니다',
|
||||
createFailed: '프로필 생성 실패',
|
||||
renameSuccess: '프로필 이름이 변경되었습니다',
|
||||
renameFailed: '프로필 이름 변경 실패',
|
||||
deleteConfirm: '프로필 "{name}"을(를) 삭제하시겠습니까?',
|
||||
deleteSuccess: '프로필이 삭제되었습니다',
|
||||
deleteFailed: '프로필 삭제 실패',
|
||||
exportSuccess: '프로필이 내보내기되었습니다',
|
||||
exportFailed: '프로필 내보내기 실패',
|
||||
importSuccess: '프로필이 가져오기되었습니다',
|
||||
importFailed: '프로필 가져오기 실패',
|
||||
importSelectFile: '아카이브 파일 선택',
|
||||
importInvalidFile: '유효한 아카이브 파일을 선택해 주세요 (.tar.gz, .tgz, .gz, .zip)',
|
||||
name: '프로필 이름',
|
||||
namePlaceholder: '영문, 숫자, 하이픈만 사용 가능',
|
||||
newName: '새 이름',
|
||||
newNamePlaceholder: '새 이름을 입력하세요',
|
||||
cloneFromCurrent: '현재 프로필에서 복제',
|
||||
archivePath: '아카이브 경로',
|
||||
archivePathPlaceholder: '아카이브 파일의 서버 경로',
|
||||
importName: '프로필 이름 (선택)',
|
||||
importNamePlaceholder: '비워두면 아카이브 이름을 사용합니다',
|
||||
active: '활성',
|
||||
model: '모델',
|
||||
gateway: '게이트웨이',
|
||||
alias: '별칭',
|
||||
provider: 'Provider',
|
||||
path: '경로',
|
||||
skills: '스킬',
|
||||
hasEnv: '.env 있음',
|
||||
hasSoulMd: 'soul.md 있음',
|
||||
noProfiles: '프로필이 없습니다. 새로 만들어 시작하세요.',
|
||||
},
|
||||
|
||||
// 로그
|
||||
logs: {
|
||||
title: '로그',
|
||||
all: '전체',
|
||||
searchPlaceholder: '검색...',
|
||||
refresh: '새로고침',
|
||||
noEntries: '로그 항목 없음',
|
||||
},
|
||||
|
||||
// 설정
|
||||
settings: {
|
||||
title: '설정',
|
||||
saved: '저장됨',
|
||||
saveFailed: '저장 실패',
|
||||
tabs: {
|
||||
display: '표시',
|
||||
agent: '에이전트',
|
||||
memory: '메모리',
|
||||
session: '세션',
|
||||
privacy: '개인정보',
|
||||
apiServer: 'API 서버',
|
||||
},
|
||||
display: {
|
||||
streaming: '스트리밍 응답',
|
||||
streamingHint: 'AI 응답을 실시간으로 표시',
|
||||
compact: '컴팩트 모드',
|
||||
compactHint: '메시지 간격 줄이기',
|
||||
showReasoning: '추론 과정 표시',
|
||||
showReasoningHint: '모델의 생각 과정 표시',
|
||||
showCost: '비용 표시',
|
||||
showCostHint: '응답에 토큰 사용량 표시',
|
||||
inlineDiffs: '인라인 변경사항',
|
||||
inlineDiffsHint: '코드 변경사항을 인라인으로 표시',
|
||||
bellOnComplete: '완료 알림음',
|
||||
bellOnCompleteHint: 'AI 응답 완료 시 알림음 재생',
|
||||
busyInputMode: '바쁨 입력 모드',
|
||||
busyInputModeHint: 'AI 처리 중에도 입력 허용',
|
||||
theme: '테마',
|
||||
themeHint: '라이트, 다크 또는 시스템 설정 따르기',
|
||||
themeLight: '라이트',
|
||||
themeDark: '다크',
|
||||
themeSystem: '시스템',
|
||||
},
|
||||
agent: {
|
||||
maxTurns: '최대 턴 수',
|
||||
maxTurnsHint: '대화당 최대 상호작용 라운드 수',
|
||||
gatewayTimeout: '게이트웨이 시간초과',
|
||||
gatewayTimeoutHint: '요청 시간초과 (초)',
|
||||
restartDrainTimeout: '재시작 드레인 시간초과',
|
||||
restartDrainTimeoutHint: '재시작 전 드레인 시간초과 (초)',
|
||||
toolEnforcement: '도구 실행 정책',
|
||||
toolEnforcementHint: '도구 호출 실행 모드 제어',
|
||||
auto: '자동',
|
||||
always: '항상',
|
||||
never: '사용 안 함',
|
||||
},
|
||||
memory: {
|
||||
enabled: '메모리 활성화',
|
||||
enabledHint: 'AI가 대화 컨텍스트를 기억하도록 허용',
|
||||
userProfile: '사용자 프로필',
|
||||
userProfileHint: 'AI가 사용자 선호를 기억하도록 허용',
|
||||
charLimit: '메모리 문자 제한',
|
||||
charLimitHint: 'MEMORY.md 최대 문자 수',
|
||||
userCharLimit: '사용자 프로필 문자 제한',
|
||||
userCharLimitHint: 'USER.md 최대 문자 수',
|
||||
},
|
||||
session: {
|
||||
mode: '초기화 모드',
|
||||
modeHint: '세션 초기화 트리거 조건',
|
||||
modeBoth: '유휴 + 예약',
|
||||
modeIdle: '유휴만',
|
||||
modeHourly: '예약만',
|
||||
idleMinutes: '유휴 시간초과',
|
||||
idleMinutesHint: '자동 초기화 대기 시간 (분)',
|
||||
atHour: '예약 초기화 시간',
|
||||
atHourHint: '매일 지정한 시간에 세션 초기화',
|
||||
},
|
||||
privacy: {
|
||||
redactPii: '개인정보 마스킹',
|
||||
redactPiiHint: '민감 정보 자동 감지 및 숨김 (비밀번호, 키 등)',
|
||||
},
|
||||
apiServer: {
|
||||
enable: '활성화',
|
||||
enableHint: 'API 서버 활성화',
|
||||
host: '호스트',
|
||||
hostHint: '수신 주소',
|
||||
port: '포트',
|
||||
portHint: '수신 포트',
|
||||
key: '키',
|
||||
keyHint: 'API 접근 키',
|
||||
cors: 'CORS 출처',
|
||||
corsHint: '허용된 교차 출처',
|
||||
},
|
||||
},
|
||||
|
||||
// 플랫폼 채널 설정
|
||||
platform: {
|
||||
requireMention: "{'@'}멘션 필요",
|
||||
requireMentionGroup: "그룹에서 {'@'}멘션 시에만 응답",
|
||||
requireMentionChannel: "채널에서 {'@'}멘션 시에만 응답",
|
||||
requireMentionRoom: "방에서 {'@'}멘션 시에만 응답",
|
||||
reactions: '반응',
|
||||
reactionsHint: '메시지에 이모지 반응',
|
||||
freeResponseChats: '자유 응답 채팅',
|
||||
freeResponseChatsHint: "{'@'}멘션 없이 응답할 채팅 ID (쉼표로 구분)",
|
||||
freeResponseChannels: '자유 응답 채널',
|
||||
freeResponseChannelsHint: "{'@'}멘션 없이 응답할 채널 ID (쉼표로 구분)",
|
||||
freeResponseRooms: '자유 응답 방',
|
||||
freeResponseRoomsHint: "{'@'}멘션 없이 응답할 방 ID (쉼표로 구분)",
|
||||
mentionPatterns: '사용자 지정 멘션 패턴',
|
||||
mentionPatternsHint: '추가 트리거 패턴',
|
||||
autoThread: '자동 스레드',
|
||||
autoThreadHint: "{'@'}멘션 후 자동으로 스레드 생성",
|
||||
autoThreadHintRoom: '방에서 자동으로 스레드 생성',
|
||||
dmMentionThreads: 'DM 멘션 스레드',
|
||||
dmMentionThreadsHint: 'DM에서 멘션 시 스레드로 응답',
|
||||
allowBots: '봇 메시지 허용',
|
||||
allowBotsHint: '다른 봇의 메시지에 응답',
|
||||
allowedChannels: '허용된 채널',
|
||||
allowedChannelsHint: '채널 ID 허용 목록 (쉼표로 구분)',
|
||||
ignoredChannels: '무시할 채널',
|
||||
ignoredChannelsHint: '봇이 응답하지 않는 채널 ID (쉼표로 구분)',
|
||||
noThreadChannels: '스레드 없는 채널',
|
||||
noThreadChannelsHint: '스레드 없이 응답할 채널 ID (쉼표로 구분)',
|
||||
botToken: 'Bot Token',
|
||||
botTokenHint: '개발자 포털에서 발급받은 Bot Token',
|
||||
accessToken: 'Access Token',
|
||||
accessTokenHint: 'Matrix Access Token',
|
||||
homeserver: 'Homeserver URL',
|
||||
homeserverHint: 'Matrix 홈서버 URL',
|
||||
appId: 'App ID',
|
||||
appIdHint: 'Feishu App ID',
|
||||
appSecret: 'App Secret',
|
||||
appSecretHint: 'Feishu App Secret',
|
||||
clientId: 'Client ID',
|
||||
clientIdHint: 'DingTalk Client ID',
|
||||
clientSecret: 'Client Secret',
|
||||
clientSecretHint: 'DingTalk Client Secret',
|
||||
botId: 'Bot ID',
|
||||
botIdHint: 'WeCom Bot ID',
|
||||
wecomSecretHint: 'WeCom Bot Secret',
|
||||
waEnabled: 'WhatsApp 활성화',
|
||||
waEnabledHint: 'QR 코드 페어링으로 WhatsApp 활성화',
|
||||
weixinToken: 'Weixin Token',
|
||||
weixinTokenHint: 'weixin CLI QR 로그인에서 가져오기 (hermes weixin)',
|
||||
accountId: 'Account ID',
|
||||
accountIdHint: 'Weixin Account ID',
|
||||
qrLogin: 'QR 로그인',
|
||||
qrRelogin: '다시 로그인',
|
||||
qrFetching: 'QR 코드를 가져오는 중...',
|
||||
qrScanHint: 'WeChat으로 QR 코드를 스캔하여 로그인',
|
||||
qrScanedHint: '스캔됨, 휴대폰에서 확인해 주세요...',
|
||||
},
|
||||
|
||||
// 언어
|
||||
language: {
|
||||
label: '언어',
|
||||
zh: '中文',
|
||||
en: 'English',
|
||||
ko: '한국어',
|
||||
},
|
||||
|
||||
// 터미널
|
||||
terminal: {
|
||||
sessions: '세션',
|
||||
newTab: '새 터미널',
|
||||
closeSession: '이 세션을 닫으시겠습니까?',
|
||||
sessionExited: '종료됨',
|
||||
processExited: '프로세스가 종료되었습니다 (코드 {code})',
|
||||
},
|
||||
|
||||
// 사용량
|
||||
usage: {
|
||||
title: '사용량 통계',
|
||||
refresh: '새로고침',
|
||||
totalTokens: '총 토큰 수',
|
||||
inputTokens: '입력',
|
||||
outputTokens: '출력',
|
||||
totalSessions: '총 세션 수',
|
||||
avgPerDay: '일평균 ~{n}',
|
||||
estimatedCost: '예상 비용',
|
||||
cacheHitRate: '캐시 적중률',
|
||||
modelBreakdown: '모델별 분포',
|
||||
dailyTrend: '일별 사용량 (최근 30일)',
|
||||
date: '날짜',
|
||||
tokens: '토큰',
|
||||
cache: '캐시',
|
||||
sessions: '세션',
|
||||
cost: '비용',
|
||||
noData: '사용량 데이터 없음',
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user