Browse Source

feat(i18n): add Korean (ko) translation (#1587)

Hijae Song 1 day ago
parent
commit
77655d8dfa
3 changed files with 5748 additions and 1 deletions
  1. 19 0
      frontend/scripts/check-i18n-parity.mjs
  2. 4 1
      frontend/src/i18n/index.ts
  3. 5725 0
      frontend/src/i18n/locales/ko.ts

+ 19 - 0
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),

+ 4 - 1
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: '繁體中文' },

+ 5725 - 0
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: '빌드 플레이트가 <strong>완전히 비어 있는지</strong> 확인한 후 캘리브레이션을 클릭하세요.',
+      calibrationDescription: '캘리브레이션은 빈 플레이트의 참조 이미지를 캡처합니다. 이후 확인 시 이 참조와 비교하여 객체를 감지합니다.',
+      calibrationTip: '<strong>팁:</strong> 다른 플레이트에 대해 최대 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: '프린터 터치스크린에서 <strong>설정</strong>으로 이동하세요',
+      step2: '<strong>펌웨어</strong>로 이동하세요',
+      step3: '<strong>SD 카드에서 업데이트</strong>를 선택하세요',
+      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>brew install ffmpeg</brew>, Linux에서는 <apt>apt install ffmpeg</apt>로 설치하세요.',
+    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/<serial>/status 등',
+    prometheusMetrics: 'Prometheus 메트릭',
+    prometheusEndpointDescription: 'Prometheus/Grafana 모니터링을 위해 <code>/api/v1/metrics</code>에서 프린터 메트릭을 노출합니다.',
+    bearerTokenOptional: '베어러 토큰 (선택사항)',
+    bearerTokenHint: '설정하면 요청에 <code>Authorization: Bearer <token></code>을 포함해야 합니다',
+    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 데이터 디렉터리가 쓰기 가능한지 확인하세요.'
+      }
+    }
+  }
+};
+