diff --git a/frontend/scripts/check-i18n-parity.mjs b/frontend/scripts/check-i18n-parity.mjs
index 02191c02e..c2cc2d418 100644
--- a/frontend/scripts/check-i18n-parity.mjs
+++ b/frontend/scripts/check-i18n-parity.mjs
@@ -285,6 +285,24 @@ const ZH_TW_COGNATES = [
'EC984C,#6CD4BC,A66EB9,D87694',
];
+// Korean: script difference means almost nothing is identical.
+// Allow loanwords/acronyms, format strings, and proper nouns that stay verbatim.
+const KO_COGNATES = [
+ 'OK', 'Bambu', 'N/A',
+ '({{count}}/8)', '(25%, 50%, 75%)',
+ 'Custom Headers (JSON)',
+ 'Box label (62 × 29 mm)',
+ 'Avery L7160 — A4 sheet (38.1 × 63.5 mm × 21)',
+ 'Avery 5160 — US Letter sheet (25.4 × 66.7 mm × 30)',
+ 'EC984C,#6CD4BC,A66EB9,D87694',
+ '{{weight}}g', // unit suffix format string
+ 'MakerWorld: {{designer}}', // brand + placeholder
+ 'email', // OIDC claim name placeholder
+ '{{printer}}: {{error}}', // pure placeholders
+ '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}', // pure placeholders
+ 'Obico ML API URL', // product name (Obico)
+];
+
// Spanish cognates — words/phrases that are genuinely identical in Spanish.
const ES_COGNATES = [
'Error', 'Firmware', 'General', 'Control', 'Total', 'total', 'Material',
@@ -306,6 +324,7 @@ const IDENTICAL_TO_EN_ALLOWED = {
fr: new Set(FR_COGNATES),
it: new Set(IT_COGNATES),
ja: new Set(JA_COGNATES),
+ ko: new Set(KO_COGNATES),
es: new Set(ES_COGNATES),
'pt-BR': new Set(PT_BR_COGNATES),
'zh-CN': new Set(ZH_CN_COGNATES),
diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts
index 83d022e1d..cf1252993 100644
--- a/frontend/src/i18n/index.ts
+++ b/frontend/src/i18n/index.ts
@@ -9,6 +9,7 @@ import es from './locales/es';
import fr from './locales/fr';
import ja from './locales/ja';
import it from './locales/it';
+import ko from './locales/ko';
import ptBR from './locales/pt-BR';
import zhCN from './locales/zh-CN';
import zhTW from './locales/zh-TW';
@@ -20,6 +21,7 @@ const resources = {
fr: { translation: fr },
ja: { translation: ja },
it: { translation: it },
+ ko: { translation: ko },
'pt-BR': { translation: ptBR },
'zh-CN': { translation: zhCN },
'zh-TW': { translation: zhTW },
@@ -31,7 +33,7 @@ i18n
.init({
resources,
fallbackLng: 'en',
- supportedLngs: ['en', 'de', 'es', 'fr', 'ja', 'it', 'pt-BR', 'zh-CN', 'zh-TW'],
+ supportedLngs: ['en', 'de', 'es', 'fr', 'ja', 'it', 'ko', 'pt-BR', 'zh-CN', 'zh-TW'],
detection: {
// Order of detection methods
@@ -61,6 +63,7 @@ export const availableLanguages = [
{ code: 'fr', name: 'French', nativeName: 'Français' },
{ code: 'ja', name: 'Japanese', nativeName: '日本語' },
{ code: 'it', name: 'Italian', nativeName: 'Italiano' },
+ { code: 'ko', name: 'Korean', nativeName: '한국어' },
{ code: 'pt-BR', name: 'Portuguese (Brazil)', nativeName: 'Português (Brasil)' },
{ code: 'zh-CN', name: 'Chinese (Simplified)', nativeName: '简体中文' },
{ code: 'zh-TW', name: 'Chinese (Traditional)', nativeName: '繁體中文' },
diff --git a/frontend/src/i18n/locales/ko.ts b/frontend/src/i18n/locales/ko.ts
new file mode 100644
index 000000000..f3300429e
--- /dev/null
+++ b/frontend/src/i18n/locales/ko.ts
@@ -0,0 +1,5725 @@
+export default {
+ nav: {
+ printers: '프린터',
+ archives: '아카이브',
+ queue: '대기열',
+ stats: '통계',
+ profiles: '프로필',
+ maintenance: '유지보수',
+ projects: '프로젝트',
+ inventory: '필라멘트',
+ files: '파일 관리자',
+ makerworld: 'MakerWorld',
+ notifications: '알림',
+ settings: '설정',
+ system: '시스템',
+ collapseSidebar: '사이드바 접기',
+ expandSidebar: '사이드바 펼치기',
+ update: '업데이트',
+ updateAvailable: '업데이트 가능: v{{version}}',
+ updateAvailableBanner: '버전 {{version}}이(가) 출시되었습니다!',
+ viewUpdate: '업데이트 보기',
+ viewOnGithub: 'GitHub에서 보기',
+ keyboardShortcuts: '키보드 단축키 (?)',
+ switchToLight: '라이트 모드로 전환',
+ switchToDark: '다크 모드로 전환',
+ switchToSystem: '기기 설정으로 전환',
+ smartSwitches: '스마트 스위치',
+ logout: '로그아웃',
+ installApp: '앱 설치',
+ installAppSuccess: 'Bambuddy가 설치되었습니다'
+ },
+ common: {
+ save: '저장',
+ saving: '저장 중...',
+ cancel: '취소',
+ delete: '삭제',
+ edit: '편집',
+ add: '추가',
+ close: '닫기',
+ confirm: '확인',
+ loading: '로딩 중...',
+ error: '오류',
+ errorLoading: '데이터 로딩 오류',
+ retry: '재시도',
+ success: '성공',
+ warning: '경고',
+ enabled: '활성화됨',
+ disabled: '비활성화됨',
+ yes: '예',
+ no: '아니요',
+ on: '켜짐',
+ off: '꺼짐',
+ all: '전체',
+ none: '없음',
+ search: '검색',
+ filter: '필터',
+ sort: '정렬',
+ refresh: '새로고침',
+ download: '다운로드',
+ upload: '업로드',
+ uploading: '업로드 중...',
+ uploadFailed: '업로드 실패',
+ actions: '작업',
+ status: '상태',
+ name: '이름',
+ description: '설명',
+ date: '날짜',
+ time: '시간',
+ hours: '시간',
+ minutes: '분',
+ seconds: '초',
+ days: '일',
+ enable: '활성화',
+ disable: '비활성화',
+ permissions: '권한',
+ noPrinters: '등록된 프린터가 없습니다',
+ noData: '데이터가 없습니다',
+ linkNotFound: '링크를 찾을 수 없습니다',
+ required: '필수',
+ optional: '선택',
+ dismiss: '닫기',
+ apply: '적용',
+ reset: '초기화',
+ export: '내보내기',
+ import: '가져오기',
+ clear: '지우기',
+ selectAll: '전체 선택',
+ deselectAll: '전체 해제',
+ noChange: '— 변경 없음 —',
+ unchanged: '변경 없음',
+ unassigned: '미할당',
+ unknown: '알 수 없음',
+ unknownError: '알 수 없는 오류',
+ today: '오늘',
+ tomorrow: '내일',
+ asap: '즉시',
+ overdue: '기한 초과',
+ now: '지금',
+ collapse: '접기',
+ expand: '펼치기',
+ viewArchive: '아카이브 보기',
+ viewInFileManager: '파일 관리자에서 보기',
+ addedBy: '{{username}}님이 추가함',
+ prints: '인쇄',
+ more: '+{{count}}개 더',
+ ascending: '오름차순',
+ descending: '내림차순',
+ back: '뒤로',
+ copy: '복사',
+ copied: '복사됨!',
+ printer: '프린터',
+ remove: '제거',
+ type: '유형',
+ print: '인쇄',
+ rename: '이름 변경',
+ move: '이동',
+ create: '만들기',
+ duplicate: '복제',
+ left: '왼쪽',
+ right: '오른쪽'
+ },
+ printers: {
+ title: '프린터',
+ addPrinter: '프린터 추가',
+ editPrinter: '프린터 편집',
+ deletePrinter: '프린터 삭제',
+ printerName: '프린터 이름',
+ serialNumber: '일련번호',
+ ipAddress: 'IP 주소 / 호스트명',
+ accessCode: '액세스 코드',
+ model: '모델',
+ nozzleCount: '노즐 수',
+ autoArchive: '자동 아카이브',
+ status: {
+ available: '사용 가능',
+ idle: '대기 중',
+ printing: '인쇄 중',
+ paused: '일시정지',
+ offline: '오프라인',
+ problem: '문제 발생',
+ error: '오류',
+ finished: '완료',
+ unknown: '알 수 없음'
+ },
+ temperatures: {
+ nozzle: '노즐',
+ bed: '베드',
+ chamber: '챔버'
+ },
+ progress: '{{percent}}% 완료',
+ timeRemaining: '{{time}} 남음',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까?',
+ maintenanceOk: '유지보수 정상',
+ maintenanceWarning: '{{count}}개 경고',
+ maintenanceWarning_plural: '{{count}}개 경고',
+ maintenanceDue: '{{count}}개 예정',
+ maintenanceDue_plural: '{{count}}개 예정',
+ sort: {
+ name: '이름',
+ status: '상태',
+ model: '모델',
+ location: '위치',
+ ascending: '오름차순 정렬',
+ descending: '내림차순 정렬'
+ },
+ cardSize: {
+ small: '작은 카드',
+ medium: '중간 카드',
+ large: '큰 카드',
+ extraLarge: '아주 큰 카드'
+ },
+ hideOffline: '오프라인 숨기기',
+ nextAvailable: '다음 가용',
+ powerOn: '전원 켜기',
+ offlinePrintersWithPlugs: '스마트 플러그가 연결된 오프라인 프린터',
+ noPrintersConfigured: '아직 설정된 프린터가 없습니다',
+ search: '프린터 검색...',
+ noSearchResults: '검색 또는 필터 조건에 맞는 프린터가 없습니다',
+ filter: {
+ allStatuses: '모든 상태',
+ allLocations: '모든 위치'
+ },
+ toolbar: {
+ filters: '필터',
+ view: '보기',
+ actions: '작업'
+ },
+ readyToPrint: '인쇄 준비 완료',
+ external: '외부',
+ extL: '외부-L',
+ extR: '외부-R',
+ deleteArchives: '인쇄 아카이브 삭제',
+ noLabel: '라벨 없음',
+ printPreview: '인쇄 미리보기',
+ width: '너비',
+ height: '높이',
+ noObjectsFound: '객체를 찾을 수 없습니다',
+ objectsLoadedOnPrintStart: '인쇄 시작 시 객체가 로드됩니다',
+ willBeSkipped: '건너뛸 예정',
+ name: '이름',
+ serialCannotBeChanged: '일련번호는 변경할 수 없습니다',
+ locationHelp: '프린터 그룹화 및 대기열 작업 필터링에 사용됩니다',
+ wifiSignal: {
+ veryWeak: '매우 약함',
+ weak: '약함',
+ fair: '보통',
+ good: '좋음',
+ excellent: '매우 좋음'
+ },
+ maintenanceUpToDate: '모든 유지보수 최신 상태 - 클릭하여 보기',
+ chamberLightOn: '챔버 조명 켜기',
+ chamberLightOff: '챔버 조명 끄기',
+ files: '파일',
+ browseFiles: '프린터 파일 탐색',
+ autoOffAfterPrint: '인쇄 후 자동 전원 끄기',
+ autoOffExecuted: '자동 끄기 실행됨 - 초기화하려면 프린터를 켜세요',
+ hmsErrors: 'HMS 오류',
+ viewHmsErrors: '{{count}}개 HMS 오류 보기',
+ resume: '재개',
+ pause: '일시정지',
+ stop: '정지',
+ camera: '카메라',
+ skipObject: '객체 건너뛰기',
+ reconnect: '재연결',
+ forceRefresh: '강제 새로고침',
+ forceRefreshSuccess: '새로고침 요청됨',
+ mqttDebug: 'MQTT 디버그',
+ printerInformation: '프린터 정보',
+ copyToClipboard: '복사',
+ copied: '복사됨!',
+ state: '상태',
+ wifiSignalLabel: 'WiFi 신호',
+ developerMode: '개발자 모드',
+ enabled: '활성화됨',
+ disabled: '비활성화됨',
+ addedOn: '추가됨',
+ sdCard: 'SD 카드',
+ inserted: '삽입됨',
+ notInserted: '삽입되지 않음',
+ totalPrintHours: '인쇄 시간',
+ activeNozzle: '활성: {{nozzle}} 노즐',
+ nozzleRack: '노즐 랙',
+ nozzleDocked: '도킹됨',
+ nozzleMounted: '장착됨',
+ nozzleActive: '활성',
+ nozzleIdle: '대기',
+ nozzleDiameter: '직경',
+ nozzleType: '유형',
+ nozzleStatus: '상태',
+ nozzleFilament: '필라멘트',
+ nozzleWear: '마모',
+ nozzleMaxTemp: '최대 온도',
+ nozzleSerial: '일련번호',
+ nozzleHardenedSteel: '경화강',
+ nozzleStainlessSteel: '스테인리스강',
+ nozzleTungstenCarbide: '텅스텐 카바이드',
+ nozzleFlow: '유량',
+ nozzleHighFlow: '고유량',
+ nozzleStandardFlow: '표준',
+ firmwareUpdate: '펌웨어 업데이트',
+ firmwareInstructions: '프린터 터치스크린에서',
+ firmwareNav: '이동',
+ settings: '설정',
+ firmware: '펌웨어',
+ discoverPrinters: '프린터 검색',
+ searching: '검색 중...',
+ manualEntry: '수동 입력',
+ addFromCloud: '클라우드에서 추가',
+ toast: {
+ printerDeleted: '프린터가 삭제되었습니다',
+ missingSpoolAssignment: '{{printer}}에서 인쇄가 시작되었습니다. 슬롯 할당 누락: {{slots}}',
+ printerAdded: '프린터가 추가되었습니다',
+ printerUpdated: '프린터가 업데이트되었습니다',
+ failedToDelete: '프린터 삭제 실패',
+ failedToAdd: '프린터 추가 실패',
+ failedToUpdate: '프린터 업데이트 실패',
+ commandSent: '명령이 전송되었습니다',
+ failedToSendCommand: '명령 전송 실패',
+ turnedOn: '{{name}} 켜짐',
+ failedToPowerOn: '{{name}} 전원 켜기 실패',
+ scriptTriggered: '스크립트가 실행되었습니다',
+ printStopped: '인쇄가 정지되었습니다',
+ printPaused: '인쇄가 일시정지되었습니다',
+ printResumed: '인쇄가 재개되었습니다',
+ referenceDeleted: '참조가 삭제되었습니다',
+ detectionAreaSaved: '감지 영역이 저장되었습니다',
+ failedToRunScript: '스크립트 실행 실패',
+ failedToStopPrint: '인쇄 정지 실패',
+ failedToPausePrint: '인쇄 일시정지 실패',
+ failedToResumePrint: '인쇄 재개 실패',
+ failedToControlChamberLight: '챔버 조명 제어 실패',
+ failedToSetSpeed: '인쇄 속도 설정 실패',
+ failedToUpdateSetting: '설정 업데이트 실패',
+ failedToSkipObjects: '객체 건너뛰기 실패',
+ failedToRereadRfid: 'RFID 재읽기 실패',
+ failedToCheckPlate: '플레이트 확인 실패',
+ failedToUpdateLabel: '라벨 업데이트 실패',
+ failedToDeleteReference: '참조 삭제 실패',
+ failedToSaveDetectionArea: '감지 영역 저장 실패',
+ plateCheckEnabled: '플레이트 확인 활성화됨',
+ plateCheckDisabled: '플레이트 확인 비활성화됨',
+ calibrationSaved: '캘리브레이션이 저장되었습니다!',
+ calibrationFailed: '캘리브레이션 실패',
+ rfidRereadInitiated: 'RFID 재읽기가 시작되었습니다',
+ loadInitiated: '필라멘트 로딩 중…',
+ unloadInitiated: '필라멘트 언로딩 중…',
+ failedToLoad: '필라멘트 로드 실패',
+ failedToUnload: '필라멘트 언로드 실패',
+ connectionFailedNotAdded: '프린터에 연결할 수 없습니다. IP, 시리얼 번호, 액세스 코드를 확인하고 LAN 전용 모드가 켜져 있는지 확인하세요. 프린터가 추가되지 않았습니다.'
+ },
+ connection: {
+ connected: '연결됨',
+ offline: '오프라인'
+ },
+ plateStatus: {
+ markCleared: '플레이트 비움으로 표시',
+ cleared: '플레이트 비워짐',
+ notCleared: '플레이트 미비움',
+ inUse: '플레이트 사용 중'
+ },
+ queue: {
+ inQueue: '대기열에 {{count}}개',
+ inQueue_plural: '대기열에 {{count}}개'
+ },
+ controls: '제어',
+ rfid: {
+ reread: 'RFID 재읽기'
+ },
+ ams: {
+ load: '로드',
+ unload: '언로드'
+ },
+ bedJog: {
+ title: '빌드 플레이트 이동',
+ bed: '베드',
+ step: '이동 거리 (mm)',
+ up: '플레이트 위로',
+ down: '플레이트 아래로',
+ disabledWhilePrinting: '인쇄 중 비활성화됨',
+ notHomedTitle: '프린터 홈 설정 필요',
+ notHomedMessage: '마지막 인쇄 이후 홈 설정이 되지 않았습니다. 안전한 위치 지정을 위해 자동 홈 설정을 먼저 실행하거나, 그냥 이동하세요 — 소프트 엔드스톱이 무시됩니다.',
+ homeZ: '자동 홈 설정',
+ moveAnyway: '그냥 이동',
+ homingStarted: '프린터 자동 홈 설정 중…'
+ },
+ permission: {
+ noAdd: '프린터를 추가할 권한이 없습니다',
+ noEdit: '프린터를 편집할 권한이 없습니다',
+ noDelete: '프린터를 삭제할 권한이 없습니다',
+ noControl: '프린터를 제어할 권한이 없습니다',
+ noFiles: '프린터 파일에 접근할 권한이 없습니다',
+ noAmsRfid: 'AMS RFID를 재읽기할 권한이 없습니다',
+ noSmartPlugControl: '스마트 플러그를 제어할 권한이 없습니다',
+ noCamera: '카메라를 볼 권한이 없습니다'
+ },
+ modal: {
+ addTitle: '프린터 추가',
+ editTitle: '프린터 편집',
+ myPrinter: '내 프린터',
+ selectModel: '모델 선택...',
+ locationGroup: '위치 / 그룹 (선택사항)',
+ locationPlaceholder: '예: 작업실, 사무실, 지하실',
+ autoArchiveLabel: '완료된 인쇄 자동 아카이브',
+ fromPrinterSettings: '프린터 설정에서',
+ modelOptional: '모델 (선택사항)',
+ saveChanges: '변경사항 저장'
+ },
+ skipObjects: {
+ tooltip: '객체 건너뛰기',
+ onlyWhilePrinting: '객체 건너뛰기 (인쇄 중에만)',
+ requiresMultiple: '객체 건너뛰기 (2개 이상 필요)',
+ title: '객체 건너뛰기',
+ matchIdsInfo: '프린터 화면의 ID와 일치',
+ printerShowsIds: '프린터 화면에서 빌드 플레이트의 객체 ID를 표시합니다',
+ skipSelected: '선택 항목 건너뛰기',
+ skipping: '건너뛰는 중...',
+ noObjectsSelected: '선택된 객체 없음',
+ selectObjectsToSkip: '현재 인쇄에서 건너뛸 객체를 선택하세요',
+ skipped: '건너뜀',
+ objectsSkipped: '객체가 건너뛰어졌습니다',
+ activeCount: '{{count}}개 활성',
+ waitForLayer: '객체를 건너뛰려면 2층 이상을 기다리세요 (현재 {{layer}}층)',
+ skip: '건너뛰기',
+ confirmTitle: '객체를 건너뛰시겠습니까?',
+ confirmMessage: '\"{{name}}\"을(를) 건너뛰시겠습니까? 이 작업은 취소할 수 없습니다.'
+ },
+ confirm: {
+ deleteTitle: '프린터 삭제',
+ deleteMessage: '\"{{name}}\"을(를) 삭제하시겠습니까? 모든 연결 설정이 제거됩니다.',
+ deleteArchivesNote: '이 프린터의 모든 인쇄 기록이 영구적으로 삭제됩니다.',
+ keepArchivesNote: '인쇄 기록은 유지되지만 이 프린터와 연결이 해제됩니다.',
+ stopTitle: '인쇄 정지',
+ stopMessage: '\"{{name}}\"의 현재 인쇄를 정지하시겠습니까? 인쇄 작업이 취소됩니다.',
+ stopButton: '인쇄 정지',
+ pauseTitle: '인쇄 일시정지',
+ pauseMessage: '\"{{name}}\"의 현재 인쇄를 일시정지하시겠습니까?',
+ pauseButton: '인쇄 일시정지',
+ resumeTitle: '인쇄 재개',
+ resumeMessage: '\"{{name}}\"의 인쇄를 재개하시겠습니까?',
+ resumeButton: '인쇄 재개',
+ powerOnTitle: '프린터 전원 켜기',
+ powerOnMessage: '\"{{name}}\"의 전원을 켜시겠습니까?',
+ powerOnButton: '전원 켜기',
+ powerOffTitle: '프린터 전원 끄기',
+ powerOffMessage: '\"{{name}}\"의 전원을 끄시겠습니까?',
+ powerOffWarning: '경고: \"{{name}}\"이(가) 현재 인쇄 중입니다! 전원을 끄시겠습니까? 인쇄가 중단되고 프린터가 손상될 수 있습니다.',
+ powerOffButton: '전원 끄기',
+ haToggleTitle: '\"{{name}}\" 토글',
+ haToggleMessage: 'Home Assistant 엔티티 {{entity}}를 토글하시겠습니까? 현재 켜져 있으면 전원이 꺼질 수 있습니다.',
+ haToggleWarning: '경고: \"{{name}}\"이(가) 현재 인쇄 중입니다! {{entity}}를 토글하면 전원이 차단되어 인쇄가 중단될 수 있습니다. 계속하시겠습니까?',
+ haToggleButton: '토글'
+ },
+ bulk: {
+ select: '선택',
+ selectAll: '전체 선택',
+ selectByLocation: '위치별 선택',
+ selected: '{{count}}개 선택됨',
+ actions: {
+ stop: '정지',
+ pause: '일시정지',
+ resume: '재개',
+ clearPlate: '베드 비우기',
+ clearHMS: '알림 지우기'
+ },
+ confirm: {
+ stopTitle: '{{count}}개 인쇄 정지',
+ stopMessage: '{{count}}개 프린터의 활성 인쇄를 취소합니다. 이 작업은 취소할 수 없습니다.',
+ stopButton: '모두 정지',
+ pauseTitle: '{{count}}개 인쇄 일시정지',
+ pauseMessage: '{{count}}개 프린터의 활성 인쇄를 일시정지합니다.',
+ pauseButton: '모두 일시정지',
+ clearPlateTitle: '{{count}}개 인쇄 베드 비우기',
+ clearPlateMessage: '{{count}}개 프린터의 인쇄 베드를 비우고 대기열 작업을 시작할 수 있습니다.',
+ clearPlateButton: '모두 비우기'
+ },
+ success: '{{count}}개 프린터에서 {{action}} 완료',
+ partial: '{{succeeded}}개 성공, {{failed}}개 실패',
+ noneApplicable: '선택된 프린터 중 이 작업에 적합한 상태의 프린터가 없습니다',
+ selectByState: '상태별 선택'
+ },
+ discovery: {
+ title: '프린터 검색',
+ searching: '검색 중...',
+ scanning: '스캔 중...',
+ scanProgress: '스캔 중... {{scanned}}/{{total}}',
+ foundPrinters: '{{count}}개 프린터 발견',
+ noPrintersFound: '프린터를 찾을 수 없습니다',
+ noPrintersFoundSubnet: '지정된 서브넷에서 프린터를 찾을 수 없습니다.',
+ noPrintersFoundNetwork: '네트워크에서 프린터를 찾을 수 없습니다.',
+ allConfigured: '검색된 모든 프린터가 이미 설정되어 있습니다.',
+ alreadyAdded: '이미 추가됨',
+ select: '선택',
+ manualEntry: '수동 입력',
+ addFromCloud: '클라우드에서 추가',
+ subnetToScan: '스캔할 서브넷',
+ dockerNote: 'Docker가 감지되었습니다. CIDR 표기법으로 프린터의 서브넷을 입력하세요. docker-compose.yml에 network_mode: host가 필요합니다.',
+ scanSubnet: '서브넷에서 프린터 스캔',
+ discoverNetwork: '네트워크에서 프린터 검색',
+ scanningSubnet: 'Bambu 프린터를 위해 서브넷 스캔 중...',
+ scanningNetwork: '네트워크 스캔 중...',
+ serialRequired: '일련번호 필수',
+ unknown: '알 수 없음',
+ failedToStart: '검색 시작 실패'
+ },
+ drying: {
+ start: '건조 시작',
+ stop: '건조 정지',
+ temperature: '온도',
+ duration: '시간',
+ hours: '시간',
+ timeRemaining: '{{time}} 남음',
+ active: '건조 중',
+ notSupported: '건조 지원 안 됨',
+ powerRequired: '건조를 활성화하려면 AMS 전원 어댑터를 연결하세요',
+ startingDrying: '건조 시작 중...',
+ stoppingDrying: '건조 정지 중...',
+ rotateTray: '건조 중 스풀 회전'
+ },
+ filaments: '필라멘트',
+ openCameraOverlay: '카메라 오버레이 열기',
+ openCameraWindow: '새 창에서 카메라 열기',
+ firmwareUpdateAvailable: '펌웨어 업데이트 가능: {{current}} → {{latest}}',
+ firmwareUpToDate: '펌웨어 {{version}} — 최신 상태',
+ firmwareUpdateButton: '업데이트',
+ plateDetection: {
+ noPermission: '프린터를 업데이트할 권한이 없습니다',
+ enabledClick: '플레이트 확인 활성화됨 - 클릭하여 비활성화',
+ disabledClick: '플레이트 확인 비활성화됨 - 클릭하여 활성화',
+ manageCalibration: '플레이트 감지 캘리브레이션 관리',
+ calibrationRequired: '캘리브레이션 필요',
+ calibrationInstructions: '빌드 플레이트가 완전히 비어 있는지 확인한 후 캘리브레이션을 클릭하세요.',
+ calibrationDescription: '캘리브레이션은 빈 플레이트의 참조 이미지를 캡처합니다. 이후 확인 시 이 참조와 비교하여 객체를 감지합니다.',
+ calibrationTip: '팁: 다른 플레이트에 대해 최대 5개의 캘리브레이션을 저장할 수 있습니다. 확인 시 시스템이 자동으로 가장 잘 맞는 것을 사용합니다.',
+ plateEmpty: '플레이트가 비어 있는 것으로 보입니다',
+ objectsDetected: '플레이트에 객체가 감지되었습니다',
+ confidence: '신뢰도',
+ difference: '차이',
+ analysisPreview: '분석 미리보기:',
+ analysisLegend: '초록 박스 = 감지 영역, 빨간 오버레이 = 캘리브레이션과의 차이',
+ savedReferences: '저장된 참조 ({{count}}/{{max}})',
+ deleteReference: '참조 삭제',
+ labelPlaceholder: '라벨...',
+ clickToEdit: '{{label}} - 클릭하여 편집',
+ clickToAddLabel: '클릭하여 라벨 추가'
+ },
+ speed: {
+ title: '인쇄 속도',
+ silent: '조용함 (50%)',
+ standard: '표준 (100%)',
+ sport: '스포츠 (124%)',
+ ludicrous: '루디크러스 (166%)'
+ },
+ airduct: {
+ title: '에어덕트 모드',
+ cooling: '냉각',
+ heating: '가열'
+ },
+ noSdCard: 'SD 없음',
+ door: {
+ open: '열림',
+ closed: '닫힘'
+ },
+ fans: {
+ partCooling: '파트 냉각 팬',
+ auxiliary: '보조 팬',
+ chamber: '챔버 팬'
+ },
+ clickToViewHmsErrors: 'HMS 오류 보기 클릭',
+ estimatedCompletion: '예상 완료 시간',
+ plateNumber: '플레이트 {{number}}',
+ slotOptions: '슬롯 옵션',
+ amsPopup: {
+ friendlyName: 'AMS 이름',
+ friendlyNamePlaceholder: '예: AMS 친숙한 이름',
+ serialNumber: '일련번호',
+ firmwareVersion: '펌웨어',
+ save: '저장',
+ clear: '지우기',
+ noEditPermission: 'AMS 유닛 이름을 변경할 권한이 없습니다'
+ },
+ firmwareModal: {
+ title: '펌웨어 업데이트',
+ titleUpToDate: '펌웨어 정보',
+ currentVersion: '현재:',
+ latestVersion: '최신:',
+ releaseNotes: '릴리스 노트',
+ checkingPrereqs: '전제 조건 확인 중...',
+ sdCardReady: 'SD 카드 준비됨. 아래를 클릭하여 펌웨어를 업로드하세요.',
+ uploadedSuccess: 'SD 카드에 펌웨어가 업로드되었습니다!',
+ applyInstructions: '프린터에서 업데이트를 적용하려면:',
+ step1: '프린터 터치스크린에서 설정으로 이동하세요',
+ step2: '펌웨어로 이동하세요',
+ step3: 'SD 카드에서 업데이트를 선택하세요',
+ step4: '업데이트에 10-20분이 소요됩니다',
+ done: '완료',
+ starting: '시작 중...',
+ uploadFirmware: '펌웨어 업로드',
+ uploadFailed: '업로드 시작 실패: {{error}}',
+ uploadedToast: '펌웨어 업로드됨! 프린터 화면에서 업데이트를 시작하세요.',
+ availableVersions: '사용 가능한 버전',
+ usable: '사용 가능',
+ unavailable: '사용 불가',
+ installed: '설치됨',
+ newerBadge: '최신',
+ olderBadge: '이전',
+ currentBadge: '현재'
+ },
+ accessCodePlaceholder: '현재 값을 유지하려면 비워두세요',
+ roi: {
+ title: '감지 영역 (ROI)',
+ xStart: 'X 시작',
+ yStart: 'Y 시작',
+ width: '너비',
+ height: '높이',
+ instruction: '빌드 플레이트에 집중할 감지 영역을 조정하세요. 미리보기의 초록 박스가 현재 영역을 표시합니다.'
+ },
+ developerModeWarning: '개발자 LAN 모드가 활성화되지 않음: {{names}}. 일부 기능이 작동하지 않을 수 있습니다.',
+ howToEnable: '활성화 방법',
+ incompatibleFile: '이 파일은 {{slicedFor}}용으로 슬라이싱되었지만, 이 프린터는 {{printerModel}}입니다',
+ dropNotPrintable: '.gcode 및 .gcode.3mf 파일만 인쇄할 수 있습니다',
+ dropToPrint: '놓아서 인쇄',
+ cannotPrint: '프린터 사용 중',
+ addPreflight: {
+ checking: '연결 확인 중...',
+ warning: '일부 연결 확인이 실패했습니다. 이 프린터가 오프라인으로 표시될 수 있습니다. 아래 항목을 검토하고 수정하거나 그냥 저장하세요.',
+ back: '뒤로',
+ saveAnyway: '그냥 저장'
+ }
+ },
+ archives: {
+ title: '인쇄 아카이브',
+ searchPlaceholder: '아카이브 검색...',
+ filterByPrinter: '프린터별 필터',
+ filterByStatus: '상태별 필터',
+ sortBy: '정렬 기준',
+ sortNewest: '최신순',
+ sortOldest: '오래된순',
+ sortName: '이름',
+ sortDuration: '시간',
+ sortLargest: '큰 것 먼저',
+ sortSmallest: '작은 것 먼저',
+ sortSize: '크기',
+ noArchives: '아카이브를 찾을 수 없습니다',
+ noArchivesSearch: '검색 조건에 맞는 아카이브가 없습니다',
+ originalPrintNotVisible: '원본 인쇄가 보이지 않음 - 필터를 지워보세요',
+ noArchivesYet: '아직 아카이브가 없습니다',
+ prints: '인쇄',
+ pagination: {
+ showing: '표시 중',
+ to: '~',
+ of: '/',
+ show: '표시',
+ page: '페이지',
+ all: '전체'
+ },
+ loadingArchives: '아카이브 로딩 중...',
+ releaseToUpload: '놓아서 업로드',
+ showAll: '모두 보기',
+ showFavoritesOnly: '즐겨찾기만 보기',
+ gridView: '그리드 보기',
+ listView: '목록 보기',
+ calendarView: '달력 보기',
+ logView: '인쇄 로그',
+ manageTags: '태그 관리',
+ showFailedPrints: '실패한 인쇄 표시',
+ hideFailedPrints: '실패한 인쇄 숨기기',
+ hideDuplicates: '중복 숨기기',
+ viewOriginalPrint: '원본 인쇄 보기 클릭 (#{{id}})',
+ printTime: '인쇄 시간',
+ filamentUsed: '사용된 필라멘트',
+ cost: '비용',
+ reprint: '재인쇄',
+ preview: '미리보기',
+ deleteArchive: '아카이브 삭제',
+ deleteConfirm: '이 아카이브를 삭제하시겠습니까?',
+ favorite: '즐겨찾기',
+ unfavorite: '즐겨찾기에서 제거',
+ viewDetails: '상세 보기',
+ status: {
+ completed: '완료',
+ failed: '실패',
+ stopped: '정지됨'
+ },
+ toast: {
+ source3mfAttached: '소스 3MF 첨부됨: {{filename}}',
+ failedUploadSource3mf: '소스 3MF 업로드 실패',
+ source3mfRemoved: '소스 3MF 제거됨',
+ failedRemoveSource3mf: '소스 3MF 제거 실패',
+ f3dAttached: 'F3D 첨부됨: {{filename}}',
+ failedUploadF3d: 'F3D 업로드 실패',
+ f3dRemoved: 'F3D 제거됨',
+ failedRemoveF3d: 'F3D 제거 실패',
+ timelapseAttached: '타임랩스 첨부됨: {{filename}}',
+ timelapseAlreadyAttached: '타임랩스가 이미 첨부됨',
+ noMatchingTimelapse: '일치하는 타임랩스를 찾을 수 없습니다',
+ failedScanTimelapse: '타임랩스 스캔 실패',
+ failedAttachTimelapse: '타임랩스 첨부 실패',
+ timelapseRemoved: '타임랩스 제거됨',
+ failedRemoveTimelapse: '타임랩스 제거 실패',
+ timelapseUploaded: '타임랩스 업로드됨: {{filename}}',
+ failedUploadTimelapse: '타임랩스 업로드 실패',
+ archiveDeleted: '아카이브가 삭제되었습니다',
+ failedDeleteArchive: '아카이브 삭제 실패',
+ addedToFavorites: '즐겨찾기에 추가됨',
+ removedFromFavorites: '즐겨찾기에서 제거됨',
+ projectUpdated: '프로젝트가 업데이트되었습니다',
+ failedUpdateProject: '프로젝트 업데이트 실패',
+ linkCopied: '링크가 클립보드에 복사되었습니다',
+ failedCopyLink: '링크 복사 실패',
+ photoDeleted: '사진이 삭제되었습니다',
+ failedDeletePhoto: '사진 삭제 실패',
+ failedDeleteArchives: '아카이브 삭제 실패',
+ failedUpdateFavorites: '즐겨찾기 업데이트 실패',
+ exportDownloaded: '내보내기 다운로드됨',
+ exportFailed: '내보내기 실패'
+ },
+ menu: {
+ print: '인쇄',
+ schedule: '예약',
+ openInBambuStudio: '슬라이서에서 열기',
+ slice: '슬라이스',
+ externalLink: '외부 링크',
+ viewOnMakerWorld: 'MakerWorld에서 보기',
+ preview3d: '3D 미리보기',
+ viewTimelapse: '타임랩스 보기',
+ scanForTimelapse: '타임랩스 검색',
+ uploadTimelapse: '타임랩스 업로드',
+ removeTimelapse: '타임랩스 제거',
+ downloadSource3mf: '소스 3MF 다운로드',
+ uploadSource3mf: '소스 3MF 업로드',
+ replaceSource3mf: '소스 3MF 교체',
+ removeSource3mf: '소스 3MF 제거',
+ uploadF3d: 'F3D 업로드',
+ replaceF3d: 'F3D 교체',
+ downloadF3d: 'F3D 다운로드',
+ removeF3d: 'F3D 제거',
+ download: '다운로드',
+ copyDownloadLink: '다운로드 링크 복사',
+ qrCode: 'QR 코드',
+ viewPhotos: '사진 보기',
+ viewPhotosCount: '사진 보기 ({{count}})',
+ projectPage: '프로젝트 페이지',
+ addToFavorites: '즐겨찾기에 추가',
+ removeFromFavorites: '즐겨찾기에서 제거',
+ edit: '편집',
+ goToProject: '프로젝트로 이동: {{name}}',
+ addToProject: '프로젝트에 추가',
+ removeFromProject: '프로젝트에서 제거',
+ loading: '로딩 중...',
+ noProjectsAvailable: '사용 가능한 프로젝트 없음',
+ searchProjects: '프로젝트 검색…',
+ select: '선택',
+ deselect: '선택 해제',
+ delete: '삭제',
+ printLog: '인쇄 기록'
+ },
+ permission: {
+ noReprint: '이 아카이브를 재인쇄할 권한이 없습니다',
+ noAddToQueue: '대기열에 추가할 권한이 없습니다',
+ noUpdateArchives: '아카이브를 업데이트할 권한이 없습니다',
+ noUploadFiles: '파일을 업로드할 권한이 없습니다',
+ noDownload: '아카이브를 다운로드할 권한이 없습니다',
+ noCopyLink: '다운로드 링크를 복사할 권한이 없습니다',
+ noDelete: '이 아카이브를 삭제할 권한이 없습니다',
+ noCreate: '아카이브를 만들 권한이 없습니다'
+ },
+ platePicker: {
+ title: '미리 볼 플레이트 선택',
+ hint: '이 아카이브에는 여러 플레이트가 있습니다. G코드 뷰어에서 열 플레이트를 선택하세요.',
+ plateLabel: '플레이트 {{index}}',
+ objectCount: '{{count}}개 객체',
+ objectCount_plural: '{{count}}개 객체',
+ noGcode: '이 아카이브에는 미리 볼 슬라이싱된 G코드가 없습니다. Bambu Studio에서 먼저 슬라이싱하세요.'
+ },
+ card: {
+ previousPlate: '이전 플레이트',
+ nextPlate: '다음 플레이트',
+ plateNumber: '플레이트 {{index}}',
+ moreOptions: '더 많은 옵션은 우클릭',
+ addToFavorites: '즐겨찾기에 추가',
+ removeFromFavorites: '즐겨찾기에서 제거',
+ cancelled: '취소됨',
+ failed: '실패',
+ duplicate: '중복',
+ duplicateTitle: '이 모델은 이전에 인쇄된 적이 있습니다',
+ openSource3mf: 'Bambu Studio에서 소스 3MF 열기 (더 많은 옵션은 우클릭)',
+ downloadF3d: 'Fusion 360 디자인 파일 다운로드',
+ viewTimelapse: '타임랩스 보기',
+ viewPhoto: '사진 1장 보기',
+ viewPhotos: '사진 {{count}}장 보기',
+ openFolder: '폴더 열기: {{name}}',
+ slicedFile: '슬라이싱된 파일 - 인쇄 준비 완료',
+ sourceFile: '소스 파일만 - AMS 매핑 없음',
+ gcode: 'GCODE',
+ source: '소스',
+ project: '프로젝트: {{name}}',
+ estimated: '예상: {{time}}',
+ actual: '실제: {{time}}',
+ accuracy: '정확도: {{percent}}%',
+ filament: '{{weight}}g',
+ layer: '{{count}}층',
+ layers: '{{count}}층',
+ object: '{{count}}개 객체',
+ objects: '{{count}}개 객체',
+ slicedFor: '{{model}}용으로 슬라이싱됨',
+ uploadedBy: '업로드한 사용자',
+ noPermissionReprint: '재인쇄 권한이 없습니다',
+ noFileForReprint: '3MF 파일 없음 — 인쇄 기록 시 프린터에서 파일을 다운로드할 수 없었습니다',
+ noPermissionEdit: '아카이브를 편집할 권한이 없습니다',
+ noPermissionDelete: '아카이브를 삭제할 권한이 없습니다',
+ reprint: '재인쇄',
+ schedulePrint: '인쇄 예약',
+ schedule: '예약',
+ openInBambuStudio: '슬라이서에서 열기',
+ openInBambuStudioToSlice: '슬라이스하려면 슬라이서에서 열기',
+ slice: '슬라이스',
+ externalLink: '외부 링크',
+ makerWorld: 'MakerWorld: {{designer}}',
+ viewProject: '프로젝트 보기',
+ noExternalLink: '외부 링크 없음',
+ preview3d: '3D 미리보기',
+ download: '다운로드',
+ edit: '편집',
+ delete: '삭제',
+ runsBadge: '{{count}}회 인쇄',
+ runsBadgeTitle: '총 {{count}}회 인쇄 — {{successful}}회 성공, {{failed}}회 실패. 전체 인쇄 기록을 보려면 클릭하세요.'
+ },
+ modal: {
+ deleteArchive: '아카이브 삭제',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ deleteButton: '삭제',
+ removeSource3mf: '소스 3MF 제거',
+ removeSource3mfConfirm: '\"{{name}}\"에서 소스 3MF 파일을 제거하시겠습니까? 원본 슬라이서 프로젝트 파일이 삭제됩니다.',
+ removeButton: '제거',
+ removeF3d: 'F3D 제거',
+ removeF3dConfirm: '\"{{name}}\"에서 Fusion 360 디자인 파일을 제거하시겠습니까?',
+ removeTimelapse: '타임랩스 제거',
+ removeTimelapseConfirm: '\"{{name}}\"에서 타임랩스 영상을 제거하시겠습니까?',
+ timelapse: '{{name}} - 타임랩스',
+ selectTimelapse: '타임랩스 선택',
+ selectTimelapseDesc: '자동 일치 항목 없음. 이 인쇄의 타임랩스를 선택하세요:',
+ deleteArchives: '아카이브 삭제',
+ deleteArchivesConfirm: '{{count}}개 아카이브를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ deleteCount: '{{count}}개 삭제',
+ deletePurgeStats: '빠른 통계에서도 이 인쇄 항목 제거 (필라멘트, 시간, 비용, 에너지)'
+ },
+ page: {
+ title: '아카이브',
+ printsCount: '{{total}}개 중 {{filtered}}개 인쇄',
+ dropFilesHere: '.3mf 파일을 여기에 놓으세요',
+ releaseToUpload: '놓아서 업로드',
+ only3mfSupported: '.3mf 파일만 지원됩니다',
+ close: '닫기',
+ selected: '{{count}}개 선택됨',
+ selectAll: '전체 선택',
+ tags: '태그',
+ project: '프로젝트',
+ favorite: '즐겨찾기',
+ delete: '삭제',
+ toggledFavorites: '{{count}}개 아카이브의 즐겨찾기가 변경됨',
+ failedUpdateFavorites: '즐겨찾기 업데이트 실패',
+ archivesDeleted: '{{count}}개 아카이브가 삭제됨',
+ failedDeleteArchives: '아카이브 삭제 실패',
+ photoDeleted: '사진이 삭제됨',
+ failedDeletePhoto: '사진 삭제 실패'
+ },
+ list: {
+ name: '이름',
+ printer: '프린터',
+ date: '날짜',
+ size: '크기',
+ actions: '작업',
+ hasTimelapse: '타임랩스 있음'
+ },
+ log: {
+ date: '날짜',
+ printName: '인쇄 이름',
+ printer: '프린터',
+ user: '사용자',
+ status: '상태',
+ duration: '소요 시간',
+ filament: '필라멘트',
+ allPrinters: '모든 프린터',
+ allUsers: '모든 사용자',
+ allStatuses: '모든 상태',
+ cancelled: '취소됨',
+ skipped: '건너뜀',
+ dateFrom: '시작',
+ dateTo: '종료',
+ noEntries: '인쇄 로그 항목이 없습니다',
+ showing: '{{total}}개 중 {{count}}개 표시',
+ rowsPerPage: '행',
+ page: '페이지',
+ prev: '이전',
+ next: '다음',
+ clearLog: '로그 지우기',
+ clearLogTitle: '인쇄 로그 지우기',
+ clearLogConfirm: '모든 인쇄 로그 항목이 영구적으로 삭제됩니다. 아카이브와 대기열 항목은 영향받지 않습니다. 이 작업은 취소할 수 없습니다. 계속하시겠습니까?',
+ clearLogButton: '모두 지우기',
+ cleared: '{{count}}개 로그 항목이 지워졌습니다',
+ clearFailed: '인쇄 로그 지우기 실패'
+ },
+ runLog: {
+ title: '인쇄 기록',
+ modalTitle: '인쇄 기록 — {{name}}',
+ modalTitleFallback: '이 아카이브',
+ empty: '이 아카이브에 대해 기록된 인쇄 이벤트가 없습니다.',
+ col: {
+ date: '날짜',
+ status: '상태',
+ duration: '소요 시간',
+ filament: '필라멘트',
+ cost: '비용'
+ },
+ status: {
+ completed: '완료',
+ failed: '실패',
+ cancelled: '취소됨',
+ stopped: '중지됨',
+ skipped: '건너뜀',
+ printing: '인쇄 중'
+ }
+ }
+ },
+ queue: {
+ title: '인쇄 대기열',
+ subtitle: '인쇄 작업을 예약하고 관리하세요',
+ addToQueue: '대기열에 추가',
+ print: '인쇄',
+ reprint: '재인쇄',
+ schedulePrint: '인쇄 예약',
+ editQueueItem: '대기열 항목 편집',
+ printToPrinters: '{{count}}개 프린터에 인쇄',
+ queueToPrinters: '{{count}}개 프린터에 대기',
+ queueSelectedPlates: '{{count}}개 플레이트 대기',
+ selectAllPlates: '{{count}}개 플레이트 전체 선택',
+ deselectAll: '전체 해제',
+ printQueued: '인쇄가 대기열에 추가됨',
+ itemsQueued: '{{count}}개 항목이 대기열에 추가됨',
+ sending: '전송 중...',
+ sendingProgress: '{{current}}/{{total}} 전송 중...',
+ adding: '추가 중...',
+ addingProgress: '{{current}}/{{total}} 추가 중...',
+ savingProgress: '{{current}}/{{total}} 저장 중...',
+ clearQueue: '대기열 지우기',
+ clearHistory: '기록 지우기',
+ emptyQueue: '대기열이 비어 있습니다',
+ position: '위치',
+ scheduledTime: '예약 시간',
+ moveUp: '위로 이동',
+ moveDown: '아래로 이동',
+ startNow: '지금 시작',
+ printingInProgress: '인쇄 중...',
+ viewArchive: '아카이브 보기',
+ viewInFileManager: '파일 관리자에서 보기',
+ itemCount: '{{count}}개 항목',
+ itemCount_plural: '{{count}}개 항목',
+ dragToReorder: '드래그하여 순서 변경 (즉시만)',
+ reorderHint: '위치는 즉시 항목에만 영향을 줍니다. 예약된 항목은 설정된 시간에 실행됩니다.',
+ sjf: {
+ label: 'SJF',
+ tooltip: '최단 작업 우선 — 스케줄러가 짧은 인쇄를 우선합니다'
+ },
+ addedBy: '{{name}}님이 추가함',
+ nextInQueue: '다음 대기',
+ clearPlateSuccess: '플레이트 비워짐 — 다음 인쇄 준비 완료',
+ plateNumber: '플레이트 {{index}}',
+ quantity: '수량',
+ quantityHint: '{{count}}개 대기열 항목 생성',
+ activeBatches: '활성 배치',
+ batchProgress: '{{total}}개 중 {{completed}}개 완료',
+ cancelBatch: '나머지 취소',
+ batchCancelled: '남은 배치 항목이 취소되었습니다',
+ cancelBatchConfirmTitle: '배치 취소',
+ cancelBatchConfirmMessage: '이 배치의 남은 대기 항목을 모두 취소하시겠습니까?',
+ batch: '배치',
+ sections: {
+ currentlyPrinting: '현재 인쇄 중',
+ queued: '대기 중',
+ history: '기록'
+ },
+ status: {
+ pending: '대기 중',
+ waiting: '기다리는 중',
+ printing: '인쇄 중',
+ paused: '일시정지',
+ completed: '완료',
+ failed: '실패',
+ skipped: '건너뜀',
+ cancelled: '취소됨'
+ },
+ summary: {
+ printing: '인쇄 중',
+ queued: '대기 중',
+ totalTime: '총 대기열 시간',
+ totalWeight: '총 대기열 무게',
+ history: '기록'
+ },
+ filter: {
+ allPrinters: '모든 프린터',
+ unassigned: '미할당',
+ allStatus: '모든 상태',
+ allLocations: '모든 위치',
+ any: '전체'
+ },
+ sort: {
+ byPosition: '위치별 정렬',
+ byName: '이름별 정렬',
+ byPrinter: '프린터별 정렬',
+ bySchedule: '예약별 정렬',
+ byDate: '날짜별 정렬',
+ ascendingOldest: '오름차순 (오래된 것 먼저)',
+ descendingNewest: '내림차순 (최신 것 먼저)'
+ },
+ badges: {
+ staged: '준비됨',
+ requiresPrevious: '이전 성공 필요',
+ autoPowerOff: '자동 전원 끄기',
+ gcodeInjection: 'G코드'
+ },
+ empty: {
+ title: '예약된 인쇄 없음',
+ description: '아카이브 페이지의 컨텍스트 메뉴에서 \"예약\" 옵션을 사용하거나 파일을 드래그 앤 드롭하여 시작하세요.'
+ },
+ time: {
+ asap: '즉시',
+ overdue: '기한 초과',
+ now: '지금',
+ lessThanMinute: '1분 이내',
+ inMinutes: '{{count}}분 후',
+ inHours: '{{count}}시간 후'
+ },
+ actions: {
+ stopPrint: '인쇄 정지',
+ startPrint: '인쇄 시작',
+ requeue: '재대기'
+ },
+ bulkEdit: {
+ title: '{{count}}개 항목 편집',
+ title_plural: '{{count}}개 항목 편집',
+ description: '변경된 설정만 선택된 항목에 적용됩니다.',
+ printer: '프린터',
+ noChange: '— 변경 없음 —',
+ queueOptions: '대기열 옵션',
+ staged: '준비됨 (수동 시작)',
+ autoPowerOff: '인쇄 후 자동 전원 끄기',
+ requirePrevious: '이전 성공 필요',
+ printOptions: '인쇄 옵션',
+ bedLevelling: '베드 레벨링',
+ flowCalibration: '유량 캘리브레이션',
+ vibrationCalibration: '진동 캘리브레이션',
+ layerInspection: '첫 번째 층 검사',
+ timelapse: '타임랩스',
+ useAms: 'AMS 사용',
+ applyChanges: '변경사항 적용',
+ selectAll: '전체 선택',
+ deselectAll: '전체 해제',
+ selected: '{{count}}개 선택됨',
+ editSelected: '선택 항목 편집',
+ cancelSelected: '선택 항목 취소'
+ },
+ confirm: {
+ cancelTitle: '예약된 인쇄 취소',
+ cancelMessage: '\"{{name}}\"을(를) 취소하시겠습니까?',
+ stopTitle: '인쇄 정지',
+ stopMessage: '\"{{name}}\"의 현재 인쇄를 정지하시겠습니까? 프린터의 인쇄 작업이 취소됩니다.',
+ removeTitle: '기록에서 제거',
+ removeMessage: '대기열 기록에서 \"{{name}}\"을(를) 제거하시겠습니까?',
+ clearHistoryTitle: '기록 지우기',
+ clearHistoryMessage: '기록에서 {{count}}개 항목을 모두 제거하시겠습니까?',
+ cancelButton: '인쇄 취소',
+ stopButton: '인쇄 정지',
+ thisPrint: '이 인쇄',
+ thisItem: '이 항목'
+ },
+ toast: {
+ cancelled: '대기열 항목이 취소되었습니다',
+ cancelFailed: '항목 취소 실패',
+ removed: '대기열 항목이 제거되었습니다',
+ removeFailed: '항목 제거 실패',
+ stopped: '인쇄가 정지되었습니다',
+ stopFailed: '인쇄 정지 실패',
+ released: '인쇄가 대기열에 릴리스되었습니다',
+ startFailed: '인쇄 시작 실패',
+ reorderFailed: '대기열 순서 변경 실패',
+ historyCleared: '{{count}}개 기록 항목이 지워졌습니다',
+ clearHistoryFailed: '기록 지우기 실패',
+ updateFailed: '항목 업데이트 실패',
+ bulkCancelled: '{{count}}개 항목이 취소되었습니다',
+ bulkCancelFailed: '항목 취소 실패'
+ },
+ timeline: {
+ listView: '목록',
+ timelineView: '타임라인',
+ unassigned: '미할당',
+ noData: '이 날에 예약된 인쇄 없음',
+ allDoneBy: '모든 인쇄 예상 완료 시간: {{time}}',
+ staged: '준비됨',
+ filterAll: '모두 표시',
+ filterPrinting: '인쇄 중',
+ filterQueued: '대기 중',
+ time: {
+ anyMoment: '잠시 후',
+ minutesLeft: '{{minutes}}분 남음',
+ hoursLeft: '{{hours}}시간 남음',
+ hoursMinutesLeft: '{{hours}}시간 {{minutes}}분 남음'
+ },
+ day: {
+ previous: '이전 날',
+ next: '다음 날',
+ today: '오늘'
+ }
+ },
+ permissions: {
+ noStopPrint: '인쇄를 정지할 권한이 없습니다',
+ noStartPrint: '인쇄를 시작할 권한이 없습니다',
+ noEdit: '이 대기열 항목을 편집할 권한이 없습니다',
+ noCancel: '이 대기열 항목을 취소할 권한이 없습니다',
+ noRequeue: '항목을 재대기할 권한이 없습니다',
+ noRemove: '이 대기열 항목을 제거할 권한이 없습니다',
+ noClearHistory: '모든 기록을 지울 권한이 없습니다',
+ noEditItems: '대기열 항목을 편집할 권한이 없습니다',
+ noCancelItems: '대기열 항목을 취소할 권한이 없습니다'
+ },
+ filamentShort: {
+ rowBadge: '할당된 스풀의 필라멘트가 부족합니다',
+ rowTooltip: '디스패치 스케줄러가 이 항목을 표시했습니다. 재생 버튼을 클릭하여 슬롯별 부족량을 확인하고 인쇄 여부를 결정하세요.',
+ confirmTitle: '필라멘트 부족',
+ confirmIntro: '할당된 스풀이 하나 이상의 슬롯을 채울 수 없습니다. 그래도 인쇄하시겠습니까?',
+ lineItem: '슬롯 {{slot}}: {{required}}g 필요, {{remaining}}g 남음',
+ unknown: '알 수 없음',
+ printAnyway: '그냥 인쇄'
+ }
+ },
+ backgroundDispatch: {
+ unknownFile: '알 수 없는 파일',
+ unknownPrinter: '알 수 없는 프린터',
+ startingPrints: '인쇄 시작 중',
+ progressSummary: '{{complete}}/{{total}} 완료 • 전송됨: {{dispatched}} • 처리 중: {{processing}}',
+ expandDetails: '전송 상세 펼치기',
+ collapseDetails: '전송 상세 접기',
+ dismissToast: '전송 알림 닫기',
+ cancelDispatchJob: '전송 작업 취소',
+ cancel: '취소',
+ cancelling: '취소 중…',
+ awaitingPrinter: '프린터 대기 중…',
+ status: {
+ dispatched: '전송됨',
+ processing: '처리 중',
+ completed: '완료',
+ failed: '실패',
+ cancelled: '취소됨'
+ },
+ toast: {
+ cancellingUpload: '업로드 취소 중...',
+ cancelled: '전송이 취소되었습니다',
+ cancelFailed: '전송 취소 실패',
+ completeWithFailures: '백그라운드 전송 완료: {{completed}}개 성공, {{failed}}개 실패',
+ completeSuccess: '백그라운드 전송 완료: {{completed}}개 성공',
+ printStartedRemaining: '{{completed}}개 인쇄 시작, {{remaining}}개 더 전송 중...'
+ }
+ },
+ stats: {
+ title: '대시보드',
+ subtitle: '위젯을 드래그하여 정렬하세요. 눈 아이콘을 클릭하여 숨기세요.',
+ overview: '개요',
+ totalPrints: '총 인쇄 수',
+ successRate: '성공률',
+ totalPrintTime: '총 인쇄 시간',
+ printTime: '인쇄 시간',
+ totalFilament: '총 사용 필라멘트',
+ filamentUsed: '사용된 필라멘트',
+ filamentCost: '필라멘트 비용',
+ totalCost: '총 비용',
+ energyUsed: '사용된 에너지',
+ energyCost: '에너지 비용',
+ energyWarmingUpTooltip: '에너지 추적이 시간별 스냅샷을 수집 중입니다. 날짜 범위 합계는 선택한 범위 이전에 하나 이상의 스냅샷이 존재하면 정확해집니다. 초기 값이 적게 집계될 수 있습니다.',
+ averagePrintTime: '평균 인쇄 시간',
+ printsPerDay: '일일 인쇄 수',
+ byPrinter: '프린터별',
+ printsByPrinter: '프린터별 인쇄',
+ byMaterial: '재료별',
+ byMonth: '월별',
+ last7Days: '최근 7일',
+ last30Days: '최근 30일',
+ last90Days: '최근 90일',
+ allTime: '전체 기간',
+ quickStats: '빠른 통계',
+ printActivity: '인쇄 활동',
+ filamentTypes: '필라멘트 종류',
+ filamentTrends: '필라멘트 추세',
+ failureAnalysis: '실패 분석',
+ timeAccuracy: '시간 정확도',
+ successful: '성공:',
+ failed: '실패:',
+ cancelled: '취소됨:',
+ perfectEstimate: '100% = 완벽한 예상',
+ noTimeAccuracyData: '아직 시간 정확도 데이터 없음',
+ noFilamentData: '필라멘트 데이터 없음',
+ noPrinterData: '프린터 데이터 없음',
+ noPrintData: '인쇄 데이터 없음',
+ noPrintDataLast30Days: '최근 30일 인쇄 데이터 없음',
+ failureReasons: '실패 원인',
+ topFailureReasons: '주요 실패 원인',
+ failedPrintsCount: '{{total}}개 인쇄 중 {{failed}}개 실패',
+ lastWeekRate: '지난 주: {{rate}}%',
+ resetLayout: '레이아웃 초기화',
+ recalculateCosts: '비용 재계산',
+ recalculateCostsHint: '현재 필라멘트 가격으로 모든 아카이브 비용 재계산',
+ exportStats: '통계 내보내기',
+ exportAsCsv: 'CSV로 내보내기',
+ exportAsExcel: 'Excel로 내보내기',
+ hiddenCount: '{{count}}개 숨겨짐',
+ exportDownloaded: '내보내기 다운로드됨',
+ exportFailed: '내보내기 실패',
+ layoutReset: '레이아웃이 초기화되었습니다',
+ recalculatedCosts: '{{count}}개 아카이브의 비용이 재계산되었습니다',
+ recalculateFailed: '비용 재계산 실패',
+ loadingStats: '통계 로딩 중...',
+ noPermissionResetLayout: '레이아웃을 초기화할 권한이 없습니다',
+ noPermissionRecalculate: '비용을 재계산할 권한이 없습니다',
+ noPrintDataInRange: '선택한 범위에 인쇄 데이터 없음',
+ periodFilament: '기간 필라멘트',
+ periodCost: '기간 비용',
+ avgPerPrint: '인쇄당 평균',
+ usageOverTime: '시간별 사용량',
+ filamentByWeight: '무게',
+ printDuration: '인쇄 시간',
+ printerUtilization: '프린터 사용률',
+ filamentSuccess: '재료별 성공률',
+ printHabits: '인쇄 습관',
+ printTimeOfDay: '시간대별 인쇄',
+ colorDistribution: '색상 분포',
+ noColorData: '색상 데이터 없음',
+ records: '기록',
+ longestPrint: '최장 인쇄',
+ heaviestPrint: '가장 무거운 인쇄',
+ mostExpensivePrint: '가장 비싼 인쇄',
+ busiestDay: '가장 바쁜 날',
+ successStreak: '연속 성공',
+ streakPrint: '연속 인쇄',
+ streakPrints: '{{count}}번 연속 인쇄',
+ printerStats: '프린터 통계',
+ hours: '시간',
+ avgPrints: '평균 인쇄',
+ noArchiveData: '인쇄 데이터 없음',
+ filamentByTime: '시간',
+ avgWeight: '평균 무게',
+ avgTime: '평균 시간',
+ filamentByPrints: '인쇄',
+ timeframe: {
+ today: '오늘',
+ "this-week": '이번 주',
+ "this-month": '이번 달',
+ "last-7": '최근 7일',
+ "last-30": '최근 30일',
+ "last-90": '최근 90일',
+ "this-year": '올해',
+ "all-time": '전체 기간',
+ custom: '사용자 지정 범위',
+ from: '시작',
+ to: '종료'
+ },
+ allUsers: '모든 사용자',
+ noUser: '사용자 없음 (시스템)',
+ filterByUser: '사용자별 필터'
+ },
+ maintenance: {
+ title: '유지보수',
+ overview: '개요',
+ allOk: '모든 유지보수 최신 상태',
+ dueCount: '{{count}}개 항목 예정',
+ dueCount_plural: '{{count}}개 항목 예정',
+ warningCount: '{{count}}개 경고',
+ warningCount_plural: '{{count}}개 경고',
+ totalPrintTime: '총 인쇄 시간',
+ nextMaintenance: '다음 유지보수',
+ nothingDue: '예정 없음',
+ tasks: '작업',
+ lastPerformed: '마지막 수행',
+ interval: '간격',
+ hoursRemaining: '{{hours}}시간 남음',
+ hoursOverdue: '{{hours}}시간 초과',
+ markDone: '완료로 표시',
+ performMaintenance: '유지보수 수행',
+ history: '기록',
+ noHistory: '유지보수 기록 없음',
+ editPrintHours: '인쇄 시간 편집',
+ currentHours: '현재 시간',
+ statusTab: '상태',
+ settingsTab: '설정',
+ overdueCount: '{{count}}개 초과',
+ dueSoonCount: '{{count}}개 곧 예정',
+ dueSoon: '곧 예정',
+ allGood: '모두 정상',
+ overdueBy: '{{duration}} 초과',
+ dueIn: '{{duration}} 후 예정',
+ timeLeft: '{{duration}} 남음',
+ day: '1일',
+ days: '{{count}}일',
+ week: '1주',
+ weeks: '{{count}}주',
+ month: '1개월',
+ months: '{{count}}개월',
+ year: '1년',
+ maintenanceTypes: '유지보수 유형',
+ maintenanceTypesDescription: '시스템 유형 및 사용자 지정 유지보수 작업',
+ addCustomType: '사용자 지정 유형 추가',
+ restoreDefaults: '기본 작업 복원',
+ intervalType: '간격 유형',
+ intervalValue: '간격 ({{type}})',
+ icon: '아이콘',
+ documentationLink: '문서 링크 (선택사항)',
+ assignToPrinters: '프린터에 할당',
+ selectAtLeastOnePrinter: '최소 한 개의 프린터를 선택하세요',
+ addType: '유형 추가',
+ custom: '사용자 지정',
+ printHours: '인쇄 시간',
+ calendarDays: '달력 일수',
+ exampleName: '예: HEPA 필터 교체',
+ viewDocumentation: '문서 보기',
+ timeBasedInterval: '시간 기반 간격',
+ intervalOverrides: '간격 재정의',
+ intervalOverridesDescription: '특정 프린터의 간격 사용자 지정',
+ assignedToPrinters: '할당된 프린터:',
+ noPrintersAssigned: '할당된 프린터 없음',
+ addPrinterShort: '추가:',
+ printersAssignedClick: '{{count}}개 프린터 할당됨 - 클릭하여 관리',
+ removeFromPrinter: '이 프린터에서 제거',
+ types: {
+ lubricateCarbonRods: '카본 로드 윤활',
+ lubricateRails: '리니어 레일 윤활',
+ cleanNozzle: '노즐/핫엔드 청소',
+ checkBelts: '벨트 장력 확인',
+ cleanBuildPlate: '빌드 플레이트 청소',
+ checkExtruder: '압출기 기어 확인',
+ checkCooling: '냉각 팬 확인',
+ generalInspection: '일반 점검',
+ cleanCarbonRods: '카본 로드 청소',
+ lubricateSteelRods: '스틸 로드 윤활',
+ cleanSteelRods: '스틸 로드 청소',
+ cleanLinearRails: '리니어 레일 청소',
+ checkPtfeTube: 'PTFE 튜브 확인',
+ replaceHepaFilter: 'HEPA 필터 교체',
+ replaceCarbonFilter: '활성탄 필터 교체',
+ lubricateLeftNozzleRail: '좌측 노즐 레일 윤활'
+ },
+ maintenanceComplete: '유지보수가 완료로 표시되었습니다',
+ typeUpdated: '유지보수 유형이 업데이트되었습니다',
+ typeDeleted: '유지보수 유형이 삭제되었습니다',
+ defaultsRestored: '{{count}}개 기본 작업이 복원되었습니다',
+ printHoursUpdated: '인쇄 시간이 업데이트되었습니다',
+ printerAssigned: '프린터가 할당되었습니다',
+ printerRemoved: '프린터가 제거되었습니다',
+ deleteTypeConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까?',
+ deleteSystemTypeTitle: '기본 유지보수 작업을 삭제하시겠습니까?',
+ deleteSystemTypeMessage: '기본 유지보수 작업 \"{{name}}\"을(를) 삭제하시겠습니까?',
+ noPermissionUpdate: '유지보수 항목을 업데이트할 권한이 없습니다',
+ noPermissionPerform: '유지보수를 수행할 권한이 없습니다',
+ noPermissionEditTypes: '유지보수 유형을 편집할 권한이 없습니다',
+ noPermissionDeleteTypes: '유지보수 유형을 삭제할 권한이 없습니다',
+ noPermissionEditHours: '인쇄 시간을 편집할 권한이 없습니다',
+ noPermissionRemovePrinter: '프린터 할당을 제거할 권한이 없습니다',
+ noPermissionAssignPrinter: '프린터를 할당할 권한이 없습니다',
+ noPermissionEditIntervals: '간격을 편집할 권한이 없습니다',
+ configureSettings: '유지보수 유형 및 간격 설정'
+ },
+ settings: {
+ title: '설정',
+ general: '일반',
+ tabs: {
+ general: '일반',
+ smartPlugs: '스마트 플러그',
+ notifications: '알림',
+ queue: '워크플로우',
+ filament: '필라멘트',
+ network: '네트워크',
+ apiKeys: 'API 키',
+ virtualPrinter: '가상 프린터',
+ spoolbuddy: 'SpoolBuddy',
+ failureDetection: '실패 감지',
+ users: '인증',
+ backup: '백업',
+ emailAuth: '이메일 인증',
+ ldap: 'LDAP',
+ twoFa: '이중 인증',
+ oidc: 'SSO / OIDC',
+ security: '보안'
+ },
+ spoolbuddy: {
+ infoTitle: 'SpoolBuddy 기기',
+ infoBody: 'SpoolBuddy 키오스크는 하트비트를 통해 자동으로 등록됩니다. 더 이상 사용하지 않거나 데몬 충돌로 인한 중복이 있는 경우 여기서 기기를 등록 해제하세요.',
+ duplicatesTitle: '{{count}}개 기기 등록됨',
+ duplicatesBody: '첫 번째로 등록된 기기만 키오스크 UI에서 사용됩니다. 충돌로 인한 오래된 중복이 있으면 등록 해제하세요 — 온라인 기기는 다음 하트비트에서 자동으로 재등록됩니다.',
+ empty: '아직 등록된 SpoolBuddy 기기가 없습니다.',
+ online: '온라인',
+ offline: '오프라인',
+ unregister: '등록 해제',
+ unregisterSuccess: '기기 등록 해제됨',
+ unregisterError: '기기 등록 해제 실패',
+ confirmTitle: 'SpoolBuddy 기기를 등록 해제하시겠습니까?',
+ confirmBody: '데이터베이스에서 \"{{hostname}}\" ({{deviceId}})를 제거합니다. 기기가 온라인이면 다음 하트비트에서 자동으로 재등록됩니다.',
+ ipAddress: 'IP 주소',
+ firmware: '펌웨어',
+ lastSeen: '마지막 확인',
+ daemonUptime: '데몬 가동 시간',
+ systemUptime: '시스템 가동 시간',
+ never: '없음',
+ nfc: 'NFC',
+ scale: '저울',
+ cpuTemp: 'CPU 온도',
+ memory: '메모리',
+ disk: '디스크',
+ update: '업데이트',
+ updateConfirmTitle: 'Spoolbuddy 데몬을 업데이트하시겠습니까?',
+ updateConfirmBody: '\"{{hostname}}\"에서 소프트웨어 업데이트를 실행하시겠습니까? 업데이트가 적용되면 데몬이 재시작됩니다.',
+ restartBrowser: '브라우저 재시작',
+ restartBrowserConfirmTitle: '키오스크 브라우저를 재시작하시겠습니까?',
+ restartBrowserConfirmBody: '\"{{hostname}}\"의 키오스크 브라우저를 재시작하시겠습니까? 화면이 잠시 꺼집니다.',
+ restartDaemon: '데몬 재시작',
+ restartDaemonConfirmTitle: 'Spoolbuddy 데몬을 재시작하시겠습니까?',
+ restartDaemonConfirmBody: '\"{{hostname}}\"의 Spoolbuddy 데몬을 재시작하시겠습니까? 기기가 몇 초 동안 오프라인 상태가 됩니다.',
+ reboot: '재부팅',
+ rebootConfirmTitle: '기기를 재부팅하시겠습니까?',
+ rebootConfirmBody: '\"{{hostname}}\"을(를) 재부팅하시겠습니까? 기기가 약 1분 동안 오프라인 상태가 됩니다.',
+ shutdown: '종료',
+ shutdownConfirmTitle: '기기를 종료하시겠습니까?',
+ shutdownConfirmBody: '\"{{hostname}}\"을(를) 종료하시겠습니까? 다시 켜려면 물리적 접근이 필요합니다.',
+ commandConfirm: '확인',
+ commandQueued: '명령이 대기열에 추가됨',
+ commandError: '명령 전송 실패',
+ cpuLoad: 'CPU 부하'
+ },
+ ldap: {
+ title: 'LDAP 인증',
+ enabledDesc: 'LDAP 인증이 활성화되어 있습니다',
+ disabledDesc: 'LDAP 인증이 비활성화되어 있습니다',
+ disabledHint: '아래에서 LDAP 설정을 구성하고 저장한 후 활성화하세요.',
+ enabled: 'LDAP 인증 활성화됨',
+ disabled: 'LDAP 인증 비활성화됨',
+ feature1: '사용자가 LDAP 자격 증명으로 로그인 가능',
+ feature2: '로컬 관리자 계정이 대체 수단으로 유지됨',
+ feature3: 'LDAP 그룹이 로그인 시 Bambuddy 그룹에 매핑됨',
+ serverConfig: 'LDAP 서버 설정',
+ serverUrl: '서버 URL',
+ serverUrlHint: 'SSL에는 ldaps://, StartTLS에는 ldap:// 사용',
+ security: '보안',
+ securityHint: 'StartTLS는 일반 연결을 TLS로 업그레이드합니다. LDAPS는 처음부터 TLS를 사용합니다.',
+ bindDn: '바인드 DN (서비스 계정)',
+ bindPassword: '바인드 비밀번호',
+ searchBase: '검색 기반 DN',
+ userFilter: '사용자 검색 필터',
+ userFilterHint: '{username}은 로그인 사용자명으로 대체됩니다. OpenLDAP의 경우 (uid={username})을 사용하세요.',
+ autoProvision: '사용자 자동 프로비저닝',
+ autoProvisionHint: '첫 LDAP 로그인 시 자동으로 Bambuddy 계정 생성',
+ defaultGroup: '기본 그룹',
+ defaultGroupNone: '— 없음 (대체 없음) —',
+ defaultGroupHint: 'LDAP 사용자가 인증되었지만 매핑된 LDAP 그룹에 없을 때 할당되는 대체 그룹. 비워두면 매핑되지 않은 사용자에게 권한이 없습니다.',
+ groupMapping: '그룹 매핑 (JSON)',
+ groupMappingHint: 'LDAP 그룹 DN을 Bambuddy 그룹에 매핑합니다. 사용 가능한 그룹: ',
+ testConnection: '연결 테스트',
+ settingsSaved: 'LDAP 설정이 저장되었습니다',
+ errors: {
+ serverRequired: 'LDAP 서버 URL이 필요합니다',
+ searchBaseRequired: '검색 기반 DN이 필요합니다',
+ enableAuthFirst: '먼저 인증을 활성화하세요',
+ configureLdapFirst: '먼저 LDAP 설정을 저장하세요'
+ },
+ advanced: '고급'
+ },
+ email: {
+ smtpSettings: 'SMTP 설정',
+ smtpHost: 'SMTP 서버',
+ smtpPort: 'SMTP 포트',
+ security: '보안',
+ authentication: '인증',
+ username: '사용자명',
+ password: '비밀번호',
+ fromEmail: '발신 이메일',
+ fromName: '발신자 이름',
+ testConnection: 'SMTP 연결 테스트',
+ testRecipient: '테스트 수신자 이메일',
+ sendTest: '테스트 이메일 전송',
+ sending: '전송 중...',
+ save: '설정 저장',
+ saving: '저장 중...',
+ advancedAuth: '고급 인증',
+ advancedAuthEnabled: '고급 인증이 활성화되어 있습니다',
+ advancedAuthEnabledDesc: '이메일 기반 사용자 관리 기능이 활성화되어 있습니다. 신규 사용자는 이메일로 자동 생성된 비밀번호를 받으며, 사용자는 비밀번호 찾기 기능으로 비밀번호를 재설정할 수 있습니다.',
+ advancedAuthDisabled: '고급 인증이 비활성화되어 있습니다',
+ advancedAuthDisabledDesc: '이메일 기반 사용자 관리 기능을 활성화하려면 고급 인증을 활성화하세요.',
+ enable: '활성화',
+ disable: '비활성화',
+ feature1: '비밀번호가 자동 생성되어 신규 사용자에게 이메일로 전송됨',
+ feature2: '사용자가 사용자명 또는 이메일로 로그인 가능',
+ feature3: '비밀번호 찾기 기능 사용 가능',
+ feature4: '관리자가 이메일로 사용자 비밀번호 재설정 가능',
+ errors: {
+ requiredFields: '모든 필수 항목을 입력하세요',
+ usernameRequired: '인증이 활성화된 경우 사용자명이 필요합니다',
+ enterTestEmail: '테스트 이메일 주소를 입력하세요',
+ smtpServerAndEmail: '테스트 전에 SMTP 서버와 발신 이메일을 입력하세요',
+ usernamePasswordRequired: '인증이 활성화된 경우 사용자명과 비밀번호가 필요합니다',
+ configureSmtpFirst: '먼저 SMTP 설정을 구성하고 테스트하세요',
+ enableAuthFirst: '이메일 기반 기능을 사용하려면 먼저 인증을 활성화하세요.'
+ },
+ success: {
+ settingsSaved: 'SMTP 설정이 성공적으로 저장되었습니다'
+ },
+ securityOptions: {
+ starttls: 'STARTTLS (포트 587)',
+ ssl: 'SSL/TLS (포트 465)',
+ none: '없음 (포트 25)'
+ },
+ authOptions: {
+ enabled: '활성화됨',
+ disabled: '비활성화됨'
+ }
+ },
+ appearance: '모양',
+ notifications: '알림',
+ smartPlugs: '스마트 플러그',
+ spoolman: 'Spoolman',
+ updates: '업데이트',
+ language: '언어',
+ languageDescription: '선호하는 언어를 선택하세요',
+ theme: '테마',
+ themeLight: '라이트',
+ themeDark: '다크',
+ themeSystem: '시스템',
+ defaultView: '기본 보기',
+ defaultViewDescription: '앱을 열 때 표시할 페이지',
+ checkForUpdates: '업데이트 확인',
+ autoUpdate: '자동 업데이트',
+ currentVersion: '현재 버전',
+ latestVersion: '최신 버전',
+ upToDate: '최신 상태입니다',
+ updateAvailable: '업데이트 가능',
+ notificationLanguage: '알림 언어',
+ notificationLanguageDescription: '푸시 알림 언어',
+ bedCooledThreshold: '베드 냉각 임계값',
+ bedCooledThresholdDescription: '인쇄 후 베드가 냉각된 것으로 간주되는 온도',
+ userNotificationsEnabled: '사용자 알림',
+ userNotificationsEnabledDescription: '사용자 알림 메뉴 및 인쇄 작업 이벤트에 대한 이메일 알림을 활성화합니다. 고급 인증이 필요합니다.',
+ userNotificationsDisabledHint: '사용자 알림을 사용하려면 고급 인증을 활성화하세요.',
+ notificationProviders: '알림 제공자',
+ addProvider: '제공자 추가',
+ editProvider: '제공자 편집',
+ providerType: '제공자 유형',
+ testNotification: '알림 테스트',
+ testSuccess: '테스트 알림이 성공적으로 전송되었습니다',
+ testFailed: '테스트 알림 전송 실패',
+ quietHours: '방해 금지 시간',
+ quietHoursDescription: '이 시간 동안 방해하지 않음',
+ quietHoursStart: '시작',
+ quietHoursEnd: '종료',
+ events: {
+ title: '알림 이벤트',
+ printStart: '인쇄 시작됨',
+ printComplete: '인쇄 완료됨',
+ printFailed: '인쇄 실패',
+ printStopped: '인쇄 정지됨',
+ printProgress: '진행 마일스톤',
+ printProgressDescription: '25%, 50%, 75%에 알림',
+ printerOffline: '프린터 오프라인',
+ printerError: '프린터 오류',
+ filamentLow: '필라멘트 부족',
+ maintenanceDue: '유지보수 예정',
+ maintenanceDueDescription: '유지보수가 필요할 때 알림'
+ },
+ smartPlug: {
+ title: '스마트 플러그',
+ add: '스마트 플러그 추가',
+ edit: '스마트 플러그 편집',
+ name: '이름',
+ ipAddress: 'IP 주소',
+ linkedPrinter: '연결된 프린터',
+ autoOn: '자동 켜기',
+ autoOnDescription: '인쇄 시작 시 켜기',
+ autoOff: '자동 끄기',
+ autoOffDescription: '인쇄 완료 후 끄기',
+ offDelay: '끄기 지연',
+ offDelayMinutes: '인쇄 후 분',
+ offDelayTemp: '노즐 온도 이하일 때',
+ currentState: '현재 상태',
+ turnOn: '켜기',
+ turnOff: '끄기'
+ },
+ filamentTracking: '필라멘트 추적',
+ filamentTrackingDesc: '필라멘트 스풀을 추적하는 방법을 선택하세요. 내장 인벤토리를 사용하거나 외부 Spoolman 서버에 연결할 수 있습니다.',
+ filamentChecks: '필라멘트 확인',
+ disableFilamentWarnings: '필라멘트 경고 비활성화',
+ disableFilamentWarningsDesc: '인쇄 또는 대기열 추가 시 필라멘트 부족 경고 표시 안 함',
+ preferLowestFilament: '남은 필라멘트가 가장 적은 것 우선',
+ preferLowestFilamentDesc: '여러 스풀이 일치할 때 남은 필라멘트가 가장 적은 것 사용',
+ trackingModeBuiltIn: '내장 인벤토리',
+ trackingModeBuiltInDesc: 'RFID 자동 매칭 및 사용량 추적 포함',
+ trackingModeSpoolmanDesc: '외부 필라멘트 관리 서버',
+ builtInFeatureRfid: 'AMS의 Bambu Lab RFID 스풀 자동 감지',
+ builtInFeatureUsage: '인쇄당 필라멘트 소비량 추적',
+ builtInFeatureCatalog: '스풀, 색상, K 팩터 프로필 관리',
+ builtInFeatureThirdParty: '서드파티 스풀을 인벤토리 스풀에 할당 가능',
+ amsSyncButton: 'AMS에서 무게 동기화',
+ amsSyncTitle: 'AMS에서 스풀 무게 동기화',
+ amsSyncMessage: '연결된 프린터의 현재 AMS 잔여% 값으로 모든 인벤토리 스풀 무게를 덮어씁니다. 손상된 무게 데이터를 복구하는 데 사용하세요. 프린터가 온라인이어야 합니다.',
+ amsSyncing: '동기화 중...',
+ amsSyncSuccess: '{{synced}}개 스풀 동기화됨, {{skipped}}개 건너뜀',
+ amsSyncError: 'AMS에서 무게 동기화 실패',
+ spoolmanAmsSyncButton: 'AMS에서 Spoolman 무게 동기화',
+ spoolmanAmsSyncTitle: 'AMS에서 Spoolman 스풀 무게 동기화',
+ spoolmanAmsSyncMessage: '연결된 프린터의 현재 AMS 잔여% 값으로 모든 Spoolman 스풀 무게를 업데이트합니다. 프린터가 온라인이어야 합니다.',
+ spoolmanAmsSyncing: '동기화 중...',
+ spoolmanAmsSyncSuccess: '{{synced}}개 스풀 동기화됨, {{skipped}}개 건너뜀',
+ spoolmanAmsSyncError: 'AMS에서 Spoolman 무게 동기화 실패',
+ spoolmanAmsSyncErrorUnreachable: 'Spoolman 무게 동기화 실패 (Spoolman 접근 불가)',
+ spoolmanAmsSyncErrorNotConfigured: 'Spoolman 무게 동기화 실패 (Spoolman 미설정)',
+ spoolmanNotConfigured: 'Spoolman 미설정',
+ spoolmanFilamentCatalogTitle: 'Spoolman 필라멘트 카탈로그',
+ spoolmanFilamentCatalogDesc: 'Spoolman 인스턴스의 필라멘트 이름 및 공 무게. 이름과 스풀 무게는 여기서 편집 가능하며 다른 속성은 Spoolman에서 직접 관리됩니다.',
+ spoolmanUrl: 'Spoolman URL',
+ spoolmanUrlHint: 'Spoolman 서버의 URL (예: http://localhost:7912)',
+ spoolmanConnected: '연결됨',
+ spoolmanDisconnected: '연결 끊김',
+ status: '상태',
+ connect: '연결',
+ disconnect: '연결 해제',
+ howSyncWorks: '동기화 작동 방식',
+ syncInfoRfidOnly: 'RFID가 있는 공식 Bambu Lab 스풀만 동기화됨',
+ syncInfoAutoCreate: '새 스풀은 첫 번째 동기화 시 Spoolman에 자동 생성됨',
+ syncInfoThirdPartySkipped: '비 Bambu Lab 스풀 (서드파티, 리필)은 건너뜀',
+ linkingExistingSpools: '기존 스풀 연결',
+ linkingExistingSpoolsDesc: '기존 Spoolman 스풀을 AMS에 연결하려면 AMS 슬롯 위에 마우스를 올리고 \"Spoolman에 연결\"을 클릭하세요.',
+ syncMode: '동기화 모드',
+ syncModeAuto: '자동',
+ syncModeManual: '수동만',
+ syncModeAutoDesc: '변경이 감지되면 AMS 데이터가 자동으로 동기화됨',
+ syncModeManualDesc: '수동으로 트리거할 때만 동기화',
+ syncAmsData: 'AMS 데이터 동기화',
+ syncAmsDataDesc: '프린터 AMS 데이터를 Spoolman에 수동으로 동기화',
+ allPrinters: '모든 프린터',
+ noDefaultPrinter: '기본값 없음 (매번 묻기)',
+ sidebarOrder: '사이드바 순서',
+ saveThumbnails: '썸네일 저장',
+ captureFinishPhoto: '완료 사진 캡처',
+ noPrintersConfigured: '설정된 프린터 없음',
+ archiveMode: {
+ always: '항상 아카이브 항목 생성',
+ never: '아카이브 항목 생성 안 함',
+ ask: '매번 묻기'
+ },
+ checkForUpdatesLabel: '업데이트 확인',
+ checkPrinterFirmware: '프린터 펌웨어 확인',
+ includeBetaUpdates: '베타 버전 포함',
+ includeBetaUpdatesDesc: '업데이트 확인 시 베타 및 사전 릴리스 버전에 대해 알림',
+ enableRetry: '재시도 활성화',
+ homeAssistantDescription: 'Home Assistant를 통해 스마트 플러그 제어',
+ environmentManagedLabel: '(환경 변수 관리)',
+ autoEnabledViaEnv: '환경 변수를 통해 자동 활성화됨',
+ urlFromEnvReadOnly: 'HA_URL 환경 변수에서 값 설정됨 (읽기 전용)',
+ tokenFromEnvReadOnly: 'HA_TOKEN 환경 변수에서 값 설정됨 (읽기 전용)',
+ mqttConnectedTo: '연결됨',
+ prometheusDescription: 'Prometheus 형식으로 프린터 데이터 노출',
+ noSmartPlugsTitle: '설정된 스마트 플러그 없음',
+ noSmartPlugsDescription: '에너지 사용량 추적 및 전원 제어 자동화를 위해 Tasmota 기반 스마트 플러그를 추가하세요.',
+ noProvidersTitle: '설정된 제공자 없음',
+ noProvidersDescription: '알림을 받으려면 제공자를 추가하세요.',
+ noTemplatesAvailable: '사용 가능한 템플릿 없음. 기본 템플릿을 시드하려면 백엔드를 재시작하세요.',
+ apiPermissionView: '프린터 상태 및 대기열 보기',
+ apiPermissionEdit: '인쇄 대기열에서 항목 추가 및 제거',
+ apiKeysEmptyTitle: 'API 키 없음',
+ apiKeysEmptyDescription: '외부 서비스와 통합하려면 API 키를 만드세요.',
+ noUsersFound: '사용자를 찾을 수 없습니다',
+ noGroupsFound: '그룹을 찾을 수 없습니다',
+ noGroupsAvailable: '사용 가능한 그룹 없음',
+ passwordsDoNotMatch: '비밀번호가 일치하지 않습니다',
+ systemGroupWarning: '시스템 그룹 이름은 변경할 수 없습니다',
+ authDisabledTitle: '인증이 비활성화되어 있습니다',
+ authDisabledFeature1: '시스템 접근 시 로그인 필요',
+ authDisabledFeature2: '그룹 기반 권한으로 여러 사용자 생성',
+ authDisabledFeature3: '50개 이상의 세분화된 권한으로 접근 제어',
+ userHasCreated: '이 사용자가 만든 항목:',
+ userItemsQuestion: '이 항목들을 어떻게 처리하시겠습니까?',
+ deleteUserConfirm: '이 사용자를 삭제하시겠습니까?',
+ actionCannotBeUndone: '이 작업은 취소할 수 없습니다.',
+ addFirstSmartPlug: '첫 번째 스마트 플러그 추가',
+ providers: '제공자',
+ log: '로그',
+ testAll: '모두 테스트',
+ testResults: '테스트 결과',
+ testPassedCount: '{{count}}개 통과',
+ testFailedCount: '{{count}}개 실패',
+ messageTemplates: '메시지 템플릿',
+ messageTemplatesDescription: '각 이벤트에 대한 알림 메시지를 사용자 지정하세요.',
+ apiKeys: 'API 키',
+ apiKeysDescription: '외부 통합 및 웹훅을 위한 API 키를 만드세요.',
+ createKey: '키 만들기',
+ apiKeyCreated: 'API 키가 성공적으로 생성되었습니다',
+ apiKeyCopyWarning: '지금 이 키를 복사하세요 - 다시 표시되지 않습니다!',
+ useInApiBrowser: 'API 브라우저에서 사용',
+ createNewApiKey: '새 API 키 만들기',
+ keyName: '키 이름',
+ keyNamePlaceholder: '예: Home Assistant, OctoPrint',
+ readStatus: '상태 읽기',
+ readStatusDescription: '프린터 상태 및 대기열 보기',
+ manageQueue: '대기열 관리',
+ manageQueueDescription: '인쇄 대기열에서 항목 추가 및 제거',
+ controlPrinter: '프린터 제어',
+ controlPrinterDescription: '인쇄 일시정지, 재개, 정지',
+ manageLibrary: '라이브러리 관리',
+ manageLibraryDescription: '라이브러리 파일 업로드, 이름 변경 및 삭제; MakerWorld에서 모델 가져오기',
+ manageInventory: '재고 관리',
+ manageInventoryDescription: '스풀 및 재고 레코드 생성, 업데이트 및 삭제. SpoolBuddy 키오스크(NFC 스캔, 저울 측정값, 키오스크 시스템 명령)에 필요합니다.',
+ libraryBadge: '라이브러리',
+ inventoryBadge: '재고',
+ cloudAccess: '클라우드 접근 허용',
+ cloudAccessDescription: '사용자를 대신하여 Bambu Cloud 프리셋 및 필라멘트를 읽습니다. Bambu Cloud에 로그인되어 있어야 합니다.',
+ cloudBadge: '클라우드',
+ legacyKey: '레거시',
+ legacyKeyTooltip: '사용자별 소유권 이전에 생성됨. 클라우드 접근을 사용하려면 재생성하세요',
+ unnamedKey: '이름 없는 키',
+ lastUsed: '마지막 사용',
+ read: '읽기',
+ control: '제어',
+ createFirstKey: '첫 번째 키 만들기',
+ webhookEndpoints: '웹훅 엔드포인트',
+ webhookApiKeyHint: 'X-API-Key 헤더에 API 키를 사용하세요.',
+ webhook: {
+ getAllStatus: '모든 프린터 상태 가져오기',
+ getSpecificStatus: '특정 프린터 상태 가져오기',
+ addToQueue: '인쇄 대기열에 추가',
+ pausePrint: '인쇄 일시정지',
+ resumePrint: '인쇄 재개',
+ stopPrint: '인쇄 정지'
+ },
+ apiBrowser: 'API 브라우저',
+ apiBrowserDescription: '사용 가능한 모든 API 엔드포인트를 탐색하고 테스트하세요.',
+ apiKeyForTesting: '테스트용 API 키',
+ apiKeyPlaceholder: '인증된 엔드포인트를 테스트하려면 API 키를 여기에 붙여넣으세요...',
+ apiKeyHint: '이 키는 요청과 함께 X-API-Key 헤더로 전송됩니다.',
+ deleteApiKeyTitle: 'API 키 삭제',
+ deleteApiKeyMessage: '이 API 키를 삭제하시겠습니까? 이 키를 사용하는 모든 통합이 작동을 멈춥니다.',
+ deleteKey: '키 삭제',
+ amsDisplayThresholds: 'AMS 표시 임계값',
+ amsThresholdsDescription: 'AMS 습도 및 온도 표시기의 색상 임계값을 설정하세요.',
+ humidity: '습도',
+ goodGreen: '좋음 (녹색)',
+ fairOrange: '보통 (주황색)',
+ aboveFairBad: '보통 임계값 초과 시 빨간색 (나쁨)으로 표시',
+ fairAlsoDryingThreshold: '이 임계값은 자동 건조 활성화 시 트리거로도 사용됨',
+ temperature: '온도',
+ goodBlue: '좋음 (파란색)',
+ aboveFairHot: '보통 임계값 초과 시 빨간색 (뜨거움)으로 표시',
+ historyRetention: '기록 보존',
+ keepSensorHistory: '센서 기록 보존 기간',
+ historyRetentionDescription: '오래된 습도 및 온도 데이터가 자동으로 삭제됩니다',
+ defaultPrintOptions: '기본 인쇄 옵션',
+ defaultPrintOptionsDescription: '새 인쇄 시작 시 기본값을 설정하세요. 인쇄 대화 상자에서 인쇄별로 재정의할 수 있습니다.',
+ defaultBedLevelling: '베드 레벨링',
+ defaultBedLevellingDesc: '인쇄 전 자동 베드 레벨링',
+ defaultFlowCali: '유량 캘리브레이션',
+ defaultFlowCaliDesc: '압출 유량 캘리브레이션',
+ defaultVibrationCali: '진동 캘리브레이션',
+ defaultVibrationCaliDesc: '링잉 아티팩트 감소',
+ defaultLayerInspect: '첫 번째 층 검사',
+ defaultLayerInspectDesc: '첫 번째 층 AI 검사',
+ defaultTimelapse: '타임랩스',
+ defaultTimelapseDesc: '타임랩스 영상 녹화',
+ staggeredStart: '엇갈린 시작',
+ staggeredStartDescription: '다중 프린터 일괄 시작 시 기본 그룹 크기 및 간격. 인쇄 모달에서 배치별로 재정의할 수 있습니다.',
+ plateClear: '플레이트 비움 확인',
+ requirePlateClear: '플레이트 비움 확인 필요',
+ requirePlateClearDescription: '활성화하면 스케줄러가 완료된 작업이 있는 프린터에서 대기 중인 인쇄를 시작하기 전에 프린터별 플레이트 비움 확인을 기다립니다.',
+ gcodeInjection: 'G코드 주입',
+ gcodeInjectionDescription: '자동 인쇄 시스템을 위한 인쇄 시작 및/또는 종료 시 주입할 사용자 지정 G코드를 설정하세요.',
+ gcodeInjectionNoPrinters: '프린터가 없습니다. G코드 스니펫을 설정하려면 프린터를 추가하세요.',
+ gcodeStartLabel: '시작 G코드',
+ gcodeEndLabel: '종료 G코드',
+ gcodeStartPlaceholder: '인쇄 시작 전 앞에 추가되는 G코드...',
+ gcodeEndPlaceholder: '인쇄 종료 후 뒤에 추가되는 G코드...',
+ staggerGroupSize: '그룹 크기',
+ staggerGroupSizeHelp: '그룹당 동시에 시작할 프린터 수',
+ staggerInterval: '간격 (분)',
+ staggerIntervalHelp: '각 그룹 시작 사이의 지연',
+ queueDrying: '대기열 자동 건조',
+ queueDryingDescription: '대기 중인 인쇄 사이에 프린터가 유휴 상태일 때 AMS 필라멘트를 자동으로 건조합니다.',
+ queueDryingEnabled: '자동 건조 활성화',
+ queueDryingEnabledDescription: '프린터가 유휴 상태이고 습도가 임계값 초과 시 자동으로 AMS 건조 시작',
+ queueDryingBlock: '건조 완료까지 대기',
+ queueDryingBlockDescription: '건조가 완료될 때까지 인쇄 대기열을 차단합니다. 끄면 인쇄가 건조보다 우선합니다.',
+ ambientDryingEnabled: '주변 건조',
+ ambientDryingEnabledDescription: '대기 중인 인쇄가 없어도 습도가 임계값을 초과하면 유휴 프린터에서 자동으로 필라멘트 건조',
+ dryingPresets: '건조 프리셋',
+ dryingPresetsDescription: '필라멘트 유형별 온도 및 시간. AMS 2 Pro는 낮은 온도, AMS-HT는 높은 온도를 지원합니다.',
+ dryingFilament: '필라멘트',
+ printModal: '인쇄 모달',
+ expandCustomMapping: '사용자 지정 매핑 기본 펼침',
+ expandCustomMappingDescription: '여러 프린터에 인쇄할 때 프린터별 AMS 매핑을 펼친 상태로 표시',
+ authentication: '인증',
+ authEnabledDescription: '인스턴스가 사용자 인증으로 보안됨',
+ authDisabledDescription: '로그인 필요 및 사용자 접근 관리를 위해 활성화',
+ authDisabledMessage: '사용자 계정 생성, 권한 관리, Bambuddy 인스턴스 보안을 위해 인증을 활성화하세요.',
+ enableAuthentication: '인증 활성화',
+ currentUser: '현재 사용자',
+ changePassword: '비밀번호 변경',
+ admin: '관리자',
+ users: '사용자',
+ addUser: '사용자 추가',
+ groups: '그룹',
+ addGroup: '그룹 추가',
+ system: '시스템',
+ noDescription: '설명 없음',
+ userCount: '{{count}}명의 사용자',
+ permissionCount: '{{count}}개 권한',
+ createUser: '사용자 만들기',
+ username: '사용자명',
+ enterUsername: '사용자명 입력',
+ password: '비밀번호',
+ enterPassword: '비밀번호 입력 (최소 6자)',
+ confirmPassword: '비밀번호 확인',
+ confirmPasswordPlaceholder: '비밀번호 확인',
+ viewReleaseOnGitHub: 'GitHub에서 릴리스 보기',
+ turnAllPlugsOn: '모든 플러그 켜기',
+ turnAllPlugsOff: '모든 플러그 끄기',
+ clearNotificationLogs: '알림 로그 지우기',
+ clearLogsMessage: '30일보다 오래된 모든 알림 로그를 영구적으로 삭제합니다. 이 작업은 취소할 수 없습니다.',
+ clearLogs: '로그 지우기',
+ resetUiPreferences: 'UI 기본 설정 초기화',
+ resetUiPreferencesMessage: '모든 UI 기본 설정을 기본값으로 초기화합니다: 사이드바 순서, 테마, 대시보드 레이아웃, 보기 모드, 정렬 기본 설정. 프린터, 아카이브, 서버 설정은 영향받지 않습니다. 지운 후 페이지가 새로고침됩니다.',
+ resetPreferences: '기본 설정 초기화',
+ deleteGroupTitle: '그룹 삭제',
+ deleteGroupMessage: '이 그룹을 삭제하시겠습니까? 이 그룹의 사용자는 이 권한을 잃게 됩니다.',
+ deleteGroup: '그룹 삭제',
+ disableAuthenticationTitle: '인증 비활성화',
+ disableAuthenticationMessage: '인증을 비활성화하시겠습니까? 이렇게 하면 로그인 없이 Bambuddy 인스턴스에 접근할 수 있게 됩니다. 모든 사용자는 데이터베이스에 유지되지만 인증은 비활성화됩니다.',
+ disableAuthentication: '인증 비활성화',
+ configureBambuddy: 'Bambuddy 설정',
+ systemDefault: '시스템 기본값',
+ archiveSettings: '아카이브 설정',
+ newWindow: '새 창',
+ embeddedOverlay: '내장 오버레이',
+ preferredSlicer: '선호하는 슬라이서',
+ preferredSlicerDescription: '파일을 열 슬라이서 앱을 선택하세요',
+ orcaslicerKnownIssuesWarning: 'OrcaSlicer 2.3.2 / 2.4.0-dev에는 Bambu 제작 3MF 파일 슬라이싱을 차단하는 알려진 CLI 버그가 있습니다. 업스트림 수정이 출시될 때까지 Bambu Studio를 사용하는 것이 좋습니다.',
+ useSlicerApi: '슬라이서 API 사용',
+ useSlicerApiDescription: '켜면 \"슬라이스\" 작업이 앱 내 슬라이서 모달을 열고 슬라이서 API 사이드카를 호출합니다. 끄면 URI 스킴을 통해 데스크톱 슬라이서로 전달합니다.',
+ slicerCard: '슬라이서',
+ orcaslicerApiUrl: 'OrcaSlicer 사이드카 URL',
+ bambuStudioApiUrl: 'Bambu Studio 사이드카 URL',
+ slicerApiUrlDescription: '슬라이서 API 사이드카 컨테이너의 URL. SLICER_API_URL / BAMBU_STUDIO_API_URL 환경 변수 기본값을 사용하려면 비워두세요.',
+ slicerBundles: {
+ title: '슬라이서 번들',
+ description: 'BambuStudio에서 내보낸 프린터 프리셋 번들(.bbscfg)을 가져오세요. 가져온 후 슬라이스 요청이 JSON 프로필 트리플렛을 다시 업로드하지 않고 번들에서 이름으로 프리셋을 선택할 수 있습니다.',
+ uploadButton: '번들 업로드',
+ uploading: '업로드 중…',
+ loading: '번들 로딩 중…',
+ empty: '아직 가져온 번들 없음.',
+ summary: '{{processCount}}개 프로세스 · {{filamentCount}}개 필라멘트 프리셋',
+ delete: '삭제',
+ uploadSuccess: '{{name}} 가져옴',
+ uploadError: '번들 업로드 실패: {{message}}',
+ deleteSuccess: '번들 제거됨',
+ deleteError: '번들 삭제 실패: {{message}}',
+ confirmDeleteTitle: '이 번들을 제거하시겠습니까?',
+ confirmDeleteMessage: '\"{{name}}\"을(를) 참조하는 슬라이스 요청은 번들이 재가져오기될 때까지 실패합니다.'
+ },
+ externalCameras: '외부 카메라',
+ costTracking: '비용 추적',
+ printsOnly: '인쇄만',
+ totalConsumption: '총 소비',
+ dataManagement: '데이터 관리',
+ storageUsage: '저장소 사용량',
+ storageUsageDescription: '카테고리별 데이터 사용량 분류',
+ storageUsageTotal: '총계',
+ storageUsageErrors: '오류',
+ storageUsageOtherBreakdown: '기타 (정적 자산, 스크립트, 구성 파일 포함)',
+ storageUsageSystem: '시스템',
+ storageUsageData: '데이터',
+ storageUsageUnavailable: '저장소 사용량 정보 불가',
+ clearNotificationLogsDescription: '30일보다 오래된 알림 로그 삭제',
+ resetUiPreferencesDescription: '사이드바 순서, 테마, 보기 모드, 레이아웃 기본 설정 초기화. 프린터, 아카이브, 설정은 영향받지 않습니다.',
+ enableHomeAssistant: 'Home Assistant 활성화',
+ enableMqtt: 'MQTT 활성화',
+ useTls: 'TLS 사용',
+ enableMetricsEndpoint: '메트릭 엔드포인트 활성화',
+ availableMetrics: '사용 가능한 메트릭',
+ editUser: '사용자 편집',
+ deleteUserTitle: '사용자 삭제',
+ groupName: '그룹 이름',
+ leaveEmptyForAnonymous: '익명으로 두려면 비워두세요',
+ leaveEmptyForNoAuth: '인증 없이 두려면 비워두세요',
+ enterNewPassword: '새 비밀번호 입력',
+ confirmNewPassword: '새 비밀번호 확인',
+ enterGroupName: '그룹 이름 입력',
+ enterDescriptionOptional: '설명 입력 (선택사항)',
+ enterCurrentPassword: '현재 비밀번호 입력',
+ enterNewPasswordMin6: '새 비밀번호 입력 (최소 6자)',
+ toast: {
+ keyCopied: '키가 클립보드에 복사되었습니다',
+ copyFailed: '키 복사 실패',
+ keyAddedToBrowser: 'API 브라우저에 키가 추가되었습니다',
+ clearLogsFailed: '로그 지우기 실패',
+ uiPreferencesReset: 'UI 기본 설정이 초기화되었습니다. 새로고침 중...',
+ authDisabled: '인증이 성공적으로 비활성화되었습니다',
+ authDisableFailed: '인증 비활성화 실패',
+ apiKeyCreated: 'API 키가 생성되었습니다',
+ apiKeyDeleted: 'API 키가 삭제되었습니다',
+ userCreated: '사용자가 성공적으로 생성되었습니다',
+ userUpdated: '사용자가 성공적으로 업데이트되었습니다',
+ userDeleted: '사용자가 성공적으로 삭제되었습니다',
+ groupCreated: '그룹이 성공적으로 생성되었습니다',
+ groupUpdated: '그룹이 성공적으로 업데이트되었습니다',
+ groupDeleted: '그룹이 성공적으로 삭제되었습니다',
+ fillRequiredFields: '모든 필수 항목을 입력하세요',
+ passwordsDoNotMatch: '비밀번호가 일치하지 않습니다',
+ passwordTooShort: '비밀번호는 최소 6자여야 합니다',
+ enterGroupName: '그룹 이름을 입력하세요',
+ settingsSaved: '설정이 저장되었습니다',
+ noPermissionUpdate: '설정을 변경할 권한이 없습니다',
+ cameraSettingsSaved: '카메라 설정이 저장되었습니다',
+ enterCameraUrl: '카메라 URL을 입력하세요',
+ passwordChanged: '비밀번호가 성공적으로 변경되었습니다',
+ connectionFailed: '연결 실패',
+ testFailed: '테스트 실패',
+ cameraConnected: '카메라 연결됨{{resolution}}',
+ passwordNeedsUppercase: '비밀번호에 대문자가 최소 1개 포함되어야 합니다',
+ passwordNeedsLowercase: '비밀번호에 소문자가 최소 1개 포함되어야 합니다',
+ passwordNeedsDigit: '비밀번호에 숫자가 최소 1개 포함되어야 합니다',
+ passwordNeedsSpecial: '비밀번호에 특수문자가 최소 1개 포함되어야 합니다'
+ },
+ testConnection: '연결 테스트',
+ catalog: {
+ spoolCatalog: '스풀 카탈로그',
+ spoolCatalogDescription: '브랜드/유형별 빈 스풀 무게. 스풀 추가 시 자동 무게 조회에 사용됩니다.',
+ searchCatalog: '카탈로그 검색...',
+ addNewEntry: '새 항목 추가',
+ namePlaceholder: '이름 (예: Bambu Lab - Plastic)',
+ weight: '무게',
+ type: '유형',
+ default: '기본',
+ custom: '사용자 지정',
+ noMatch: '검색에 일치하는 항목 없음',
+ empty: '카탈로그에 항목 없음',
+ deleteEntry: '항목 삭제',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까?',
+ resetCatalog: '카탈로그 초기화',
+ resetConfirm: '카탈로그를 기본값으로 초기화하시겠습니까? 모든 사용자 지정 항목이 제거됩니다.',
+ loadFailed: '스풀 카탈로그 로드 실패',
+ nameWeightRequired: '이름과 무게가 필요합니다',
+ entryAdded: '항목이 추가되었습니다',
+ addFailed: '항목 추가 실패',
+ entryUpdated: '항목이 업데이트되었습니다',
+ updateFailed: '항목 업데이트 실패',
+ entryDeleted: '항목이 삭제되었습니다',
+ deleteFailed: '항목 삭제 실패',
+ resetSuccess: '카탈로그가 기본값으로 초기화되었습니다',
+ resetFailed: '카탈로그 초기화 실패',
+ exported: '{{count}}개 항목이 내보내졌습니다',
+ imported: '{{added}}개 항목 가져옴 ({{skipped}}개 건너뜀)',
+ importFailed: '가져오기 실패: 잘못된 JSON 형식',
+ exportTooltip: 'JSON으로 카탈로그 내보내기',
+ importTooltip: 'JSON에서 카탈로그 가져오기',
+ resetTooltip: '기본값으로 초기화',
+ selectedCount: '{{count}}개 선택됨',
+ deleteSelected: '선택 항목 삭제',
+ bulkDeleteConfirm: '{{count}}개 항목을 삭제하시겠습니까?',
+ bulkDeleted: '{{count}}개 항목이 삭제되었습니다',
+ bulkDeleteFailed: '항목 삭제 실패',
+ material: '재료',
+ spoolWeight: '스풀 무게',
+ color: '색상',
+ updateSpoolWeight: '스풀 무게 업데이트',
+ filamentUpdated: '필라멘트가 업데이트되었습니다',
+ filamentUpdateFailed: '필라멘트 업데이트 실패',
+ filamentUpdateInvalid: '잘못된 필라멘트 데이터',
+ keepExistingSpoolWeight: '기존 스풀에 이전 무게 유지',
+ keepExistingSpoolWeightDesc: '이 필라멘트 유형으로 이미 생성된 스풀은 이전 공 무게를 유지합니다. 새 스풀은 업데이트된 값을 사용합니다.',
+ applyToAllSpools: '모든 스풀에 적용',
+ applyToAllSpoolsDesc: '이 필라멘트 유형의 모든 무게 계산이 즉시 새 공 무게를 사용합니다.'
+ },
+ colorCatalog: {
+ title: '색상 카탈로그',
+ description: '제조사/재료별 필라멘트 색상. 스풀 추가 시 자동 색상 조회에 사용됩니다.',
+ searchColors: '색상 검색...',
+ allManufacturers: '모든 제조사',
+ addNewColor: '새 색상 추가',
+ manufacturer: '제조사',
+ colorName: '색상 이름',
+ hex: '헥스',
+ materialOptional: '재료 (선택사항)',
+ showing: '{{total}}개 중 {{filtered}}개 색상 표시',
+ noMatch: '검색에 일치하는 색상 없음',
+ empty: '카탈로그에 색상 없음',
+ deleteColor: '색상 삭제',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까?',
+ resetCatalog: '색상 카탈로그 초기화',
+ resetConfirm: '카탈로그를 기본값으로 초기화하시겠습니까? 모든 사용자 지정 색상이 제거됩니다.',
+ sync: '동기화',
+ starting: '시작 중...',
+ syncTooltip: 'FilamentColors.xyz에서 동기화 (2000개 이상 색상, 약 1분 소요)',
+ loadFailed: '색상 카탈로그 로드 실패',
+ fieldsRequired: '제조사, 색상 이름, 헥스 색상이 필요합니다',
+ colorAdded: '색상이 추가되었습니다',
+ addFailed: '색상 추가 실패',
+ colorUpdated: '색상이 업데이트되었습니다',
+ updateFailed: '색상 업데이트 실패',
+ colorDeleted: '색상이 삭제되었습니다',
+ deleteFailed: '색상 삭제 실패',
+ resetSuccess: '색상 카탈로그가 기본값으로 초기화되었습니다',
+ resetFailed: '카탈로그 초기화 실패',
+ syncUpToDate: '이미 최신 상태 ({{count}}개 색상 확인됨)',
+ syncComplete: '{{added}}개 새 색상 추가됨 ({{skipped}}개 이미 존재)',
+ syncError: '동기화 오류',
+ syncFailed: 'FilamentColors.xyz에서 동기화 실패',
+ exported: '{{count}}개 색상이 내보내졌습니다',
+ imported: '{{added}}개 색상 가져옴 ({{skipped}}개 건너뜀)',
+ importFailed: '가져오기 실패: 잘못된 JSON 형식',
+ selectedCount: '{{count}}개 선택됨',
+ deleteSelected: '선택 항목 삭제',
+ bulkDeleteConfirm: '{{count}}개 색상을 삭제하시겠습니까?',
+ bulkDeleted: '{{count}}개 색상이 삭제되었습니다',
+ bulkDeleteFailed: '색상 삭제 실패'
+ },
+ dateFormat: '날짜 형식',
+ dateFormatUs: '미국 (MM/DD/YYYY)',
+ dateFormatEu: '유럽 (DD/MM/YYYY)',
+ dateFormatIso: 'ISO (YYYY-MM-DD)',
+ timeFormat: '시간 형식',
+ timeFormat12: '12시간 (오후 3:30)',
+ timeFormat24: '24시간 (15:30)',
+ defaultPrinter: '기본 프린터',
+ defaultPrinterDescription: '업로드, 재인쇄 등 작업에서 이 프린터를 미리 선택합니다.',
+ slicerBambuStudio: 'Bambu Studio',
+ slicerOrcaSlicer: 'OrcaSlicer',
+ sidebarOrderDescription: '사이드바의 항목을 드래그하여 순서를 변경하세요. 여기서 기본 순서로 초기화하세요.',
+ setDefault: '기본값 설정',
+ sidebarOrderSetDefaultHint: '기본값 설정은 현재 메뉴 순서를 사용자 지정하지 않은 사용자에게 적용합니다.',
+ sidebarDefaultSet: '기본 메뉴 순서가 설정되었습니다.',
+ sidebarDefaultCleared: '기본 메뉴 순서가 지워졌습니다.',
+ sidebarDefaultFailed: '기본 메뉴 순서 설정 실패.',
+ reset: '초기화',
+ darkMode: '다크 모드',
+ lightMode: '라이트 모드',
+ active: '(활성)',
+ background: '배경',
+ accent: '강조',
+ style: '스타일',
+ bgNeutral: '중립',
+ bgWarm: '따뜻함',
+ bgCool: '시원함',
+ bgOled: 'OLED 블랙',
+ bgSlate: '슬레이트 블루',
+ bgForest: '포레스트 그린',
+ accentGreen: '그린',
+ accentTeal: '틸',
+ accentBlue: '블루',
+ accentOrange: '오렌지',
+ accentPurple: '퍼플',
+ accentRed: '레드',
+ styleClassic: '클래식',
+ styleGlow: '글로우',
+ styleVibrant: '비브런트',
+ themeToggleHint: '사이드바의 태양/달 아이콘으로 다크 모드와 라이트 모드를 전환하세요.',
+ autoArchivePrints: '인쇄 자동 아카이브',
+ autoArchiveDescription: '인쇄 완료 시 3MF 파일 자동 저장',
+ saveThumbnailsDescription: '3MF 파일에서 미리보기 이미지 추출 및 저장',
+ captureFinishPhotoDescription: '인쇄 완료 시 프린터 카메라로 사진 촬영',
+ ffmpegNotInstalled: 'ffmpeg 미설치',
+ ffmpegRequired: '카메라 캡처에 ffmpeg가 필요합니다. macOS에서는 brew install ffmpeg, Linux에서는 apt install ffmpeg로 설치하세요.',
+ camera: '카메라',
+ cameraViewMode: '카메라 보기 모드',
+ cameraOverlayDescription: '카메라가 메인 화면의 크기 조절 가능한 오버레이에서 열립니다',
+ cameraWindowDescription: '카메라가 별도의 브라우저 창에서 열립니다',
+ externalCamerasDescription: '내장 프린터 카메라를 교체할 외부 카메라를 설정하세요. MJPEG 스트림, RTSP, HTTP 스냅샷, USB 카메라(V4L2)를 지원합니다.',
+ cameraPlaceholderUsb: '장치 경로 (/dev/video0)',
+ cameraPlaceholderUrl: '카메라 URL (rtsp://... 또는 http://...)',
+ cameraTypeMjpeg: 'MJPEG 스트림',
+ cameraTypeRtsp: 'RTSP 스트림',
+ cameraTypeSnapshot: 'HTTP 스냅샷',
+ cameraTypeUsb: 'USB 카메라 (V4L2)',
+ cameraSnapshotUrl: '스냅샷 URL (선택사항)',
+ cameraSnapshotUrlPlaceholder: 'http://192.168.1.61:1984/api/frame.jpeg?src=printer',
+ cameraSnapshotUrlHelp: '알림 썸네일, 완료 사진, 타임랩스, 플레이트 감지에 사용되는 단일 프레임 URL.',
+ cameraRotation: '회전',
+ test: '테스트',
+ connected: '연결됨',
+ disconnected: '연결 끊김',
+ currency: '통화',
+ defaultFilamentCost: '기본 필라멘트 비용 (kg당)',
+ electricityCost: 'kWh당 전기 비용',
+ energyDisplayMode: '에너지 표시 모드',
+ energyModePrintDescription: '대시보드가 인쇄 중 사용된 에너지 합계를 표시',
+ energyModeTotalDescription: '대시보드가 스마트 플러그의 전체 에너지를 표시',
+ fileManager: '파일 관리자',
+ createArchiveEntry: '인쇄 시 아카이브 항목 생성',
+ createArchiveEntryDescription: '파일 관리자에서 인쇄할 때 선택적으로 아카이브 항목 생성',
+ lowDiskSpaceWarning: '디스크 공간 부족 경고',
+ lowDiskSpaceDescription: '여유 디스크 공간이 이 임계값 아래로 떨어지면 경고 표시',
+ printerFirmware: '프린터 펌웨어',
+ checkFirmwareDescription: 'Bambu Lab의 프린터 펌웨어 업데이트 확인',
+ bambuddySoftware: 'Bambuddy 소프트웨어',
+ autoCheckDescription: '시작 시 자동으로 새 버전 확인',
+ checkNow: '지금 확인',
+ updateAvailableVersion: '업데이트 가능: v{{version}}',
+ releaseNotes: '릴리스 노트',
+ updateViaDocker: 'Docker Compose로 업데이트:',
+ updateViaHomeAssistant: '업데이트는 Home Assistant 수퍼바이저에서 관리됩니다. Home Assistant에서 설정 → 애드온 → Bambuddy를 열어 새 버전을 설치하세요.',
+ installUpdate: '업데이트 설치',
+ latestVersionRunning: '최신 버전을 실행 중입니다',
+ failedToCheckUpdates: '업데이트 확인 실패: {{error}}',
+ backupRestore: '백업 및 복원',
+ backupRestoreDescription: '설정 내보내기/가져오기 및 GitHub 백업 설정',
+ goToBackup: '백업으로 이동',
+ externalUrl: '외부 URL',
+ externalUrlDescription: 'Bambuddy에 접근할 수 있는 외부 URL. 알림 이미지 및 외부 통합에 사용됩니다.',
+ bambuddyUrl: 'Bambuddy URL',
+ externalUrlHint: '프로토콜과 포트를 포함하세요 (예: http://192.168.1.100:8000)',
+ ftpRetry: 'FTP 재시도',
+ ftpRetryDescription: '프린터 WiFi가 불안정할 때 FTP 작업을 재시도합니다.',
+ autoRetryDescription: '실패한 FTP 작업 자동 재시도',
+ retryAttempts: '재시도 횟수',
+ retryDelay: '재시도 지연',
+ connectionTimeout: '연결 제한 시간',
+ time_one: '{{count}}번',
+ time_other: '{{count}}번',
+ second_one: '{{count}}초',
+ second_other: '{{count}}초',
+ nSeconds: '{{count}}초',
+ increaseForWeakWifi: 'WiFi가 약한 프린터에서 늘리세요',
+ homeAssistant: 'Home Assistant',
+ homeAssistantFullDescription: 'Home Assistant의 REST API를 통해 스마트 플러그를 제어하려면 연결하세요.',
+ homeAssistantUrl: 'Home Assistant URL',
+ longLivedAccessToken: '장기 액세스 토큰',
+ haTokenHint: 'HA에서 토큰 생성: 프로필 → 장기 액세스 토큰 → 토큰 생성',
+ connectionSuccessful: '연결 성공',
+ connectionFailed: '연결 실패',
+ haConnectionSuccess: 'Home Assistant에 성공적으로 연결되었습니다.',
+ haConnectionFailed: 'Home Assistant 연결 실패.',
+ mqttPublishing: 'MQTT 게시',
+ mqttDescription: 'Node-RED, Home Assistant 등 자동화 시스템과 통합하기 위해 Bambuddy 이벤트를 외부 MQTT 브로커에 게시하세요.',
+ mqttEnableDescription: '외부 MQTT 브로커에 이벤트 게시',
+ brokerHostname: '브로커 호스트명',
+ port: '포트',
+ usernameOptional: '사용자명 (선택사항)',
+ passwordOptional: '비밀번호 (선택사항)',
+ topicPrefix: '토픽 접두사',
+ topicPrefixHint: '토픽은 다음과 같습니다: {{prefix}}/printers//status 등',
+ prometheusMetrics: 'Prometheus 메트릭',
+ prometheusEndpointDescription: 'Prometheus/Grafana 모니터링을 위해 /api/v1/metrics에서 프린터 메트릭을 노출합니다.',
+ bearerTokenOptional: '베어러 토큰 (선택사항)',
+ bearerTokenHint: '설정하면 요청에 Authorization: Bearer 을 포함해야 합니다',
+ metricsConnectionStatus: '연결 상태',
+ metricsPrinterState: '프린터 상태 (유휴/인쇄 중/등)',
+ metricsPrintProgress: '인쇄 진행 0-100%',
+ metricsBedTemp: '베드 온도',
+ metricsNozzleTemp: '노즐 온도',
+ metricsPrintsTotal: '결과별 총 인쇄 수',
+ metricsMore: '...및 더 많은 것 (레이어, 팬, 대기열, 필라멘트 사용량)',
+ smartPlugsDescription: '에너지 사용량 추적 및 프린터 전원 제어를 자동화하기 위해 스마트 플러그(Tasmota 또는 Home Assistant)를 연결하세요.',
+ allOn: '모두 켜기',
+ allOff: '모두 끄기',
+ addSmartPlug: '스마트 플러그 추가',
+ energySummary: '에너지 요약',
+ currentPower: '현재 전력',
+ plugsOnline: '{{reachable}}/{{total}}개 플러그 온라인',
+ today: '오늘',
+ yesterday: '어제',
+ total: '총계',
+ enablePlugsForSummary: '에너지 요약을 보려면 플러그를 활성화하세요',
+ addNotificationProvider: '추가',
+ systemBadge: '(시스템)',
+ creating: '생성 중...',
+ changing: '변경 중...',
+ deleteUserAndItems: '사용자 및 항목 삭제',
+ deleteUserKeepItems: '사용자 삭제, 항목 유지 (소유자 없음)',
+ ok: '확인',
+ twoFa: {
+ totpTitle: '인증 앱 (TOTP)',
+ totpDesc: 'Google Authenticator, Aegis, Authy 같은 인증 앱을 사용하세요.',
+ emailOtpTitle: '이메일 OTP',
+ emailOtpDesc: '로그인 시 {{email}}로 일회용 코드를 전송합니다.',
+ emailOtpNoEmail: '이 방법을 활성화하려면 계정에 이메일 주소를 추가하세요.',
+ addEmailFirst: '계정에 이메일 주소가 없습니다. 이메일 OTP를 활성화하기 전에 관리자에게 추가를 요청하세요.',
+ setupTotp: '인증 앱 설정',
+ setupAuthApp: '인증 앱 설정',
+ setupInstructions: '아래 QR 코드를 인증 앱으로 스캔한 후 코드로 확인하세요.',
+ manualEntry: '스캔할 수 없나요? 이 비밀을 수동으로 입력하세요:',
+ scannedContinue: '코드를 스캔했습니다 — 계속',
+ enterCodeToConfirm: '인증 앱의 6자리 코드를 입력하여 설정을 확인하세요.',
+ activate: '활성화',
+ disableTotp: '인증기 비활성화',
+ disableConfirmHint: '인증기를 비활성화하려면 유효한 TOTP 코드나 백업 코드를 입력하세요.',
+ totpDisabled: '인증 앱이 비활성화되었습니다.',
+ emailOtpEnabled: '이메일 OTP가 활성화되었습니다.',
+ emailOtpDisabled: '이메일 OTP가 비활성화되었습니다.',
+ smtpRequired: '먼저 SMTP 설정을 구성하고 테스트하세요.',
+ invalidCode: '잘못된 코드입니다. 다시 시도하세요.',
+ enableEmailOtp: '이메일 OTP 활성화',
+ disableEmailOtp: '이메일 OTP 비활성화',
+ emailSetupEnterCode: '이메일 주소로 인증 코드가 전송되었습니다. 아래에 입력하여 이 받은 편지함을 소유하고 있음을 확인하세요.',
+ verifyAndEnable: '확인 및 활성화',
+ emailDisablePasswordHint: '이메일 OTP 비활성화를 확인하려면 계정 비밀번호를 입력하세요.',
+ passwordPlaceholder: '비밀번호 입력',
+ backupCodesTitle: '백업 코드 저장',
+ backupCodesWarning: '이 코드를 안전한 곳에 저장하세요. 각 코드는 한 번만 사용할 수 있으며 다시 표시되지 않습니다.',
+ backupCodesRemaining: '{{count}}개 백업 코드 남음',
+ savedCodes: '코드를 저장했습니다',
+ regenBackup: '백업 코드 재생성',
+ regenBackupHint: '현재 TOTP 코드를 입력하여 10개의 새 백업 코드를 생성하세요. 기존 백업 코드는 모두 무효화됩니다.',
+ newBackupCodes: '새 백업 코드',
+ linkedAccounts: '연결된 SSO 계정',
+ linkedAccountsDesc: '이 외부 ID 제공자가 계정에 연결되어 있습니다.',
+ oidcUnlinked: '계정 연결이 해제되었습니다.'
+ },
+ oidc: {
+ title: 'SSO / OIDC 제공자',
+ desc: '외부 ID 제공자를 통해 싱글 사인온을 허용하도록 OpenID Connect 제공자를 설정하세요.',
+ addProvider: '제공자 추가',
+ newProvider: '새 제공자',
+ empty: '아직 설정된 OIDC 제공자가 없습니다.',
+ created: '제공자가 생성되었습니다.',
+ updated: '제공자가 업데이트되었습니다.',
+ deleted: '제공자가 삭제되었습니다.',
+ deleteTitle: '제공자 삭제',
+ deleteMessage: '\"{{name}}\"을(를) 삭제하시겠습니까? 연결된 모든 사용자 계정의 연결이 해제됩니다.',
+ form: {
+ name: '표시 이름',
+ issuerUrl: '발급자 URL',
+ clientId: '클라이언트 ID',
+ clientSecret: '클라이언트 시크릿',
+ scopes: '범위',
+ iconUrl: '아이콘 URL (선택사항)',
+ enabled: '활성화됨',
+ autoCreate: '사용자 자동 생성',
+ autoCreateDesc: '첫 번째 로그인 시 자동으로 로컬 계정 생성.',
+ autoLink: '기존 계정 자동 연결',
+ autoLinkDesc: '첫 번째 로그인 시 이메일 일치로 기존 로컬 계정 연결.',
+ secretHint: '현재 값을 유지하려면 비워두세요',
+ secretPlaceholder: '새 시크릿',
+ emailClaim: '이메일 클레임',
+ emailClaimDesc: '이메일 ID로 사용되는 JWT 클레임.',
+ emailClaimPlaceholder: 'email',
+ emailClaimCustomClaimAutoLinkWarning: '사용자 지정 클레임은 값이 테넌트 관리인 경우에만 자동 연결에 안전합니다. IdP가 사용자가 이 클레임을 직접 주장할 수 있게 하면 자동 연결을 활성화하지 마세요.',
+ requireEmailVerified: '이메일 확인 필요',
+ requireEmailVerifiedDesc: '제공자가 확인된 것으로 표시한 경우에만 이메일 클레임을 수락합니다.',
+ requireEmailVerifiedWarning: '경고: 확인 없이도 이메일이 수락됩니다. 신뢰할 수 있는 제공자에만 사용하세요.',
+ requireEmailVerifiedAutoLink: '이 설정을 변경하려면 먼저 자동 연결을 비활성화하세요.',
+ defaultGroup: '기본 그룹',
+ defaultGroupDesc: '자동 생성된 사용자에게 할당되는 그룹. 설정되지 않으면 Viewers로 대체됩니다.',
+ defaultGroupViewersFallback: 'Viewers (기본값)'
+ },
+ refreshIcon: '아이콘 새로고침',
+ removeIcon: '아이콘 제거',
+ iconRefreshed: '아이콘이 새로고침되었습니다.',
+ iconRemoved: '아이콘이 제거되었습니다.',
+ iconFetchFailed: '공급자 URL에서 아이콘을 가져올 수 없습니다.'
+ },
+ encryption: {
+ title: 'MFA 암호화 상태',
+ enabledFromEnv: '저장 시 암호화 활성화됨 (MFA_ENCRYPTION_KEY 환경 변수에서 키)',
+ enabledFromFile: '저장 시 암호화 활성화됨 (데이터 디렉토리에서 키 로드됨)',
+ enabledGenerated: '자동 생성된 키로 저장 시 암호화 활성화됨',
+ notConfigured: '저장 시 암호화가 설정되지 않음',
+ notConfiguredDesc: 'TOTP 시크릿 및 OIDC client_secret이 일반 텍스트로 저장됩니다. MFA_ENCRYPTION_KEY를 설정하거나 쓰기 가능한 데이터 디렉토리로 Bambuddy를 재시작하여 자동 생성하세요.',
+ allEncrypted: '모든 MFA 시크릿이 저장 시 암호화되어 있습니다.',
+ legacyRowsLabel: '레거시 일반 텍스트 행',
+ encryptedRowsLabel: '암호화된 행',
+ legacyRowsWarning: '{{count}}개 레거시 일반 텍스트 행이 감지되었습니다. 암호화된 저장소로 마이그레이션하려면 OIDC 제공자를 다시 저장하거나 사용자의 인증 앱을 재등록하세요.',
+ backupHint: '자동 생성된 키는 DATA_DIR/.mfa_encryption_key에 저장되며 로컬 백업 ZIP에 포함됩니다. 백업을 안전하게 보관하거나 MFA_ENCRYPTION_KEY를 명시적으로 설정하세요.',
+ decryptionBrokenTitle: '암호화 키 누락',
+ decryptionBrokenError: '암호화 키를 더 이상 사용할 수 없어 {{count}}개의 암호화된 레코드를 복호화할 수 없습니다.',
+ migrationErrorWarning: '시작 시 {{count}}개 레거시 행을 재암호화하지 못했습니다. 서버 로그를 확인하고 Bambuddy를 재시작하여 재시도하세요.'
+ },
+ updateEnergyCost: '전기 요금 업데이트',
+ updateEnergyCostDescription: '이 키가 /settings/electricity-price에 새 kWh당 전기 요금을 POST할 수 있도록 허용합니다. Home Assistant 동적 요금 자동화(Tibber, Octopus 등)에 유용합니다. API 키로 쓸 수 있는 유일한 설정 필드입니다.',
+ energyCostBadge: '에너지',
+ passwordRequirements: '최소 8자, 대문자, 소문자, 숫자, 특수문자 각 1개 이상 포함'
+ },
+ notification: {
+ printStarted: {
+ title: '인쇄 시작됨',
+ body: '{{printer}}: {{filename}} 인쇄가 시작되었습니다'
+ },
+ printCompleted: {
+ title: '인쇄 완료됨',
+ body: '{{printer}}: {{filename}}이(가) 성공적으로 완료되었습니다'
+ },
+ printFailed: {
+ title: '인쇄 실패',
+ body: '{{printer}}: {{filename}}이(가) 실패했습니다'
+ },
+ printStopped: {
+ title: '인쇄 정지됨',
+ body: '{{printer}}: {{filename}}이(가) 정지되었습니다'
+ },
+ printProgress: {
+ title: '인쇄 진행',
+ body: '{{printer}}: {{filename}} {{percent}}% 완료'
+ },
+ printerOffline: {
+ title: '프린터 오프라인',
+ body: '{{printer}}이(가) 오프라인 상태입니다'
+ },
+ printerError: {
+ title: '프린터 오류',
+ body: '{{printer}}: {{error}}'
+ },
+ filamentLow: {
+ title: '필라멘트 부족',
+ body: '{{printer}}: 필라멘트가 부족합니다'
+ },
+ maintenanceDue: {
+ title: '유지보수 예정',
+ body: '{{printer}}: {{items}} 주의 필요'
+ }
+ },
+ errors: {
+ generic: '문제가 발생했습니다',
+ networkError: '네트워크 오류. 연결을 확인하세요.',
+ notFound: '찾을 수 없습니다',
+ unauthorized: '권한 없음',
+ serverError: '서버 오류',
+ validationError: '입력값을 확인하세요',
+ printerConnectionFailed: '프린터 연결 실패',
+ saveFailed: '변경사항 저장 실패',
+ deleteFailed: '삭제 실패',
+ loadFailed: '데이터 로드 실패'
+ },
+ hmsErrors: {
+ title: '오류 - {{name}}',
+ noErrors: '오류 없음',
+ viewOnWiki: 'Bambu Lab 위키에서 보기',
+ clearInstructions: '오류를 해제하려면 프린터에서 오류를 지우세요.',
+ clearErrors: '오류 지우기',
+ clearSuccess: 'HMS 오류가 지워졌습니다',
+ clearFailed: 'HMS 오류 지우기 실패'
+ },
+ mqttDebug: {
+ title: 'MQTT 디버그 로그',
+ searchPlaceholder: '토픽 또는 페이로드 검색...',
+ noMessages: '아직 기록된 메시지 없음',
+ startLoggingHint: '\"로깅 시작\"을 클릭하여 MQTT 메시지 캡처 시작',
+ noMessagesMatch: '필터에 일치하는 메시지 없음',
+ adjustFilterHint: '검색 또는 필터 기준을 조정해 보세요',
+ incoming: '수신',
+ outgoing: '송신',
+ loggingStopped: '로깅 정지됨',
+ loggingActive: '로깅 활성 - 메시지가 자동 새로고침됨',
+ startLogging: '로깅 시작',
+ stopLogging: '로깅 정지',
+ clearLog: '로그 지우기',
+ topic: '토픽',
+ timestamp: '타임스탬프',
+ direction: '방향',
+ all: '전체'
+ },
+ printerFiles: {
+ title: '파일 관리자',
+ storageUsed: '사용됨:',
+ storageFree: '여유:',
+ filterPlaceholder: '파일 필터...',
+ deleteButton: '삭제',
+ deleteFiles: '{{count}}개 파일 삭제',
+ deleteFileConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ deleteFilesConfirm: '선택된 {{count}}개 파일을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ noFiles: '프린터에 파일 없음',
+ loadingFiles: '파일 로딩 중...',
+ failedToLoad: '파일 로드 실패',
+ toast: {
+ filesDeleted: '{{count}}개 파일이 삭제되었습니다',
+ deleteFailed: '삭제 실패: {{error}}'
+ }
+ },
+ confirm: {
+ delete: '이것을 삭제하시겠습니까?',
+ unsavedChanges: '저장되지 않은 변경사항이 있습니다. 정말 나가시겠습니까?',
+ clearQueue: '대기열을 지우시겠습니까?'
+ },
+ login: {
+ title: 'Bambuddy 로그인',
+ subtitle: '계정에 로그인하세요',
+ username: '사용자명',
+ usernamePlaceholder: '사용자명을 입력하세요',
+ usernameOrEmail: '사용자명 또는 이메일',
+ usernameOrEmailPlaceholder: '사용자명 또는 @ 이메일',
+ password: '비밀번호',
+ passwordPlaceholder: '비밀번호를 입력하세요',
+ signIn: '로그인',
+ signingIn: '로그인 중...',
+ rememberMe: '로그인 유지',
+ forgotPassword: '비밀번호를 잊으셨나요?',
+ loginSuccess: '성공적으로 로그인되었습니다',
+ loginFailed: '로그인 실패',
+ enterCredentials: '사용자명과 비밀번호를 입력하세요',
+ enterEmail: '이메일 주소를 입력하세요',
+ oidcLoginFailed: 'OIDC 로그인 실패',
+ oidcErrors: {
+ providerError: 'ID 제공자에서 오류가 반환되었습니다',
+ missingParameters: 'OIDC 콜백에 필수 매개변수가 없습니다',
+ invalidState: 'OIDC 상태가 잘못되었거나 이미 사용되었습니다',
+ stateExpired: 'OIDC 로그인 세션이 만료되었습니다 — 다시 시도하세요',
+ providerNotFound: 'OIDC 제공자를 찾을 수 없습니다',
+ discoveryFailed: 'OIDC 검색 문서를 가져오지 못했습니다',
+ invalidDiscovery: 'OIDC 검색 문서가 잘못되었습니다',
+ networkError: 'OIDC 토큰 교환 중 네트워크 오류',
+ badResponse: 'OIDC 토큰 교환 중 예상치 못한 응답',
+ noIdToken: 'OIDC 제공자가 ID 토큰을 반환하지 않았습니다',
+ validationFailed: 'OIDC 토큰 검증 실패',
+ nonceMismatch: 'OIDC 논스 불일치 — 재생 공격 가능성',
+ missingSubClaim: 'OIDC 토큰에 sub 클레임이 없습니다',
+ noLinkedAccount: 'OIDC ID에 연결된 로컬 계정이 없습니다',
+ accountInactive: '계정이 비활성 상태입니다',
+ userResolutionFailed: '계정 확인 실패',
+ internalError: 'OIDC 로그인 중 내부 오류 발생',
+ tokenExchangeFailed: 'OIDC 토큰 교환 실패'
+ },
+ forgotPasswordTitle: '비밀번호 찾기',
+ forgotPasswordMessage: '비밀번호를 잊으셨다면 시스템 관리자에게 초기화를 요청하세요.',
+ forgotPasswordEmailMessage: '이메일 주소를 입력하면 새 비밀번호를 전송해 드립니다.',
+ emailAddress: '이메일 주소',
+ emailPlaceholder: 'your.email@example.com',
+ cancel: '취소',
+ sending: '전송 중...',
+ sendResetEmail: '초기화 이메일 전송',
+ howToReset: '비밀번호 초기화 방법:',
+ resetStep1: 'Bambuddy 관리자에게 문의하세요',
+ resetStep2: '사용자 관리에서 비밀번호 초기화를 요청하세요',
+ resetStep3: '관리자가 임시 비밀번호를 설정해 드립니다',
+ resetStep4: '새 비밀번호로 로그인하고 설정에서 변경하세요',
+ gotIt: '확인',
+ resetPassword: {
+ title: '새 비밀번호 설정',
+ subtitle: '아래에 새 비밀번호를 입력하고 확인하세요.',
+ newPassword: '새 비밀번호',
+ newPasswordPlaceholder: '최소 8자',
+ confirmPassword: '비밀번호 확인',
+ confirmPasswordPlaceholder: '새 비밀번호 반복',
+ saving: '저장 중…',
+ submit: '새 비밀번호 설정',
+ backToLogin: '로그인으로 돌아가기',
+ passwordsDoNotMatch: '비밀번호가 일치하지 않습니다',
+ passwordTooShort: '비밀번호는 최소 8자여야 합니다',
+ resetFailed: '비밀번호 초기화 실패. 링크가 만료되었을 수 있습니다.'
+ },
+ twoFA: {
+ title: '이중 인증',
+ subtitle: '계정이 2FA로 보호되어 있습니다. 아래에 인증 코드를 입력하세요.',
+ methodAuthenticator: '인증 앱',
+ methodEmail: '이메일 코드',
+ methodBackup: '백업 코드',
+ instructionsTotp: '인증 앱을 열고 Bambuddy의 6자리 코드를 입력하세요.',
+ instructionsEmail: '이메일 주소로 6자리 코드가 전송되었습니다. 10분 후 만료됩니다.',
+ instructionsEmailNotSent: '아래 버튼을 클릭하여 이메일로 인증 코드를 받으세요.',
+ instructionsBackup: '8자리 백업 복구 코드 중 하나를 입력하세요. 각 코드는 한 번만 사용할 수 있습니다.',
+ sendCodeButton: '이메일로 코드 전송',
+ sendingCode: '전송 중...',
+ resendCode: '코드 재전송',
+ codeLabel: '인증 코드',
+ backupCodeLabel: '백업 코드',
+ codePlaceholder: '000000',
+ backupCodePlaceholder: 'XXXXXXXX',
+ verifyButton: '확인',
+ verifyingButton: '확인 중...',
+ backToLogin: '← 로그인으로 돌아가기',
+ orContinueWith: '또는 계속',
+ signInWith: '{{provider}}로 로그인',
+ enterCode: '인증 코드를 입력하세요',
+ sendCodeFailed: '인증 코드 전송 실패',
+ invalidCode: '잘못된 코드입니다. 다시 시도하세요.'
+ }
+ },
+ setup: {
+ title: 'Bambuddy 설정',
+ subtitle: 'Bambuddy 인스턴스의 인증을 설정하세요',
+ enableAuth: '인증 활성화',
+ adminAccount: '관리자 계정',
+ adminAccountDesc: '관리자 사용자가 이미 있는 경우 기존 관리자 계정으로 인증이 활성화됩니다. 기존 관리자를 사용하려면 아래 필드를 비워두거나, 새 관리자 사용자를 만들려면 자격 증명을 입력하세요.',
+ adminUsername: '관리자 사용자명',
+ adminPassword: '관리자 비밀번호',
+ optionalIfAdminExists: '(관리자 사용자가 있는 경우 선택사항)',
+ adminUsernamePlaceholder: '관리자 사용자명 입력 (선택사항)',
+ adminPasswordPlaceholder: '관리자 비밀번호 입력 (선택사항)',
+ confirmPassword: '비밀번호 확인',
+ confirmPasswordPlaceholder: '관리자 비밀번호 확인',
+ settingUp: '설정 중...',
+ completeSetup: '설정 완료',
+ toast: {
+ authEnabledAdminCreated: '인증 활성화 및 관리자 사용자 생성됨',
+ authEnabledExistingAdmins: '기존 관리자 사용자로 인증 활성화됨',
+ setupCompleted: '설정이 완료되었습니다',
+ enterBothCredentials: '관리자 사용자명과 비밀번호를 모두 입력하거나, 기존 관리자 사용자를 사용하려면 둘 다 비워두세요',
+ passwordsDoNotMatch: '비밀번호가 일치하지 않습니다',
+ passwordTooShort: '비밀번호는 최소 6자여야 합니다'
+ }
+ },
+ changePassword: {
+ title: '비밀번호 변경',
+ currentPassword: '현재 비밀번호',
+ currentPasswordPlaceholder: '현재 비밀번호 입력',
+ newPassword: '새 비밀번호',
+ newPasswordPlaceholder: '새 비밀번호 입력 (최소 6자)',
+ confirmPassword: '새 비밀번호 확인',
+ confirmPasswordPlaceholder: '새 비밀번호 확인',
+ passwordsDoNotMatch: '비밀번호가 일치하지 않습니다',
+ passwordTooShort: '비밀번호는 최소 6자여야 합니다',
+ changing: '변경 중...',
+ success: '비밀번호가 성공적으로 변경되었습니다',
+ failed: '비밀번호 변경 실패'
+ },
+ plateAlert: {
+ title: '인쇄 일시정지됨!',
+ message: '빌드 플레이트에 객체가 감지되었습니다. 인쇄가 자동으로 일시정지되었습니다. 플레이트를 비우고 인쇄를 재개하세요.',
+ understand: '확인했습니다'
+ },
+ camera: {
+ title: '카메라 보기',
+ invalidPrinterId: '유효하지 않은 프린터 ID',
+ live: '실시간',
+ snapshot: '스냅샷',
+ restartStream: '스트림 재시작',
+ refreshSnapshot: '스냅샷 새로고침',
+ fullscreen: '전체 화면',
+ exitFullscreen: '전체 화면 종료',
+ connectingToCamera: '카메라에 연결 중...',
+ capturingSnapshot: '스냅샷 캡처 중...',
+ connectionLost: '연결 끊김',
+ connectionFailed: '카메라 연결 실패',
+ reconnecting: '{{countdown}}초 후 재연결 중... (시도 {{attempt}}/{{max}})',
+ reconnectNow: '지금 재연결',
+ cameraUnavailable: '카메라를 사용할 수 없음',
+ cameraUnavailableDesc: '프린터가 켜져 있고 연결되어 있는지 확인하세요.',
+ noCamera: '사용 가능한 카메라 없음',
+ retry: '다시 시도',
+ cameraStream: '카메라 스트림',
+ zoomOut: '축소',
+ zoomIn: '확대',
+ resetZoom: '배율 초기화',
+ recording: '녹화 중',
+ startRecording: '녹화 시작',
+ stopRecording: '녹화 중지',
+ chamberLight: '챔버 조명 전환',
+ unavailable: '카메라 사용 불가',
+ diagnose: {
+ button: '진단',
+ modalTitle: '카메라 진단',
+ running: '진단 실행 중...',
+ runFailed: '진단 실행 실패: {{error}}',
+ retry: '다시 실행',
+ stage: {
+ tcp_reachable: '네트워크 연결 가능 여부',
+ first_frame: '프레임 캡처',
+ live_stream_active: '라이브 스트림 활성'
+ },
+ summary: {
+ all_ok: '카메라가 정상 작동 중입니다. 모든 단계를 성공적으로 완료했습니다.',
+ live_stream_active_healthy: '카메라가 최근 프레임으로 스트리밍 중입니다 — 테스트가 필요 없습니다.',
+ printer_unreachable: '프린터에 연결할 수 없습니다. IP 주소, 네트워크 연결, 프린터 전원을 확인하세요.',
+ camera_port_closed: '프린터에 연결됐지만 카메라 포트가 닫혀 있습니다. 프린터 설정에서 LAN 전용 모드와 개발자 모드가 활성화되어 있는지 확인하세요.',
+ no_frame: '카메라에 연결됐지만 프레임이 수신되지 않았습니다. 다시 시도하거나 프린터 설정에서 카메라가 활성화되어 있는지 확인하세요.',
+ unknown_failure: '알 수 없는 이유로 카메라 진단에 실패했습니다. 지원 로그를 확인하세요.'
+ },
+ meta: {
+ protocol: '프로토콜',
+ port: '포트',
+ profile: '프로파일'
+ }
+ }
+ },
+ groups: {
+ title: '그룹 관리',
+ subtitle: '접근 제어를 위한 권한 그룹 관리',
+ backToSettings: '설정으로 돌아가기',
+ createGroup: '그룹 생성',
+ noPermission: '이 페이지에 접근할 권한이 없습니다.',
+ system: '시스템',
+ noDescription: '설명 없음',
+ usersCount: '{{count}}명의 사용자',
+ permissionsCount: '{{count}}개의 권한',
+ edit: '편집',
+ delete: '삭제',
+ toast: {
+ created: '그룹이 성공적으로 생성되었습니다',
+ updated: '그룹이 성공적으로 업데이트되었습니다',
+ deleted: '그룹이 성공적으로 삭제되었습니다',
+ enterGroupName: '그룹 이름을 입력해 주세요'
+ },
+ modal: {
+ editGroup: '그룹 편집',
+ createGroup: '그룹 생성',
+ cancel: '취소',
+ saving: '저장 중...',
+ creating: '생성 중...',
+ saveChanges: '변경 사항 저장'
+ },
+ form: {
+ groupName: '그룹 이름',
+ groupNamePlaceholder: '그룹 이름 입력',
+ systemGroupWarning: '시스템 그룹 이름은 변경할 수 없습니다',
+ description: '설명',
+ descriptionPlaceholder: '설명 입력 (선택사항)',
+ permissions: '권한 ({{count}}개 선택됨)'
+ },
+ deleteModal: {
+ title: '그룹 삭제',
+ message: '이 그룹을 삭제하시겠습니까? 이 그룹의 사용자는 해당 권한을 잃게 됩니다.',
+ confirm: '그룹 삭제'
+ },
+ editor: {
+ title: '그룹 편집',
+ createTitle: '그룹 생성',
+ search: '권한 검색...',
+ selectAll: '모두 선택',
+ clearAll: '모두 해제',
+ permissionsSelected: '{{count}}개 선택됨',
+ noResults: '검색과 일치하는 권한이 없습니다'
+ }
+ },
+ users: {
+ title: '사용자 관리',
+ subtitle: 'Bambuddy 인스턴스에 대한 사용자 및 접근 권한 관리',
+ backToSettings: '설정으로 돌아가기',
+ createUser: '사용자 생성',
+ noPermission: '이 페이지에 접근할 권한이 없습니다.',
+ admin: '관리자',
+ noGroups: '그룹 없음',
+ active: '활성',
+ inactive: '비활성',
+ edit: '편집',
+ delete: '삭제',
+ system: '시스템',
+ noGroupsAvailable: '사용 가능한 그룹 없음',
+ table: {
+ username: '사용자 이름',
+ groups: '그룹',
+ status: '상태',
+ actions: '작업'
+ },
+ toast: {
+ created: '사용자가 성공적으로 생성되었습니다',
+ updated: '사용자가 성공적으로 업데이트되었습니다',
+ deleted: '사용자가 성공적으로 삭제되었습니다',
+ fillRequired: '모든 필수 항목을 입력해 주세요',
+ passwordsDoNotMatch: '비밀번호가 일치하지 않습니다',
+ passwordTooShort: '비밀번호는 최소 6자 이상이어야 합니다',
+ ldapProvisioned: 'LDAP 사용자 \"{{username}}\"이(가) 생성되었습니다'
+ },
+ modal: {
+ createUser: '사용자 생성',
+ editUser: '사용자 편집',
+ cancel: '취소',
+ creating: '생성 중...',
+ saving: '저장 중...',
+ saveChanges: '변경 사항 저장',
+ advancedAuthSubtitle: '고급 인증 사용',
+ tabsAriaLabel: '사용자 소스',
+ localTab: '로컬',
+ ldapTab: 'LDAP',
+ ldapSearchLabel: '디렉터리 검색',
+ ldapSearchPlaceholder: '사용자명, 이름, 이메일을 입력하세요...',
+ ldapMinChars: '검색하려면 최소 2자 이상 입력하세요',
+ ldapTypeToSearch: 'LDAP 디렉터리를 검색하려면 입력을 시작하세요',
+ ldapSearching: '디렉터리 검색 중...',
+ ldapNoResults: '디렉터리에서 일치하는 사용자가 없습니다',
+ ldapSearchError: '디렉터리 검색에 실패했습니다. LDAP 서버 상태를 확인하세요.',
+ ldapAlreadyProvisioned: '이미 생성됨',
+ ldapSelectedLabel: '선택됨',
+ ldapProvision: '사용자 생성',
+ ldapProvisioning: '생성 중...',
+ ldapErrorProvision: '생성에 실패했습니다. LDAP 서버 상태를 확인하고 다시 시도하세요.'
+ },
+ form: {
+ username: '사용자 이름',
+ usernamePlaceholder: '사용자 이름 입력',
+ email: '이메일',
+ emailPlaceholder: 'user@example.com',
+ password: '비밀번호',
+ passwordPlaceholder: '비밀번호 입력',
+ confirmPassword: '비밀번호 확인',
+ confirmPasswordPlaceholder: '비밀번호 확인',
+ newPasswordPlaceholder: '새 비밀번호 입력',
+ confirmNewPasswordPlaceholder: '새 비밀번호 확인',
+ leaveBlankToKeep: '현재 비밀번호 유지 시 비워두기',
+ groups: '그룹',
+ optional: '선택사항',
+ autoGeneratedPassword: '안전한 비밀번호가 자동으로 생성되어 사용자에게 이메일로 전송됩니다.',
+ passwordManagedByAdvancedAuth: '비밀번호는 고급 인증에 의해 관리됩니다. \"비밀번호 재설정\"을 사용하여 이메일로 새 비밀번호를 전송하세요.',
+ resetPassword: '비밀번호 재설정',
+ resettingPassword: '비밀번호 재설정 중...'
+ },
+ deleteModal: {
+ title: '사용자 삭제',
+ message: '이 사용자를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ confirm: '사용자 삭제'
+ }
+ },
+ streamOverlay: {
+ title: '스트림 오버레이',
+ invalidPrinterId: '유효하지 않은 프린터 ID',
+ cameraStream: '카메라 스트림',
+ progress: '진행률',
+ eta: '예상 완료',
+ printerIdle: '프린터 대기 중',
+ printerOffline: '프린터 오프라인',
+ status: {
+ printing: '인쇄 중',
+ paused: '일시 중지됨',
+ finished: '완료됨',
+ failed: '실패',
+ idle: '대기 중',
+ unknown: '알 수 없음'
+ }
+ },
+ profiles: {
+ title: '프로필',
+ subtitle: '슬라이서 프리셋 및 압력 전진 보정 관리',
+ tabs: {
+ cloud: '클라우드 프로필',
+ local: '로컬 프로필',
+ kprofiles: 'K-프로필'
+ },
+ localProfiles: {
+ title: '로컬 프로필',
+ subtitle: 'OrcaSlicer에서 슬라이서 프리셋 가져오기 및 관리',
+ import: '프로필 가져오기',
+ importDesc: '.bbscfg, .bbsflmt, .orca_filament, .zip 또는 .json 파일을 여기에 드롭하세요',
+ importing: '가져오는 중...',
+ search: '로컬 프리셋 검색...',
+ noPresets: '로컬 프리셋 없음',
+ badge: '로컬',
+ edit: '편집',
+ delete: '삭제',
+ cancel: '취소',
+ deleteConfirmTitle: '프리셋 삭제',
+ deleteConfirm: '이 프리셋을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ source: '출처',
+ inheritsFrom: '상속',
+ filamentType: '유형',
+ vendor: '제조사',
+ compatiblePrinters: '프린터',
+ nozzleTemp: '노즐 온도',
+ cost: '비용',
+ density: '밀도',
+ pressureAdvance: '압력 전진',
+ filament: '필라멘트',
+ process: '프로세스',
+ printer: '프린터',
+ toast: {
+ importSuccess: '{{count}}개 프리셋 가져옴',
+ importSkipped: '{{count}}개 프리셋 건너뜀 (중복)',
+ importError: '가져오기 중 {{count}}개 오류 발생',
+ deleted: '프리셋 삭제됨',
+ updated: '프리셋 업데이트됨'
+ },
+ noSearchResults: '검색어와 일치하는 프리셋이 없습니다'
+ },
+ connectedAs: '연결된 계정',
+ logout: '로그아웃',
+ noLogoutPermission: '로그아웃 권한이 없습니다',
+ failedToLoad: '프로필 불러오기 실패',
+ retry: '다시 시도',
+ time: {
+ justNow: '방금',
+ minsAgo: '{{count}}분 전',
+ hoursAgo: '{{count}}시간 전',
+ daysAgo: '{{count}}일 전'
+ },
+ toast: {
+ loggedOut: '로그아웃되었습니다'
+ },
+ login: {
+ title: 'Bambu 클라우드 연결',
+ subtitle: '기기 간 슬라이서 프리셋 동기화',
+ email: '이메일',
+ password: '비밀번호',
+ region: '지역',
+ regionGlobal: '글로벌',
+ regionChina: '중국',
+ verificationCode: '인증 코드',
+ totpCode: '인증앱 코드',
+ checkEmail: '이메일({{email}})로 전송된 6자리 코드를 확인하세요',
+ enterTotpHint: '인증앱에서 6자리 코드를 입력하세요',
+ accessToken: '액세스 토큰',
+ accessTokenHint: 'Bambu Studio에서 Bambu Lab 액세스 토큰을 붙여넣으세요',
+ back: '뒤로',
+ loginButton: '로그인',
+ verifyButton: '인증',
+ setTokenButton: '토큰 설정',
+ useToken: '액세스 토큰 대신 사용',
+ useEmail: '이메일로 로그인',
+ toast: {
+ loggedIn: '성공적으로 로그인되었습니다',
+ codeSent: '이메일로 인증 코드가 전송되었습니다',
+ enterTotp: '인증앱에서 코드를 입력하세요',
+ tokenSet: '토큰이 성공적으로 설정되었습니다'
+ }
+ },
+ presets: {
+ myPreset: '내 프리셋 (편집 가능)',
+ duplicate: '복제',
+ editable: '편집 가능',
+ failedToLoadDetails: '프리셋 세부 정보 불러오기 실패',
+ deleteConfirm: '이 프리셋을 삭제하시겠습니까?',
+ deleteWarning: 'Bambu 클라우드에서 \"{{name}}\"을(를) 영구적으로 삭제합니다. 이 작업은 취소할 수 없습니다.',
+ noDuplicatePermission: '프리셋 복제 권한이 없습니다',
+ noEditPermission: '프리셋 편집 권한이 없습니다',
+ noDeletePermission: '프리셋 삭제 권한이 없습니다',
+ types: {
+ filament: '필라멘트 프리셋',
+ printer: '프린터 프리셋',
+ process: '프로세스 프리셋'
+ },
+ toast: {
+ deleted: '프리셋 삭제됨',
+ created: '프리셋 생성됨',
+ updated: '프리셋 업데이트됨',
+ duplicated: '프리셋 복제됨',
+ fieldAdded: '\"{{key}}\" 필드 추가됨',
+ exported: '프리셋 내보냄'
+ },
+ baseLabel: '기본: {{name}}',
+ currentLabel: '현재: {{name}}',
+ newPreset: '새 프리셋',
+ editPreset: '프리셋 편집',
+ duplicatePreset: '프리셋 복제',
+ createNewPreset: '새 프리셋 생성',
+ customizeSettings: '새 프리셋의 설정 사용자 지정',
+ compareWithBase: '기본 프리셋과 비교',
+ compare: '비교',
+ basePreset: '기본 프리셋',
+ selectBasePreset: '기본 프리셋 선택...',
+ presetName: '프리셋 이름',
+ myCustomPreset: '내 사용자 지정 프리셋',
+ inheritsFrom: '상속 출처',
+ dropJsonToImport: 'JSON 파일을 드롭하여 가져오기',
+ tabs: {
+ common: '공통',
+ allFields: '모든 필드'
+ },
+ availableFields: '사용 가능한 필드',
+ searchFieldsPlaceholder: '필드 검색...',
+ noMatchingFields: '일치하는 필드 없음',
+ allFieldsAdded: '모든 필드 추가됨',
+ addCustomField: '사용자 지정 필드 추가',
+ yourOverrides: '내 재정의',
+ noOverridesYet: '아직 재정의 없음',
+ clickFieldsToAdd: '왼쪽 필드를 클릭하여 추가',
+ saveAsTemplate: '템플릿으로 저장',
+ jsonTip: '팁: 이 모달 어디서나 .json 파일을 드래그 앤 드롭하여 설정을 가져올 수 있습니다'
+ },
+ cloudView: {
+ searchPlaceholder: '프리셋 검색...',
+ templates: '템플릿',
+ refresh: '새로고침',
+ newPreset: '새 프리셋',
+ clearFilters: '필터 초기화',
+ compareMode: '비교 모드',
+ selectAnotherPreset: '다른 {{type}} 프리셋 선택',
+ clickTwoPresets: '같은 유형의 프리셋 두 개를 클릭하여 비교',
+ selectFirst: '1. 첫 번째 선택',
+ selectSecond: '2. 두 번째 선택',
+ compareNow: '지금 비교',
+ lastSynced: '마지막 동기화:',
+ showingCount: '{{total}}개 중 {{showing}}개 표시',
+ noPresetsFound: '프리셋을 찾을 수 없음',
+ columns: {
+ filament: '필라멘트',
+ process: '프로세스',
+ printer: '프린터'
+ },
+ noFilamentPresets: '필라멘트 프리셋 없음',
+ noProcessPresets: '프로세스 프리셋 없음',
+ noPrinterPresets: '프린터 프리셋 없음',
+ filters: {
+ type: '유형',
+ owner: '소유자',
+ printer: '프린터',
+ nozzle: '노즐',
+ filament: '필라멘트',
+ layer: '레이어',
+ all: '전체',
+ myPresets: '내 프리셋',
+ builtIn: '기본 제공',
+ process: '프로세스'
+ },
+ noTemplatesPermission: '템플릿 관리 권한이 없습니다',
+ noRefreshPermission: '프로필 새로고침 권한이 없습니다',
+ noCreatePermission: '프리셋 생성 권한이 없습니다'
+ },
+ templates: {
+ title: '빠른 템플릿',
+ noTemplates: '아직 템플릿 없음',
+ createFirst: '프리셋 편집기에서 템플릿을 생성하세요',
+ typeFilter: '유형:',
+ deleteTitle: '템플릿 삭제',
+ deleteWarning: '이 작업은 취소할 수 없습니다',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까?',
+ namePlaceholder: '템플릿 이름',
+ descriptionPlaceholder: '설명',
+ settingsJson: '설정 (JSON)',
+ fieldsCount: '{{count}}개 필드',
+ shownInModals: '모달에 표시됨',
+ hiddenInModals: '모달에서 숨겨짐',
+ apply: '적용',
+ toast: {
+ deleted: '템플릿 삭제됨',
+ updated: '템플릿 업데이트됨',
+ created: '템플릿 생성됨',
+ applied: '템플릿 적용됨'
+ }
+ }
+ },
+ support: {
+ debugLoggingActive: '디버그 로깅이 활성화되어 있습니다',
+ manageLogs: '관리',
+ collectItem7: '프린터 연결 및 펌웨어 버전',
+ collectItem8: '통합 상태 (Spoolman, MQTT, HA)',
+ collectItem9: '네트워크 인터페이스 (서브넷만)',
+ collectItem10: 'Python 패키지 버전',
+ collectItem11: '데이터베이스 상태 확인',
+ collectItem12: 'Docker 환경 세부 정보',
+ bundleGenerating: '번들 생성 중...',
+ bundleStepConnection: '프린터 연결 확인 실행 중',
+ bundleStepVirtualPrinters: '가상 프린터 설정 확인 실행 중',
+ bundleStepLogScan: '알려진 문제가 있는지 최근 로그 스캔 중',
+ bundleStepBuild: '지원 번들 ZIP 빌드 중'
+ },
+ fileManager: {
+ title: '파일 관리자',
+ subtitle: '인쇄 파일 정리 및 관리',
+ uploadFiles: '파일 업로드',
+ newFolder: '새 폴더',
+ folderName: '폴더 이름',
+ folderNamePlaceholder: '예: 기능성 부품',
+ renameFile: '파일 이름 바꾸기',
+ renameFolder: '폴더 이름 바꾸기',
+ invalidFilenameChar: '\"{{char}}\" 문자는 인쇄 파일 이름에 허용되지 않습니다. 프린터 SD 카드가 거부하는 문자: < > : \" / \\ | ? *',
+ moveFiles: '{{count}}개 파일 이동',
+ rootNoFolder: '루트 (폴더 없음)',
+ current: '현재',
+ linkFolder: '폴더 연결',
+ linkFolderDescription: '\"{{name}}\"을(를) 프로젝트 또는 아카이브에 연결하여 빠른 접근.',
+ project: '프로젝트',
+ archive: '아카이브',
+ noProjectsFound: '프로젝트를 찾을 수 없음',
+ noArchivesFound: '아카이브를 찾을 수 없음',
+ unlink: '연결 해제',
+ link: '연결',
+ dragDropFiles: '파일을 여기에 드래그 앤 드롭',
+ dropFilesHere: '파일을 여기에 드롭',
+ orClickToBrowse: '또는 클릭하여 탐색',
+ allFileTypesSupported: '모든 파일 형식 지원. ZIP 파일은 압축 해제됩니다.',
+ zipFilesDetected: 'ZIP 파일 감지됨',
+ zipExtractOptions: 'ZIP 파일이 압축 해제됩니다. 폴더 구조 처리 방법을 선택하세요:',
+ preserveZipStructure: 'ZIP에서 폴더 구조 유지',
+ createFolderFromZip: 'ZIP 파일 이름으로 폴더 생성',
+ stlThumbnailGeneration: 'STL 썸네일 생성',
+ zipMayContainStl: 'ZIP 파일에 STL 파일이 포함될 수 있습니다. 압축 해제 중 썸네일을 생성할 수 있습니다.',
+ thumbnailsCanBeGenerated: 'STL 파일의 썸네일을 생성할 수 있습니다. 대형 모델은 처리 시간이 더 걸릴 수 있습니다.',
+ generateThumbnailsForStl: 'STL 파일의 썸네일 생성',
+ threemfDetected: '3MF 파일 감지됨',
+ threemfExtractionInfo: '프린터 모델, 재료, 색상 및 인쇄 설정이 3MF 파일에서 자동으로 추출됩니다.',
+ willBeExtracted: '추출 예정',
+ filesExtracted: '{{count}}개 파일 추출됨',
+ uploadComplete: '업로드 완료: {{succeeded}}개 성공',
+ uploadFailed: '업로드 실패',
+ zipFilesFailed: '{{count}}개 파일 실패',
+ uploading: '업로드 중...',
+ changeLink: '링크 변경...',
+ linkTo: '연결 대상...',
+ linkToProjectOrArchive: '프로젝트 또는 아카이브에 연결',
+ addToQueue: '대기열에 추가',
+ schedulePrint: '예약',
+ generateThumbnail: '썸네일 생성',
+ generateThumbnails: '썸네일 생성',
+ generateThumbnailsForMissing: '썸네일이 없는 STL 파일의 썸네일 생성',
+ gridView: '격자 보기',
+ listView: '목록 보기',
+ lowDiskSpaceWarning: '디스크 공간 부족 경고',
+ lowDiskSpaceDetails: '전체 {{total}} 중 {{free}}만 남음. 임계값은 설정에서 {{threshold}}GB로 설정됩니다.',
+ files: '파일',
+ folders: '폴더',
+ size: '크기',
+ free: '여유',
+ allFiles: '모든 파일',
+ wrap: '줄 바꿈',
+ enableTextWrapping: '텍스트 줄 바꿈 활성화',
+ disableTextWrapping: '텍스트 줄 바꿈 비활성화',
+ collapse: '접기',
+ collapseFoldersByDefault: '기본적으로 폴더 접기',
+ expandFoldersByDefault: '기본적으로 폴더 펼치기',
+ dragToResizeTooltip: '드래그하여 크기 조정, 더블클릭하여 초기화',
+ searchFiles: '파일 검색...',
+ allTypes: '모든 유형',
+ prints: '인쇄물',
+ ascending: '오름차순',
+ descending: '내림차순',
+ resultsCount: '전체 {{total}}개 중 {{showing}}개',
+ selectAll: '모두 선택',
+ deselectAll: '모두 선택 해제',
+ selected: '{{count}}개 선택됨',
+ adding: '추가 중...',
+ loadingFiles: '파일 불러오는 중...',
+ folderIsEmpty: '폴더가 비어 있음',
+ noFilesYet: '파일 없음',
+ folderEmptyDescription: '파일을 업로드하거나 이 폴더로 이동하여 시작하세요.',
+ noFilesDescription: '파일을 업로드하여 인쇄 관련 파일을 정리하세요.',
+ noMatchingFiles: '일치하는 파일 없음',
+ noMatchingFilesDescription: '현재 검색 또는 필터 조건과 일치하는 파일이 없습니다.',
+ clearFilters: '필터 초기화',
+ printedCount: '{{count}}회 인쇄됨',
+ uploadedBy: '업로드한 사람',
+ deleteFolder: '폴더 삭제',
+ deleteFile: '파일 삭제',
+ deleteFilesCount: '{{count}}개 파일 삭제',
+ deleteFolderConfirm: '이 폴더를 삭제하시겠습니까? 안의 모든 파일도 삭제됩니다.',
+ deleteFileConfirm: '이 파일을 삭제하시겠습니까?',
+ deleteFilesConfirm: '선택한 {{count}}개 파일을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ deleting: '삭제 중...',
+ noPermissionRenameFolder: '폴더 이름 변경 권한이 없습니다',
+ noPermissionLinkFolder: '폴더 연결 권한이 없습니다',
+ noPermissionDeleteFolder: '폴더 삭제 권한이 없습니다',
+ noPermissionPrint: '인쇄 권한이 없습니다',
+ noPermissionAddToQueue: '대기열 추가 권한이 없습니다',
+ noPermissionSlice: '파일 슬라이싱 권한이 없습니다',
+ noPermissionDownload: '파일 다운로드 권한이 없습니다',
+ noPermissionRenameFile: '파일 이름 변경 권한이 없습니다',
+ noPermissionGenerateThumbnail: '썸네일 생성 권한이 없습니다',
+ noPermissionDeleteFile: '파일 삭제 권한이 없습니다',
+ noPermissionCreateFolder: '폴더 생성 권한이 없습니다',
+ noPermissionUpload: '파일 업로드 권한이 없습니다',
+ noPermissionMoveFiles: '파일 이동 권한이 없습니다',
+ noPermissionDeleteFiles: '파일 삭제 권한이 없습니다',
+ linkExternal: '외부 연결',
+ linkExternalFolder: '외부 폴더 연결',
+ linkExternalFolderDescription: '호스트 디렉토리(NAS, USB, 네트워크 공유)를 파일 관리자에 마운트합니다. 파일은 복사되지 않고 원래 경로에서 직접 접근합니다.',
+ externalFolderNamePlaceholder: '예: NAS 인쇄물',
+ externalPath: '호스트 경로',
+ externalPathHelp: 'Docker 호스트의 디렉토리 절대 경로. 컨테이너에 바인드 마운트되어야 합니다.',
+ readOnly: '읽기 전용',
+ readOnlyHelp: '업로드 및 삭제 방지',
+ showHiddenFiles: '숨김 파일 표시 (dotfiles)',
+ externalFolder: '외부 폴더',
+ scanFolder: '스캔',
+ toast: {
+ folderCreated: '폴더 생성됨',
+ folderDeleted: '폴더 삭제됨',
+ fileDeleted: '파일 삭제됨',
+ filesDeleted: '{{count}}개 파일 삭제됨',
+ filesMoved: '파일 이동됨',
+ folderLinked: '폴더 연결됨',
+ folderUnlinked: '폴더 연결 해제됨',
+ externalFolderLinked: '외부 폴더 연결 및 스캔됨',
+ folderScanned: '스캔 완료: {{added}}개 추가, {{removed}}개 제거',
+ addedToQueue: '{{count}}개 파일을 대기열에 추가함',
+ addedToQueuePartial: '{{added}}개 추가됨, {{failed}}개 실패',
+ failedToAddToQueue: '파일 추가 실패: {{error}}',
+ fileRenamed: '파일 이름 변경됨',
+ folderRenamed: '폴더 이름 변경됨',
+ thumbnailsGenerated: '{{count}}개 썸네일 생성됨',
+ thumbnailsGeneratedPartial: '{{succeeded}}개 썸네일 생성됨, {{failed}}개 실패',
+ noStlMissingThumbnails: '썸네일이 없는 STL 파일 없음',
+ failedToGenerateThumbnails: '썸네일 생성 실패: {{error}}',
+ thumbnailGenerated: '썸네일 생성됨',
+ failedToGenerateThumbnail: '썸네일 생성 실패: {{error}}'
+ }
+ },
+ projects: {
+ title: '프로젝트',
+ subtitle: '3D 인쇄 프로젝트 정리 및 추적',
+ newProject: '새 프로젝트',
+ editProject: '프로젝트 편집',
+ deleteProject: '프로젝트 삭제',
+ projectName: '프로젝트 이름',
+ description: '설명',
+ noProjects: '프로젝트 없음',
+ noProjectsFiltered: '{{status}} 프로젝트 없음',
+ noProjectsFilteredHelp: '{{status}} 프로젝트가 없습니다. 상태가 변경되면 여기에 표시됩니다.',
+ createFirst: '첫 번째 프로젝트를 만들어 관련 인쇄물을 정리하고 진행 상황을 추적하며 빌드를 관리하세요.',
+ createFirstButton: '첫 번째 프로젝트 만들기',
+ create: '만들기',
+ files: '파일',
+ prints: '인쇄물',
+ plates: '플레이트',
+ parts: '부품',
+ lastModified: '마지막 수정',
+ deleteConfirm: '이 프로젝트를 삭제하시겠습니까? 아카이브 및 대기열 항목은 연결 해제되지만 삭제되지는 않습니다.',
+ addFiles: '파일 추가',
+ removeFile: '파일 제거',
+ viewDetails: '세부 정보 보기',
+ namePlaceholder: '예: Voron 2.4 빌드',
+ descriptionPlaceholder: '선택적 설명...',
+ urlLabel: 'URL',
+ urlPlaceholder: 'https://makerworld.com/...',
+ urlInvalid: 'URL은 http:// 또는 https://로 시작해야 합니다',
+ openExternalUrl: '프로젝트 URL 열기',
+ coverImageLabel: '커버 사진',
+ coverImageAlt: '프로젝트 커버 사진',
+ coverImageUpload: '업로드',
+ coverImageReplace: '교체',
+ coverImageRemove: '제거',
+ color: '색상',
+ targetPlates: '목표 플레이트',
+ targetPlatesPlaceholder: '예: 25',
+ targetPlatesHelp: '인쇄 작업 수',
+ targetParts: '목표 부품',
+ targetPartsPlaceholder: '예: 150',
+ targetPartsHelp: '필요한 총 개체 수',
+ tagsLabel: '태그 (쉼표로 구분)',
+ tagsPlaceholder: '예: voron, 기능성, 선물',
+ dueDate: '마감일',
+ priority: '우선순위',
+ priorityLow: '낮음',
+ priorityNormal: '보통',
+ priorityHigh: '높음',
+ priorityUrgent: '긴급',
+ statusActive: '활성',
+ statusCompleted: '완료됨',
+ statusArchived: '보관됨',
+ done: '완료',
+ completed: '완료됨',
+ failed: '실패',
+ inQueue: '대기 중',
+ noPrintsYet: '인쇄물 없음',
+ printJobs: '인쇄 작업 (플레이트)',
+ partsPrinted: '인쇄된 부품',
+ failedParts: '실패한 부품',
+ import: '가져오기',
+ export: '내보내기',
+ importProject: '프로젝트 가져오기',
+ exportAll: '모든 프로젝트 내보내기',
+ loading: '프로젝트 불러오는 중...',
+ noEditPermission: '프로젝트 편집 권한이 없습니다',
+ noDeletePermission: '프로젝트 삭제 권한이 없습니다',
+ noCreatePermission: '프로젝트 생성 권한이 없습니다',
+ noImportPermission: '프로젝트 가져오기 권한이 없습니다',
+ noExportPermission: '프로젝트 내보내기 권한이 없습니다',
+ toast: {
+ created: '프로젝트 생성됨',
+ updated: '프로젝트 업데이트됨',
+ deleted: '프로젝트 삭제됨',
+ imported: '프로젝트 가져옴',
+ multipleImported: '{{count}}개 프로젝트 가져옴',
+ importFailed: '가져오기 실패',
+ exported: '프로젝트 내보냄 (메타데이터만)'
+ }
+ },
+ projectDetail: {
+ notFound: '프로젝트를 찾을 수 없음',
+ backToProjects: '프로젝트로 돌아가기',
+ export: '내보내기',
+ exportProject: '프로젝트 내보내기',
+ noExportPermission: '프로젝트 내보내기 권한이 없습니다',
+ noEditPermission: '프로젝트 편집 권한이 없습니다',
+ partOf: '속한 프로젝트:',
+ priorityLabel: '우선순위:',
+ noPrints: '이 프로젝트에 아직 인쇄물이 없습니다',
+ status: {
+ active: '활성',
+ completed: '완료됨',
+ archived: '보관됨'
+ },
+ priority: {
+ low: '낮음',
+ normal: '보통',
+ high: '높음',
+ urgent: '긴급'
+ },
+ dueDate: {
+ overdue: '기한 초과',
+ today: '오늘 마감',
+ daysLeft: '{{count}}일 남음'
+ },
+ progress: {
+ platesProgress: '플레이트 진행률',
+ partsProgress: '부품 진행률',
+ printJobs: '인쇄 작업',
+ parts: '부품',
+ percentComplete: '{{percent}}% 완료',
+ remaining: '{{count}}개 남음'
+ },
+ stats: {
+ printJobs: '인쇄 작업',
+ total: '합계',
+ failed: '{{count}}개 실패',
+ partsPrinted: '{{count}}개 부품 인쇄됨',
+ printTime: '인쇄 시간',
+ filamentUsed: '사용된 필라멘트'
+ },
+ cost: {
+ title: '비용 추적',
+ filamentCost: '필라멘트 비용',
+ energy: '에너지',
+ totalCost: '총 비용',
+ total: '합계',
+ includesBom: 'BOM 포함',
+ budget: '예산',
+ remaining: '남은 예산'
+ },
+ subProjects: {
+ title: '하위 프로젝트 ({{count}})'
+ },
+ notes: {
+ title: '메모',
+ noEditPermission: '메모 편집 권한이 없습니다',
+ placeholder: '이 프로젝트에 대한 메모 추가...',
+ empty: '아직 메모가 없습니다. 편집을 클릭하여 메모를 추가하세요.'
+ },
+ files: {
+ title: '파일',
+ linkFolders: '파일 관리자에서 폴더 연결',
+ forQuickAccess: '빠른 접근을 위해 이 프로젝트에 연결합니다.',
+ fileCount: '{{count}}개 파일',
+ empty: '연결된 폴더가 없습니다. 파일 관리자로 이동하여 폴더를 이 프로젝트에 연결하세요.',
+ noFiles: '이 폴더에 파일이 없습니다.',
+ print: '지금 인쇄',
+ addToQueue: '대기열에 추가'
+ },
+ bom: {
+ title: '부품 목록',
+ acquired: '{{total}}개 중 {{completed}}개 확보',
+ showAll: '전체 표시',
+ hideDone: '완료된 것 숨기기',
+ addPart: '부품 추가',
+ noAddPermission: '부품 추가 권한이 없습니다',
+ partNamePlaceholder: '부품 이름 (예: M3x8 나사)',
+ partName: '부품 이름',
+ qty: '수량',
+ price: '가격 ({{currency}})',
+ sourcingUrlPlaceholder: '구매 URL (선택사항)',
+ remarksPlaceholder: '비고 (선택사항)',
+ deletePart: '부품 삭제',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까?',
+ noUpdatePermission: '부품 업데이트 권한이 없습니다',
+ noEditPermission: '부품 편집 권한이 없습니다',
+ noDeletePermission: '부품 삭제 권한이 없습니다',
+ totalCost: '총 비용:',
+ empty: '부품 목록에 부품이 없습니다. 하드웨어, 전자 부품 또는 기타 구성품을 추가하여 조달이 필요한 것을 추적하세요.'
+ },
+ timeline: {
+ title: '활동 타임라인',
+ empty: '아직 활동이 없습니다.'
+ },
+ template: {
+ saveAsTemplate: '템플릿으로 저장',
+ noCreatePermission: '템플릿 생성 권한이 없습니다'
+ },
+ queue: {
+ title: '대기열',
+ viewAll: '전체 보기',
+ printing: '{{count}}개 인쇄 중',
+ queued: '{{count}}개 대기 중'
+ },
+ prints: {
+ title: '인쇄물 ({{count}})'
+ },
+ toast: {
+ projectUpdated: '프로젝트 업데이트됨',
+ partAdded: '부품 추가됨',
+ partRemoved: '부품 제거됨',
+ exportFailed: '내보내기 실패',
+ projectExported: '프로젝트 내보냄',
+ templateCreated: '템플릿 생성됨'
+ }
+ },
+ system: {
+ title: '시스템 정보',
+ version: '버전',
+ uptime: '가동 시간',
+ cpuUsage: 'CPU 사용량',
+ memoryUsage: '메모리 사용량',
+ diskUsage: '디스크 사용량',
+ networkInfo: '네트워크 정보',
+ logs: '로그',
+ debugMode: '디버그 모드',
+ enableDebug: '디버그 로깅 활성화',
+ disableDebug: '디버그 로깅 비활성화',
+ downloadLogs: '로그 다운로드',
+ clearLogs: '로그 초기화',
+ dockerInfo: 'Docker 정보',
+ containerName: '컨테이너 이름',
+ imageName: '이미지 이름',
+ platform: '플랫폼',
+ architecture: '아키텍처'
+ },
+ library: {
+ title: '필라멘트 라이브러리',
+ addFilament: '필라멘트 추가',
+ editFilament: '필라멘트 편집',
+ deleteFilament: '필라멘트 삭제',
+ vendor: '제조사',
+ material: '재료',
+ color: '색상',
+ kFactor: 'K 계수',
+ temperature: '온도',
+ noFilaments: '라이브러리에 필라멘트 없음',
+ deleteConfirm: '이 필라멘트를 삭제하시겠습니까?',
+ importFromPrinter: '프린터에서 가져오기',
+ exportToFile: '파일로 내보내기'
+ },
+ slice: {
+ title: '모델 슬라이싱',
+ action: '슬라이싱',
+ slicing: '슬라이싱 중…',
+ printer: '프린터 프로필',
+ process: '프로세스 프로필',
+ filament: '필라멘트 프로필',
+ filamentSlot: '필라멘트 {{index}} ({{type}})',
+ selectPreset: '— 프리셋 선택 —',
+ loadingPresets: '프리셋 불러오는 중…',
+ analyzingPlateFilaments: '플레이트 필라멘트 분석 중…',
+ analyzingPlateFilamentsHint: '이 플레이트가 사용하는 AMS 슬롯을 확인하기 위해 미리보기 슬라이싱을 실행합니다. 캐시 후에는 재오픈이 즉각적입니다.',
+ previewToast: '{{name}} 분석 중 — {{elapsed}}',
+ previewWithProgress: '{{name}} 분석 중 — {{stage}} ({{percent}}%) — {{elapsed}}',
+ notUsedByPlate: '— 이 플레이트에서 사용되지 않음',
+ noPresetsForSlot: '사용 가능한 프리셋 없음',
+ presetsLoadFailed: '프리셋 불러오기 실패. 먼저 설정 → 프로필에서 가져오세요.',
+ refreshPresets: '새로 고침',
+ refreshPresetsTitle: '프리셋 새로 고침 — 최신 클라우드 및 번들 목록 가져오기 (Bambu Studio 또는 Bambu Handy에서 프리셋 삭제 후 사용)',
+ allPresetsRequired: '모든 프리셋을 선택해야 합니다',
+ enqueuing: '슬라이싱 작업 제출 중…',
+ queued: '대기 중…',
+ failed: '슬라이싱 실패. 슬라이서 사이드카 로그를 확인하세요.',
+ startedToast: '백그라운드에서 {{name}} 슬라이싱 중…',
+ queuedToast: '대기 중: {{name}} — {{elapsed}}',
+ runningToast: '{{name}} 슬라이싱 중 — {{elapsed}}',
+ runningWithProgress: '{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}',
+ completedToast: '{{name}} 슬라이싱 완료',
+ failedToast: '{{name}} 슬라이싱 실패: {{detail}}',
+ tier: {
+ local: '가져온 것',
+ cloud: '클라우드',
+ standard: '표준'
+ },
+ cloud: {
+ notAuthenticated: '클라우드 프리셋을 보려면 Bambu 클라우드에 로그인하세요 (설정 → 프로필 → 클라우드).',
+ expired: 'Bambu 클라우드 세션이 만료되었습니다 — 다시 로그인하여 클라우드 프리셋을 새로고침하세요.',
+ unreachable: '현재 Bambu 클라우드에 연결할 수 없습니다. 로컬 및 표준 프리셋은 계속 작동합니다.'
+ },
+ actionAll: '{{count}}개 플레이트 모두 슬라이싱',
+ actionAllTitle: '모든 플레이트를 단일 다중 플레이트 출력으로 슬라이싱합니다 (단일 아카이브). 필라멘트 선택은 프로젝트가 정의하는 모든 슬롯을 포함합니다.',
+ allPlatesToggle: '{{count}}개 플레이트 모두 슬라이싱',
+ otherPrinters: '다른 프린터',
+ bundle: '슬라이서 번들',
+ bundleNone: '— 없음 (개별로 프리셋 선택) —',
+ bundleAllRequired: '번들 프로세스 및 모든 필라멘트 슬롯을 선택해야 합니다',
+ runningWithProgressMultiPlate: '플레이트 {{plateIndex}}/{{plateCount}} • {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}',
+ failedTitle: '슬라이싱 실패',
+ bedType: {
+ label: '빌드 플레이트',
+ auto: '자동 (프로세스 프리셋 사용)',
+ coolPlate: '쿨 플레이트',
+ coolPlateSuperTack: '쿨 플레이트 슈퍼택',
+ engineering: '엔지니어링 플레이트',
+ highTemp: '고온 플레이트',
+ texturedPEI: '텍스처 PEI 플레이트',
+ smoothPEI: '매끄러운 PEI 플레이트'
+ }
+ },
+ spoolman: {
+ title: 'Spoolman 통합',
+ enabled: 'Spoolman 활성화됨',
+ url: 'Spoolman URL',
+ connected: '연결됨',
+ disconnected: '연결되지 않음',
+ testConnection: '연결 테스트',
+ sync: '동기화',
+ syncing: '동기화 중...',
+ lastSync: '마지막 동기화',
+ linkToSpoolman: 'Spoolman에 연결',
+ openInSpoolman: 'Spoolman에서 열기',
+ unlinkSpool: '스풀 연결 해제',
+ unlinkConfirmTitle: '스풀 할당 해제?',
+ unlinkConfirmMessage: '이 슬롯에서 스풀을 제거합니다. 스풀 데이터 자체는 변경되지 않습니다.',
+ selectSpool: '스풀 선택',
+ noUnlinkedSpools: '할당되지 않은 스풀 없음',
+ linkSuccess: '스풀이 성공적으로 할당되었습니다',
+ linkFailed: '스풀 할당 실패',
+ unlinkSuccess: '스풀이 성공적으로 할당 해제되었습니다',
+ unlinkFailed: '스풀 할당 해제 실패',
+ linkedSpool: '할당된 스풀',
+ spoolId: '스풀 ID',
+ fillSourceLabel: '(Spoolman)',
+ weight: '무게',
+ remaining: '남은 양',
+ disableWeightSync: 'AMS 예상 무게 동기화 비활성화',
+ disableWeightSyncDesc: 'AMS 추정치에서 남은 용량을 업데이트하지 않습니다. AMS 백분율 기반 추정 대신 Spoolman의 사용량 추적을 선호하는 경우 사용하세요. 새 스풀은 여전히 AMS 추정치를 초기 무게로 사용합니다.',
+ reportPartialUsage: '실패한 인쇄물에 대한 부분 사용량 보고',
+ reportPartialUsageDesc: '인쇄가 실패하거나 취소될 때 레이어 진행률을 기반으로 해당 시점까지 사용된 예상 필라멘트를 보고합니다.'
+ },
+ inventory: {
+ title: '스풀 재고',
+ spoolmanMixedContentTitle: 'HTTPS에서 Spoolman을 불러올 수 없음 — 브라우저가 혼합 콘텐츠를 차단함',
+ spoolmanMixedContentBody: 'Bambuddy가 HTTPS로 서비스되고 있지만 Spoolman URL은 여전히 HTTP입니다. 브라우저는 보안상 혼합 콘텐츠를 차단하므로 내장된 Spoolman UI가 렌더링되지 않습니다. 이 기능이 작동하려면 Spoolman이 HTTPS로 접근 가능해야 합니다.',
+ spoolmanMixedContentFixReverseProxy: 'Spoolman을 Bambuddy와 같은 리버스 프록시(Traefik / Nginx / Caddy) 뒤에 HTTPS로 배치한 다음 설정에서 Spoolman URL을 새 HTTPS 주소로 업데이트하세요.',
+ spoolmanMixedContentFixOpenNewTab: '임시 방편으로 HTTP로 새 브라우저 탭에서 Spoolman을 여세요 — 혼합 콘텐츠 규칙은 내장 프레임에만 적용되므로 독립 탭은 여전히 작동합니다.',
+ spoolmanOpenInNewTab: '새 탭에서 Spoolman 열기',
+ labels: {
+ title: '스풀 라벨 인쇄',
+ selectedCount: '{{count}}개 선택됨',
+ pickSpools: '라벨을 인쇄할 스풀 선택:',
+ searchPlaceholder: '이름, 브랜드 또는 #ID 검색',
+ filterByMaterial: '재료:',
+ allMaterials: '전체',
+ selectVisible: '보이는 모든 항목 선택 ({{count}})',
+ deselectVisible: '보이는 항목 선택 해제',
+ clearAll: '모두 초기화',
+ noSpoolsToShow: '표시할 스풀이 없습니다. 필터를 조정하고 다시 시도하세요.',
+ noMatches: '현재 검색 또는 필터와 일치하는 스풀이 없습니다.',
+ printOne: '이 스풀의 라벨 인쇄',
+ printLabels: '라벨 인쇄…',
+ bulkTitle: '현재 표시된 {{count}}개에서 라벨을 인쇄할 스풀 선택',
+ noSpoolsTitle: '라벨을 붙일 스풀 없음',
+ error: '라벨을 생성할 수 없습니다: {{msg}}',
+ templates: {
+ box40x30: {
+ label: '박스 라벨 (40 × 30 mm)',
+ hint: '페이지당 단일 라벨; 일반 DK/Brother 롤 크기, 필라멘트 가방 및 보관함 라벨에 적합.'
+ },
+ box: {
+ label: '박스 라벨 (62 × 29 mm)',
+ hint: '페이지당 단일 라벨; Brother PT/QL 및 Dymo 소형 라벨에 맞는 크기.'
+ },
+ averyL7160: {
+ label: 'Avery L7160 — A4 시트 (38.1 × 63.5 mm × 21)',
+ hint: 'EU 시트; A4 페이지당 21개 라벨.'
+ },
+ avery5160: {
+ label: 'Avery 5160 — US Letter 시트 (25.4 × 66.7 mm × 30)',
+ hint: 'US 시트; Letter 페이지당 30개 라벨.'
+ },
+ amsHolderSmall: {
+ label: 'AMS 홀더 — 소형 (74 × 33 mm)',
+ hint: '페이지당 단일 레이블; MakerWorld 모델 752566 (AMS 필라멘트 레이블 홀더)의 인쇄 가능 레이블과 일치합니다.'
+ },
+ amsHolderLarge: {
+ label: 'AMS 홀더 — 대형 (75 × 55 mm)',
+ hint: '페이지당 단일 레이블; AMS 필라멘트 레이블 홀더의 카드스톡 삽입 변형에 맞습니다. 스와치, 브랜드, 재질, ID, QR 코드에 충분한 공간이 있습니다.'
+ }
+ },
+ sortBy: {
+ label: '정렬:',
+ id: 'ID 순',
+ color: '색상 순'
+ }
+ },
+ addSpool: '스풀 추가',
+ editSpool: '스풀 편집',
+ copySpool: '스풀 복사',
+ material: '재료',
+ selectMaterial: '재료 선택...',
+ subtype: '하위 유형',
+ brand: '브랜드',
+ searchBrand: '브랜드 검색...',
+ useCustomBrand: '\"{{brand}}\" 사용',
+ useCustomMaterial: '사용자 지정 재료 사용: {{material}}',
+ colorName: '색상 이름',
+ colorNamePlaceholder: '제이드 화이트, 파이어 레드...',
+ color: '색상',
+ hexColor: '16진수 색상',
+ pickColor: '사용자 지정 색상 선택',
+ labelWeight: '라벨 무게',
+ coreWeight: '빈 스풀 무게',
+ searchSpoolWeight: '스풀 무게 검색...',
+ weightUsed: '사용됨',
+ currentWeight: '남은 무게',
+ measuredWeight: '측정된 무게',
+ spoolName: '스풀',
+ costPerKg: 'kg당 비용',
+ storageLocation: '보관 위치',
+ storageLocationPlaceholder: '예: 선반 A, 서랍 1',
+ openInInventory: '재고에서 열기',
+ measuredWeightError: '측정된 무게는 {{min}}g과 {{max}}g 사이여야 합니다.',
+ slicerFilament: '슬라이서 필라멘트',
+ slicerFilamentName: '슬라이서 프리셋 이름',
+ slicerPreset: '슬라이서 프리셋',
+ searchPresets: '필라멘트 프리셋 검색...',
+ selectedPreset: '선택됨',
+ noPresetsFound: '프리셋을 찾을 수 없음',
+ tempOverrides: '온도 재정의',
+ note: '메모',
+ notePlaceholder: '이 스풀에 대한 추가 메모...',
+ category: '카테고리',
+ categoryPlaceholder: '예: 생산, 프로토타입, 고객 A',
+ categoryNone: '미분류',
+ lowStockThresholdOverride: '재고 부족 임계값 (이 스풀)',
+ lowStockThresholdOverrideHelp: '전역 임계값({{global}}%)을 사용하려면 비워두세요.',
+ clearRfid: 'RFID 태그 초기화',
+ rfidCleared: 'RFID 태그가 초기화되었습니다',
+ archive: '보관',
+ restore: '복원',
+ noSpools: '아직 스풀이 없습니다. 첫 번째 스풀을 추가하여 시작하세요.',
+ noAvailableSpools: '사용 가능한 스풀이 없습니다. 재고에 스풀을 추가하거나 먼저 다른 슬롯에서 해제하세요.',
+ kProfiles: 'K-프로필',
+ addKProfile: 'K-프로필 추가',
+ assignSpool: '스풀 할당',
+ unassignSpool: '할당 해제',
+ assignSuccess: '스풀 할당 및 AMS 슬롯 구성됨',
+ assignFailed: '스풀 할당 실패',
+ selectSpool: '이 슬롯에 할당할 스풀 선택',
+ assigned: '할당됨',
+ assigning: '할당 중...',
+ searchSpools: '스풀 검색...',
+ showAllSpools: '모든 스풀 표시',
+ spoolmanSpools: 'Spoolman 스풀',
+ allMaterials: '모든 재료',
+ filterByBrand: '브랜드로 필터...',
+ showArchived: '보관된 항목 표시',
+ quickAdd: '빠른 추가 (재고)',
+ quantity: '수량',
+ stock: '재고',
+ configured: '구성됨',
+ spoolsCreated: '{{count}}개 스풀 생성됨',
+ spoolsPartiallyCreated: '{{total}}개 중 {{created}}개 스풀 생성됨 (일부 실패)',
+ spoolCreated: '스풀 생성됨',
+ spoolUpdated: '스풀 업데이트됨',
+ spoolDeleted: '스풀 삭제됨',
+ deepLinkSpoolNotFound: '스풀을 찾을 수 없음',
+ deepLinkFetchFailed: '스풀을 불러올 수 없음 — 다시 시도하세요',
+ spoolArchived: '스풀 보관됨',
+ spoolRestored: '스풀 복원됨',
+ kProfileSaveFailed: 'K-프로필 설정을 저장할 수 없습니다',
+ syncWeightSpoolNotFound: '스풀을 찾을 수 없음 — 삭제되었을 수 있습니다',
+ syncWeightSpoolmanUnreachable: 'Spoolman에 연결할 수 없음 — 나중에 다시 시도하세요',
+ syncWeightFailed: '무게 동기화 실패',
+ spoolmanUnreachable: 'Spoolman에 연결할 수 없습니다 — 나중에 다시 시도하세요',
+ deleteSpoolNotFound: '스풀을 찾을 수 없음 — 이미 삭제되었을 수 있습니다',
+ deleteFailed: '스풀 삭제 실패',
+ archiveSpoolNotFound: '스풀을 찾을 수 없음 — 이미 삭제되었을 수 있습니다',
+ archiveFailed: '스풀 보관 실패',
+ restoreSpoolNotFound: '스풀을 찾을 수 없음 — 이미 삭제되었을 수 있습니다',
+ restoreFailed: '스풀 복원 실패',
+ saveFailed: '변경 사항 저장 실패',
+ tagClearFailed: '태그 초기화 실패',
+ deleteConfirm: '이 스풀을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ archiveConfirm: '이 스풀을 보관하시겠습니까?',
+ advancedSettings: '고급 설정',
+ filamentInfoTab: '필라멘트 정보',
+ paProfileTab: 'PA 프로필',
+ filamentInfo: '필라멘트',
+ additional: '추가',
+ loadingPresets: '클라우드 프리셋 불러오는 중...',
+ cloudConnected: '클라우드 연결됨',
+ cloudNotConnected: '클라우드 연결되지 않음 (기본값 사용)',
+ recentColors: '최근',
+ searchColors: '색상 검색...',
+ searchResults: '검색 결과',
+ allColors: '모든 색상',
+ commonColors: '일반 색상',
+ showLess: '간략히 보기',
+ showAll: '모두 보기',
+ noColorsFound: '검색과 일치하는 색상 없음',
+ noResults: '일치하는 항목 없음',
+ extraColorsLabel: '추가 색상',
+ extraColorsPlaceholder: 'EC984C,#6CD4BC,A66EB9,D87694',
+ extraColorsHint: '2~8개의 16진수 색상값을 쉼표로 구분하여 붙여넣으세요. 그라데이션으로 렌더링됩니다.',
+ extraColorsInvalid: '유효하지 않은 16진수 무시됨: {{tokens}}',
+ colorEffectLabel: '효과',
+ colorEffect: {
+ none: '없음',
+ sparkle: '스파클',
+ wood: '우드',
+ marble: '마블',
+ glow: '글로우',
+ matte: '매트',
+ silk: '실크',
+ galaxy: '갤럭시',
+ rainbow: '레인보우',
+ metal: '메탈',
+ translucent: '반투명',
+ gradient: '그라데이션',
+ dualColor: '듀얼 컬러',
+ triColor: '트리 컬러',
+ multicolor: '멀티컬러'
+ },
+ selectMaterialFirst: '먼저 필라멘트 정보 탭에서 재료를 선택해 주세요.',
+ noPrintersConfigured: '구성된 프린터 없음. PA 프로필을 사용하려면 프린터를 추가하세요.',
+ matchingFilter: '일치',
+ anyBrand: '모든 브랜드',
+ anyVariant: '모든 변형',
+ autoSelect: '자동 선택',
+ matches: '일치',
+ match: '일치',
+ noMatches: '일치 없음',
+ connected: '연결됨',
+ offline: '오프라인',
+ printerOffline: '프린터가 오프라인입니다. 연결하여 보정 프로필을 확인하세요.',
+ noKProfilesMatch: '선택한 필라멘트와 일치하는 K-프로필이 없습니다.',
+ leftNozzle: '왼쪽 노즐',
+ rightNozzle: '오른쪽 노즐',
+ profilesSelected: '보정 프로필 선택됨',
+ totalInventory: '총 재고',
+ totalConsumed: '총 소비량',
+ byMaterial: '재료별',
+ inPrinter: '프린터 내',
+ lowStock: '재고 부족',
+ sinceTracking: '추적 시작 이후',
+ loadedInAms: 'AMS/외부에 장착됨',
+ remaining: '남은 양',
+ weightCheck: '무게 확인',
+ lastWeighed: '마지막 계량',
+ neverWeighed: '계량 기록 없음',
+ search: '스풀 검색...',
+ showing: '표시 중',
+ to: '~',
+ of: '/',
+ show: '표시',
+ spools: '스풀',
+ spool: '스풀',
+ page: '페이지',
+ noSpoolsMatch: '결과를 찾을 수 없음',
+ noSpoolsMatchDesc: '검색 또는 필터를 조정하여 원하는 항목을 찾아보세요.',
+ active: '활성',
+ archived: '보관됨',
+ all: '전체',
+ used: '사용됨',
+ new: '새것',
+ clearFilters: '필터 초기화',
+ table: '테이블',
+ cards: '카드',
+ net: '순',
+ groupSimilar: '그룹화',
+ groupedSpools: '동일한 스풀 {{count}}개',
+ groupedRows: '행',
+ columns: '열',
+ configureColumns: '열 구성',
+ configureColumnsDesc: '드래그하여 열 순서를 변경하거나 화살표를 사용하세요. 눈 아이콘으로 표시 여부를 전환합니다.',
+ visible: '표시됨',
+ reset: '초기화',
+ cancel: '취소',
+ applyChanges: '변경 사항 적용',
+ moveUp: '위로 이동',
+ moveDown: '아래로 이동',
+ hideColumn: '열 숨기기',
+ showColumn: '열 표시',
+ linkToSpool: '스풀에 연결',
+ tagLinked: '태그가 스풀에 연결됨',
+ tagLinkFailed: '태그 연결 실패',
+ tagAlreadyLinked: '태그가 이미 다른 스풀에 연결됨',
+ unknownTag: '알 수 없는 RFID 태그 감지됨',
+ usageHistory: '사용 기록',
+ noUsageHistory: '사용 기록 없음',
+ printName: '인쇄 이름',
+ weightConsumed: '소비 무게',
+ clearHistory: '초기화',
+ historyCleared: '사용 기록 초기화됨',
+ fillSourceLabel: '(재고)',
+ lowStockThresholdError: '임계값은 0.1에서 99.9 사이여야 합니다',
+ assignMismatchTitle: '재료 불일치',
+ assignMismatchMessage: '선택한 스풀 재료 \"{{spoolMaterial}}\"이(가) {{location}}의 트레이 재료 \"{{trayMaterial}}\"과(와) 일치하지 않습니다. 그래도 할당하시겠습니까?',
+ assignMismatchConfirm: '그래도 할당',
+ assignPartialMismatchMessage: '스풀 재료 \"{{spoolMaterial}}\"이(가) {{location}}의 \"{{trayMaterial}}\"과(와) 유사하지만 정확히 일치하지 않습니다. 계속하시겠습니까?',
+ assignProfileMismatchMessage: '스풀 프로필 \"{{spoolProfile}}\"이(가) {{location}}의 트레이 프로필 \"{{trayProfile}}\"과(와) 일치하지 않습니다. 계속하시겠습니까?',
+ assignReconfigureNote: 'AMS 슬롯이 스풀의 프로필을 사용하도록 재구성됩니다.',
+ spoolmanFilamentCatalog: 'Spoolman 필라멘트 카탈로그',
+ pickFromSpoolmanCatalog: 'Spoolman 카탈로그에서 선택…',
+ spoolmanFilamentSelected: 'Spoolman 카탈로그에서 필라멘트 선택됨',
+ spoolmanFilamentUnlinked: '필라멘트 카탈로그 연결 해제됨',
+ noSpoolmanFilaments: 'Spoolman 카탈로그에서 필라멘트를 찾을 수 없음',
+ spoolmanFilamentColorSwatch: '필라멘트 색상',
+ spoolWeightManagedBySpoolman: '빈 스풀 무게는 Spoolman에서 필라멘트 유형별로 관리됩니다',
+ spoolmanCatalogLoadFailed: 'Spoolman 필라멘트 카탈로그 불러오기 실패',
+ subtitle: '스풀 관리',
+ storageLocationNone: '위치 미설정',
+ resetUsage: '사용량을 0으로 초기화',
+ resetUsageTooltip: '이 스풀의 소비된 그램 카운터를 0으로 초기화합니다',
+ resetUsageConfirm: '이 스풀의 소비된 그램 카운터를 0으로 초기화하시겠습니까? 이후 인쇄는 처음부터 추적됩니다. 스풀 자체, 잔여 무게 계산 및 설정은 변경되지 않습니다.',
+ resetAllUsage: '모든 스풀 사용량 초기화',
+ resetAllUsageTooltip: '모든 스풀의 소비된 그램 카운터를 0으로 초기화합니다',
+ resetAllUsageConfirm: '{{count}}개 스풀(아카이브 포함)의 소비된 그램 카운터를 모두 0으로 초기화하시겠습니까? 이는 \"총 소비량\" 통계를 지워 이후 인쇄가 처음부터 추적되도록 합니다. 스풀과 잔여 무게는 변경되지 않습니다.',
+ usageReset: '스풀 사용량이 0으로 초기화되었습니다',
+ allUsageReset: '{{count}}개 스풀 초기화됨',
+ resetUsageFailed: '스풀 사용량 초기화 실패'
+ },
+ timelapse: {
+ title: '타임랩스',
+ create: '타임랩스 만들기',
+ download: '다운로드',
+ delete: '삭제',
+ preview: '미리보기',
+ frameRate: '프레임 속도',
+ quality: '품질',
+ processing: '처리 중...',
+ noTimelapses: '사용 가능한 타임랩스 없음'
+ },
+ ams: {
+ title: 'AMS',
+ slot: '슬롯',
+ empty: '비어 있음',
+ emptySlot: '빈 슬롯',
+ unknown: '알 수 없음',
+ humidity: '습도',
+ temperature: '온도',
+ filamentType: '필라멘트 유형',
+ filamentColor: '색상',
+ remaining: '남은 양',
+ history: 'AMS 기록',
+ noHistory: '기록 없음',
+ configureSlot: '슬롯 구성',
+ externalSpool: '외부 스풀',
+ profile: '프로필',
+ kFactor: 'K 계수',
+ fill: '채우기',
+ configure: '구성',
+ used: '사용됨',
+ remainingUnit: '남음',
+ slotEmpty: '비어 있음',
+ emptySlotReset: '필라멘트가 할당되지 않음'
+ },
+ printModal: {
+ title: '인쇄 시작',
+ selectPrinter: '프린터 선택',
+ selectPlate: '플레이트 선택',
+ filamentMapping: '필라멘트 매핑',
+ totalCost: '총 비용:',
+ slotRemainingShort: ' - {{grams}}g 남음',
+ printSettings: '인쇄 설정',
+ bedLeveling: '베드 레벨링',
+ flowCalibration: '유량 보정',
+ vibrationCalibration: '진동 보정',
+ layerInspection: '첫 번째 레이어 검사',
+ timelapse: '타임랩스',
+ startPrint: '인쇄 시작',
+ addToQueue: '대기열에 추가',
+ cancel: '취소',
+ noPrintersAvailable: '사용 가능한 프린터 없음',
+ printerBusy: '프린터가 사용 중입니다',
+ printerOffline: '프린터가 오프라인입니다',
+ sameTypeDifferentColor: '같은 유형, 다른 색상',
+ filamentTypeNotLoaded: '필라멘트 유형이 장착되지 않음',
+ openCalendar: '달력 열기',
+ leftNozzle: 'L',
+ rightNozzle: 'R',
+ leftNozzleTooltip: '왼쪽 노즐',
+ rightNozzleTooltip: '오른쪽 노즐',
+ filamentOverride: '필라멘트 재정의',
+ filamentOverrideHint: '선택적으로 모델 기반 할당을 위해 필라멘트를 재정의합니다. 스케줄러는 원래 3MF 값 대신 선택한 필라멘트와 일치시킵니다.',
+ originalFilament: '원래',
+ overrideWith: '재정의',
+ resetToOriginal: '원래대로 초기화',
+ insufficientFilamentTitle: '필라멘트 부족',
+ insufficientFilamentMessage: '일부 할당된 스풀에 이 인쇄에 필요한 것보다 적은 필라멘트가 남아 있습니다:',
+ insufficientFilamentLine: '{{printer}} - {{slot}}: {{required}}g 필요, {{remaining}}g 남음',
+ printAnyway: '그래도 인쇄',
+ forceColorMatch: '색상 일치 강제',
+ staggerPrinterStarts: '프린터 시작 분산',
+ staggerGroupSize: '그룹 크기',
+ staggerInterval: '간격 (분)',
+ staggerPreview: '{{printers}}대 프린터 → {{size}}대씩 {{groups}}개 그룹, 매 {{interval}}분마다 시작',
+ staggerLastGroup: '마지막 그룹: {{count}}',
+ staggerTotal: '합계: {{minutes}}분',
+ staggerToPrinters: '{{count}}대 프린터에 분산',
+ gcodeInjection: '자동 인쇄 G-code 삽입'
+ },
+ backup: {
+ includesEncryptionKey: '로컬 백업에는 MFA 암호화 키 파일(DATA_DIR/.mfa_encryption_key)이 포함되어 백업 ZIP이 자체 완결됩니다. ZIP 파일을 민감하게 취급하세요 — 파일을 가진 누구나 내부에 저장된 OIDC 클라이언트 비밀과 TOTP 비밀을 복호화할 수 있습니다.',
+ title: '백업 및 복원',
+ createBackup: '백업 만들기',
+ restoreBackup: '백업 복원',
+ restoreDescription: '백업 파일에서 모든 데이터 교체',
+ downloadBackup: '백업 다운로드',
+ uploadBackup: '백업 업로드',
+ lastBackup: '마지막 백업',
+ autoBackup: '자동 백업',
+ backupNow: '지금 백업',
+ restoreWarning: '경고: 백업을 복원하면 현재 모든 데이터를 덮어씁니다.',
+ includeArchives: '아카이브 포함',
+ includeSettings: '설정 포함',
+ includeProfiles: '프로필 포함',
+ backupSuccess: '백업이 성공적으로 생성되었습니다',
+ restoreSuccess: '백업이 성공적으로 복원되었습니다',
+ backupFailed: '백업 실패',
+ restoreFailed: '복원 실패',
+ restoreNote: '복원 중 가상 프린터가 중지됩니다',
+ githubBackup: 'Git 백업',
+ enabled: '활성화됨',
+ cloudLoginRequired: 'Bambu 클라우드 로그인 필요. GitHub 백업을 활성화하려면 프로필 → 클라우드 프로필에서 로그인하세요.',
+ cloudLoginRequiredShort: '클라우드 로그인 필요',
+ githubDescription: '백업 및 버전 기록을 위해 비공개 GitHub 저장소에 프로필을 자동으로 동기화합니다.',
+ repositoryUrl: '저장소 URL',
+ repoUrlPlaceholderGitHub: 'https://github.com/username/repo-name',
+ repoUrlPlaceholderGitea: 'https://gitea.example.com/username/repo-name',
+ repoUrlPlaceholderForgejo: 'https://forgejo.example.com/username/repo-name',
+ repoUrlPlaceholderGitLab: 'https://gitlab.com/username/repo-name',
+ allowInsecureHttp: '비보안 HTTP 허용',
+ allowInsecureHttpHint: 'TLS가 없는 개인 네트워크의 자체 호스팅 인스턴스에 활성화',
+ personalAccessToken: '개인 액세스 토큰',
+ tokenSaved: '(저장됨)',
+ enterNewToken: '업데이트하려면 새 토큰 입력',
+ tokenHint: '콘텐츠 읽기/쓰기 권한이 있는 세분화된 토큰',
+ branch: '브랜치',
+ provider: 'Git 제공자',
+ providerGitHub: 'GitHub',
+ providerGitLab: 'GitLab',
+ providerGitea: 'Gitea',
+ providerForgejo: 'Forgejo',
+ manualOnly: '수동만',
+ hourly: '매시간',
+ daily: '매일',
+ weekly: '매주',
+ includeInBackup: '백업에 포함',
+ kProfiles: 'K-프로필',
+ kProfilesDescription: '연결된 프린터의 압력 전진 보정',
+ noPrintersConnected: '연결된 프린터 없음',
+ printersConnected: '{{total}}개 중 {{connected}}개 연결됨',
+ cloudProfiles: '클라우드 프로필',
+ cloudProfilesDescription: 'Bambu 클라우드의 필라멘트, 프린터 및 프로세스 프리셋',
+ appSettings: '앱 설정',
+ appSettingsDescription: 'Bambuddy 구성 (전체 데이터베이스)',
+ spoolInventory: '스풀 재고',
+ spoolInventoryDescription: '필라멘트 스풀, 사용 기록 및 비용 추적',
+ printArchives: '인쇄 아카이브',
+ printArchivesDescription: '인쇄 기록 메타데이터 (gcode/3MF 파일 제외)',
+ lastBackupAt: '마지막 백업:',
+ noBackupsYet: '아직 백업 없음',
+ next: '다음:',
+ startingBackup: '백업 시작 중...',
+ test: '테스트',
+ enableBackup: '백업 활성화',
+ testConnection: '연결 테스트',
+ enterRepoUrl: '저장소 URL 입력',
+ enterRepoAndToken: '저장소 URL 및 액세스 토큰 입력',
+ repoRequired: '저장소 URL이 필요합니다',
+ tokenRequired: '액세스 토큰이 필요합니다',
+ githubBackupEnabled: 'GitHub 백업 활성화됨',
+ tokenUpdated: '토큰 업데이트됨',
+ settingsSaved: '설정 저장됨',
+ failedToSave: '저장 실패: {{message}}',
+ backupCompleteFiles: '백업 완료 - {{count}}개 파일 업데이트됨',
+ backupSkippedNoChanges: '변경 사항 없어 백업 건너뜀',
+ backupFailed2: '백업 실패: {{message}}',
+ clearedLogs: '{{count}}개 로그 초기화됨',
+ failedToClearLogs: '로그 초기화 실패: {{message}}',
+ history: '기록',
+ clear: '초기화',
+ date: '날짜',
+ status: '상태',
+ commit: '커밋',
+ localBackup: '로컬 백업',
+ localBackupDescription: '데이터베이스, 아카이브, 업로드 및 모든 파일을 포함한 Bambuddy 데이터의 전체 백업을 만듭니다.',
+ downloadBackupLabel: '백업 다운로드',
+ completeBackupZip: '전체 백업: 데이터베이스 + 모든 파일 (ZIP)',
+ download: '다운로드',
+ preparingBackup: '백업 준비 중...',
+ creatingArchive: '백업 아카이브 생성 중... 대용량 아카이브의 경우 시간이 걸릴 수 있습니다.',
+ downloadingFile: '백업 파일 다운로드 중...',
+ backupDownloaded: '백업이 성공적으로 다운로드되었습니다',
+ failedToCreateBackup: '백업 생성 실패: {{message}}',
+ restore: '복원',
+ restoreReplacesAll: '복원은 모든 데이터를 교체합니다.',
+ restoreReplacesAllDetail: '현재 데이터베이스와 파일이 완전히 교체됩니다. 복원 후 재시작이 필요합니다.',
+ restoreConfirmTitle: '백업 복원',
+ restoreConfirmMessage: '\"{{filename}}\"에서 복원하시겠습니까? 현재 데이터베이스와 모든 파일이 완전히 교체됩니다. 복원 후 애플리케이션을 재시작해야 합니다.',
+ restoreConfirmButton: '백업 복원',
+ uploadingFile: '백업 파일 업로드 중...',
+ backupRestoredRestart: '백업 복원됨. Bambuddy를 재시작하세요.',
+ failedToRestore: '백업 복원 실패. 파일 형식을 확인하세요.',
+ reloadNow: '지금 새로고침',
+ creatingBackup: '백업 만드는 중',
+ restoringBackup: '백업 복원 중',
+ preparing: '준비 중...',
+ processing: '처리 중...',
+ doNotClosePage: '이 페이지를 닫거나 다른 곳으로 이동하지 마세요. 대용량 백업의 경우 몇 분이 걸릴 수 있습니다.',
+ restoring: '복원 중...',
+ restoreComplete: '복원 완료',
+ restoreFailed2: '복원 실패',
+ importSettings: '백업 파일에서 설정 가져오기',
+ pleaseWaitRestoring: '데이터가 복원되는 동안 기다려 주세요',
+ selectBackupFile: '백업 파일 클릭하여 선택 (.json 또는 .zip)',
+ duplicateHandling: '중복 처리 방법:',
+ matchPrinters: '프린터',
+ matchPrintersBy: '일련번호로 일치',
+ matchSmartPlugs: '스마트 플러그',
+ matchSmartPlugsBy: 'IP 주소로 일치',
+ matchNotificationProviders: '알림 제공자',
+ matchNotificationProvidersBy: '이름으로 일치',
+ matchFilaments: '필라멘트',
+ matchFilamentsBy: '이름 + 유형 + 브랜드로 일치',
+ matchArchives: '아카이브',
+ matchArchivesBy: '콘텐츠 해시로 일치 (항상 건너뜀)',
+ matchPendingUploads: '대기 중인 업로드',
+ matchPendingUploadsBy: '파일 이름으로 일치',
+ matchSettingsTemplates: '설정 및 템플릿',
+ matchSettingsTemplatesBy: '항상 덮어씀',
+ replaceExisting: '기존 데이터 교체',
+ keepExisting: '기존 데이터 유지',
+ overwriteDescription: '백업 데이터로 이미 존재하는 항목 덮어쓰기',
+ keepDescription: '아직 존재하지 않는 항목만 복원',
+ overwriteCaution: '주의:',
+ overwriteWarning: '덮어쓰기는 현재 구성을 백업 데이터로 교체합니다. 보안상 프린터 액세스 코드는 절대 덮어쓰지 않습니다.',
+ cancel: '취소',
+ processingBackup: '백업 파일 처리 중...',
+ itemsRestored: '복원된 항목',
+ itemsSkipped: '건너뛴 항목',
+ restored: '복원됨',
+ skippedAlreadyExist: '건너뜀 (이미 존재)',
+ filesCategory: '파일 (3MF, 썸네일 등)',
+ andMore: '...및 {{count}}개 더',
+ newApiKeysGenerated: '새 API 키 생성됨',
+ keysShownOnce: '이 키는 한 번만 표시됩니다. 지금 복사하세요!',
+ copy: '복사',
+ noDataFound: '백업 파일에서 복원할 데이터를 찾을 수 없습니다.',
+ close: '닫기',
+ scheduledBackup: '예약 백업',
+ scheduledBackupDescription: '일정에 따라 백업 스냅샷을 자동으로 생성합니다. 출력 디렉토리를 NAS 또는 외부 저장소에 마운트할 수 있습니다.',
+ frequency: '주기',
+ backupTime: '시간',
+ retention: '보존',
+ retentionDescription: '유지할 백업 수',
+ outputPath: '출력 경로',
+ outputPathPlaceholder: '기본값: {{path}}',
+ outputPathDescription: '기본 위치를 사용하려면 비워두세요',
+ runNow: '지금 실행',
+ backupFiles: '백업 파일',
+ noScheduledBackups: '아직 백업 없음',
+ deleteBackup: '삭제',
+ deleteBackupConfirm: '이 백업 파일을 삭제하시겠습니까?',
+ backupRunning: '백업 진행 중...',
+ scheduledBackupComplete: '백업이 성공적으로 완료되었습니다',
+ scheduledBackupFailed: '백업 실패',
+ nextBackup: '다음 백업',
+ backupSize: '크기',
+ utc: 'UTC',
+ defaultPathLabel: '기본값:',
+ categories: {
+ settings: '설정',
+ notification_providers: '알림 제공자',
+ notification_templates: '알림 템플릿',
+ smart_plugs: '스마트 플러그',
+ printers: '프린터',
+ filaments: '필라멘트',
+ maintenance_types: '유지 관리 유형',
+ archives: '아카이브',
+ projects: '프로젝트',
+ pending_uploads: '대기 중인 업로드',
+ external_links: '외부 링크',
+ api_keys: 'API 키'
+ },
+ repoIsPrivate: '저장소가 비공개입니다 — 안전하게 백업할 수 있습니다.',
+ repoIsPublicWarning: '저장소가 공개입니다. Bambuddy 백업에는 MQTT 자격증명, Home Assistant 토큰, Prometheus 토큰, Bambu Cloud 이메일, K-프로파일을 통한 프린터 액세스 코드가 포함됩니다. 공급자 설정에서 저장소를 비공개로 변경할 때까지 저장이 차단됩니다.',
+ repoVisibilityUnknown: '저장소 공개 여부를 확인할 수 없습니다. Bambuddy는 비공개로 확인된 저장소에만 백업하며, 저장이 차단됩니다.'
+ },
+ tags: {
+ title: '태그',
+ addTag: '태그 추가',
+ editTag: '태그 편집',
+ deleteTag: '태그 삭제',
+ tagName: '태그 이름',
+ tagColor: '태그 색상',
+ noTags: '태그 없음',
+ deleteConfirm: '이 태그를 삭제하시겠습니까?',
+ manageTags: '태그 관리'
+ },
+ uploadModal: {
+ title: '3MF 파일 업로드',
+ dragDrop: '.3mf 파일을 여기에 드래그 앤 드롭',
+ or: '또는',
+ browseFiles: '파일 탐색',
+ extractionInfo: '프린터 모델은 3MF 파일 메타데이터에서 자동으로 추출됩니다.',
+ uploaded: '업로드됨',
+ failed: '실패',
+ uploading: '업로드 중...',
+ upload: '업로드',
+ uploadFailed: '업로드 실패'
+ },
+ editArchive: {
+ title: '아카이브 편집',
+ name: '이름',
+ namePlaceholder: '인쇄 이름',
+ printer: '프린터',
+ noPrinter: '프린터 없음',
+ project: '프로젝트',
+ noProject: '프로젝트 없음',
+ itemsPrinted: '인쇄된 항목',
+ itemsPrintedHelp: '이 인쇄 작업에서 생산된 항목 수',
+ notes: '메모',
+ notesPlaceholder: '이 인쇄에 대한 메모 추가...',
+ externalLink: '외부 링크',
+ externalLinkPlaceholder: 'https://printables.com/model/...',
+ externalLinkHelp: 'Printables, Thingiverse 또는 다른 출처 링크',
+ tags: '태그',
+ tagsPlaceholder: '태그 추가...',
+ addMoreTags: '더 많은 태그 추가...',
+ matchingTags: '\"{{query}}\"와 일치',
+ existingTags: '기존 태그',
+ clickToAdd: '(클릭하여 추가)',
+ status: '상태',
+ failureReason: '실패 원인',
+ selectReason: '원인 선택...',
+ photos: '인쇄 결과 사진',
+ photosHelp: '+를 클릭하여 인쇄 결과 사진 추가',
+ printResult: '인쇄 결과',
+ saving: '저장 중...',
+ failureReasons: {
+ adhesionFailure: '접착 실패',
+ spaghettiDetached: '스파게티 / 분리',
+ layerShift: '레이어 시프트',
+ cloggedNozzle: '노즐 막힘',
+ filamentRunout: '필라멘트 소진',
+ warping: '휨',
+ stringing: '스트링',
+ underExtrusion: '압출 부족',
+ powerFailure: '전원 실패',
+ userCancelled: '사용자 취소',
+ other: '기타'
+ },
+ statuses: {
+ completed: '완료됨',
+ failed: '실패',
+ aborted: '취소됨',
+ printing: '인쇄 중'
+ }
+ },
+ kProfiles: {
+ title: 'K-프로필',
+ noPrintersConfigured: '구성된 프린터 없음',
+ addPrinterInSettings: 'K-프로필을 관리하려면 설정에서 프린터를 추가하세요',
+ noActivePrinters: '활성 프린터 없음',
+ enablePrinterConnection: 'K-프로필을 보려면 프린터 연결을 활성화하세요',
+ loadingProfiles: 'K-프로필 불러오는 중...',
+ printerOffline: '프린터 오프라인',
+ printerOfflineDesc: '선택한 프린터가 연결되지 않았습니다. 켜서 K-프로필을 확인하세요.',
+ noMatchingProfiles: '일치하는 프로필 없음',
+ noMatchingProfilesDesc: '검색 기준과 일치하는 프로필이 없습니다',
+ noKProfiles: 'K-프로필 없음',
+ noKProfilesDesc: '{{diameter}}mm 노즐에 대한 압력 전진 프로필이 없습니다',
+ createFirstProfile: '첫 번째 프로필 만들기',
+ printer: '프린터',
+ nozzle: '노즐',
+ refresh: '새로고침',
+ addProfile: '프로필 추가',
+ export: '내보내기',
+ import: '가져오기',
+ select: '선택',
+ selectAll: '모두 선택',
+ delete: '삭제',
+ searchPlaceholder: '이름 또는 필라멘트로 검색...',
+ allExtruders: '모든 압출기',
+ leftOnly: '왼쪽만',
+ rightOnly: '오른쪽만',
+ allFlow: '모든 유량',
+ hfOnly: 'HF만',
+ sOnly: 'S만',
+ sortName: '정렬: 이름',
+ sortKValue: '정렬: K값',
+ sortFilament: '정렬: 필라멘트',
+ leftExtruder: '왼쪽 압출기',
+ rightExtruder: '오른쪽 압출기',
+ modal: {
+ addTitle: 'K-프로필 추가',
+ editTitle: 'K-프로필 편집',
+ profileName: '프로필 이름',
+ profileNamePlaceholder: '내 PLA 프로필',
+ kValue: 'K값',
+ kValuePlaceholder: '0.020',
+ kValueHelp: '일반 범위: PLA 0.01~0.06, PETG 0.02~0.10',
+ filament: '필라멘트',
+ selectFilament: '필라멘트 선택...',
+ noFilamentsHelp: '필라멘트를 찾을 수 없습니다. 먼저 Bambu Studio에서 K-프로필을 만드세요.',
+ flowType: '유량 유형',
+ highFlow: '고유량',
+ standard: '표준',
+ nozzleSize: '노즐 크기',
+ extruder: '압출기',
+ extruders: '압출기',
+ left: '왼쪽',
+ right: '오른쪽',
+ notes: '메모 (로컬 저장)',
+ notesPlaceholder: '이 프로필에 대한 메모 추가...',
+ notesHelp: '메모는 프린터가 아닌 Bambuddy에 저장됩니다',
+ syncing: '프린터와 동기화 중...',
+ savingExtruder: '압출기 {{current}}/{{total}}에 저장 중...',
+ pleaseWait: '기다려 주세요'
+ },
+ deleteConfirm: {
+ title: '프로필 삭제',
+ cannotUndo: '이 작업은 취소할 수 없습니다',
+ message: '프린터에서 \"{{name}}\"을(를) 삭제하시겠습니까?'
+ },
+ bulkDelete: {
+ title: '프로필 삭제',
+ cannotUndo: '이 작업은 취소할 수 없습니다',
+ message: '프린터에서 선택한 {{count}}개 프로필을 삭제하시겠습니까?'
+ },
+ toast: {
+ profileSaved: 'K-프로필 저장됨',
+ profilesSaved: '{{count}}개 압출기에 K-프로필 저장됨',
+ selectAtLeastOneExtruder: '적어도 하나의 압출기를 선택해 주세요',
+ profileDeleted: 'K-프로필 삭제됨',
+ profilesDeleted: '{{count}}개 프로필 삭제됨',
+ exportedProfiles: '{{count}}개 프로필 내보냄',
+ importedProfiles: '{{total}}개 중 {{count}}개 프로필 가져옴',
+ noProfilesToExport: '내보낼 프로필 없음',
+ invalidFileFormat: '유효하지 않은 파일 형식',
+ failedToParseImport: '가져오기 파일 파싱 실패',
+ failedToSaveBatch: 'K-프로필 저장 실패',
+ noteSaved: '메모 저장됨',
+ failedToSaveNote: '메모 저장 실패'
+ },
+ permission: {
+ noRead: '프로필 새로고침 권한이 없습니다',
+ noCreate: '프로필 추가 권한이 없습니다',
+ noUpdate: 'K-프로필 업데이트 권한이 없습니다',
+ noDelete: 'K-프로필 삭제 권한이 없습니다',
+ noExport: '프로필 내보내기 권한이 없습니다',
+ noImport: '프로필 가져오기 권한이 없습니다'
+ }
+ },
+ virtualPrinter: {
+ title: '가상 프린터',
+ running: '실행 중',
+ stopped: '중지됨',
+ description: {
+ default: 'Bambu Studio 및 OrcaSlicer에 표시되는 가상 프린터를 활성화합니다. 이 프린터로 전송된 파일은 인쇄 없이 바로 아카이브됩니다.',
+ proxy: '실제 프린터로 슬라이서 트래픽을 릴레이하는 프록시를 활성화하여 모든 네트워크에서 원격 인쇄가 가능합니다.'
+ },
+ enable: {
+ title: '가상 프린터 활성화',
+ visibleInSlicer: '슬라이서 검색에서 \"Bambuddy\"로 표시됨',
+ proxyingTo: '{{name}}으로 프록시 중',
+ notActive: '활성화되지 않음'
+ },
+ model: {
+ title: '프린터 모델',
+ description: '에뮬레이션할 프린터 모델을 선택하세요.',
+ restartWarning: '모델 변경 시 가상 프린터가 재시작됩니다'
+ },
+ accessCode: {
+ title: '액세스 코드',
+ isSet: '액세스 코드가 설정됨',
+ notSet: '액세스 코드가 설정되지 않음 - 활성화하려면 필요',
+ placeholder: '8자리 코드 입력',
+ placeholderChange: '변경하려면 새 코드 입력',
+ hint: '정확히 8자여야 합니다. 슬라이서가 인증하는 데 사용됩니다.',
+ charCount: '({{count}}/8)'
+ },
+ targetPrinter: {
+ title: '대상 프린터',
+ configured: '프록시 대상 구성됨',
+ notConfigured: '대상 프린터가 선택되지 않음 - 프록시 모드에 필요',
+ placeholder: '프린터 선택...',
+ hint: '슬라이서 트래픽을 프록시할 프린터를 선택하세요. 프린터는 LAN 모드여야 합니다.',
+ noPrinters: '구성된 프린터 없음. 프록시 모드를 사용하려면 먼저 프린터를 추가하세요.'
+ },
+ remoteInterface: {
+ title: '네트워크 인터페이스 재정의',
+ configured: '인터페이스 재정의 활성',
+ optional: '선택사항 - 자동 감지된 IP가 잘못된 경우 사용 (예: 여러 NIC, Docker, VPN)',
+ placeholder: '자동 감지 (기본값)...',
+ hint: 'SSDP를 통해 광고되고 TLS 인증서에 사용되는 IP 주소를 재정의합니다. Bambuddy에 여러 네트워크 인터페이스가 있을 때 유용합니다.'
+ },
+ mode: {
+ title: '모드',
+ archive: '아카이브',
+ archiveDesc: '파일 즉시 아카이브',
+ review: '검토',
+ reviewDesc: '아카이브 전 검토',
+ queue: '대기열',
+ queueDesc: '아카이브 후 대기열 추가',
+ proxy: '프록시',
+ proxyDesc: '실제 프린터로 릴레이'
+ },
+ autoDispatch: {
+ title: '자동 발송',
+ description: '대기열에 추가될 때 자동으로 인쇄를 시작합니다. 꺼져 있으면 수동 발송을 기다립니다.'
+ },
+ queueForceColorMatch: {
+ title: '색상 일치 강제',
+ description: '정확한 필라멘트 유형과 색상이 장착되지 않은 프린터에는 발송을 거부합니다. 기본적으로 꺼져 있음 — 이 옵션 없이는 대기열이 모델 전용 매칭을 사용하여 잘못된 색상이 장착된 프린터를 선택할 수 있습니다.'
+ },
+ tailscaleDisabled: {
+ title: 'Tailscale 통합',
+ description: '이 가상 프린터가 Tailscale을 통해 노출되도록 표시하려면 활성화하세요. 슬라이서에 붙여넣을 IP를 알 수 있도록 호스트의 Tailscale 주소를 표시합니다. CA 가져오기 단계는 변경되지 않음 — 이 토글은 인증서에 영향을 미치지 않습니다.'
+ },
+ setupRequired: {
+ title: '설정 필요',
+ description: '가상 프린터 기능이 작동하려면 추가 시스템 구성이 필요합니다. 여기에는 포트 포워딩, 방화벽 규칙 및 플랫폼별 설정이 포함됩니다.',
+ readGuide: '활성화 전에 설정 가이드를 읽으세요'
+ },
+ archiveNameSource: {
+ title: '아카이브 이름 출처',
+ description: '가상 프린터를 통해 파일이 도착할 때 새 아카이브의 이름 지정 방법을 선택합니다. \"메타데이터\"는 3MF의 슬라이서 내장 제목을 사용합니다(기본값). \"파일 이름\"은 Bambu Studio가 FTP를 통해 전송한 파일 이름을 사용합니다.',
+ metadata: '메타데이터',
+ filename: '파일 이름'
+ },
+ howItWorks: {
+ title: '작동 방식',
+ step1: '같은 LAN에서 가상 프린터는 검색을 통해 슬라이서(Bambu Studio / OrcaSlicer)에 자동으로 나타납니다. 다른 네트워크에서는 IP 주소와 액세스 코드로 수동으로 추가하세요.',
+ step2: '아카이브, 검토, 대기열 모드에서 슬라이서의 \"전송\" 버튼을 사용하여 3MF 파일을 Bambuddy에 업로드하세요. 슬라이서는 \"인쇄 성공\"을 표시하지만 파일은 저장되고 인쇄되지 않습니다.',
+ step3: '프록시 모드에서 가상 프린터는 모든 트래픽을 실제 프린터로 릴레이합니다 — 직접 연결된 것처럼 즉시 인쇄가 시작됩니다.'
+ },
+ status: {
+ title: '상태 세부 정보',
+ printerName: '프린터 이름',
+ model: '모델',
+ serialNumber: '일련 번호',
+ mode: '모드',
+ pendingFiles: '대기 중인 파일',
+ targetPrinter: '대상 프린터',
+ ftpPort: 'FTP 포트',
+ mqttPort: 'MQTT 포트',
+ ftpConnections: 'FTP 연결',
+ mqttConnections: 'MQTT 연결'
+ },
+ toast: {
+ updated: '가상 프린터 설정 업데이트됨',
+ failedToUpdate: '설정 업데이트 실패',
+ copyFailed: '복사 실패 — 텍스트를 수동으로 선택하여 복사해 보세요',
+ accessCodeRequired: '먼저 액세스 코드를 설정해 주세요',
+ targetPrinterRequired: '먼저 대상 프린터를 선택해 주세요',
+ bindIpRequired: '먼저 바인드 IP를 설정해 주세요',
+ accessCodeEmpty: '액세스 코드는 비워둘 수 없습니다',
+ accessCodeLength: '액세스 코드는 정확히 8자여야 합니다',
+ created: '가상 프린터 생성됨',
+ failedToCreate: '가상 프린터 생성 실패',
+ deleted: '가상 프린터 삭제됨',
+ failedToDelete: '가상 프린터 삭제 실패'
+ },
+ list: {
+ title: '가상 프린터',
+ add: '추가',
+ addFirst: '가상 프린터 추가',
+ empty: '구성된 가상 프린터 없음. 하나를 추가하여 시작하세요.'
+ },
+ bindIp: {
+ title: '바인드 인터페이스',
+ placeholder: '인터페이스 선택...',
+ hint: '이 가상 프린터가 바인딩할 네트워크 인터페이스. 프린터당 고유해야 합니다.'
+ },
+ proxy: {
+ accessCodeHint: '프록시 모드에서는 슬라이서에서 대상 프린터의 액세스 코드를 사용하세요. 연결은 실제 프린터로 투명하게 전달됩니다.'
+ },
+ addDialog: {
+ title: '가상 프린터 추가',
+ name: '이름',
+ hint: '생성 후 액세스 코드, 대상 프린터 및 기타 설정을 구성할 수 있습니다.',
+ create: '생성'
+ },
+ deleteConfirm: {
+ title: '가상 프린터 삭제',
+ message: '\"{{name}}\"을(를) 삭제하시겠습니까? 이 프린터의 모든 서비스가 중지됩니다.'
+ },
+ caCert: {
+ title: '슬라이서 인증서',
+ description: '가상 프린터는 Bambuddy CA가 서명한 TLS 인증서를 사용합니다. 이 CA 인증서를 슬라이서의 신뢰 저장소에 한 번만 가져오면 연결을 수락합니다 — 명령줄에서 복사할 필요가 없습니다.',
+ copy: '복사',
+ copied: '복사됨',
+ download: '다운로드',
+ fingerprint: 'SHA-256'
+ }
+ },
+ modelViewer: {
+ openInSlicer: '슬라이서에서 열기',
+ tabs: {
+ model: '3D 모델',
+ gcode: 'G-code 미리보기'
+ },
+ notAvailable: '사용 불가',
+ notSliced: '슬라이싱되지 않음',
+ plates: '플레이트',
+ allPlates: '모든 플레이트',
+ plateNumber: '플레이트 {{number}}',
+ plateCount: '플레이트 {{count}}개',
+ plateCount_other: '플레이트 {{count}}개',
+ objectCount: '개체 {{count}}개',
+ objectCount_other: '개체 {{count}}개',
+ filamentCount: '필라멘트 {{count}}개',
+ filamentCount_other: '필라멘트 {{count}}개',
+ eta: '예상 {{minutes}}분',
+ noPreview: '이 파일에 대한 미리보기를 사용할 수 없습니다',
+ pagination: {
+ pageOf: '{{total}}페이지 중 {{current}}',
+ prev: '이전',
+ next: '다음'
+ },
+ errors: {
+ failedToLoad: '파일 불러오기 실패',
+ noMeshes: '3MF 파일에서 메쉬를 찾을 수 없음',
+ unsupportedFormat: '지원되지 않는 파일 형식'
+ }
+ },
+ maintenanceDescriptions: {
+ lubricateCarbonRods: '부드러운 움직임을 위해 카본 로드에 윤활유 도포',
+ lubricateRails: '부드러운 움직임을 위해 선형 레일에 윤활유 도포',
+ cleanNozzle: '막힘 방지를 위해 핫엔드와 노즐 청소',
+ checkBelts: '정확한 인쇄를 위해 벨트 장력 확인',
+ cleanBuildPlate: '접착력 향상을 위해 빌드 플레이트 청소',
+ checkExtruder: '마모 여부 확인을 위해 압출기 기어 점검',
+ checkCooling: '냉각 팬이 제대로 작동하는지 확인',
+ generalInspection: '전반적인 프린터 점검',
+ cleanCarbonRods: '마찰 감소를 위해 카본 로드 청소',
+ lubricateSteelRods: '부드러운 움직임을 위해 스틸 로드에 윤활유 도포',
+ cleanSteelRods: '마찰 감소를 위해 스틸 로드 청소',
+ cleanLinearRails: '먼지와 이물질 제거를 위해 선형 레일 닦기',
+ checkPtfeTube: '마모 또는 손상 여부 확인을 위해 PTFE 튜브 점검',
+ replaceHepaFilter: '공기 품질을 위해 HEPA 필터 교체',
+ replaceCarbonFilter: '활성탄 필터 교체',
+ lubricateLeftNozzleRail: '왼쪽 노즐 레일 윤활 (H2 시리즈)'
+ },
+ smartPlugs: {
+ offline: '오프라인',
+ admin: '관리자',
+ openPlugAdminPage: '플러그 관리 페이지 열기',
+ deleteSmartPlug: '스마트 플러그 삭제',
+ turnOnSmartPlug: '스마트 플러그 켜기',
+ turnOffSmartPlug: '스마트 플러그 끄기',
+ turnOn: '켜기',
+ turnOff: '끄기',
+ addSmartPlug: {
+ scanningNetwork: '네트워크 스캔 중...',
+ chooseEntity: '엔티티 선택...',
+ connectionFailed: '연결 실패',
+ searchEntities: '엔티티 검색...',
+ searchPowerSensors: '전력 센서 검색...',
+ searchEnergySensors: '에너지 센서 검색...',
+ placeholders: {
+ plugName: '거실 플러그',
+ mqttStateOnValue: 'ON, true, 1',
+ mqttSameAsPower: '전력 토픽과 같거나 다름'
+ }
+ },
+ linkedTo: '연결됨:',
+ monitorOnly: '모니터만',
+ alerts: '알림',
+ scheduleOn: '켜기 {{time}}',
+ scheduleOff: '끄기 {{time}}',
+ on: '켜짐',
+ off: '꺼짐',
+ power: '전력',
+ kwhToday: '오늘 kWh',
+ settings: '설정',
+ automationSettings: '자동화 설정',
+ showInSwitchbar: '스위치바에 표시',
+ quickAccessSidebar: '사이드바에서 빠른 접근',
+ enabled: '활성화됨',
+ enableAutomation: '이 플러그의 자동화 활성화',
+ autoOn: '자동 켜기',
+ autoOnDescription: '인쇄 시작 시 켜기',
+ autoOff: '자동 끄기',
+ autoOffDescription: '인쇄 완료 시 끄기 (1회)',
+ autoOffPersistent: '계속 활성화',
+ autoOffPersistentDescription: '1회성 대신 인쇄 사이에 활성화 유지',
+ turnOffDelayMode: '끄기 지연 모드',
+ time: '시간',
+ temp: '온도',
+ delayMinutes: '지연 (분)',
+ tempThreshold: '온도 임계값 (°C)',
+ tempThresholdDescription: '노즐이 이 온도 이하로 냉각될 때 끄기',
+ edit: '편집',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ turnOnConfirm: '\"{{name}}\"을(를) 켜시겠습니까?',
+ turnOffConfirm: '\"{{name}}\"을(를) 끄시겠습니까? 연결된 장치의 전원이 차단됩니다.',
+ failedToTurn: '\"{{name}}\" {{action}} 실패',
+ unknown: '알 수 없음',
+ addTitle: '스마트 플러그 추가',
+ editTitle: '스마트 플러그 편집',
+ stopScanning: '스캔 중지',
+ discoverTasmota: 'Tasmota 장치 검색',
+ foundDevices: '{{count}}개 장치 발견 - 클릭하여 선택:',
+ noDevicesFound: '네트워크에서 Tasmota 장치를 찾을 수 없음',
+ haNotConfigured: 'Home Assistant가 구성되지 않았습니다.',
+ haSettingsPath: '설정 → 네트워크 → Home Assistant',
+ selectEntity: '엔티티 선택 *',
+ ipAddress: 'IP 주소 *',
+ nameLabel: '이름 *',
+ username: '사용자 이름',
+ password: '비밀번호',
+ authHint: 'Tasmota 장치에 인증이 필요하지 않으면 비워두세요',
+ linkToPrinter: '프린터에 연결',
+ noPrinter: '프린터 없음 (수동 제어만)',
+ linkingDescription: '연결하면 인쇄 시작/완료 시 자동 켜기/끄기가 활성화됩니다',
+ powerAlerts: '전력 알림',
+ alertAbove: '초과 시 알림 (W)',
+ alertBelow: '미만 시 알림 (W)',
+ alertDescription: '전력 소비가 이 임계값을 초과할 때 알림 받기. 해당 방향을 비활성화하려면 비워두세요.',
+ dailySchedule: '일일 스케줄',
+ turnOnAt: '켜기 시각',
+ turnOffAt: '끄기 시각',
+ scheduleDescription: '매일 이 시간에 자동으로 켜기/끄기. 해당 동작을 건너뛰려면 비워두세요.',
+ showOnPrinterCard: '프린터 카드에 표시',
+ displayOnPrinterCard: '프린터 카드에 버튼 표시',
+ connectedResult: '연결됨!',
+ deviceLabel: '장치: {{name}} - ',
+ stateLabel: '상태: {{state}}',
+ test: '테스트',
+ delete: '삭제',
+ save: '저장',
+ add: '추가',
+ cancel: '취소',
+ failedToStartScan: '스캔 시작 실패',
+ nameRequired: '이름이 필요합니다',
+ entityRequired: 'Home Assistant 플러그에는 엔티티가 필요합니다',
+ mqttTopicRequired: '전력, 에너지 또는 상태 모니터링을 위한 MQTT 토픽이 하나 이상 구성되어야 합니다',
+ loadingEntities: '엔티티 불러오는 중...',
+ loading: '불러오는 중...',
+ failedToLoadEntities: '엔티티 불러오기 실패: {{error}}',
+ noEntitiesMatching: '\"{{search}}\"과 일치하는 엔티티를 찾을 수 없음',
+ noEntitiesAvailable: '사용 가능한 엔티티 없음',
+ searchingEntities: '모든 엔티티 검색 중 ({{count}}개 발견)',
+ showingEntities: 'switch, light, input_boolean 표시 중 ({{count}}개 사용 가능)',
+ energyMonitoringOptional: '에너지 모니터링 (선택사항)',
+ energyMonitoringHint: '전력/에너지 데이터를 제공하는 센서를 검색하여 선택하세요.',
+ powerSensorW: '전력 센서 (W)',
+ energyTodayKwh: '오늘 에너지 (kWh)',
+ totalEnergyKwh: '총 에너지 (kWh)',
+ noMatchingSensors: '일치하는 센서 없음',
+ none: '없음',
+ mqttNotConfigured: 'MQTT 브로커가 구성되지 않았습니다.',
+ mqttSettingsPath: '설정 → 네트워크 → MQTT 게시',
+ mqttNotConfiguredSuffix: '(게시를 활성화할 필요는 없고 브로커 세부 정보만 입력하면 됩니다).',
+ mqttMonitorOnlyDescription: 'MQTT 플러그는 MQTT 구독을 통해 전력/에너지 데이터를 받습니다. 켜기/끄기 제어는 불가능 — MQTT 브로커나 홈 자동화 시스템을 사용하세요.',
+ powerMonitoring: '전력 모니터링',
+ energyMonitoring: '에너지 모니터링',
+ stateMonitoring: '상태 모니터링',
+ optional: '선택사항',
+ topic: '토픽',
+ jsonPath: 'JSON 경로',
+ multiplier: '배수',
+ onValue: 'ON 값',
+ mqttPowerHint: 'JSON 경로는 JSON 페이로드에서 값을 추출합니다 (예: \"power_l1\"). 토픽이 원시 숫자 값을 게시하면 비워두세요.\nmW→W에는 배수 0.001, kW→W에는 1000을 사용하세요.',
+ mqttEnergyHint: 'JSON 경로는 JSON 페이로드에서 값을 추출합니다. 원시 값에는 비워두세요.\nWh→kWh에는 배수 0.001, MWh→kWh에는 1000을 사용하세요.',
+ mqttStateHint: 'JSON 경로는 JSON 페이로드에서 값을 추출합니다. 원시 값에는 비워두세요.\nON 값: \"ON\"을 의미하는 정확한 문자열. 자동 감지(ON, true, 1)를 위해 비워두세요.',
+ restControl: '제어',
+ restOnUrl: '켜기 URL',
+ restOffUrl: '끄기 URL',
+ restOnBody: 'ON 요청 본문',
+ restOffBody: 'OFF 요청 본문',
+ restMethod: 'HTTP 방법',
+ restHeaders: '사용자 지정 헤더 (JSON)',
+ restStatusUrl: '상태 URL',
+ restStatusPath: '상태 JSON 경로',
+ restStatusOnValue: 'ON 값',
+ restPowerUrl: '전력 URL',
+ restPowerPath: '전력 JSON 경로',
+ restPowerMultiplier: '전력 배수',
+ restEnergyUrl: '에너지 URL',
+ restEnergyPath: '에너지 JSON 경로',
+ restEnergyMultiplier: '에너지 배수',
+ restUrlRequired: 'REST 플러그에는 URL(ON 또는 OFF) 중 하나 이상이 필요합니다',
+ restHeadersHint: '예: {\"Authorization\": \"Bearer your-token\"}',
+ restBodyHint: '예: ON, {\"state\": \"on\"}',
+ restStatusHint: '현재 상태를 폴링할 URL',
+ restPathHint: '예: state 또는 data.power.status',
+ restPowerUrlHint: '전력 데이터의 별도 URL (비어 있으면 상태 URL 사용)',
+ restEnergyUrlHint: '에너지 데이터의 별도 URL (비어 있으면 상태 URL 사용)',
+ restEnergyHint: '각 값은 자체 URL을 사용하거나 상태 URL로 대체할 수 있습니다. 단위 변환에 배수를 사용하세요 (예: Wh→kWh에 0.001).',
+ testConnection: '연결 테스트',
+ connectionSuccess: '연결 성공',
+ noSwitchesInSwitchbar: '스위치바에 스위치 없음',
+ enableSwitchbarHint: '설정 > 스마트 플러그에서 \"스위치바에 표시\"를 활성화하세요',
+ autoOffAfterDrying: '건조 후 자동 끄기',
+ autoOffAfterDryingDescription: 'AMS 건조가 완료되면 끄기',
+ delayAfterDryingMinutes: '건조 후 지연 (분)'
+ },
+ notifications: {
+ providerTypes: {
+ callmebot: 'CallMeBot/WhatsApp',
+ ntfy: 'ntfy',
+ pushover: 'Pushover',
+ telegram: 'Telegram',
+ email: '이메일',
+ discord: 'Discord',
+ webhook: 'Webhook',
+ homeassistant: 'Home Assistant'
+ },
+ providerDescriptions: {
+ email: 'SMTP 이메일 알림',
+ telegram: 'Telegram 봇을 통한 알림',
+ discord: 'Webhook을 통해 Discord 채널로 전송',
+ ntfy: '무료, 자체 호스팅 가능한 푸시 알림',
+ pushover: '간단하고 신뢰할 수 있는 푸시 알림',
+ callmebot: 'CallMeBot을 통한 무료 WhatsApp 알림',
+ webhook: '모든 URL에 일반 HTTP POST',
+ homeassistant: 'Home Assistant 대시보드의 지속적인 알림'
+ },
+ lastSuccess: '마지막: {{date}}',
+ error: '오류',
+ printer: '프린터:',
+ allPrinters: '모든 프린터',
+ sendTestNotification: '테스트 알림 전송',
+ eventSettings: '이벤트 설정',
+ enabled: '활성화됨',
+ sendFromProvider: '이 제공자에서 알림 전송',
+ printEvents: '인쇄 이벤트',
+ printerStatus: '프린터 상태',
+ amsAlarms: 'AMS 알람',
+ amsHtAlarms: 'AMS-HT 알람',
+ printQueue: '인쇄 대기열',
+ start: '시작',
+ plateCheck: '플레이트 확인',
+ complete: '완료',
+ failed: '실패',
+ stopped: '중지됨',
+ progress: '진행률',
+ offline: '오프라인',
+ lowFilament: '필라멘트 부족',
+ maintenance: '유지 관리',
+ amsHumidity: 'AMS 습도',
+ amsTemp: 'AMS 온도',
+ amsHtHumidity: 'AMS-HT 습도',
+ amsHtTemp: 'AMS-HT 온도',
+ bedCooled: '베드 냉각됨',
+ firstLayer: '첫 번째 레이어',
+ quiet: '방해 금지',
+ digest: '요약 {{time}}',
+ printStarted: '인쇄 시작됨',
+ plateNotEmpty: '플레이트 비어 있지 않음',
+ plateNotEmptyDescription: '인쇄 전 개체 감지됨',
+ printCompleted: '인쇄 완료됨',
+ bedCooledLabel: '베드 냉각됨',
+ bedCooledDescription: '인쇄 후 베드가 임계값 이하로 냉각됨',
+ firstLayerCompleteLabel: '첫 번째 레이어 완료',
+ firstLayerCompleteDescription: '첫 번째 레이어 완료 시 스냅샷과 함께 알림',
+ missingSpoolAssignmentLabel: '스풀 할당 누락',
+ missingSpoolAssignmentDescription: '인쇄 시작 시 필요한 트레이에 할당된 스풀이 없을 때 알림',
+ printFailed: '인쇄 실패',
+ printStopped: '인쇄 중지됨',
+ progressMilestones: '진행률 이정표',
+ progressMilestonesDescription: '25%, 50%, 75%에서 알림',
+ printerOffline: '프린터 오프라인',
+ printerError: '프린터 오류',
+ lowFilamentLabel: '필라멘트 부족',
+ maintenanceDue: '유지 관리 필요',
+ maintenanceDueDescription: '유지 관리가 필요할 때 알림',
+ amsHumidityHigh: 'AMS 습도 높음',
+ amsHumidityHighDescription: '일반 AMS 습도가 임계값 초과',
+ amsTemperatureHigh: 'AMS 온도 높음',
+ amsTemperatureHighDescription: '일반 AMS 온도가 임계값 초과',
+ amsHtHumidityHigh: 'AMS-HT 습도 높음',
+ amsHtHumidityHighDescription: 'AMS-HT 습도가 임계값 초과',
+ amsHtTemperatureHigh: 'AMS-HT 온도 높음',
+ amsHtTemperatureHighDescription: 'AMS-HT 온도가 임계값 초과',
+ inventoryAlerts: '재고 알림',
+ stockReorderAlert: '재주문 알림',
+ stockReorderAlertDescription: 'SKU가 재주문 시점에 도달함',
+ stockBreakAlert: '재고 소진 알림',
+ stockBreakAlertDescription: '보충 전에 재고가 소진될 것임',
+ jobAdded: '작업 추가됨',
+ jobAddedDescription: '대기열에 작업 추가됨',
+ jobAssigned: '작업 할당됨',
+ jobAssignedDescription: '모델 기반 작업이 프린터에 할당됨',
+ jobStarted: '작업 시작됨',
+ jobStartedDescription: '대기열 작업 인쇄 시작됨',
+ jobWaiting: '작업 대기 중',
+ jobWaitingDescription: '필라멘트 또는 프린터를 기다리는 작업',
+ jobSkipped: '작업 건너뜀',
+ jobSkippedDescription: '작업 건너뜀 (이전 실패)',
+ jobFailed: '작업 실패',
+ jobFailedDescription: '작업 시작 실패',
+ queueComplete: '대기열 완료',
+ queueCompleteDescription: '모든 대기열 작업 완료',
+ quietHours: '방해 금지 시간',
+ noNotificationsDuring: '이 시간 동안 알림 없음',
+ editProviderToChangeQuietHours: '방해 금지 시간을 변경하려면 제공자를 편집하세요',
+ dailyDigest: '일일 요약',
+ batchNotifications: '알림을 하나의 일일 요약으로 묶기',
+ sendAt: '{{time}}에 전송',
+ editProviderToChangeDigestTime: '요약 시간을 변경하려면 제공자를 편집하세요',
+ edit: '편집',
+ deleteProvider: '알림 제공자 삭제',
+ deleteConfirm: '\"{{name}}\"을(를) 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.',
+ delete: '삭제',
+ addTitle: '알림 제공자 추가',
+ editTitle: '알림 제공자 편집',
+ nameLabel: '이름 *',
+ namePlaceholder: '내 알림',
+ providerTypeLabel: '제공자 유형 *',
+ configuration: '구성',
+ testConfiguration: '구성 테스트',
+ printerFilter: '프린터 필터',
+ onlyFromPrinter: '이 프린터의 이벤트에 대한 알림만 전송',
+ quietHoursDnd: '방해 금지 시간',
+ quietStart: '시작',
+ quietEnd: '종료',
+ dailyDigestLabel: '일일 요약',
+ sendDigestAt: '요약 전송 시각',
+ digestCollected: '이벤트가 수집되어 이 시간에 하나의 요약으로 전송됩니다',
+ notificationEvents: '알림 이벤트',
+ progressPercent: '(25%, 50%, 75%)',
+ bedCooledAfterPrint: '(인쇄 완료 후)',
+ eventPriority: {
+ sectionTitle: 'ntfy 우선순위',
+ helpNtfy: '각 활성화된 이벤트에 대한 우선순위를 선택하세요. ntfy는 이를 사용하여 알림을 에스컬레이션합니다(소리, 가시성, 푸시 동작). 여기서 설정되지 않은 수준은 ntfy 서버 기본값을 사용합니다.',
+ min: '최소',
+ low: '낮음',
+ default: '기본값',
+ high: '높음',
+ urgent: '긴급'
+ },
+ cancel: '취소',
+ save: '저장',
+ add: '추가',
+ nameRequired: '이름이 필요합니다',
+ fieldRequired: '{{field}}이(가) 필요합니다',
+ phoneNumber: '전화번호',
+ apiKey: 'API 키',
+ serverUrl: '서버 URL',
+ topic: '토픽',
+ authToken: '인증 토큰',
+ userKey: '사용자 키',
+ appToken: '앱 토큰',
+ priority: '우선순위',
+ botToken: '봇 토큰',
+ chatId: '채팅 ID',
+ smtpServer: 'SMTP 서버',
+ smtpPort: 'SMTP 포트',
+ security: '보안',
+ authentication: '인증',
+ username: '사용자 이름',
+ password: '비밀번호',
+ fromEmail: '발신 이메일',
+ toEmail: '수신 이메일',
+ webhookUrl: 'Webhook URL',
+ payloadFormat: '페이로드 형식',
+ authorization: '인증',
+ titleFieldName: '제목 필드 이름',
+ messageFieldName: '메시지 필드 이름',
+ editTemplate: '템플릿 편집: {{name}}',
+ titleLabel: '제목',
+ bodyLabel: '본문',
+ titlePlaceholder: '알림 제목...',
+ bodyPlaceholder: '알림 본문...',
+ availableVariables: '사용 가능한 변수',
+ clickToInsert: '클릭하여 본문의 커서 위치에 삽입',
+ livePreview: '실시간 미리보기',
+ hide: '숨기기',
+ show: '표시',
+ loadingPreview: '미리보기 불러오는 중...',
+ enterTemplateContent: '미리보기를 보려면 템플릿 내용을 입력하세요',
+ titlePreview: '제목:',
+ bodyPreview: '본문:',
+ resetToDefault: '기본값으로 초기화',
+ titleRequired: '제목이 필요합니다',
+ bodyRequired: '본문이 필요합니다',
+ notificationLog: '알림 로그',
+ showFailedOnly: '실패만',
+ last24Hours: '최근 24시간',
+ last7Days: '최근 7일',
+ last30Days: '최근 30일',
+ last90Days: '최근 90일',
+ justNow: '방금',
+ noFailedNotifications: '실패한 알림 없음',
+ noNotificationsLogged: '기록된 알림 없음',
+ unknownProvider: '알 수 없는 제공자',
+ logTitle: '제목',
+ logMessage: '메시지',
+ logError: '오류',
+ logProvider: '제공자: {{type}}',
+ logTime: '시간: {{time}}',
+ refresh: '새로고침',
+ clearOld: '오래된 것 삭제',
+ statsSummary: '최근 {{days}}일:',
+ statsNotifications: '알림',
+ statsSent: '{{count}}개 전송됨',
+ statsFailed: '{{count}}개 실패',
+ eventTypes: {
+ print_start: '인쇄 시작됨',
+ print_complete: '인쇄 완료',
+ print_failed: '인쇄 실패',
+ print_stopped: '인쇄 중지됨',
+ print_progress: '진행률',
+ printer_offline: '프린터 오프라인',
+ printer_error: '프린터 오류',
+ filament_low: '필라멘트 부족',
+ maintenance_due: '유지 관리 필요',
+ test: '테스트'
+ },
+ userEmail: {
+ title: '알림',
+ emailNotifications: '이메일 알림',
+ emailNotificationsDesc: '내 인쇄 작업에 대한 이메일 알림을 받습니다. 이메일은 고급 인증에서 구성된 시스템 SMTP 설정을 사용하여 전송됩니다.',
+ sendingTo: '알림이 전송될 주소',
+ noEmailWarning: '계정에 이메일 주소가 없습니다. 관리자에게 연락하여 추가하세요.',
+ printJobNotifications: '인쇄 작업 알림',
+ printJobNotificationsDesc: '내가 제출한 인쇄 작업에 대해 이메일 알림을 트리거할 이벤트를 선택하세요.',
+ printJobStarts: '인쇄 작업 시작',
+ printJobStartsDesc: '인쇄 작업이 시작될 때 알림 받기.',
+ printJobFinishes: '인쇄 작업 완료',
+ printJobFinishesDesc: '인쇄 작업이 성공적으로 완료될 때 알림 받기.',
+ printErrors: '인쇄 오류',
+ printErrorsDesc: '인쇄 작업이 실패하거나 오류가 발생할 때 알림 받기.',
+ printJobStops: '인쇄 작업 중지',
+ printJobStopsDesc: '인쇄 작업이 취소되거나 중지될 때 알림 받기.',
+ saveSuccess: '알림 환경 설정이 저장되었습니다.',
+ saveError: '알림 환경 설정 저장 실패.'
+ }
+ },
+ richTextEditor: {
+ bold: '굵게',
+ italic: '기울임',
+ underline: '밑줄',
+ bulletList: '글머리 기호 목록',
+ numberedList: '번호 목록',
+ alignLeft: '왼쪽 정렬',
+ alignCenter: '가운데 정렬',
+ alignRight: '오른쪽 정렬',
+ addLink: '링크 추가',
+ removeLink: '링크 제거'
+ },
+ externalLinks: {
+ noLinksConfigured: '구성된 외부 링크 없음',
+ deleteLink: '링크 삭제',
+ removeCustomIcon: '사용자 지정 아이콘 제거',
+ openInNewTab: '새 탭에서 열기',
+ placeholders: {
+ linkName: '내 링크'
+ }
+ },
+ keyboardShortcuts: {
+ title: '키보드 단축키',
+ navigation: '탐색',
+ archivesSection: '아카이브',
+ kProfilesSection: 'K-프로필',
+ generalSection: '일반',
+ shortcuts: {
+ goToPrinters: '프린터로 이동',
+ goToArchives: '아카이브로 이동',
+ goToQueue: '대기열로 이동',
+ goToStats: '통계로 이동',
+ goToProfiles: '클라우드 프로필로 이동',
+ goToSettings: '설정으로 이동',
+ focusSearch: '검색 포커스',
+ openUploadModal: '업로드 모달 열기',
+ clearSelection: '선택 초기화 / 입력 포커스 해제',
+ contextMenu: '카드 컨텍스트 메뉴',
+ refreshProfiles: '프로필 새로고침',
+ newProfile: '새 프로필',
+ exitSelectionMode: '선택 모드 종료',
+ showHelp: '이 도움말 표시'
+ },
+ footer: 'Esc를 누르거나 외부를 클릭하여 닫기'
+ },
+ notificationLog: {
+ title: '알림 로그',
+ events: {
+ printStarted: '인쇄 시작됨',
+ printComplete: '인쇄 완료',
+ printFailed: '인쇄 실패',
+ printStopped: '인쇄 중지됨',
+ progress: '진행률',
+ printerOffline: '프린터 오프라인',
+ printerError: '프린터 오류',
+ lowFilament: '필라멘트 부족',
+ maintenanceDue: '유지 관리 필요',
+ test: '테스트'
+ },
+ timeAgo: {
+ justNow: '방금',
+ minutesAgo: '{{minutes}}분 전',
+ hoursAgo: '{{hours}}시간 전'
+ }
+ },
+ restoreBackup: {
+ title: '백업 복원',
+ restoring: '복원 중...',
+ restoreComplete: '복원 완료',
+ restoreFailed: '복원 실패',
+ importSettings: '백업 파일에서 설정 가져오기',
+ pleaseWait: '데이터가 복원되는 동안 기다려 주세요',
+ clickToSelect: '백업 파일 클릭하여 선택 (.json 또는 .zip)',
+ howDuplicateHandling: '중복 처리 방법:',
+ categories: {
+ printers: '프린터',
+ smartPlugs: '스마트 플러그',
+ notificationProviders: '알림 제공자',
+ filaments: '필라멘트',
+ archives: '아카이브',
+ pendingUploads: '대기 중인 업로드',
+ settingsTemplates: '설정 및 템플릿'
+ },
+ matchingInfo: {
+ printers: '일련번호로 일치',
+ smartPlugs: 'IP 주소로 일치',
+ notificationProviders: '이름으로 일치',
+ filaments: '이름 + 유형 + 브랜드로 일치',
+ archives: '콘텐츠 해시로 일치',
+ pendingUploads: '파일 이름으로 일치',
+ settingsTemplates: '항상 덮어씀'
+ },
+ replaceExisting: '기존 데이터 교체',
+ keepExisting: '기존 데이터 유지',
+ replaceDescription: '백업 데이터로 이미 존재하는 항목 덮어쓰기',
+ keepDescription: '아직 존재하지 않는 항목만 복원',
+ caution: '주의:',
+ cautionText: '덮어쓰기는 현재 구성을 백업 데이터로 교체합니다. 보안상 프린터 액세스 코드는 절대 덮어쓰지 않습니다.',
+ itemsRestored: '복원된 항목',
+ itemsSkipped: '건너뛴 항목',
+ restored: '복원됨',
+ skipped: '건너뜀 (이미 존재)',
+ filesLabel: '파일 (3MF, 썸네일 등)',
+ newApiKeysGenerated: '새 API 키 생성됨',
+ newApiKeysWarning: '이 키는 한 번만 표시됩니다. 지금 복사하세요!',
+ processingBackup: '백업 파일 처리 중...',
+ noDataFound: '백업 파일에서 복원할 데이터를 찾을 수 없습니다.',
+ failedToRestore: '백업 복원 실패. 파일 형식을 확인하세요.'
+ },
+ backupExport: {
+ title: '백업 내보내기',
+ selectData: '포함할 데이터 선택',
+ selectAll: '모두 선택',
+ selectNone: '선택 없음',
+ categoryDescriptions: {
+ settings: '언어, 테마, 업데이트 환경 설정',
+ notifications: 'ntfy, Pushover, Discord 등',
+ templates: '사용자 지정 메시지 템플릿',
+ smartPlugs: 'Tasmota 플러그 구성',
+ externalLinks: '외부 서비스에 대한 사이드바 링크',
+ printers: '프린터 정보 (액세스 코드 제외)',
+ plateDetection: '빈 플레이트 기준 이미지',
+ filaments: '필라멘트 유형 및 비용',
+ maintenance: '사용자 지정 유지 관리 일정',
+ archives: '모든 인쇄 데이터 + 파일 (3MF, 썸네일, 사진)',
+ projects: '프로젝트, BOM 항목 및 첨부 파일',
+ pendingUploads: '검토 대기 중인 가상 프린터 업로드',
+ apiKeys: 'Webhook API 키 (가져오기 시 새 키 생성)'
+ },
+ requiresPrinters: '프린터 선택 필요',
+ zipFileWarning: 'ZIP 파일이 생성됩니다.',
+ zipFileDescription: '모든 3MF 파일, 썸네일, 타임랩스 및 사진을 포함합니다. 시간이 걸리고 파일이 커질 수 있습니다.',
+ includeAccessCodes: '액세스 코드 포함',
+ includeAccessCodesDescription: '다른 기기로 전송하는 경우',
+ includeAccessCodesWarning: '액세스 코드가 평문으로 포함됩니다. 이 백업 파일을 안전하게 보관하세요!',
+ categoriesSelected: '{{selectedCount}}개 카테고리 선택됨'
+ },
+ pendingUploads: {
+ placeholders: {
+ notes: '이 인쇄에 대한 메모 추가...'
+ },
+ discardUpload: '업로드 삭제',
+ archiveAllUploads: '모든 업로드 아카이브',
+ discardAllUploads: '모든 업로드 삭제',
+ archive: '아카이브',
+ timeAgo: {
+ justNow: '방금',
+ minutesAgo: '{{minutes}}분 전',
+ hoursAgo: '{{hours}}시간 전',
+ daysAgo: '{{days}}일 전'
+ }
+ },
+ apiBrowser: {
+ placeholders: {
+ requestBody: 'JSON 요청 본문...',
+ searchEndpoints: '엔드포인트 검색...'
+ }
+ },
+ configureAmsSlot: {
+ title: 'AMS 슬롯 구성',
+ slotConfigured: '슬롯 구성됨!',
+ configuringSlot: '슬롯 구성 중:',
+ slotLabel: '{{ams}} 슬롯 {{slot}}',
+ searchPresets: '프리셋 검색...',
+ colorPlaceholder: '색상 이름 또는 16진수 (예: brown, FF8800)',
+ clearCustomColor: '사용자 지정 색상 초기화',
+ noCloudPresets: '클라우드 프리셋 없음. Bambu 클라우드에 로그인하여 동기화하세요.',
+ noPresetsAvailable: '사용 가능한 프리셋 없음. Bambu 클라우드에 로그인하거나 로컬 프로필을 가져오세요.',
+ noMatchingPresets: '일치하는 프리셋을 찾을 수 없습니다.',
+ custom: '사용자 지정',
+ builtin: '기본 제공',
+ settingsSentToPrinter: '설정이 프린터로 전송됨',
+ filamentProfile: '필라멘트 프로필',
+ kProfileLabel: 'K 프로필 (압력 전진)',
+ filteringFor: '필터링 중: {{material}}',
+ noKProfile: 'K 프로필 없음 (기본값 0.020 사용)',
+ noMatchingKProfiles: '일치하는 K 프로필을 찾을 수 없습니다. 기본값 K=0.020이 사용됩니다.',
+ selectFilamentFirst: '먼저 필라멘트 프로필을 선택하세요',
+ kFromCalibration: 'K={{value}} (프린터 보정에서)',
+ customColorLabel: '사용자 지정 색상 (선택사항)',
+ presetColors: '{{name}} 색상:',
+ showLessColors: '색상 간략히 보기',
+ showMoreColors: '더 많은 색상 보기',
+ clear: '초기화',
+ hexLabel: '16진수: #{{hex}}',
+ resetting: '초기화 중...',
+ resetSlot: '슬롯 초기화',
+ cancel: '취소',
+ configuring: '구성 중...',
+ configureSlot: '슬롯 구성'
+ },
+ githubBackup: {
+ title: 'Git 백업',
+ history: '기록',
+ downloadBackup: '백업 다운로드',
+ restoreBackup: '백업 복원',
+ noBackupsYet: '아직 백업 없음'
+ },
+ emailSettings: {
+ placeholders: {
+ fromName: 'Bambuddy'
+ }
+ },
+ tagManagement: {
+ searchTags: '태그 검색...',
+ renameTag: '태그 이름 바꾸기',
+ deleteTag: '태그 삭제'
+ },
+ notificationTemplates: {
+ placeholders: {
+ title: '알림 제목...',
+ body: '알림 본문...'
+ }
+ },
+ batchTag: {
+ placeholders: {
+ newTag: '새 태그 입력...'
+ }
+ },
+ photoGallery: {
+ deletePhoto: '사진 삭제'
+ },
+ filamentHoverCard: {
+ copySpoolUuid: '스풀 UUID 복사'
+ },
+ kProfilesView: {
+ hasNote: '메모 있음',
+ copyProfile: '프로필 복사'
+ },
+ layout: {
+ openMenu: '메뉴 열기',
+ noPermissionSystemInfo: '시스템 정보를 볼 권한이 없습니다'
+ },
+ dashboard: {
+ dragToReorder: '드래그하여 순서 변경',
+ hideWidget: '위젯 숨기기'
+ },
+ notificationProviderCard: {
+ deleteNotificationProvider: '알림 제공자 삭제'
+ },
+ fileManagerModal: {
+ closeFileManager: '파일 관리자 닫기',
+ sortFiles: '파일 정렬',
+ goToParentFolder: '상위 폴더로 이동',
+ threeView: '3D 보기'
+ },
+ embeddedCameraViewer: {
+ refreshStream: '스트림 새로고침',
+ close: '닫기',
+ zoomOut: '축소',
+ resetZoom: '배율 초기화',
+ zoomIn: '확대',
+ dragToResize: '드래그하여 크기 조정'
+ },
+ timelapseViewer: {
+ skipBack5s: '5초 뒤로',
+ skipForward5s: '5초 앞으로'
+ },
+ notificationProviders: {
+ descriptions: {
+ email: 'SMTP 이메일 알림',
+ telegram: 'Telegram 봇을 통한 알림',
+ discord: 'Webhook을 통해 Discord 채널로 전송',
+ ntfy: '무료, 자체 호스팅 가능한 푸시 알림',
+ pushover: '간단하고 신뢰할 수 있는 푸시 알림',
+ callmebot: 'CallMeBot을 통한 무료 WhatsApp 알림',
+ webhook: '모든 URL에 일반 HTTP POST'
+ }
+ },
+ logViewer: {
+ searchPlaceholder: '메시지 또는 로거 이름 검색...',
+ noLogEntries: '로그 항목을 찾을 수 없음'
+ },
+ switchbarPopover: {
+ noSwitchesInSwitchbar: '스위치바에 스위치 없음'
+ },
+ projectPageModal: {
+ placeholders: {
+ title: '제목',
+ designer: '디자이너',
+ license: '라이선스',
+ description: '설명 입력...',
+ profileTitle: '프로필 제목',
+ profileDescription: '프로필 설명...'
+ }
+ },
+ SpoolmanSettings: {},
+ time: {
+ unknown: '-',
+ waiting: '대기 중',
+ justNow: '방금',
+ now: '지금',
+ minsAgo: '{{count}}분 전',
+ inMins: '{{count}}분 후',
+ hoursAgo: '{{count}}시간 전',
+ inHours: '{{count}}시간 후',
+ daysAgo: '{{count}}일 전',
+ inDays: '{{count}}일 후'
+ },
+ spoolbuddy: {
+ nav: {
+ dashboard: '대시보드',
+ ams: 'AMS',
+ inventory: '재고',
+ writeTag: '태그 쓰기',
+ settings: '설정'
+ },
+ status: {
+ nfcReady: 'NFC 준비됨',
+ nfcOff: 'NFC 꺼짐',
+ offline: '오프라인',
+ online: '온라인',
+ noPrinters: '프린터 없음',
+ deviceOffline: '장치 오프라인',
+ waitingConnection: '장치 연결 대기 중...',
+ systemReady: '시스템 준비됨',
+ status: '상태'
+ },
+ dashboard: {
+ readyToScan: '스캔 준비됨',
+ idleMessage: '스풀을 저울에 올려 식별하세요',
+ nfcHint: 'NFC 태그가 자동으로 읽힙니다',
+ device: '장치',
+ syncWeight: '무게 동기화',
+ weightSynced: '동기화됨!',
+ unknownTag: '알 수 없는 태그',
+ newTag: '새 태그 감지됨',
+ onScale: '저울 위',
+ linkSpool: '스풀에 연결',
+ linkTagTitle: '태그를 스풀에 연결',
+ linkTag: '태그 연결',
+ selectSpool: '이 태그를 연결할 스풀 선택:',
+ noUntagged: '태그 없는 스풀을 찾을 수 없음',
+ tagDetected: '태그 감지됨',
+ noTag: '태그 없음',
+ tagId: '태그',
+ grossWeight: '총 무게',
+ spoolSize: '스풀 크기',
+ close: '닫기',
+ currentSpool: '현재 스풀',
+ plateReady: '플레이트 준비됨: {{name}}',
+ plateReadyLabel: '초기화할 플레이트',
+ plateClearAction: '초기화',
+ plateClearedToast: '플레이트가 초기화됨으로 표시됨',
+ plateClearFailed: '플레이트를 초기화됨으로 표시할 수 없음'
+ },
+ modal: {
+ spoolDetected: '스풀 감지됨',
+ assignToAms: 'AMS에 할당',
+ syncWeight: '무게 동기화',
+ weightSynced: '동기화됨!',
+ syncing: '동기화 중...',
+ newTagDetected: '새 태그 감지됨',
+ addToInventory: '재고에 추가',
+ assignToAmsTitle: 'AMS에 할당',
+ selectSlot: '슬롯 선택',
+ assign: '할당',
+ assigning: '할당 중...',
+ assignSuccess: '할당됨!',
+ assignPendingInsert: '할당됨. 스풀을 삽입하면 슬롯이 구성됩니다.',
+ assignError: '스풀 할당 실패. 다시 시도하세요.',
+ noPrinterSelected: '프린터 선택...',
+ noAmsDetected: '이 프린터에서 AMS가 감지되지 않음',
+ slot: '슬롯'
+ },
+ weight: {
+ noReading: '읽기 없음',
+ stable: '안정됨',
+ measuring: '측정 중...',
+ tare: '영점 조정',
+ calibrate: '보정'
+ },
+ spool: {
+ remaining: '남은 양',
+ material: '재료',
+ brand: '브랜드',
+ color: '색상',
+ coreWeight: '코어',
+ labelWeight: '라벨',
+ scaleWeight: '저울',
+ netWeight: '순 무게',
+ lastUsed: '마지막 사용'
+ },
+ ams: {
+ noData: 'AMS가 감지되지 않음',
+ connectAms: '필라멘트 슬롯을 보려면 AMS를 연결하세요',
+ noPrinter: '선택된 프린터 없음',
+ selectPrinter: '상단 표시줄에서 프린터를 선택하세요',
+ printerDisconnected: '프린터 연결 끊김',
+ humidity: '습도',
+ level: '레벨',
+ active: '활성',
+ slot: '슬롯',
+ empty: '비어 있음'
+ },
+ inventory: {
+ search: '스풀 검색...',
+ empty: '재고에 스풀 없음',
+ noResults: '일치하는 스풀 없음',
+ spools: '스풀',
+ addSpool: '스풀 추가'
+ },
+ settings: {
+ tabDevice: '장치',
+ tabDisplay: '화면',
+ tabScale: '저울',
+ tabUpdates: '업데이트',
+ nfcReader: 'NFC 리더',
+ type: '유형',
+ connection: '연결',
+ notConnected: 'N/A',
+ deviceInfo: '장치 정보',
+ hostname: '호스트',
+ uptime: '가동 시간',
+ systemConfig: '백엔드 및 인증',
+ backendUrl: 'Bambuddy 백엔드 URL',
+ apiToken: 'API 토큰',
+ apiTokenPlaceholder: 'API 토큰 입력',
+ saveConfig: '구성 저장',
+ systemQueued: '구성 대기 중.',
+ nfcDiagnostic: 'NFC 진단',
+ scaleDiagnostic: '저울 진단',
+ readTagDiagnostic: '태그 읽기 진단',
+ testNfc: '리더 테스트',
+ testScale: '정확도 테스트',
+ testReadTag: '태그 읽기',
+ systemFieldsRequired: '백엔드 URL이 필요합니다.',
+ brightness: '밝기',
+ saved: '저장됨',
+ noBacklight: 'DSI 백라이트가 감지되지 않음. 밝기 제어는 DSI 디스플레이가 필요합니다.',
+ screenBlank: '화면 꺼짐 대기 시간',
+ screenBlankDesc: '비활성 후 화면이 꺼집니다. 터치하여 깨우세요.',
+ displayNote: '밝기는 소프트웨어 필터로 적용됩니다.',
+ scaleCalibration: '저울 보정',
+ currentWeight: '현재 무게',
+ tareOffset: '영점',
+ calFactor: '계수',
+ knownWeight: '알려진 무게',
+ calStep1: '저울에서 모든 물건을 제거하고 영점 설정을 누르세요.',
+ calStep2: '저울에 알려진 무게를 올리세요.',
+ setZero: '영점 설정',
+ calibrateNow: '보정',
+ calibrated: '보정됨',
+ tareSet: '영점 조정 명령 전송됨. 장치 대기 중...',
+ tareComplete: '영점 조정 완료!',
+ tareTimedOut: '영점 조정 시간 초과 — SpoolBuddy 데몬이 실행 중인가요?',
+ tareFailed: '영점 조정 명령 전송 실패',
+ zeroSet: '영점이 설정됨. 저울에 알려진 무게를 올리세요.',
+ calibrationDone: '보정 완료!',
+ calibrationFailed: '보정 실패',
+ lastCalibrated: '마지막 보정',
+ stable: '안정됨',
+ settling: '안정화 중...',
+ firmware: '펌웨어',
+ scale: '저울',
+ noDevice: 'SpoolBuddy 장치를 찾을 수 없음',
+ daemonVersion: '데몬 버전',
+ currentVersion: '현재',
+ versionPending: '데몬 대기 중...',
+ checking: '확인 중...',
+ checkUpdates: '업데이트 확인',
+ updateAvailable: '업데이트 사용 가능',
+ updateInstructions: 'SSH를 통해 업데이트: SpoolBuddy 설치 스크립트를 실행하여 업그레이드하세요.',
+ upToDate: '최신 버전',
+ includeBeta: '베타 버전 포함'
+ },
+ writeTag: {
+ tabExisting: '기존 스풀',
+ tabNew: '새 스풀',
+ tabReplace: '태그 교체',
+ searchPlaceholder: '재료, 색상, 브랜드로 검색...',
+ noUntaggedSpools: '태그 없는 스풀 없음',
+ noTaggedSpools: '태그 있는 스풀 없음',
+ selectSpool: '스풀을 선택한 후 빈 NTAG를 리더에 올려놓으세요',
+ placeTag: 'NTAG를 리더에 올려놓으세요',
+ tagReady: '태그 감지됨 — 쓰기 준비됨',
+ writeTag: '태그 쓰기',
+ replaceTag: '태그 교체',
+ writing: '태그 쓰는 중...',
+ waiting: 'SpoolBuddy 대기 중...',
+ writeSuccess: '태그 성공적으로 쓰여짐!',
+ writeFailed: '쓰기 실패',
+ queueFailed: '쓰기 명령 대기 실패',
+ tryAgain: '다시 시도',
+ cancel: '취소',
+ replaceWarning: '이전 태그가 연결 해제됩니다. 새 태그가 교체합니다.',
+ deviceOffline: 'SpoolBuddy가 오프라인입니다',
+ material: '재료',
+ colorName: '색상 이름',
+ color: '색상',
+ brand: '브랜드',
+ weight: '무게 (g)',
+ createSpool: '스풀 생성',
+ creating: '생성 중...',
+ spoolCreated: '스풀 생성됨! 쓰기 준비됨.',
+ createFailed: '스풀 생성 실패',
+ incompleteDataWarning: '불완전한 Spoolman 데이터로 태그 쓰여짐'
+ },
+ quickMenu: {
+ printerPower: '프린터 전원',
+ systemControls: '시스템',
+ restartDaemon: '데몬 재시작',
+ restartBrowser: '브라우저 재시작',
+ reboot: '재부팅',
+ shutdown: '종료',
+ swipeToClose: '아래로 스와이프하여 닫기',
+ confirmTitle: '확인',
+ confirmShutdown: 'SpoolBuddy를 종료하시겠습니까? 다시 켜려면 물리적 접근이 필요합니다.',
+ confirmReboot: 'SpoolBuddy를 재부팅하시겠습니까?',
+ confirmRestartDaemon: 'SpoolBuddy 데몬을 재시작하시겠습니까? NFC와 저울이 일시적으로 사용 불가능합니다.',
+ confirmRestartBrowser: '키오스크 브라우저를 재시작하시겠습니까? 화면이 잠시 꺼집니다.',
+ confirm: '확인',
+ confirmPlugOn: '{{name}}을(를) 켜시겠습니까?',
+ confirmPlugOff: '{{name}}을(를) 끄시겠습니까?',
+ turnOn: '켜기',
+ turnOff: '끄기'
+ }
+ },
+ bugReport: {
+ title: '버그 신고',
+ description: '설명',
+ descriptionPlaceholder: '무엇이 잘못되었나요? 문제를 설명해 주세요...',
+ email: '이메일 (선택사항)',
+ emailPlaceholder: 'your@email.com',
+ emailPrivacy: '제공하면 이메일이 GitHub 이슈의 접힌 섹션에 포함되어 관리자가 후속 조치를 취할 수 있습니다.',
+ screenshot: '스크린샷',
+ uploadOrPaste: '이미지 업로드, 붙여넣기 또는 드래그',
+ dataCollectedSummary: '보고서에 포함되는 데이터는?',
+ dataIncluded: '포함됨:',
+ dataIncludedList: '앱 버전, OS, 아키텍처, Python 버전, 데이터베이스 통계(개수만), 프린터 모델, 노즐 개수, 펌웨어 버전, 연결 상태, 통합 상태(Spoolman, MQTT, HA), 비민감 설정, 네트워크 인터페이스 수, Docker 세부 정보, 의존성 버전.',
+ dataNeverIncluded: '절대 포함되지 않음:',
+ dataNeverIncludedList: '프린터 이름, 일련 번호, 액세스 코드, 비밀번호, IP 주소, 이메일 주소, API 키, 토큰, Webhook URL, 호스트 이름 또는 사용자 이름.',
+ submit: '제출',
+ startLogging: '디버그 로깅 시작',
+ stepEnableLogging: '디버그 로깅 활성화됨',
+ stepReproduce: '이제 문제를 재현하세요',
+ stepStopLogging: '중지 후 보고서 제출',
+ stopAndSubmit: '중지 후 제출',
+ maxDuration: '{{minutes}}분 후 자동 중지',
+ stoppingLogs: '로그 수집 및 제출 중...',
+ submitting: '버그 보고서 제출 중...',
+ submitSuccess: '버그 보고서가 성공적으로 제출되었습니다!',
+ submitFailed: '버그 보고서 제출 실패',
+ thankYou: '감사합니다!',
+ submitted: '버그 보고서가 제출되었습니다.',
+ viewIssue: '이슈 보기',
+ unexpectedError: '예상치 못한 오류가 발생했습니다',
+ submittingStepConnection: '프린터 연결 확인 실행 중',
+ submittingStepVirtualPrinters: '가상 프린터 설정 확인 실행 중',
+ submittingStepLogScan: '알려진 문제가 있는지 최근 로그 스캔 중',
+ submittingStepSubmit: 'GitHub에 보고서 제출 중',
+ diagnosticChecking: '프린터 연결 확인 중...',
+ diagnosticHealthy: '연결 확인 통과 — 프린터에서 문제가 발견되지 않았습니다.',
+ diagnosticSummary: '{{total}}개 프린터 중 {{problems}}개에서 연결 문제가 있습니다',
+ diagnosticIntro: '하나 이상의 프린터에 연결 문제가 있어 현재 문제의 원인일 수 있습니다. 아래에서 프린터를 펼쳐 수정 방법을 확인하세요 — 해결하면 버그 보고서 없이 문제가 해결될 수 있습니다. 아래에서 보고서를 제출할 수도 있습니다.',
+ logHealthSummary: '로그에서 알려진 문제가 발견되었습니다',
+ logHealthIntro: '최근 로그가 알려진 문제와 일치합니다. 아래 수정 방법을 확인하세요 — 해결하면 버그 보고서 없이 문제가 해결될 수 있습니다. 아래에서 보고서를 제출할 수도 있습니다.'
+ },
+ failureDetection: {
+ title: 'AI 실패 감지',
+ description: '자체 호스팅 Obico ML API로 인쇄를 모니터링하고 감지된 실패에 자동으로 조치합니다.',
+ mlUrl: 'Obico ML API URL',
+ mlUrlHint: '자체 호스팅 Obico ml_api 컨테이너의 기본 URL (예: http://192.168.1.10:3333).',
+ test: '테스트',
+ testSuccess: 'ML API에 도달 가능하며 정상입니다.',
+ testFailed: 'ML API에 도달할 수 없습니다.',
+ sensitivity: '민감도',
+ sensitivityLow: '낮음 (오탐 적음)',
+ sensitivityMedium: '중간 (균형)',
+ sensitivityHigh: '높음 (조기 감지, 오탐 많음)',
+ sensitivityHint: '경고 및 실패를 트리거하는 신뢰도 임계값을 조정합니다.',
+ action: '감지된 실패에 대한 조치',
+ actionNotify: '알림만',
+ actionPause: '인쇄 일시 중지',
+ actionPauseOff: '일시 중지 후 전원 끄기',
+ pollInterval: '폴링 간격 (초)',
+ pollIntervalHint: '인쇄 중 각 프린터를 확인하는 빈도. 최소 5초, 최대 120초.',
+ externalUrlMissing: '외부 URL이 설정되지 않았습니다.',
+ externalUrlHint: 'ML API가 URL을 통해 카메라 스냅샷을 가져옵니다. ML API 컨테이너가 Bambuddy에 도달할 수 있도록 일반 설정에서 외부 URL을 설정하세요.',
+ perPrinterTitle: '모니터링되는 프린터',
+ perPrinterHint: '감지 서비스가 감시할 프린터를 선택하세요.',
+ monitorAll: '연결된 모든 프린터 모니터링',
+ statusTitle: '상태',
+ serviceRunning: '서비스 실행 중',
+ thresholds: '낮음 / 높음 임계값',
+ activePrinters: '활성 인쇄물',
+ noActivePrints: '현재 실행 중인 인쇄물 없음.',
+ historyTitle: '최근 감지',
+ noHistory: '아직 감지 없음.'
+ },
+ makerworld: {
+ title: 'MakerWorld',
+ description: 'MakerWorld 모델 URL을 붙여넣어 Bambu Handy 앱을 떠나지 않고 Bambuddy에서 직접 가져오고 인쇄하세요.',
+ pasteUrlHeader: 'MakerWorld에서 가져오기',
+ pasteUrlPlaceholder: 'https://makerworld.com/en/models/… 또는 MakerWorld 링크 붙여넣기',
+ resolveButton: '확인',
+ signInRequiredTitle: '다운로드하려면 Bambu 클라우드 로그인 필요',
+ signInRequiredBody: '익명으로 모델 세부 정보를 탐색할 수 있지만 MakerWorld는 3MF 파일을 다운로드하려면 Bambu 클라우드 계정이 필요합니다.',
+ openCloudSettings: '클라우드 설정 열기',
+ untitledModel: '제목 없는 모델',
+ byCreator: '{{name}} 제작',
+ downloadsCount: '{{count}}회 다운로드',
+ licensePrefix: '라이선스',
+ alreadyImported: '이미 라이브러리에 있음',
+ openOnMakerworld: 'MakerWorld에서 열기',
+ alreadyInLibrary: '이 모델이 이미 라이브러리에 있습니다 — 파일 관리자 → MakerWorld에서 찾으세요',
+ importSuccess: '{{filename}} 가져옴 — 파일 관리자 → MakerWorld에 저장됨',
+ platesHeader: '플레이트 ({{count}})',
+ plateDefaultName: '플레이트 {{n}}',
+ materialCount: '{{count}}개 필라멘트',
+ amsRequired: 'AMS 필요',
+ slicedFor: '{{printer}}용으로 슬라이싱됨',
+ alsoCompatible: '호환 가능으로도 표시됨: {{printers}}',
+ importToLibrary: '저장',
+ sliceIn: '{{slicer}}에서 저장 및 슬라이싱',
+ disclaimer: 'MakerWorld 통합은 커뮤니티가 문서화한 API 엔드포인트를 사용합니다. Bambuddy는 MakerWorld 또는 Bambu Lab과 제휴하거나 이들의 승인을 받지 않았습니다.',
+ lastImportSuccess: '라이브러리에 가져옴',
+ lastImportAlreadyInLibrary: '이미 라이브러리에 있음',
+ viewInLibrary: '파일 관리자에서 보기',
+ openInBambuStudio: 'Bambu Studio에서 열기',
+ openInOrcaSlicer: 'OrcaSlicer에서 열기',
+ importTo: '파일 관리자로 가져오기',
+ recentImportsHeader: '최근 가져오기',
+ phaseResolving: '확인 중',
+ phaseDownloading: '다운로드 중',
+ folderAuto: 'MakerWorld (기본값)',
+ importAll: '모두 가져오기',
+ importAllProgress: '{{total}}개 중 {{current}}개 가져오는 중',
+ openGallery: '이미지 갤러리 열기',
+ galleryPrev: '이전 이미지',
+ galleryNext: '다음 이미지',
+ deleteImport: '라이브러리에서 제거',
+ importDeleting: '제거 중…',
+ importDeleted: '라이브러리에서 제거됨',
+ confirmDelete: '라이브러리에서 {{filename}}을(를) 제거하시겠습니까? 로컬 파일이 삭제되지만 MakerWorld에서 다시 가져올 수 있습니다.',
+ errors: {
+ resolveFailed: 'MakerWorld URL을 확인할 수 없습니다.',
+ downloadFailed: '다운로드 실패. 다시 시도하세요.',
+ deleteFailed: '라이브러리에서 파일을 제거할 수 없습니다.'
+ }
+ },
+ gcodeViewer: {
+ back: '뒤로',
+ backToArchives: '인쇄 아카이브로 돌아가기',
+ backToFiles: '파일 관리자로 돌아가기'
+ },
+ libraryTrash: {
+ title: '휴지통',
+ headerButton: '휴지통',
+ headerTooltip: '휴지통으로 이동된 파일 보기',
+ backToFiles: '파일 관리자로 돌아가기',
+ subtitleAdmin: '삭제된 파일은 {{days}}일 동안 여기에 보관된 후 자동 삭제됩니다. 이 보기는 모든 사용자의 휴지통 파일을 표시합니다.',
+ subtitleUser: '삭제된 파일은 {{days}}일 동안 여기에 보관된 후 자동 삭제됩니다.',
+ loading: '휴지통 불러오는 중…',
+ loadError: '휴지통을 불러올 수 없습니다.',
+ empty: '휴지통이 비어 있습니다.',
+ summary: '{{count}}개 파일 · {{size}}',
+ emptyTrash: '휴지통 비우기',
+ restore: '복원',
+ purgeNow: '지금 삭제',
+ autoPurgeIn: '{{when}} 후 자동 삭제',
+ days: '일',
+ retentionLabel: '자동 삭제 기간',
+ selectAll: '모두 선택',
+ selectOne: '{{filename}} 선택',
+ selectionCount: '{{count}}개 선택됨',
+ bulkRestore: '선택 항목 복원',
+ bulkPurge: '선택 항목 삭제',
+ col: {
+ filename: '파일',
+ folder: '폴더',
+ size: '크기',
+ deleted: '휴지통 이동일',
+ autoPurge: '자동 삭제일',
+ owner: '소유자',
+ actions: '작업'
+ },
+ confirm: {
+ purgeTitle: '영구 삭제?',
+ purgeBody: '{{filename}}이(가) 디스크에서 삭제되며 복원할 수 없습니다.',
+ emptyTitle: '휴지통을 비우시겠습니까?',
+ emptyBody: '{{count}}개의 모든 파일이 디스크에서 삭제됩니다. 이 작업은 취소할 수 없습니다.',
+ bulkPurgeTitle: '선택한 파일을 영구 삭제하시겠습니까?',
+ bulkPurgeBody: '선택한 {{count}}개 파일이 디스크에서 삭제되며 복원할 수 없습니다.',
+ cta: '영구 삭제'
+ },
+ toast: {
+ restored: '파일이 복원되었습니다.',
+ restoreFailed: '파일을 복원할 수 없습니다.',
+ purged: '파일이 영구 삭제되었습니다.',
+ purgeFailed: '파일을 삭제할 수 없습니다.',
+ emptied: '휴지통에서 {{count}}개 파일이 삭제되었습니다.',
+ emptyFailed: '휴지통을 비울 수 없습니다.',
+ retentionSaved: '자동 삭제가 {{days}}일로 설정되었습니다.',
+ retentionFailed: '보존 설정을 저장할 수 없습니다.',
+ bulkRestored: '{{count}}개 파일이 복원되었습니다.',
+ bulkPurged: '{{count}}개 파일이 삭제되었습니다.'
+ }
+ },
+ libraryPurge: {
+ title: '오래된 파일 삭제',
+ headerButton: '오래된 파일 삭제',
+ headerTooltip: '오래된 파일을 휴지통으로 일괄 이동',
+ description: '라이브러리에서 오래된 파일을 한 번에 정리합니다. 인쇄 기록이 있는 파일은 마지막 인쇄 날짜 기준으로, 한 번도 인쇄되지 않은 파일은 업로드 날짜 기준으로 계산됩니다.',
+ ageLabel: '다음보다 오래된 파일 이동',
+ days: '일',
+ includeNeverPrinted: '한 번도 인쇄되지 않은 파일 포함',
+ effectsTitle: '삭제 클릭 시 일어나는 일',
+ effect1: '일치하는 파일이 휴지통으로 이동됩니다 — 디스크에서 아직 삭제되지 않습니다.',
+ effect2: '보존 기간이 만료되기 전까지 언제든 휴지통에서 복원할 수 있습니다.',
+ effect3: '보존 기간 후 휴지통 청소기가 디스크에서 영구적으로 제거합니다.',
+ effect4: '외부(연결된) 폴더의 파일은 건너뜁니다 — Bambuddy는 자신이 소유하지 않은 바이트는 절대 삭제하지 않습니다.',
+ previewLoading: '일치하는 파일 수 확인 중…',
+ previewFailed: '삭제 미리보기를 불러올 수 없습니다.',
+ previewSummary: '{{count}}개 파일 · {{size}}이(가) 휴지통으로 이동됩니다',
+ andMore: '…및 {{count}}개 더',
+ warning: '휴지통 파일은 보존 기간이 만료될 때까지 저장 공간을 차지합니다. 즉시 디스크를 확보하려면 나중에 휴지통을 비우세요.',
+ confirmCta: '{{count}}개를 휴지통으로 이동',
+ purging: '휴지통으로 이동 중…',
+ toast: {
+ success: '{{count}}개 파일을 휴지통으로 이동했습니다.',
+ failed: '파일을 삭제할 수 없습니다.'
+ }
+ },
+ libraryAutoPurge: {
+ enableLabel: '오래된 파일 자동 삭제',
+ enableDescription: '매일 한 번 관리자 삭제를 실행합니다. 파일이 먼저 휴지통으로 이동됩니다 — 즉시 삭제되지 않습니다.',
+ ageLabel: '다음보다 오래된 파일 자동 삭제',
+ ageDescription: '최소 7일, 최대 10년. 수동 삭제 버튼과 같은 날짜 규칙을 사용합니다.',
+ days: '일',
+ includeNeverPrinted: '한 번도 인쇄되지 않은 파일 포함',
+ saveFailed: '자동 삭제 설정을 저장할 수 없습니다.'
+ },
+ archivePurge: {
+ headerButton: '오래된 것 삭제',
+ headerTooltip: '오래된 아카이브 일괄 삭제',
+ title: '오래된 아카이브 삭제',
+ description: '오래된 인쇄 기록을 정리합니다. 각 아카이브는 가장 최근 인쇄 완료 시점 기준으로 계산됩니다 — 아카이브를 다시 인쇄하면 날짜가 새로고침되므로 활성 작업은 절대 삭제되지 않습니다.',
+ ageLabel: '다음 기간 동안 인쇄되지 않은 아카이브 삭제',
+ days: '일',
+ effectsTitle: '삭제 클릭 시 일어나는 일',
+ effect1: '일치하는 각 아카이브가 데이터베이스에서 영구적으로 제거됩니다.',
+ effect2: '3MF, 썸네일, 타임랩스, 소스 3MF, F3D 디자인 파일 및 사진 폴더가 모두 디스크에서 삭제됩니다.',
+ effect3: '아카이브에 대한 휴지통이 없습니다 — 삭제는 즉각적이며 취소할 수 없습니다.',
+ effect4: '아카이브를 다시 인쇄하면 날짜 카운터가 초기화되므로 여전히 사용하는 아카이브는 안전합니다.',
+ previewLoading: '일치하는 아카이브 수 확인 중…',
+ previewFailed: '삭제 미리보기를 불러올 수 없습니다.',
+ previewSummary: '{{count}}개 아카이브 · {{size}}이(가) 삭제됩니다',
+ andMore: '…및 {{count}}개 더',
+ warning: '영구적입니다. 계속하기 전에 보관하고 싶은 것을 다운로드하거나 즐겨찾기에 추가하세요.',
+ confirmCta: '{{count}}개 아카이브 삭제',
+ purging: '삭제 중…',
+ toast: {
+ success: '{{count}}개 아카이브가 삭제되었습니다.',
+ failed: '아카이브를 삭제할 수 없습니다.'
+ },
+ purgeStatsLabel: '통계에서도 제거',
+ purgeStatsHint: '일치하는 아카이브를 빠른 통계(필라멘트, 시간, 비용, 에너지)에서 삭제합니다. 이 옵션 없이는 빠른 통계는 모든 기여를 유지하고 파일만 디스크에서 제거됩니다.'
+ },
+ archiveAutoPurge: {
+ enableLabel: '오래된 아카이브 자동 삭제',
+ enableDescription: '매일 한 번, 임계값 내에 인쇄되지 않은 아카이브를 영구적으로 삭제합니다. 아카이브를 다시 인쇄하면 카운터가 초기화됩니다. 휴지통 없음 — 삭제는 즉각적입니다.',
+ ageLabel: '다음 기간 동안 인쇄되지 않은 아카이브 자동 삭제',
+ ageDescription: '최소 7일, 최대 10년. 가장 최근 인쇄 완료 시점 기준 — 아카이브를 다시 인쇄하면 날짜가 새로고침됩니다. 아카이브, 3MF, 썸네일, 타임랩스 및 사진을 삭제합니다.',
+ days: '일',
+ runNow: '지금 아카이브 삭제',
+ saveFailed: '자동 삭제 설정을 저장할 수 없습니다.',
+ purgeStatsLabel: '통계에서도 제거',
+ purgeStatsDescription: '활성화되면 일일 정리 작업도 각 삭제된 아카이브를 빠른 통계(필라멘트, 시간, 비용, 에너지)에서 제거합니다. 기본값 비활성화 — 빠른 통계는 기여를 유지하고 파일만 디스크에서 제거됩니다.'
+ },
+ cameraTokens: {
+ title: '카메라 API 토큰',
+ navTitle: '카메라 API 토큰',
+ description: 'Home Assistant, Frigate, 키오스크 또는 안정적인 URL이 필요한 다른 도구에 카메라 스트림을 내장하기 위한 장기 토큰. 각 토큰은 카메라 스트림 전용이며 언제든지 취소할 수 있습니다.',
+ loading: '불러오는 중…',
+ confirmRevoke: {
+ title: '이 토큰을 취소하시겠습니까?',
+ body: '\"{{name}}\"을(를) 사용하는 모든 장치가 즉시 접근을 잃습니다. 이 작업은 취소할 수 없습니다.',
+ cancel: '취소',
+ confirm: '취소'
+ },
+ create: {
+ title: '새 토큰 만들기',
+ nameLabel: '토큰 이름',
+ namePlaceholder: '예: Home Assistant',
+ daysLabel: '만료까지 일 수',
+ submit: '만들기',
+ hint: '최대 수명은 365일입니다. 토큰 값은 생성 시 한 번만 표시됩니다 — 지금 복사하세요.'
+ },
+ created: {
+ title: '토큰 생성됨 — 지금 복사하세요',
+ warning: '이 토큰은 이 번만 볼 수 있습니다. 이 대화상자를 닫으면 다시는 볼 수 없습니다.',
+ copy: '복사',
+ dismiss: '저장했습니다'
+ },
+ list: {
+ myTitle: '내 토큰',
+ allTitle: '모든 사용자 (관리자 보기)',
+ empty: '아직 토큰 없음.',
+ name: '이름',
+ owner: '소유자',
+ prefix: '접두사',
+ created: '생성일',
+ expires: '만료일',
+ lastUsed: '마지막 사용',
+ revoke: '취소',
+ expired: '만료됨'
+ },
+ toast: {
+ created: '토큰 생성됨',
+ createFailed: '토큰 생성 실패',
+ revoked: '토큰 취소됨',
+ revokeFailed: '토큰 취소 실패',
+ loadFailed: '토큰 불러오기 실패',
+ copied: '클립보드에 복사됨',
+ copyFailed: '복사 실패 — 수동으로 선택하여 복사하세요'
+ }
+ },
+ forecast: {
+ title: '예측',
+ noSpools: '활성 스풀을 찾을 수 없습니다. 예측 데이터를 보려면 재고에 스풀을 추가하세요.',
+ noUsageData: '사용 데이터를 사용할 수 없습니다 — 재고 타임라인을 예측할 수 없습니다.',
+ sku: 'SKU',
+ material: '재료',
+ stock: '재고',
+ dailyRate: '소비율',
+ daysLeft: '남은 일수',
+ emptyBy: '소진 예정일',
+ reorderBy: '재주문 기한',
+ actions: '작업',
+ trend: '추세',
+ estimated: '추정',
+ noData: '데이터 없음',
+ timeframe: '기간',
+ chartTitle: '예상 재고 — 상위 5개 재료',
+ dashedLinesROP: '점선 = 재주문 시점',
+ stockLevel: '재고 수준',
+ reorderPoint: '재주문 시점',
+ safetyMargin: '안전 마진',
+ trendLegend: '추세 (기록 기반, 95% 서비스 수준)',
+ estimatedLegend: '추정 (무게 변화)',
+ noDataLegend: '데이터 없음',
+ ropLabel: 'ROP',
+ ssLabel: 'SS',
+ safetyStockLegend: '안전 재고',
+ stockArrivalLegend: '재고 입고',
+ stockoutLegend: '재고 소진',
+ alertCount_one: '{{count}}개 알림',
+ alertCount_other: '{{count}}개 알림',
+ order: '주문',
+ save: '저장',
+ cancel: '취소',
+ settingsSaved: '설정 저장됨',
+ failedSaveSettings: '설정 저장 실패',
+ globalLeadTimeSaved: '전역 리드 타임 저장됨',
+ globalLeadTime: '전역 리드 타임',
+ globalLeadTimeHint: '전역 리드 타임 하한값 — 모든 SKU의 재주문 시점 계산에 사용됨',
+ skuLeadTimeOverride: 'SKU 리드 타임 재정의',
+ skuLeadTimeHint: '0 = 전역 리드 타임 사용. 이 SKU에 대해 재정의하려면 >0으로 설정.',
+ safetyMarginLabel: '안전 마진',
+ effectiveLeadTime: '유효 리드 타임',
+ effectiveLeadTimeHint: 'max(전역 {{global}}일, SKU {{sku}}일)',
+ reorderPointHint: 'd̄ × LT + 안전 마진 — 재고가 이 수준에 도달하면 주문',
+ safetyMarginHint: '통계적 안전 재고 (z=1.65 × σ × √LT) + 사용자 정의 버퍼',
+ safetyMarginHintDays: '통계적 안전 재고 위에 추가되는 버퍼.{{approx}}',
+ safetyMarginHintDaysApprox: ' ≈ 현재 소비율로 {{g}}g.',
+ safetyMarginHintG: '통계적 안전 재고 위에 추가되는 고정 무게 버퍼.{{approx}}',
+ safetyMarginHintGApprox: ' ≈ 현재 소비율로 {{days}}일.',
+ individualSpools: '개별 스풀',
+ labelWeight: '라벨',
+ spoolCount_one: '스풀 {{count}}개',
+ spoolCount_other: '스풀 {{count}}개',
+ stockBreakRisk: '재고 소진 위험',
+ stockBreakDetail: '{{days}}일 남음, 리드 타임 {{lt}}일.',
+ stockBreakBefore: '보충 전 재고 소진',
+ reorderNow: '지금 재주문',
+ reorderTriggerPassed: '트리거 날짜 {{date}}가 지났습니다.',
+ shoppingList: '쇼핑 목록',
+ shoppingListItems_one: '({{count}}개 항목)',
+ shoppingListItems_other: '({{count}}개 항목)',
+ shoppingListEmpty: '쇼핑 목록이 비어 있습니다. 항목을 추가하려면 행의 장바구니 아이콘을 클릭하세요.',
+ addToCart: '쇼핑 목록에 추가',
+ alertsSnoozed: '이 SKU의 알림 음소거',
+ alertsEnabled: '이 SKU의 알림 음소거 해제',
+ addedToCart: '쇼핑 목록에 추가됨',
+ failedAddItem: '항목 추가 실패',
+ listView: '목록',
+ logisticsView: '물류',
+ qty: '수량',
+ weight: '무게',
+ leadTime: '리드 타임',
+ expectedRestock: '예상 재입고',
+ status: '상태',
+ note: '메모',
+ pending: '대기 중',
+ purchased: '구매됨',
+ received: '수령됨',
+ markPurchased: '구매됨으로 표시',
+ markReceived: '수령됨으로 표시 — 재고에 스풀 추가',
+ resetToPending: '대기 중으로 초기화',
+ remove: '제거',
+ clearAll: '모두 초기화',
+ downloadCsv: 'CSV',
+ addToCartTitle: '쇼핑 목록에 추가',
+ byQuantity: '수량 기준',
+ byDuration: '기간 기준',
+ numberOfSpools: '스풀 수',
+ lastHowManyDays: '몇 일 동안 지속되어야 합니까?',
+ noUsageQty: '사용 데이터 없음 — 수량을 1로 설정합니다.',
+ noteOptional: '메모 (선택사항)',
+ notePlaceholder: '예: 프로젝트 X용, 긴급…',
+ addNSpools_one: '스풀 {{count}}개 추가',
+ addNSpools_other: '스풀 {{count}}개 추가',
+ onArrival: '입고 시',
+ stockBreakIn: '{{days}}일 후 재고 소진.',
+ stockRunsOutBefore: '{{lt}}일 리드 타임이 경과하기 전에 재고가 소진됩니다.',
+ atRate: '{{rate}}g/일 소비율로',
+ moreSpools_one: '스풀 {{count}}개 더',
+ moreSpools_other: '스풀 {{count}}개 더',
+ bridgeGap: '격차를 메우기 위해 필요합니다.',
+ noReadAccess: '재고 예측을 볼 권한이 없습니다.',
+ noWriteAccess: '예측 설정을 수정할 권한이 없습니다.'
+ },
+ diagnostic: {
+ modalTitle: '연결 진단 — {{name}}',
+ running: '진단 실행 중...',
+ runFailed: '진단 실행 실패: {{error}}',
+ retry: '다시 실행',
+ runButton: '진단 실행',
+ sectionTitle: '연결 진단',
+ sectionDescription: '프린터가 연결되지 않거나 인쇄되지 않는 이유를 확인합니다 — 포트 연결 가능 여부, LAN 개발자 모드, Docker 네트워크 모드, 자격증명.',
+ noPrinters: '구성된 프린터가 없습니다.',
+ overall: {
+ ok: '문제가 발견되지 않았습니다 — 프린터 연결이 정상입니다.',
+ warnings: '프린터가 작동하지만 일부 항목에 주의가 필요합니다.',
+ problems: '프린터가 연결되지 않거나 인쇄되지 않는 원인이 되는 문제가 발견되었습니다.'
+ },
+ check: {
+ port_mqtt: {
+ title: '제어 포트 (MQTT 8883)',
+ pass: '연결 가능 — 프린터가 제어 연결을 수락하고 있습니다.',
+ fail: '포트 8883에 연결할 수 없습니다. 프린터가 꺼져 있거나, IP 주소가 다르거나, 방화벽이 차단하고 있습니다. 프린터 IP를 확인하고 포트 8883이 차단되지 않았는지 확인하세요.'
+ },
+ port_ftps: {
+ title: '파일 전송 포트 (FTPS 990)',
+ pass: '연결 가능 — 인쇄 파일 전송이 작동합니다.',
+ warn: '포트 990에 연결할 수 없습니다. 모니터링은 작동할 수 있지만 프린터로 파일 전송에 실패합니다. 포트 990이 차단되지 않았는지 확인하세요.'
+ },
+ port_rtsps: {
+ title: '카메라 포트 (RTSPS 322)',
+ pass: '연결 가능 — 카메라 스트림이 작동합니다.',
+ warn: '포트 322에 연결할 수 없습니다. 라이브 카메라 보기가 작동하지 않습니다. 인쇄에는 영향을 주지 않습니다.'
+ },
+ network_mode: {
+ title: 'Docker 네트워크 모드',
+ pass: '호스트 네트워크 모드로 실행 중입니다.',
+ warn: 'Bambuddy가 Docker 브리지 네트워킹으로 실행 중입니다. 프린터 검색과 가상 프린터에는 호스트 네트워크 모드가 필요합니다 — \"network_mode: host\"로 컨테이너를 재생성하세요.',
+ skip: 'Docker에서 실행 중이 아닙니다 — 해당 없음.'
+ },
+ subnet: {
+ title: '네트워크 서브넷',
+ pass: '프린터와 Bambuddy가 같은 서브넷에 있습니다.',
+ warn: '프린터({{printer_ip}})와 Bambuddy({{host_ip}})가 다른 서브넷에 있습니다. 서브넷 간 라우팅이 구성되어 있지 않으면 서로 연결하지 못할 수 있습니다.',
+ skip: '서브넷을 확인할 수 없어 건너뜁니다.'
+ },
+ mqtt_auth: {
+ title: '프린터 자격증명',
+ pass: '프린터가 연결을 수락했습니다.',
+ fail: '프린터에 연결됐지만 연결을 거부했습니다. 액세스 코드 또는 시리얼 번호가 잘못됐을 가능성이 높습니다. 개발자 모드를 토글할 때마다 액세스 코드가 변경됩니다 — 프린터 화면에서 다시 복사하세요.',
+ skip: '확인하지 않음 — 프린터에 연결할 수 없었습니다.'
+ },
+ developer_mode: {
+ title: 'LAN 개발자 모드',
+ pass: '개발자 모드가 활성화되어 있습니다.',
+ fail: '프린터에서 개발자 모드가 꺼져 있습니다. 프린터의 LAN 설정에서 활성화하고 확인을 누르세요. 이 없으면 인쇄가 시작되지 않습니다.',
+ skip: '확인할 수 없음 — 프린터에 연결되어 있어야 합니다.'
+ }
+ }
+ },
+ systemHealth: {
+ sectionTitle: '시스템 상태',
+ sectionDescription: '최근 로그에서 지원 티켓이 되기 전에 직접 해결할 수 있는 알려진 문제를 스캔합니다.',
+ rescan: '다시 스캔',
+ clean: '최근 {{times}}개 로그 항목에서 알려진 문제가 발견되지 않았습니다.',
+ logUnavailable: '파일 로깅이 비활성화되어 로그를 스캔할 수 없습니다. 이 확인을 사용하려면 파일 로깅을 활성화하세요.',
+ learnMore: '수정 방법',
+ fixLabel: '수정:',
+ occurrences: '{{times}}회 발견 — 마지막: {{lastSeen}}',
+ category: {
+ layer8: '직접 해결 가능',
+ environment: '환경',
+ bug: '버그 보고 바람'
+ },
+ signature: {
+ "ftp-auth-rejected": {
+ name: '프린터가 액세스 코드를 거부함',
+ cause: '프린터가 파일 전송 로그인을 거부했습니다. 액세스 코드가 잘못됐거나 개발자 모드를 토글한 후 변경됐습니다.',
+ fix: '프린터 화면(LAN 설정)에서 액세스 코드를 다시 복사하여 Bambuddy의 프린터 설정에서 업데이트하세요.'
+ },
+ "ftp-connection-timeout": {
+ name: '파일 전송 연결 시간 초과',
+ cause: 'Bambuddy가 프린터의 파일 전송 포트(FTPS 990)에 연결할 수 없었습니다. 포트가 차단됐거나 프린터가 꺼져 있거나 다른 서브넷에 있습니다.',
+ fix: 'Bambuddy와 프린터 사이에서 포트 990을 차단하는 것이 없는지 확인하고, 같은 네트워크에 있는지 확인하세요.'
+ },
+ "ftp-ssl-error": {
+ name: '보안 파일 전송 핸드셰이크 실패',
+ cause: '프린터의 파일 전송 서버와의 TLS 핸드셰이크가 실패했습니다. 주로 방화벽이나 오래된 프린터 펌웨어가 원인입니다.',
+ fix: '프린터 펌웨어를 업데이트하고 방화벽이나 프록시가 포트 990에서 연결을 가로채지 않는지 확인하세요.'
+ },
+ "mqtt-connection-flapping": {
+ name: '프린터 연결이 계속 끊김',
+ cause: '제어 연결(MQTT 8883)이 반복적으로 끊어지고 다시 연결됩니다 — 주로 불안정한 네트워크 경로나 부분적으로 차단된 포트가 원인입니다.',
+ fix: '프린터의 Wi-Fi 신호를 확인하고, 유선 연결을 권장하며, 포트 8883이 안정적으로 연결 가능한지 확인하세요.'
+ },
+ "camera-connection-refused": {
+ name: '카메라 스트림 연결 불가',
+ cause: '포트 RTSPS 322에서 라이브 카메라에 연결할 수 없었습니다. 포트가 차단됐거나 프린터에서 카메라 또는 LAN 라이브뷰가 꺼져 있습니다.',
+ fix: '프린터에서 카메라와 LAN 라이브뷰를 활성화하고 포트 322가 차단되지 않았는지 확인하세요. 인쇄에는 영향을 주지 않습니다.'
+ },
+ "database-locked": {
+ name: '데이터베이스 쓰기 경합',
+ cause: 'SQLite 데이터베이스에 부하 시 \"database is locked\" 오류가 발생합니다 — 여러 프린터를 동시에 실행할 때 흔한 문제입니다.',
+ fix: 'Bambuddy를 외부 PostgreSQL 데이터베이스로 전환하세요. 설명서의 PostgreSQL 가이드를 참고하세요.'
+ }
+ }
+ },
+ vpDiagnostic: {
+ title: '설정 확인 — {{name}}',
+ runButton: '설정 확인 실행',
+ running: '설정 확인 실행 중...',
+ runFailed: '설정 확인을 실행할 수 없습니다: {{error}}',
+ retry: '다시 실행',
+ overall: {
+ ok: '모든 확인이 통과됐습니다 — 이 가상 프린터가 올바르게 설정되었습니다.',
+ warnings: '가상 프린터가 작동하지만 일부 항목에 주의가 필요합니다.',
+ problems: '슬라이서가 이 가상 프린터를 인식하거나 사용할 수 없는 원인이 되는 문제가 발견되었습니다.'
+ },
+ check: {
+ enabled: {
+ title: '가상 프린터 활성화',
+ fail: '이 가상 프린터가 꺼져 있습니다. 검색 가능하게 하려면 켜세요.'
+ },
+ running: {
+ title: '서비스 실행 중',
+ fail: '가상 프린터가 활성화됐지만 서비스가 실행 중이 아닙니다. Bambuddy 로그를 확인하세요 — 바인드 IP 충돌이나 권한 오류가 보통 원인입니다.'
+ },
+ bind_interface: {
+ title: '바인드 네트워크 인터페이스',
+ fail: '바인드 인터페이스가 설정되지 않았거나 이 호스트에 더 이상 존재하지 않습니다. 바인드 인터페이스 드롭다운에서 현재 인터페이스를 선택하세요.'
+ },
+ access_code: {
+ title: '액세스 코드 설정됨',
+ fail: '액세스 코드가 설정되지 않았습니다. 슬라이서에는 여기에 설정한 것과 동일한 8자리 액세스 코드가 필요합니다.'
+ },
+ target_printer: {
+ title: '대상 프린터',
+ fail: '대상 프린터가 선택되지 않았습니다. 프록시 모드에는 실제 프린터가 필요합니다.',
+ warn: '대상 프린터가 현재 오프라인입니다 — 재연결되면 프록시가 재개됩니다.'
+ },
+ port_ftps: {
+ title: '파일 업로드 서비스 (포트 {{port}})',
+ fail: '바인드 IP의 포트 {{port}}에서 수신 중인 서비스가 없어 슬라이서가 파일을 업로드할 수 없습니다. 이 인터페이스의 포트 충돌이 일반적인 원인입니다.'
+ },
+ port_mqtt: {
+ title: '제어 서비스 (포트 {{port}})',
+ fail: '바인드 IP의 포트 {{port}}에서 수신 중인 서비스가 없어 슬라이서가 연결하거나 상태를 표시할 수 없습니다.'
+ },
+ port_bind: {
+ title: '검색 서비스 (포트 {{port}})',
+ fail: '바인드 IP의 포트 {{port}}에서 수신 중인 서비스가 없어 슬라이서의 검색 핸드셰이크가 실패합니다.'
+ },
+ certificate: {
+ title: 'TLS 인증서',
+ pass: '인증서가 준비됐습니다. Bambuddy CA 인증서(위)가 슬라이서의 신뢰 저장소에 가져와져 있는지 확인하세요.',
+ fail: '이 가상 프린터의 TLS 인증서가 없습니다. Bambuddy 데이터 디렉터리가 쓰기 가능한지 확인하세요.'
+ }
+ }
+ }
+};
+