feat(i18n): add multi-language support (ja/ko/vi/ru/zh-TW) with system auto-detection

- Extend AppLanguage to 7 locales: zh-CN, zh-TW, en, ja, ko, vi, ru
- Auto-detect system language via navigator.languages; fallback to English
- Add BCP47 locale mapping for date formatting and sorting
- Create 50 translation JSON files (5 languages × 10 namespaces, 1137 keys each)
- Update language selector with native language names
- Extend locale key parity test to cover all 7 languages (70 assertions)
- Add VNC/RDP desktop, serial terminal, AI agent, port forwarding, and SFTP features
- Add credential encryption, host metrics, session backup crypto, and zmodem bridge
- Update Rust backend: desktop services, host metrics, SSH/SFTP enhancements
This commit is contained in:
Logan.Li committed 2026-08-12 00:07:48 +08:00
1 parent fea6d8db04
commit b0d0e3a5f3
301 files changed
+28002 -2705

No files matched your search

+237
View File
@@ -0,0 +1,237 @@
{
"sidebar": {
"quickConnect": "빠른 연결",
"quickConnectShort": "연결",
"newSession": "새 세션",
"newSessionShort": "새로",
"searchPlaceholder": "세션 검색...",
"batchMode": "일괄 작업",
"exitBatchMode": "일괄 모드 종료",
"batchSelected": "{{count}}개 SSH 선택됨",
"batchExcludedDesktop": " · RDP/VNC 제외됨",
"selectAllVisible": "보이는 항목 모두 선택",
"deselectAllVisible": "보이는 항목 선택 해제",
"batchExec": "일괄 실행",
"settings": "설정",
"resizeHint": "드래그하여 크기 조정; 더블클릭하여 접기"
},
"tree": {
"selectSession": "세션 선택",
"noMatchTitle": "일치하는 세션 없음",
"noMatchDesc": "다른 키워드를 시도해 보세요",
"emptyTitle": "아직 세션이 없습니다",
"emptyDesc": "빠른 연결 또는 세션 생성; 더블클릭하여 터미널 열기",
"emptyAction": "새 세션"
},
"contextMenu": {
"blank": {
"newGroup": "새 그룹",
"newSession": "새 세션"
},
"group": {
"newSessionHere": "여기에 새 세션",
"newGroup": "새 그룹",
"renameGroup": "그룹 이름 변경",
"deleteEmptyGroup": "빈 그룹 삭제"
},
"session": {
"open": "열기",
"edit": "편집",
"duplicate": "복제",
"delete": "삭제"
}
},
"groups": {
"default": "기본",
"new": {
"title": "새 그룹",
"message": "그룹 이름 입력",
"placeholder": "예: 프로덕션",
"confirm": "생성"
},
"rename": {
"title": "그룹 이름 변경",
"message": "\"{{name}}\"을(를) 다음으로 변경",
"placeholder": "그룹 이름",
"confirm": "저장"
},
"deleteBlocked": {
"title": "삭제할 수 없음",
"message": "그룹 \"{{name}}\"에 아직 세션이 있습니다. 먼저 이동하거나 삭제하세요.",
"confirm": "확인"
},
"newOption": "새 그룹…",
"hint": "다른 것을 선택하거나 생성하지 않으면 기본 그룹이 사용됩니다"
},
"deleteSession": {
"title": "세션 삭제",
"message": "세션 \"{{name}}\"을(를) 삭제하시겠습니까?",
"confirm": "삭제"
},
"welcome": {
"tagline": "원격 터미널 · SFTP · 포트 포워딩",
"sectionStart": "시작하기",
"sectionDesktop": "원격 데스크톱",
"sectionRecent": "최근 세션",
"quickConnect": {
"title": "빠른 연결",
"desc": "1회성 SSH; 라이브러리에 저장되지 않음"
},
"newSession": {
"title": "새 세션",
"desc": "호스트 저장; 사이드바에서 더블클릭하여 연결"
},
"localShell": {
"title": "로컬 셸",
"selectShell": "셸 선택",
"default": "기본"
},
"rdp": {
"title": "RDP 원격 데스크톱",
"desc": "Windows · NLA / CredSSP"
},
"vnc": {
"title": "VNC 원격 데스크톱",
"desc": "RFB · 크로스 플랫폼 그래픽 세션"
},
"recentEmpty": {
"title": "저장된 세션 없음",
"desc": "빠른 연결을 시도하거나, 나중에 재사용할 세션을 생성하세요"
}
},
"launcher": {
"searchPlaceholder": "호스트, 그룹 또는 탭 검색"
},
"quickConnect": {
"title": "빠른 연결",
"target": "대상",
"targetPlaceholder": "root@192.168.1.10:22",
"targetHint": "호스트, user@host, user@host:port 지원",
"password": "비밀번호",
"passwordOptional": "선택 사항 · 키 사용 시 비워두세요",
"connect": "연결",
"errorInvalidTarget": "호스트를 입력하세요, 예: root@192.168.1.10 또는 opsbase.cn:5555",
"errorConnectFailed": "연결 실패"
},
"dialog": {
"create": "새 세션",
"edit": "세션 편집",
"subtitle": "1줄 대상 · 고급 옵션 접힘",
"saving": "저장 중…",
"save": "저장",
"createAndSave": "생성 및 저장",
"basic": "기본",
"login": "로그인",
"advanced": "고급",
"advancedCollapsed": "프록시 · 점프 호스트 · 태그",
"collapse": "접기",
"protocol": "프로토콜",
"displayName": "표시 이름 (선택 사항)",
"displayNamePlaceholder": "기본값은 user@host 또는 vnc:host",
"host": "호스트",
"hostPlaceholder": "192.168.1.10",
"hostHint": "IP 또는 호스트명; host:port도 허용됨",
"port": "포트",
"username": "사용자 이름",
"usernamePlaceholderRdp": "Administrator",
"usernamePlaceholderSsh": "root",
"width": "너비",
"height": "높이",
"group": "그룹",
"authPassword": "비밀번호",
"authKey": "키",
"password": "비밀번호",
"domain": "도메인 (선택 사항)",
"domainPlaceholder": "도메인 계정을 사용하지 않으면 거의 필요하지 않음",
"keySource": "키 소스",
"keyFile": "파일",
"keyText": "텍스트",
"privateKeyPath": "개인 키 경로",
"privateKeyText": "개인 키 텍스트",
"privateKeyTextHint": "붙여넣은 키는 비밀번호처럼 디스크에 암호화됩니다",
"pickKeyFile": "찾아보기…",
"pickKeyDialogTitle": "개인 키 파일 선택",
"allFilesFilter": "모든 파일",
"passphrase": "키 암호 (선택 사항)",
"passphrasePlaceholder": "선택 사항",
"tags": "태그",
"tagsPlaceholder": "prod, web",
"startupCommand": "시작 명령 (선택 사항)",
"startupCommandPlaceholder": "연결 후 실행, 예: cd /var/log",
"proxy": "프록시",
"proxyNone": "없음",
"proxyHostPlaceholder": "프록시 호스트",
"proxyPortPlaceholder": "포트",
"proxyUserPlaceholder": "사용자 이름 (선택 사항)",
"proxyPasswordPlaceholder": "비밀번호 (선택 사항)",
"jumpHost": "점프 호스트 (선택 사항)",
"jumpNone": "점프 호스트 없음",
"jumpNoneAlt": "점프 호스트 없음",
"jumpHint": "저장된 세션 하나를 점프 호스트로 사용할 수 있습니다"
},
"batch": {
"title": "일괄 실행",
"subtitle": "{{selected}}개 선택됨 · 동시성 {{concurrency}} · 탭 닫기 시 결과 폐기",
"dialogTitle": "일괄 명령",
"dialogDesc": "{{selected}}/{{total}}개 호스트 선택됨 · 최대 동시성 {{concurrency}}",
"targetCount": "{{count}}개 대상",
"runningProgress": "실행 중 {{completed}}/{{total}}",
"execute": "{{count}}개 호스트에서 실행",
"executeAgain": "다시 실행",
"success": "{{count}}개 성공",
"failed": "{{count}}개 실패",
"command": "원격 명령",
"commandPlaceholder": "예: uptime",
"targets": "대상 호스트",
"filterPlaceholder": "이름, IP, 그룹 또는 태그",
"filterAria": "호스트 필터",
"noMatchHosts": "일치하는 호스트 없음",
"resultMatrix": "결과 매트릭스",
"resultMatrixHint": "호스트 × 상태 × 출력",
"emptySelection": "왼쪽에서 대상을 선택하거나, 사이드바 일괄 모드에서 선택한 상태로 여세요",
"noOutput": "(출력 없음)",
"errorReadConfig": "세션 설정을 읽을 수 없음",
"errorConnectFailed": "연결 실패",
"errorExecFailed": "명령 실행 실패",
"results": "결과",
"resultsHint": "출력은 이 대화상자에만 보관됩니다",
"ctrlEnterHint": "Ctrl/⌘ + Enter로 실행",
"executeTo": "{{count}}개 호스트에서 실행",
"selectFromLeft": "왼쪽에서 대상 선택"
},
"importExport": {
"exportTitle": "세션 내보내기",
"exportDefaultPath": "opsxshell-sessions.bak",
"exportFilterBak": "OpsXShell 백업",
"exportFilterJson": "JSON",
"exportSuccess": "{{count}}개 세션을 다음으로 내보냄:\n{{path}}",
"exportWriteFailed": "내보내기 파일 쓰기 실패",
"exportFailed": "세션 내보내기 실패",
"exportFailedDetail": "세션 내보내기 실패: {{message}}",
"exportPasswordTitle": "백업 비밀번호 설정",
"exportPasswordMessage": "내보내기 파일은 호스트 그룹, 개인 키, 비밀번호 및 기타 비밀을 암호화합니다. 백업 비밀번호를 선택하세요.",
"exportPasswordPlaceholder": "백업 비밀번호 입력",
"exportPasswordConfirmTitle": "백업 비밀번호 확인",
"exportPasswordConfirmMessage": "확인을 위해 백업 비밀번호를 다시 입력하세요.",
"exportPasswordConfirmPlaceholder": "백업 비밀번호 재입력",
"exportPasswordMismatch": "비밀번호가 일치하지 않습니다",
"exportPasswordRequired": "내보내기에는 백업 비밀번호가 필요합니다",
"importTitle": "세션 가져오기",
"importFilterBak": "OpsXShell 백업",
"importFilterJson": "JSON",
"importFilterSshConfig": "SSH Config",
"importFilterAll": "모든 파일",
"readFileFailed": "파일 읽기 실패",
"readFileFailedDetail": "파일 읽기 실패: {{message}}",
"importPasswordTitle": "백업 비밀번호 입력",
"importPasswordMessage": "이 파일은 암호화되어 있습니다. 호스트 그룹과 자격 증명을 가져오려면 내보낼 때 설정한 비밀번호를 입력하세요.",
"importPasswordPlaceholder": "백업 비밀번호 입력",
"importPasswordRequired": "암호화된 백업을 가져오려면 비밀번호가 필요합니다",
"importPasswordInvalid": "잘못된 백업 비밀번호이거나 파일이 손상되었습니다",
"noSessionsFound": "가져올 수 있는 세션을 찾지 못했습니다",
"noValidSessions": "파일에 유효한 세션 항목이 없습니다",
"importSuccess": "{{created}}/{{total}}개 세션을 가져왔습니다",
"importFailed": "세션 가져오기 실패",
"importFailedDetail": "세션 가져오기 실패: {{message}}"
}
}