diff --git a/.runner-token b/.runner-token new file mode 100644 index 0000000..70c1297 --- /dev/null +++ b/.runner-token @@ -0,0 +1 @@ +GITEA_RUNNER_TOKEN=YF9I7H3BI5ovPnMC7iU2I86Hga8dcWUakqH9qT85 diff --git a/VERSION b/VERSION index 46e7a71..0dfdb9c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.26 +0.9.27-nightly3 diff --git a/config/config.ini.example b/config/config.ini.example index b954b90..bea9879 100644 --- a/config/config.ini.example +++ b/config/config.ini.example @@ -31,6 +31,88 @@ default_ams_slot = auto # Auto-Leveling vor jedem Druck (1 = an, 0 = aus) auto_leveling = 1 +# Kamera-Stream bei Druckstart automatisch einschalten (1 = an, 0 = aus) +camera_on_print = 0 + +# Warnung vor Druck von Web-Uploads (1 = an, 0 = aus) +web_upload_warning = 1 + +# Nach Upload: Filament/Color-Selector automatisch öffnen (1 = an, 0 = aus) +print_start_dialog = 1 + +# ─── Filament-Profile pro AMS-Slot (optional) ──────────────────────────────── +# Beim Slicer-Sync nimmt OrcaSlicer per Default immer "Generic PLA/PETG/...". +# Mit diesen Mappings sendet die Bridge die konkrete Orca-Filament-ID + +# Vendor mit (Anzeige im Slicer dann z.B. "PolyTerra PLA — Polymaker" statt +# nur "Generic PLA"). Mapping wird über die Web-UI gepflegt. +# Beispiel: +# [filament_profiles] +# slot_0_id = OGFL01 +# slot_0_vendor = Polymaker +# slot_1_id = OGFG23 +# slot_1_vendor = Polymaker + [bridge] # Poll-Intervall in Sekunden poll_interval = 3 + +# ─── Multi-Printer (optional) ────────────────────────────────────────────────── +# Mehrere Drucker können als [printer_1], [printer_2], … definiert werden. +# Jede Bridge-Instanz verbindet sich mit einem Drucker (je eigener Port). +# bridge_url zeigt auf die jeweilige Bridge-Instanz (für den /kx/printers-Endpunkt). +# Die [connection]-Sektion wird weiterhin als Fallback für diese Instanz verwendet. +# +# Beispiel: +# [printer_1] +# name = Kobra X Links +# bridge_url = http://192.168.178.95:7125 +# printer_ip = 192.168.178.95 +# mqtt_port = 9883 +# username = userXXXXXXXXXX +# password = XXXXXXXXXXXXXXX +# device_id = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +# mode_id = 20030 +# +# [printer_2] +# name = Kobra X Rechts +# bridge_url = http://192.168.178.96:7125 +# printer_ip = 192.168.178.96 +# mqtt_port = 9883 +# username = userYYYYYYYYYY +# password = YYYYYYYYYYYYYYY +# device_id = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy +# mode_id = 20030 + +[ace_dry_presets] +# Vordefinierte Dry-Set Presets (Temp in °C, Dauer in Sekunden) +pla_temp = 45 +pla_duration_sec = 14400 +pla_plus_temp = 45 +pla_plus_duration_sec = 14400 +petg_temp = 50 +petg_duration_sec = 14400 +tpu_temp = 55 +tpu_duration_sec = 14400 +abs_asa_temp = 45 +abs_asa_duration_sec = 28800 +pa_pc_temp = 55 +pa_pc_duration_sec = 43200 + +# Custom Presets (Name + Temp + Dauer) +custom_1_name = Custom 1 +custom_1_temp = 45 +custom_1_duration_sec = 14400 +custom_2_name = Custom 2 +custom_2_temp = 45 +custom_2_duration_sec = 14400 +custom_3_name = Custom 3 +custom_3_temp = 45 +custom_3_duration_sec = 14400 + +[spoolman] +# URL der Spoolman-Instanz (leer lassen um Spoolman zu deaktivieren) +# server = http://192.168.x.x:7912 + +# Wie oft (Sekunden) der Filamentverbrauch während des Drucks gemeldet wird +# (0 = nur beim Druckende) +# sync_rate = 0 diff --git a/config_loader.py b/config_loader.py index b1012e1..bf41b85 100644 --- a/config_loader.py +++ b/config_loader.py @@ -13,6 +13,7 @@ _BASE = pathlib.Path(sys.executable).parent if getattr(sys, "frozen", False) els CONFIG_SECTION_CONNECTION = "connection" CONFIG_SECTION_PRINT = "print" CONFIG_SECTION_BRIDGE = "bridge" +CONFIG_SECTION_SPOOLMAN = "spoolman" def _find_config_file() -> pathlib.Path | None: @@ -63,6 +64,8 @@ def _load_config_file(path: pathlib.Path): "WEB_UPLOAD_WARNING": (CONFIG_SECTION_PRINT, "web_upload_warning"), "PRINT_START_DIALOG": (CONFIG_SECTION_PRINT, "print_start_dialog"), "BRIDGE_PRINTER_NAME": (CONFIG_SECTION_BRIDGE, "printer_name"), + "SPOOLMAN_SERVER": (CONFIG_SECTION_SPOOLMAN, "server"), + "SPOOLMAN_SYNC_RATE": (CONFIG_SECTION_SPOOLMAN, "sync_rate"), } for env_key, (section, option) in mapping.items(): if env_key not in os.environ: @@ -317,3 +320,5 @@ AUTO_LEVELING = int(get("AUTO_LEVELING","1")) CAMERA_ON_PRINT = int(get("CAMERA_ON_PRINT","0")) WEB_UPLOAD_WARNING = int(get("WEB_UPLOAD_WARNING", "1")) PRINT_START_DIALOG = int(get("PRINT_START_DIALOG", get("FILE_READY_DIALOG", "1"))) +SPOOLMAN_SERVER = get("SPOOLMAN_SERVER", "") +SPOOLMAN_SYNC_RATE = int(get("SPOOLMAN_SYNC_RATE", "0")) diff --git a/kobrax_moonraker_bridge.py b/kobrax_moonraker_bridge.py index 930c34f..442d392 100644 --- a/kobrax_moonraker_bridge.py +++ b/kobrax_moonraker_bridge.py @@ -602,10 +602,23 @@ class CameraCache: self._task_jpeg: "asyncio.Task | None" = None self._task_h264: "asyncio.Task | None" = None self._lock = asyncio.Lock() + self._fail_count_jpeg: int = 0 + self._fail_count_h264: int = 0 def set_url(self, url: str): self._url = url + def reset(self): + """Backoff-Zähler zurücksetzen und laufende ffmpeg-Prozesse killen.""" + self._fail_count_jpeg = 0 + self._fail_count_h264 = 0 + for proc in (self._proc_jpeg, self._proc_h264): + if proc is not None: + try: + proc.kill() + except Exception: + pass + async def ensure_running(self): if self._proc_jpeg is None or self._proc_jpeg.returncode is not None: self._task_jpeg = asyncio.create_task(self._run_jpeg_loop()) @@ -629,13 +642,13 @@ class CameraCache: continue try: self._proc_jpeg = await asyncio.create_subprocess_exec( - _find_ffmpeg(), "-loglevel", "quiet", + _find_ffmpeg(), "-loglevel", "warning", *self._input_args(url), "-i", url, "-vf", "fps=2", "-f", "image2pipe", "-vcodec", "mjpeg", "-q:v", "3", "-flush_packets", "1", "pipe:1", stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.DEVNULL, + stderr=asyncio.subprocess.PIPE, ) except Exception as e: log.warning(f"CameraCache: ffmpeg-jpeg start fehlgeschlagen: {e}") @@ -643,6 +656,7 @@ class CameraCache: continue buf = b"" + rc = None try: while True: chunk = await self._proc_jpeg.stdout.read(self.TS_CHUNK) @@ -676,8 +690,23 @@ class CameraCache: await self._proc_jpeg.wait() except Exception: pass + rc = self._proc_jpeg.returncode + if rc: + try: + err = await self._proc_jpeg.stderr.read(500) + if err: + log.warning(f"CameraCache: ffmpeg-jpeg stderr: {err.decode(errors='replace').strip()}") + except Exception: + pass self._proc_jpeg = None - await asyncio.sleep(2.0) # restart delay + if rc: + self._fail_count_jpeg += 1 + delay = min(2.0 * (2 ** self._fail_count_jpeg), 300.0) + log.warning(f"CameraCache: ffmpeg-jpeg exit {rc}, retry in {delay:.0f}s (Versuch {self._fail_count_jpeg})") + await asyncio.sleep(delay) + else: + self._fail_count_jpeg = 0 + await asyncio.sleep(2.0) async def _run_h264_loop(self): """Hält einen ffmpeg-Prozess am Leben der MPEG-TS an alle Subscriber fanoutet.""" @@ -688,18 +717,19 @@ class CameraCache: continue try: self._proc_h264 = await asyncio.create_subprocess_exec( - _find_ffmpeg(), "-loglevel", "quiet", + _find_ffmpeg(), "-loglevel", "warning", *self._input_args(url), "-i", url, "-c:v", "copy", "-an", "-f", "mpegts", "pipe:1", stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.DEVNULL, + stderr=asyncio.subprocess.PIPE, ) except Exception as e: log.warning(f"CameraCache: ffmpeg-h264 start fehlgeschlagen: {e}") await asyncio.sleep(3.0) continue + rc = None try: while True: chunk = await self._proc_h264.stdout.read(self.TS_CHUNK) @@ -729,8 +759,57 @@ class CameraCache: await self._proc_h264.wait() except Exception: pass + rc = self._proc_h264.returncode + if rc: + try: + err = await self._proc_h264.stderr.read(500) + if err: + log.warning(f"CameraCache: ffmpeg-h264 stderr: {err.decode(errors='replace').strip()}") + except Exception: + pass self._proc_h264 = None - await asyncio.sleep(2.0) + if rc: + self._fail_count_h264 += 1 + delay = min(2.0 * (2 ** self._fail_count_h264), 300.0) + log.warning(f"CameraCache: ffmpeg-h264 exit {rc}, retry in {delay:.0f}s (Versuch {self._fail_count_h264})") + await asyncio.sleep(delay) + else: + self._fail_count_h264 = 0 + await asyncio.sleep(2.0) + + +class SpoolmanClient: + """Thin synchronous HTTP client for Spoolman filament tracking. + + Designed to be called from daemon threads (poll loop, _on_print callbacks). + Uses requests (already in requirements) so no event-loop dependency. + """ + + def __init__(self, server_url: str, sync_rate: int = 0): + self.server_url = server_url.rstrip("/") + self.sync_rate = sync_rate + + def _req(self, method: str, path: str, **kwargs): + import requests + r = requests.request(method, f"{self.server_url}{path}", timeout=5, **kwargs) + r.raise_for_status() + return r.json() + + def health_check(self) -> bool: + try: + self._req("GET", "/api/v1/health") + return True + except Exception: + return False + + def list_spools(self) -> list: + return self._req("GET", "/api/v1/spool") + + def use_filament(self, spool_id: int, use_length_mm: float) -> None: + """Report consumed filament length in mm. Spoolman converts to weight + using the spool's filament profile density.""" + self._req("PUT", f"/api/v1/spool/{spool_id}/use", + json={"use_length": round(use_length_mm, 2)}) class KobraXBridge: @@ -793,6 +872,7 @@ class KobraXBridge: "file_ready": "", "print_start_dialog": getattr(args, "print_start_dialog", 1), "filament_mode": "toolhead", + "supplies_usage": 0, "ace_drying": {"status": 0, "target_temp": 0, "duration": 0, "remain_time": 0, "humidity": None, "current_temp": None}, } self._ams_slots: list[dict] = [] # flat global list; each entry has global_index + box_id @@ -819,6 +899,18 @@ class KobraXBridge: self._pending_preprint_skip: list[str] = [] self._pending_preprint_skip_deadline: float = 0.0 + # Spoolman filament tracking + _sm_url = (getattr(args, "spoolman_server", "") or "").strip() + self._spoolman: SpoolmanClient | None = ( + SpoolmanClient(_sm_url, getattr(args, "spoolman_sync_rate", 0)) + if _sm_url else None + ) + self._spoolman_slot_spools: dict[int, int] = {} # {ams_slot_idx: spoolman_spool_id} + self._spoolman_slot_usage: dict[int, float] = {} # per-slot accumulated mm this print + self._spoolman_slot_reported: dict[int, float] = {} # per-slot mm already sent to Spoolman + self._spoolman_last_usage: float = 0.0 # supplies_usage at last attribution tick + self._spoolman_last_sync: float = 0.0 + # Theme-Name prüfen (keine Sonderzeichen oder Umlaute) raw_theme = (getattr(args, "ui_theme", None) or "default").strip() if not _UI_THEME_NAME_RE.match(raw_theme): @@ -837,6 +929,139 @@ class KobraXBridge: client.callbacks["light/report"] = self._on_light client.callbacks["skip/report"] = self._on_skip + if self._spoolman: + threading.Thread( + target=lambda: log.info( + f"Spoolman: {'OK' if self._spoolman.health_check() else 'unreachable'} " + f"at {self._spoolman.server_url}" + ), + daemon=True, name="spoolman-health", + ).start() + + # ── Spoolman helpers ────────────────────────────────────────────────────── + + def _spoolman_filament_mm(self) -> float: + """Total filament_used_mm for the current print file from the GCode DB.""" + filename = self._state.get("filename", "") + if not filename: + return 0.0 + try: + gf = self._store.get_file_by_name(filename) + return float(gf.get("filament_used_mm") or 0.0) if gf else 0.0 + except Exception: + return 0.0 + + def _spoolman_attribute_tick(self, activity_map: dict) -> None: + """Attribute the supplies_usage delta since last tick to the active slot. + + Skips attribution during loading/unloading transitions (tool changes + + purges) to avoid charging the wrong spool for purge material.""" + if not self._spoolman or not self._spoolman_slot_spools: + return + if self._state.get("print_state") != "printing": + return + current = self._state.get("supplies_usage", 0) + delta = current - self._spoolman_last_usage + self._spoolman_last_usage = current + if delta <= 0: + return + loaded = self._ams_loaded_slot + if loaded < 0: + return + if activity_map.get(loaded): + return + self._spoolman_slot_usage[loaded] = self._spoolman_slot_usage.get(loaded, 0.0) + delta + + def _spoolman_unreported(self) -> dict[int, float]: + """Return {slot_idx: mm} of usage not yet reported to Spoolman. + + Falls back to equal split of total supplies_usage when per-slot + attribution data is absent (e.g. single-extruder with no AMS).""" + total_used = self._state.get("supplies_usage", 0) + if self._spoolman_slot_usage: + return { + slot: self._spoolman_slot_usage.get(slot, 0.0) + - self._spoolman_slot_reported.get(slot, 0.0) + for slot in self._spoolman_slot_spools + } + n = len(self._spoolman_slot_spools) + already = sum(self._spoolman_slot_reported.values()) + per = (total_used - already) / n if n else 0.0 + return {slot: per for slot in self._spoolman_slot_spools} + + def _spoolman_report(self, unreported: dict[int, float], min_mm: float = 0.1) -> None: + """Fire-and-forget report of unreported mm to each mapped spool.""" + sm = self._spoolman + for slot_idx, mm in unreported.items(): + if mm < min_mm: + continue + spool_id = self._spoolman_slot_spools.get(slot_idx) + if not spool_id: + continue + self._spoolman_slot_reported[slot_idx] = ( + self._spoolman_slot_reported.get(slot_idx, 0.0) + mm + ) + def _send(sid=spool_id, length=mm): + try: + sm.use_filament(sid, length) + log.info(f"Spoolman: {length:.1f} mm → spool {sid}") + except Exception as e: + log.warning(f"Spoolman: report failed (spool {sid}): {e}") + threading.Thread(target=_send, daemon=True, name="spoolman-report").start() + + def _spoolman_notify_end(self): + """Report remaining filament on print end.""" + if not self._spoolman or not self._spoolman_slot_spools: + return + self._spoolman_report(self._spoolman_unreported()) + + def _spoolman_sync_midprint(self): + """Report incremental filament usage during a print (sync_rate interval).""" + if not self._spoolman or not self._spoolman_slot_spools: + return + self._spoolman_report(self._spoolman_unreported(), min_mm=10.0) + + # ── Spoolman API handlers ───────────────────────────────────────────────── + + async def handle_kx_spoolman_status(self, request): + """GET /kx/spoolman/status""" + return self._json_cors({ + "configured": bool(self._spoolman), + "server": self._spoolman.server_url if self._spoolman else "", + "sync_rate": self._spoolman.sync_rate if self._spoolman else 0, + "slot_spools": {str(k): v for k, v in self._spoolman_slot_spools.items()}, + }) + + async def handle_kx_spoolman_spools(self, request): + """GET /kx/spoolman/spools — proxied from Spoolman.""" + if not self._spoolman: + return self._json_cors({"error": "Spoolman not configured"}, status=503) + try: + spools = await asyncio.get_event_loop().run_in_executor( + None, self._spoolman.list_spools + ) + return self._json_cors({"spools": spools}) + except Exception as e: + log.warning(f"Spoolman: list_spools failed: {e}") + return self._json_cors({"error": str(e)}, status=502) + + async def handle_kx_spoolman_set_active(self, request): + """POST /kx/spoolman/active-spool + Body: {"slot_map": {"0": 42, "2": 17}} — AMS slot index → Spoolman spool ID.""" + try: + data = await request.json() + except Exception: + return self._json_cors({"error": "invalid JSON"}, status=400) + slot_map = data.get("slot_map") or {} + self._spoolman_slot_spools = { + int(k): int(v) for k, v in slot_map.items() + if str(v).isdigit() and int(v) > 0 + } + self._spoolman_slot_usage = {} + self._spoolman_slot_reported = {} + self._spoolman_last_usage = 0.0 + return self._json_cors({"slot_spools": {str(k): v for k, v in self._spoolman_slot_spools.items()}}) + def _default_ace_dry_presets(self) -> dict[str, dict]: return { "pla": {"temp": 45, "duration_sec": 4 * 3600}, @@ -951,15 +1176,21 @@ class KobraXBridge: printer_id=self._printer_id, ) log.info(f"Job started: {self._current_job_id} for {filename}") + self._spoolman_slot_usage = {} + self._spoolman_slot_reported = {} + self._spoolman_last_usage = 0.0 + self._spoolman_last_sync = 0.0 # Job-History: Druckende erkennen if kobra_state in ("finished",) and self._current_job_id: self._store.finish_job(self._current_job_id, status="completed") log.info(f"Job abgeschlossen: {self._current_job_id}") + self._spoolman_notify_end() self._current_job_id = "" elif kobra_state in ("stoped", "canceled") and self._current_job_id: self._store.finish_job(self._current_job_id, status="cancelled") log.info(f"Job abgebrochen: {self._current_job_id}") + self._spoolman_notify_end() self._current_job_id = "" # Nach Druckende das Upload-Banner verschwinden lassen (Issue #29): der @@ -976,6 +1207,7 @@ class KobraXBridge: self._state["slicer_time"] = 0 self._state["layer_height"] = 0.0 self._state["first_layer_height"] = 0.0 + self._state["supplies_usage"] = 0 self._thumbnail_b64 = "" self._state["filename"] = d.get("filename", self._state["filename"]) if "progress" in d: @@ -990,6 +1222,8 @@ class KobraXBridge: self._state["total_layers"] = d["total_layers"] if "taskid" in d: self._state["taskid"] = str(d["taskid"]) + if "supplies_usage" in d: + self._state["supplies_usage"] = int(d["supplies_usage"]) settings = d.get("settings") or {} if "print_speed_mode" in settings: self._state["print_speed_mode"] = int(settings["print_speed_mode"]) @@ -2967,10 +3201,10 @@ class KobraXBridge: if not file_data: return web.json_response({"error": "no file received"}, status=400) - # Nur druckbare Dateien zulassen (Issue #59) — verhindert dass z.B. ein - # JPG im File-Browser landet. OrcaSlicer-Uploads sind .gcode/.gcode.3mf, - # der Kobra X akzeptiert .gcode/.3mf/.bgcode. - _allowed_ext = (".gcode", ".gcode.3mf", ".3mf", ".bgcode") + # Nur druckbare Dateien zulassen (Issue #59) — der Kobra X akzeptiert + # ausschließlich .gcode und .bgcode; .3mf-Uploads werden vom Drucker + # nicht verarbeitet und daher abgelehnt (Issue #59, @gangoke). + _allowed_ext = (".gcode", ".bgcode") _fn_lower = (remote_filename or "").lower() if not _fn_lower.endswith(_allowed_ext): log.warning(f"Upload abgelehnt (kein GCode): {remote_filename}") @@ -3674,6 +3908,16 @@ class KobraXBridge: self._camera_user_stopped = True return web.json_response({"result": "ok"}) + async def handle_api_camera_reset(self, request): + """Backoff-Zähler zurücksetzen und ffmpeg sofort neu starten. + Nützlich nach 429-Sperre (Retry-After abgelaufen) oder nach Drucker-Neustart.""" + self.camera_cache.reset() + url = self._state.get("camera_url", "") + if url: + self.camera_cache.set_url(url) + await self.camera_cache.ensure_running() + return web.json_response({"result": "ok"}) + async def handle_api_camera_snapshot(self, request): """Letzter JPEG-Frame aus dem CameraCache — instant aus dem RAM, keine eigene ffmpeg-Instanz mehr (verhindert Single-Client-429 am @@ -4029,6 +4273,8 @@ class KobraXBridge: "filament_profiles": {str(k): v for k, v in self._filament_profiles.items()}, "visible_vendors": self._visible_vendors, "ace_dry_presets": self._ace_dry_presets, + "spoolman_server": getattr(self._args, "spoolman_server", "") or "", + "spoolman_sync_rate": getattr(self._args, "spoolman_sync_rate", 0), }) async def handle_api_settings_post(self, request): @@ -4043,7 +4289,7 @@ class KobraXBridge: cfg.read(config_path, encoding="utf-8") # Sections sicherstellen - for section in ("connection", "print", "bridge", "ace_dry_presets"): + for section in ("connection", "print", "bridge", "ace_dry_presets", "spoolman"): if not cfg.has_section(section): cfg.add_section(section) @@ -4073,6 +4319,16 @@ class KobraXBridge: elif cfg.has_option("bridge", "printer_name"): cfg.remove_option("bridge", "printer_name") + # Spoolman + if "spoolman_server" in data: + cfg.set("spoolman", "server", str(data["spoolman_server"]).strip()) + if "spoolman_sync_rate" in data: + try: + sr = max(0, int(data["spoolman_sync_rate"])) + except (TypeError, ValueError): + sr = 30 + cfg.set("spoolman", "sync_rate", str(sr)) + incoming_presets = data.get("ace_dry_presets") if isinstance(data, dict) else None presets = self._sanitize_ace_dry_presets(incoming_presets if isinstance(incoming_presets, dict) else self._ace_dry_presets) for key, val in presets.items(): @@ -4804,6 +5060,14 @@ class KobraXBridge: print_r = self.client.publish("print", "query", timeout=3.0) if print_r: self._on_print(print_r) + # Spoolman mid-print sync + if (self._spoolman and self._spoolman.sync_rate > 0 + and self._spoolman_slot_spools + and self._state.get("print_state") == "printing"): + now = time.time() + if now - self._spoolman_last_sync >= self._spoolman.sync_rate: + self._spoolman_sync_midprint() + self._spoolman_last_sync = now box = self.client.query_multicolor_box() if box: data = box.get("data") or {} @@ -4820,6 +5084,10 @@ class KobraXBridge: if global_slots: self._ams_slots = global_slots self._ams_loaded_slot = global_loaded + self._spoolman_attribute_tick(activity_map) + else: + # No multiColorBox data — still attribute (no transitions to skip) + self._spoolman_attribute_tick({}) except Exception as e: log.warning(f"Poll-Fehler: {e}") # Prüfen ob Drucker wirklich weg ist @@ -4919,6 +5187,7 @@ def build_app(bridge: KobraXBridge) -> web.Application: r.add_get("/api/camera/snapshot", bridge.handle_api_camera_snapshot) r.add_post("/api/camera/start", bridge.handle_api_camera_start) r.add_post("/api/camera/stop", bridge.handle_api_camera_stop) + r.add_post("/api/camera/reset", bridge.handle_api_camera_reset) r.add_get("/api/state", bridge.handle_api_state) r.add_get("/api/settings", bridge.handle_api_settings_get) r.add_post("/api/settings", bridge.handle_api_settings_post) @@ -4954,6 +5223,9 @@ def build_app(bridge: KobraXBridge) -> web.Application: r.add_post("/kx/skip", bridge.handle_kx_skip) r.add_post("/kx/skip/query", bridge.handle_kx_skip_query) r.add_get("/kx/skip/state", bridge.handle_kx_skip_state) + r.add_get("/kx/spoolman/status", bridge.handle_kx_spoolman_status) + r.add_get("/kx/spoolman/spools", bridge.handle_kx_spoolman_spools) + r.add_post("/kx/spoolman/active-spool", bridge.handle_kx_spoolman_set_active) r.add_route("OPTIONS", "/kx/{path:.*}", bridge.handle_kx_options) # Root + Printer-Routen (Single-Page, JS liest Pathname) @@ -5119,6 +5391,10 @@ def main(): parser.add_argument("--web-upload-warning", type=int, default=env_loader.WEB_UPLOAD_WARNING) parser.add_argument("--print-start-dialog", dest="print_start_dialog", type=int, default=env_loader.PRINT_START_DIALOG) parser.add_argument("--file-ready-dialog", dest="print_start_dialog", type=int) + parser.add_argument("--spoolman-server", default=env_loader.SPOOLMAN_SERVER, + help="Spoolman URL (e.g. http://192.168.x.x:7912); leave empty to disable") + parser.add_argument("--spoolman-sync-rate", type=int, default=env_loader.SPOOLMAN_SYNC_RATE, + help="Mid-print filament sync interval in seconds (0 = only on print end)") parser.add_argument("--host", default="0.0.0.0", help="Bind-Adresse für den Bridge-Server") diff --git a/web/themes/default/app.js b/web/themes/default/app.js index 52bacf9..3e8d6d4 100644 --- a/web/themes/default/app.js +++ b/web/themes/default/app.js @@ -44,6 +44,73 @@ var ACE_DRY_PRESETS={ custom_3:{name:'Custom 3',temp:45,duration_sec:4*3600} }; +// Spoolman state +var _spoolmanStatus={configured:false,server:'',sync_rate:0,slot_spools:{}}; +var _spoolmanSpools=[]; +var _slotSpoolMap={}; // {String(global_index): spoolman_spool_id} — last committed assignment + +function _loadSpoolmanStatus(){ + fetch(_apiUrl('/kx/spoolman/status')).then(function(r){return r.json();}).then(function(d){ + _spoolmanStatus=d; + _slotSpoolMap=d.slot_spools||{}; + _updateSpoolmanStatusDot(); + }).catch(function(){}); +} +function _updateSpoolmanStatusDot(){ + var dot=document.getElementById('spoolman-status-dot'); + var lbl=document.getElementById('spoolman-status-lbl'); + if(!dot||!lbl)return; + if(_spoolmanStatus.configured){ + dot.style.color='var(--ok)';lbl.textContent=_spoolmanStatus.server||'verbunden'; + } else { + dot.style.color='var(--txt2)';lbl.textContent='nicht konfiguriert'; + } +} + +function _buildSpoolmanSection(){ + var sec=document.getElementById('fd-spoolman-section'); + var rows=document.getElementById('fd-spoolman-rows'); + var loading=document.getElementById('fd-spoolman-loading'); + if(!sec||!rows)return; + if(!_spoolmanStatus.configured){sec.style.display='none';return;} + sec.style.display=''; + rows.innerHTML=''; + if(loading)loading.style.display=''; + + var usedSlots={}; + document.querySelectorAll('#fd-slots select').forEach(function(sel){ + var idx=parseInt(sel.value); + if(idx>=0){ + var slot=(_amsSlots||[]).find(function(s){return s.slot_index===idx;}); + if(slot&&!usedSlots[idx])usedSlots[idx]=slot; + } + }); + + fetch(_apiUrl('/kx/spoolman/spools')).then(function(r){return r.json();}).then(function(d){ + if(loading)loading.style.display='none'; + _spoolmanSpools=d.spools||[]; + var slotKeys=Object.keys(usedSlots).map(Number).sort(function(a,b){return a-b;}); + if(!slotKeys.length){rows.innerHTML='';return;} + rows.innerHTML=slotKeys.map(function(idx){ + var slot=usedSlots[idx]; + var col=(slot.color_hex||'#888'); + var currentSpool=_slotSpoolMap[String(idx)]||''; + var opts=''+_spoolmanSpools.map(function(sp){ + var rem=sp.remaining_weight!=null?' ('+sp.remaining_weight.toFixed(0)+'g)':''; + var vendor=sp.filament&&sp.filament.vendor?sp.filament.vendor+' ':''; + var name=sp.filament&&sp.filament.name?sp.filament.name:'Spool'; + return ''; + }).join(''); + return '
'+ + ''+ + 'Slot '+(idx+1)+''+ + '
'; + }).join(''); + }).catch(function(){if(loading)loading.style.display='none';}); +} + function _aceAutoRefillGet(aceId){return !!aceAutoRefillPrefs[String(aceId)];} function _aceAutoRefillSet(aceId,on){ aceAutoRefillPrefs[String(aceId)]=!!on; @@ -329,6 +396,11 @@ function applyLang(){ setText('setcat-lbl-display',T.settings_cat_display||'Darstellung'); setText('setcat-lbl-display2',T.settings_cat_display||'Darstellung'); setText('setcat-lbl-filament',T.settings_cat_filament||'Filament'); + setText('setcat-lbl-integrations',T.settings_integrations||'Integrationen'); + setText('modal-sec-spoolman',T.modal_sec_spoolman||'Spoolman'); + setText('lbl-spoolman-url',T.lbl_spoolman_url||'Server-URL'); + setText('lbl-spoolman-sync-rate',T.lbl_spoolman_sync_rate||'Sync-Rate (s, 0=aus)'); + setText('modal-sec-obico',T.modal_sec_obico||'Obico'); setText('setcat-lbl-system',T.settings_version||'System'); setText('lbl-set-lang',T.settings_cat_language||'Sprache'); setText('lbl-set-theme',T.settings_cat_theme||'Hell / Dunkel umschalten'); @@ -1002,6 +1074,10 @@ function openSettings(){ pi.value=sec; } renderFilamentMapping(d.filament_profiles||{}); + // Spoolman + var su=document.getElementById('s-spoolman-url');if(su)su.value=d.spoolman_server||''; + var sr=document.getElementById('s-spoolman-sync-rate');if(sr)sr.value=(d.spoolman_sync_rate!==undefined?d.spoolman_sync_rate:30); + _updateSpoolmanStatusDot(); }); // Sprach-Select im Settings-Panel mit aktueller Sprache spiegeln var ls=document.getElementById('s-lang-select'); @@ -1570,6 +1646,8 @@ function saveSettings(){ print_start_dialog: parseInt((document.getElementById('s-file-ready-mode')||{}).value||'1',10), web_upload_warning:webUploadWarning, poll_interval: Math.min(60,Math.max(1,parseInt((document.getElementById('s-poll-interval')||{}).value,10)||3)), + spoolman_server: (document.getElementById('s-spoolman-url')||{}).value||'', + spoolman_sync_rate: Math.max(0,parseInt((document.getElementById('s-spoolman-sync-rate')||{}).value||'30',10)), }).then(function(){ btn.textContent=T.update_restarting; setTimeout(function(){ @@ -1793,6 +1871,7 @@ function camStart(){ post('/api/camera/start',{}).then(function(){ camOn=true; document.getElementById('cam-toggle-btn').textContent=tr('btn_cam_stop'); + var rb=document.getElementById('cam-reset-btn');if(rb)rb.style.display=''; clog(tr('log_cam_start'),'msg-ok'); setTimeout(function(){ sp.style.display='none'; img.style.display='block'; },1200); if(/Android/i.test(navigator.userAgent)){ @@ -1827,6 +1906,7 @@ function camStop(){ camOn=false; camUserStopped=true; // suppress auto-restart for remainder of this print document.getElementById('cam-toggle-btn').textContent=tr('btn_cam_start'); + var rb=document.getElementById('cam-reset-btn');if(rb)rb.style.display='none'; clog(tr('log_cam_stop'),'msg-ok'); } @@ -2077,6 +2157,13 @@ function aceDryToggle(aceId,on){ function toggleCam(){if(camOn)camStop();else camStart()} +function resetCamera(){ + post('/api/camera/reset',{}).then(function(){ + var btn=document.getElementById('cam-reset-btn'); + if(btn){btn.textContent='↻';setTimeout(function(){btn.textContent='↺';},1000);} + }).catch(function(){}); +} + function aceDryStop(aceId){ aceId=(typeof aceId==='number'&&aceId>=0)?aceId:0; return post('/api/ace/dry',{action:'stop',ace_id:aceId}) @@ -2494,6 +2581,7 @@ function openFilamentDialog(slots){ _amsSlots=slots .filter(function(s){return s.status==='loaded';}) .sort(function(a,b){return (a.slot_index||0)-(b.slot_index||0);}); + _loadSpoolmanStatus(); var dlg=document.getElementById('filament-dialog'); var title=document.getElementById('fd-title'); var body=document.getElementById('fd-slots'); @@ -2623,6 +2711,8 @@ function openFilamentDialog(slots){ }).join(''); } if(dlg)dlg.classList.add('open'); + // Spoolman-Section nach Slot-Render aufbauen (braucht die selects im DOM) + setTimeout(_buildSpoolmanSection, 0); } function closeFilamentDialog(){ @@ -2675,6 +2765,17 @@ function confirmFilamentPrint(){ var excludedObjects=_printObjects.filter(function(o){return o.skip;}).map(function(o){return o.name;}); var fdAlEl=document.getElementById('fd-auto-leveling'); var fdAutoLeveling=fdAlEl?( fdAlEl.checked?1:0):(S.auto_leveling===undefined?1:S.auto_leveling?1:0); + // Spoolman: Slot→Spool-Mapping aus Dialog sammeln und senden + if(_spoolmanStatus.configured){ + var slotMap={}; + document.querySelectorAll('[data-spool-slot]').forEach(function(sel){ + var idx=sel.dataset.spoolSlot; + var val=parseInt(sel.value); + if(val>0)slotMap[idx]=val; + }); + _slotSpoolMap=slotMap; + post('/kx/spoolman/active-spool',{slot_map:slotMap}).catch(function(){}); + } closeFilamentDialog(); if(_filamentDialogMode==='banner'){ // Banner-Modus: /kx/print bevorzugen wenn _storeFileId bekannt (gleicher Pfad wie File-Browser). diff --git a/web/themes/default/index.html b/web/themes/default/index.html index 843d553..560a58b 100644 --- a/web/themes/default/index.html +++ b/web/themes/default/index.html @@ -157,6 +157,7 @@
+ @@ -435,6 +436,7 @@ + @@ -570,6 +572,33 @@ + +
+ +
+
🧵 Spoolman
+
+ + +
+
+ + +
+
+ +
+
+ +
+
🕵 Obico
+
+ Obico wird über den moonraker-obico-Container konfiguriert.
+ Config-Datei: /mnt/dockerdata/KobraXStack/moonraker-obico/moonraker-obico.cfg +
+
+
+
@@ -646,6 +675,13 @@
+
diff --git a/web/translations/de.json b/web/translations/de.json index c5011df..a8a8f66 100644 --- a/web/translations/de.json +++ b/web/translations/de.json @@ -1,291 +1,327 @@ { - "header_status_standby": "Bereit", - "header_status_printing": "Druckt", - "header_status_complete": "Fertig", - "header_status_error": "Fehler", - "kobra_free": "Bereit", - "kobra_busy": "Beschäftigt", - "kobra_printing": "Druckt", - "kobra_preheating": "Aufheizen", - "kobra_auto_leveling": "Nivellierung", - "kobra_checking": "Prüfung", - "kobra_updated": "Aktualisierung", - "kobra_init": "Initialisierung", - "kobra_pausing": "Pausiert...", - "kobra_paused": "Pausiert", - "kobra_resuming": "Fortsetzen...", - "kobra_resumed": "Fortgesetzt", - "kobra_stopping": "Stoppt...", - "kobra_stoped": "Gestoppt", - "kobra_finished": "Abgeschlossen", - "kobra_failed": "Fehler", - "kobra_canceled": "Abgebrochen", - "kobra_offline": "Offline", - "nav_dashboard": "Dashboard", - "nav_print": "Druck", - "nav_temps": "Temperaturen", - "nav_motion": "Achsen", - "nav_ams": "AMS", - "nav_extras": "Licht / Lüfter", - "nav_console": "Konsole", - "card_progress": "Fortschritt", - "card_temps": "Temperaturen", - "card_light_fan": "Lüfter", - "card_speed": "Druckgeschwindigkeit", - "card_cam": "Kamera", - "lbl_elapsed": "Verstrichen:", - "lbl_remaining": "Restzeit:", - "lbl_slicer_time": "Slicer-Schätzung:", - "lbl_layers": "Layer", - "lbl_zpos": "Z (mm)", - "speed_silent": "🐢 Leise", - "speed_normal": "⚡ Normal", - "speed_sport": "🚀 Sport", - "lbl_light": "💡 Licht", - "lbl_feed": "Einziehen", - "lbl_unload": "Ausziehen", - "card_ace_dry": "ACE Trocknung", + "ace_dry_auto_refill": "Auto-Nachschub", + "ace_dry_chart": "Verlauf (Temp/Feuchte)", + "ace_dry_current_temp": "Temperatur", + "ace_dry_dialog_cancel": "Abbrechen", + "ace_dry_dialog_confirm": "Bestätigen", + "ace_dry_dialog_custom_name": "Eigener Name", + "ace_dry_dialog_reset_default": "Auf Standard zurücksetzen", + "ace_dry_dialog_save_restart": "Speichern & Neustart", + "ace_dry_dialog_temp": "Temperatur (30-80°C)", + "ace_dry_dialog_time": "Restzeit (h:m:s)", + "ace_dry_dialog_title": "Trockner Temp/Zeit-Einstellungen", "ace_dry_dryer": "Trockner", + "ace_dry_duration": "Dauer (Min)", + "ace_dry_enable": "Trocknung aktivieren", + "ace_dry_humidity": "Luftfeuchte", + "ace_dry_preset_abs_asa": "ABS / ASA", + "ace_dry_preset_custom": "Custom", + "ace_dry_preset_pa_pc": "PA / PC", + "ace_dry_preset_petg": "PETG", + "ace_dry_preset_pla": "PLA", + "ace_dry_preset_pla_plus": "PLA+", + "ace_dry_preset_tpu": "TPU", + "ace_dry_start": "▶ Start", "ace_dry_status_off": "Status: Aus", "ace_dry_status_on": "Status: Aktiv", "ace_dry_status_remaining": "Rest", - "ace_dry_humidity": "Luftfeuchte", - "ace_dry_current_temp": "Temperatur", - "ace_dry_chart": "Verlauf (Temp/Feuchte)", - "ace_dry_temp": "Temperatur (°C)", - "ace_dry_duration": "Dauer (Min)", - "ace_dry_start": "▶ Start", "ace_dry_stop": "■ Stop", - "ace_dry_auto_refill": "Auto-Nachschub", - "ace_dry_enable": "Trocknung aktivieren", + "ace_dry_temp": "Temperatur (°C)", "ace_dry_temp_line": "Trocknungstemperatur", "ace_dry_time_line": "Trocknungszeit", "ace_dry_ui_pending": "(nur UI, Backend folgt)", - "ace_dry_dialog_title": "Trockner Temp/Zeit-Einstellungen", - "ace_dry_dialog_temp": "Temperatur (30-80°C)", - "ace_dry_dialog_time": "Restzeit (h:m:s)", - "ace_dry_dialog_confirm": "Bestätigen", - "ace_dry_dialog_cancel": "Abbrechen", - "ace_dry_dialog_save_restart": "Speichern & Neustart", - "ace_dry_dialog_custom_name": "Eigener Name", - "ace_dry_dialog_reset_default": "Auf Standard zurücksetzen", - "cam_placeholder": "📷 Kamera nicht gestartet", - "cam_stream_unavailable": "Stream nicht verfügbar", + "add_printer": "Drucker hinzufügen", + "ams_empty": "Leer", + "ams_no_data": "Keine AMS-Daten empfangen", + "apd_cancel": "Abbrechen", + "apd_confirm": "Hinzufügen", + "apd_err_ip": "Bitte IP-Adresse eingeben", + "apd_fetching": "Hole Daten vom Drucker…", + "apd_lbl_ip": "Drucker-IP", + "apd_lbl_name": "Name (optional)", + "apd_placeholder_name": "z.B. Kobra X Wohnzimmer", + "apd_success": "Drucker hinzugefügt, Bridge startet neu…", + "apd_title": "Drucker hinzufügen", "btn_cam_start": "▶ Kamera", + "btn_cam_start2": "▶ Start", "btn_cam_stop": "◼ Kamera", + "btn_cam_stop2": "◼ Stop", + "btn_cancel": "✕ Stopp", + "btn_cancel_generic": "Abbrechen", + "btn_confirm_generic": "Bestätigen", + "btn_connect": "⚡ Verbinden", + "btn_delete": "Löschen", + "btn_disable_motors": "Motoren aus", + "btn_disconnect": "✕ Trennen", + "btn_home_all": "Home All", + "btn_home_xy": "Home XY", + "btn_home_z": "Home Z", "btn_pause": "⏸ Pause", "btn_resume": "▶ Weiter", - "btn_cancel": "✕ Stopp", - "label_nozzle": "Düse", + "cam_placeholder": "📷 Kamera nicht gestartet", + "cam_stream_unavailable": "Stream nicht verfügbar", + "card_ace_dry": "ACE Trocknung", + "card_ams": "Filament", + "card_cam": "Kamera", + "card_light_fan": "Lüfter", + "card_progress": "Fortschritt", + "card_speed": "Druckgeschwindigkeit", + "card_temps": "Temperaturen", + "confirm_cancel": "Druck wirklich abbrechen?", + "fd_cancel": "Abbrechen", + "fd_no_matching_material": "Kein passendes Material", + "fd_no_slots_msg": "Keine belegten AMS-Slots.{br}Druck trotzdem starten?", + "fd_objects_hint": "Objekte überspringen (optional):", + "fd_objects_toggle": "Objekte überspringen", + "fd_options_title": "Optionen", + "fd_print": "▶ Drucken", + "fd_slot": "Slot", + "fd_slots_hint": "GCode-Kanal → AMS-Slot zuweisen:", + "fd_title": "Slot-Zuweisung", + "fd_used": "BELEGT", + "file_cancel_btn": "✕ Abbrechen", + "file_ready_btn": "▶ Druck starten", + "file_slots_btn": "🎨 Slots wählen", + "header_status_complete": "Fertig", + "header_status_error": "Fehler", + "header_status_printing": "Druckt", + "header_status_standby": "Bereit", + "hint_ip_no_port": "Nur IP-Adresse, kein Port (z.B. 192.168.1.102)", + "kobra_auto_leveling": "Nivellierung", + "kobra_busy": "Beschäftigt", + "kobra_canceled": "Abgebrochen", + "kobra_checking": "Prüfung", + "kobra_failed": "Fehler", + "kobra_finished": "Abgeschlossen", + "kobra_free": "Bereit", + "kobra_init": "Initialisierung", + "kobra_offline": "Offline", + "kobra_paused": "Pausiert", + "kobra_pausing": "Pausiert...", + "kobra_preheating": "Aufheizen", + "kobra_printing": "Druckt", + "kobra_resumed": "Fortgesetzt", + "kobra_resuming": "Fortsetzen...", + "kobra_stoped": "Gestoppt", + "kobra_stopping": "Stoppt...", + "kobra_updated": "Aktualisierung", "label_bed": "Bett", "label_fan": "🌀 Lüfter", "label_light": "💡 Licht", - "label_on_off": "Ein / Aus", - "label_speed": "Geschwindigkeit", - "panel_print_title": "Drucksteuerung", - "panel_print_btn_pause": "⏸ Pause", - "panel_print_btn_resume": "▶ Fortsetzen", - "panel_print_btn_cancel": "✕ Abbrechen", - "panel_print_temps_live": "Temperaturen (Live)", - "label_set": "Setzen", + "label_nozzle": "Düse", "label_off": "Aus", - "panel_temps_nozzle": "Düse", - "panel_temps_bed": "Heizbett", - "panel_temps_chart": "Verlauf (letzte 60 Messungen)", - "label_target_c": "Ziel:", - "panel_motion_xy": "XY-Achsen", - "panel_motion_z": "Z-Achse", - "label_step": "Schrittweite:", - "btn_home_z": "Home Z", - "btn_home_xy": "Home XY", - "btn_home_all": "Home All", - "btn_disable_motors": "Motoren aus", - "panel_ams_title": "Filament", - "card_ams": "Filament", - "ams_no_data": "Keine AMS-Daten empfangen", + "label_on_off": "Ein / Aus", + "label_set": "Setzen", "label_slot": "Slot", - "ams_empty": "Leer", - "panel_extras_light": "Licht", - "panel_extras_fan": "Lüfter", - "panel_extras_camera": "Kamera", - "btn_cam_start2": "▶ Start", - "btn_cam_stop2": "◼ Stop", - "panel_console_title": "Ereignis-Log", - "log_light_on": "Licht an", - "log_light_off": "Licht aus", - "log_fan": "Lüfter →", - "log_nozzle": "Düse →", - "log_bed": "Bett →", + "label_speed": "Geschwindigkeit", + "label_step": "Schrittweite:", + "label_target_c": "Ziel:", + "lbl_conn_error": "Verbindungsfehler:", + "lbl_elapsed": "Verstrichen:", + "lbl_feed": "Einziehen", + "lbl_layers": "Layer", + "lbl_light": "💡 Licht", + "lbl_remaining": "Restzeit:", + "lbl_slicer_time": "Slicer-Schätzung:", + "lbl_spoolman_sync_rate": "Sync-Rate (s, 0=aus)", + "lbl_spoolman_url": "Server-URL", + "lbl_unload": "Ausziehen", + "lbl_zpos": "Z (mm)", + "log_auto": "⬇ Auto", "log_axis": "Achse", - "log_home": "Home", - "log_home_all": "Home All", + "log_bed": "Bett →", "log_cam_start": "Kamera gestartet:", "log_cam_stop": "Kamera gestoppt", - "log_poll_error": "Poll-Fehler:", + "log_clear": "✕ Leeren", + "log_delete_failed": "Löschung fehlgeschlagen", + "log_dir_all": "Alle", + "log_dir_label": "Richtung:", + "log_dir_rx": "RX", + "log_dir_tx": "TX", + "log_download": "⬇ Download", "log_error": "Fehler:", - "confirm_cancel": "Druck wirklich abbrechen?", - "settings_title": "Einstellungen", - "settings_connection": "Verbindung", - "settings_print": "Druckeinstellungen", - "settings_poll": "Poll-Intervall (Sekunden)", - "settings_version": "Version", + "log_fan": "Lüfter →", + "log_filter_placeholder": "Filtern…", + "log_home": "Home", + "log_home_all": "Home All", + "log_light_off": "Licht aus", + "log_light_on": "Licht an", + "log_lvl_err": "⛔ Fehler", + "log_lvl_label": "Level:", + "log_lvl_warn": "⚠ Warnung", + "log_nozzle": "Düse →", + "log_poll_error": "Poll-Fehler:", + "log_print_action": "Druck:", + "log_print_start": "Druckstart:", + "log_topic_ams": "AMS", + "log_topic_info": "Info", + "log_topic_label": "Thema:", + "log_topic_print": "Druck", + "log_topic_status": "Status", + "modal_sec_obico": "Obico", + "modal_sec_spoolman": "Spoolman", + "nav_ams": "AMS", + "nav_browser": "Browser", + "nav_console": "Konsole", + "nav_dashboard": "Dashboard", + "nav_extras": "Licht / Lüfter", + "nav_motion": "Achsen", + "nav_print": "Druck", + "nav_printers": "Drucker", "nav_settings": "Einstellungen", - "settings_cat_display": "Darstellung", - "settings_cat_filament": "Filament", - "settings_cat_language": "Sprache", - "settings_cat_theme": "Hell / Dunkel umschalten", - "settings_filament_mapping": "Filament-Profil-Mapping (pro Slot)", - "settings_filament_mapping_save": "Mapping speichern", - "settings_visible_vendors": "Sichtbare Hersteller (Profil-Dropdown)", - "settings_visible_vendors_hint": "Nur diese Hersteller erscheinen im Slot-Profil-Dropdown. Nichts ausgewählt = alle anzeigen. „Generic\" und eigene Profile sind immer sichtbar.", - "settings_visible_vendors_save": "Auswahl speichern", - "progress_action_print": "Drucken", - "progress_action_slots": "Slots zuordnen", - "progress_action_clear": "Leeren", - "settings_save": "Speichern & Neustart", - "settings_printer_name": "Drucker-Name", - "settings_printer_ip": "Drucker-IP", - "settings_mqtt_port": "MQTT-Port", - "settings_username": "MQTT-Benutzername", - "settings_password": "MQTT-Passwort", - "settings_device_id": "Device-ID", - "settings_mode_id": "Mode-ID", - "hint_ip_no_port": "Nur IP-Adresse, kein Port (z.B. 192.168.1.102)", - "settings_default_slot": "Standard-Slot (Einfarbdruck)", - "settings_slot_auto": "Auto (alle belegten Slots)", - "settings_auto_leveling": "Auto-Leveling vor Druck", - "settings_camera_on_print": "Kamera bei Druckstart einschalten", - "settings_web_upload_warning": "Warnung bei Web-Upload-Druck anzeigen", - "update_check": "Auf Updates prüfen", - "update_checking": "Prüfe...", - "update_available": "verfügbar", - "update_none": "Bereits aktuell", - "update_apply": "Jetzt installieren", - "update_applying": "Lade herunter...", - "update_restarting": "Starte neu...", - "update_error": "Fehler", - "btn_connect": "⚡ Verbinden", - "btn_disconnect": "✕ Trennen", - "lbl_conn_error": "Verbindungsfehler:", - "slot_edit_title": "Slot bearbeiten", - "slot_edit_color": "Farbe", - "slot_edit_material": "Material", - "slot_edit_load": "⬇ Einziehen", - "slot_edit_unload": "⬆ Ausziehen", - "slot_edit_save": "💾 Speichern", - "slot_edit_custom": "z.B. PLA, PETG, ABS…", - "slot_edit_ok": "AMS Slot", - "slot_edit_profile": "OrcaSlicer-Profil", - "slot_edit_profile_hint": "Sendet beim OrcaSlicer-Sync die konkrete Marke statt nur „Generic\"", - "slot_edit_profile_default": "— Generic (Default) —", - "orca_profile_section": "OrcaSlicer-Profile", + "nav_temps": "Temperaturen", + "orca_profile_done": "Importiert", + "orca_profile_dropmsg": "Hierher ziehen oder klicken", + "orca_profile_help_html": "Lade ein ZIP deines OrcaSlicer-Filament-Ordners oder einzelne .json-Files hoch.
In OrcaSlicer: Help → Show Configuration Folder → user/<id>/filament/", "orca_profile_hint": "Eigene Profile aus OrcaSlicer importieren (User-Dir öffnen via Help → Show Configuration Folder)", "orca_profile_import_btn": "Profile importieren", "orca_profile_import_link": "★ Eigene Profile importieren…", "orca_profile_import_title": "Eigene OrcaSlicer-Profile importieren", - "orca_profile_help_html": "Lade ein ZIP deines OrcaSlicer-Filament-Ordners oder einzelne .json-Files hoch.
In OrcaSlicer: Help → Show Configuration Folder → user/<id>/filament/", - "orca_profile_dropmsg": "Hierher ziehen oder klicken", "orca_profile_list_label": "Aktuell importiert", - "orca_profile_user_label": "Eigene Profile", - "orca_profile_user_empty": "– keine –", - "orca_profile_uploading": "Lade hoch…", - "orca_profile_done": "Importiert", + "orca_profile_section": "OrcaSlicer-Profile", "orca_profile_skipped": "übersprungen", - "log_dir_all": "Alle", - "log_lvl_label": "Level:", - "file_ready_btn": "▶ Druck starten", - "file_slots_btn": "🎨 Slots wählen", - "file_cancel_btn": "✕ Abbrechen", - "nav_printers": "Drucker", - "skip_title": "✂ Objekte überspringen", - "skip_hint": "Objekte abwählen, die nicht weiter gedruckt werden sollen:", - "skip_btn_label": "Objekte", - "skip_no_objects": "Keine Objekte in diesem Druck.", + "orca_profile_uploading": "Lade hoch…", + "orca_profile_user_empty": "– keine –", + "orca_profile_user_label": "Eigene Profile", + "panel_ams_title": "Filament", + "panel_browser_title": "Datei-Browser", + "panel_console_title": "Ereignis-Log", + "panel_extras_camera": "Kamera", + "panel_extras_fan": "Lüfter", + "panel_extras_light": "Licht", + "panel_motion_xy": "XY-Achsen", + "panel_motion_z": "Z-Achse", + "panel_print_btn_cancel": "✕ Abbrechen", + "panel_print_btn_pause": "⏸ Pause", + "panel_print_btn_resume": "▶ Fortsetzen", + "panel_print_temps_live": "Temperaturen (Live)", + "panel_print_title": "Drucksteuerung", + "panel_temps_bed": "Heizbett", + "panel_temps_chart": "Verlauf (letzte 60 Messungen)", + "panel_temps_nozzle": "Düse", + "print_auto_leveling": "Auto-Leveling für diesen Druck", + "printers_active": "● aktiv", + "printers_current": "Aktueller Drucker", + "printers_empty_hint": "Noch kein Drucker eingerichtet.", + "printers_loading": "Lade…", + "printers_none": "Keine Drucker konfiguriert.", + "printers_remove": "Drucker entfernen", + "printers_remove_confirm": "Drucker \"{name}\" entfernen? Die Bridge startet neu.", + "printers_switch": "Wechseln →", + "progress_action_clear": "Leeren", + "progress_action_print": "Drucken", + "progress_action_slots": "Slots zuordnen", + "settings_auto_leveling": "Auto-Leveling vor Druck", + "settings_auto_leveling_label": "Auto-Leveling vor dem Druck", + "settings_btn_tooltip": "Einstellungen", + "settings_camera_on_print": "Kamera bei Druckstart einschalten", + "settings_cat_connection": "Verbindung", + "settings_cat_display": "Darstellung", + "settings_cat_filament": "Filament", + "settings_cat_language": "Sprache", + "settings_cat_printer": "Drucker", + "settings_cat_system": "System", + "settings_cat_theme": "Hell / Dunkel umschalten", + "settings_connection": "Verbindung", + "settings_default_slot": "Standard-Slot (Einfarbdruck)", + "settings_device_id": "Device-ID", + "settings_device_id_hint": "32 Hexzeichen", + "settings_device_id_placeholder": "32 Hexzeichen", + "settings_filament_mapping": "Filament-Profil-Mapping (pro Slot)", + "settings_filament_mapping_hint": "Festes Orca-Profil pro AMS-Slot. Bei der Slicer-Synchronisierung sendet die Bridge dieses Profil statt \"Generic\".", + "settings_filament_mapping_label": "Filament-Profil-Mapping (pro Slot)", + "settings_filament_mapping_save": "Mapping speichern", + "settings_filament_mapping_save_label": "Mapping speichern", + "settings_file_ready_banner": "Druckleiste", + "settings_file_ready_dialog": "Druckdialog", + "settings_file_ready_mode": "Nach Upload: Druckstart-Verhalten", + "settings_integrations": "Integrationen", + "settings_language": "Sprache", + "settings_mode_id": "Mode-ID", + "settings_mode_id_placeholder": "20030", + "settings_mqtt_port": "MQTT-Port", + "settings_mqtt_username_placeholder": "userXXXXXXXX", + "settings_orca_profiles_import": "Profile importieren", + "settings_orca_profiles_label": "OrcaSlicer-Profile", + "settings_password": "MQTT-Passwort", + "settings_poll": "Poll-Intervall (Sekunden)", + "settings_poll_interval_hint": "Wie oft die Bridge den Druckerstatus abfragt", + "settings_poll_interval_label": "Poll-Intervall (Sekunden)", + "settings_print": "Druckeinstellungen", + "settings_printer_ip": "Drucker-IP", + "settings_printer_name": "Drucker-Name", + "settings_printer_name_placeholder": "z.B. Kobra X Links", + "settings_save": "Speichern & Neustart", + "settings_slot_auto": "Auto (alle belegten Slots)", + "settings_theme_toggle": "Wechsel Hell / Dunkel", + "settings_title": "Einstellungen", + "settings_username": "MQTT-Benutzername", + "settings_vendor_filter_placeholder": "Hersteller suchen…", + "settings_version": "Version", + "settings_visible_vendors": "Sichtbare Hersteller (Profil-Dropdown)", + "settings_visible_vendors_hint": "Nur diese Hersteller erscheinen im Slot-Profil-Dropdown. Nichts ausgewählt = alle anzeigen. „Generic\" und eigene Profile sind immer sichtbar.", + "settings_visible_vendors_label": "Sichtbare Hersteller (Profil-Dropdown)", + "settings_visible_vendors_save": "Auswahl speichern", + "settings_visible_vendors_save_label": "Auswahl speichern", + "settings_web_upload_warning": "Warnung bei Web-Upload-Druck anzeigen", + "sf_all": "Alle", + "sf_err": "✗ Fehler", + "sf_new": "Neu", + "sf_ok": "✓ Erfolgreich", "skip_already": "übersprungen", + "skip_btn_label": "Objekte", + "skip_cancel": "Abbrechen", + "skip_confirm": "Überspringen", + "skip_confirm_btn": "Überspringen", + "skip_hint": "Objekte abwählen, die nicht weiter gedruckt werden sollen:", + "skip_no_objects": "Keine Objekte in diesem Druck.", "skip_select_at_least_one": "Bitte mindestens ein Objekt wählen.", "skip_sending": "Sende …", "skip_success": "Objekte werden übersprungen.", - "fd_objects_hint": "Objekte überspringen (optional):", - "fd_objects_toggle": "Objekte überspringen", - "fd_slots_hint": "GCode-Kanal → AMS-Slot zuweisen:", - "fd_cancel": "Abbrechen", - "fd_print": "▶ Drucken", - "fd_no_slots_msg": "Keine belegten AMS-Slots.{br}Druck trotzdem starten?", - "fd_slot": "Slot", - "fd_no_matching_material": "Kein passendes Material", - "fd_used": "BELEGT", - "add_printer": "Drucker hinzufügen", - "apd_lbl_ip": "Drucker-IP", - "apd_lbl_name": "Name (optional)", - "apd_placeholder_name": "z.B. Kobra X Wohnzimmer", - "apd_cancel": "Abbrechen", - "apd_confirm": "Hinzufügen", - "apd_fetching": "Hole Daten vom Drucker…", - "apd_success": "Drucker hinzugefügt, Bridge startet neu…", - "apd_err_ip": "Bitte IP-Adresse eingeben", - "printers_remove": "Drucker entfernen", - "printers_remove_confirm": "Drucker \"{name}\" entfernen? Die Bridge startet neu.", - "printers_active": "● aktiv", - "printers_switch": "Wechseln →", - "printers_current": "Aktueller Drucker", - "printers_loading": "Lade…", - "printers_none": "Keine Drucker konfiguriert.", - "printers_empty_hint": "Noch kein Drucker eingerichtet.", - "nav_browser": "Browser", - "panel_browser_title": "Datei-Browser", - "store_search_placeholder": "🔍 Suche…", - "store_empty": "Noch keine Dateien hochgeladen.", - "store_refresh": "↻ Aktualisieren", - "store_print": "▶ Drucken", - "store_download": "⬇ Download", - "store_delete_confirm": "Datei löschen?", - "store_print_confirm": "Datei drucken?", - "store_web_verify_title": "Datei verifizieren", - "store_web_verify_msg": "Bitte bestätige, dass diese Datei für den Anycubic Kobra X erstellt wurde.", - "store_web_verify_confirm": "Bestätigen", - "store_web_verify_abort": "Abbrechen", - "store_no_results": "Keine Dateien gefunden.", - "store_never": "noch nicht gedruckt", - "store_estimate": "Schätzung", - "store_upload_label_prefix": "GCode hierher ziehen oder ", - "store_upload_label_browse": "durchsuchen", - "store_upload_busy": "⏳ Hochladen…", - "store_upload_success": "✓ {file}", - "store_upload_error": "✗ {error}", - "store_upload_only_gcode": "✗ Nur GCode-Dateien erlaubt (.gcode, .3mf, .bgcode)", - "sf_all": "Alle", - "sf_ok": "✓ Erfolgreich", - "sf_err": "✗ Fehler", - "sf_new": "Neu", + "skip_title": "✂ Objekte überspringen", + "slot_edit_color": "Farbe", + "slot_edit_custom": "z.B. PLA, PETG, ABS…", + "slot_edit_load": "⬇ Einziehen", + "slot_edit_material": "Material", + "slot_edit_ok": "AMS Slot", + "slot_edit_profile": "OrcaSlicer-Profil", + "slot_edit_profile_default": "— Generic (Default) —", + "slot_edit_profile_hint": "Sendet beim OrcaSlicer-Sync die konkrete Marke statt nur „Generic\"", + "slot_edit_save": "💾 Speichern", + "slot_edit_title": "Slot bearbeiten", + "slot_edit_unload": "⬆ Ausziehen", + "speed_normal": "⚡ Normal", + "speed_silent": "🐢 Leise", + "speed_sport": "🚀 Sport", "ss_date": "↓ Datum", - "ss_name": "A–Z Name", "ss_dur": "⏱ Druckzeit", - "ace_dry_preset_pla": "PLA", - "ace_dry_preset_pla_plus": "PLA+", - "ace_dry_preset_petg": "PETG", - "ace_dry_preset_tpu": "TPU", - "ace_dry_preset_abs_asa": "ABS / ASA", - "ace_dry_preset_pa_pc": "PA / PC", - "ace_dry_preset_custom": "Custom", - "fd_options_title": "Optionen", - "print_auto_leveling": "Auto-Leveling für diesen Druck", - "settings_file_ready_mode": "Druckdialog starten", - "settings_file_ready_banner": "Druckleiste", - "settings_file_ready_dialog": "Druckdialog", - "log_dir_rx": "RX", - "log_dir_tx": "TX", - "log_dir_label": "Richtung:", - "log_lvl_err": "⛔ Fehler", - "log_lvl_warn": "⚠ Warnung", - "log_topic_label": "Thema:", - "log_topic_ams": "AMS", - "log_topic_print": "Druck", - "log_topic_info": "Info", - "log_topic_status": "Status", - "log_download": "⬇ Download", - "log_auto": "⬇ Auto", - "log_clear": "✕ Leeren", - "log_filter_placeholder": "Filtern…", - "skip_cancel": "Abbrechen", - "skip_confirm": "Überspringen" + "ss_name": "A–Z Name", + "store_delete_confirm": "Datei löschen?", + "store_download": "⬇ Download", + "store_empty": "Noch keine Dateien hochgeladen.", + "store_estimate": "Schätzung", + "store_never": "noch nicht gedruckt", + "store_no_results": "Keine Dateien gefunden.", + "store_print": "▶ Drucken", + "store_print_confirm": "Datei drucken?", + "store_refresh": "↻ Aktualisieren", + "store_search_placeholder": "🔍 Suche…", + "store_upload_busy": "⏳ Hochladen…", + "store_upload_error": "✗ {error}", + "store_upload_label_browse": "durchsuchen", + "store_upload_label_prefix": "GCode hierher ziehen oder ", + "store_upload_only_gcode": "✗ Nur GCode-Dateien erlaubt (.gcode, .3mf, .bgcode)", + "store_upload_success": "✓ {file}", + "store_web_verify_abort": "Abbrechen", + "store_web_verify_confirm": "Bestätigen", + "store_web_verify_msg": "Bitte bestätige, dass diese Datei für den Anycubic Kobra X erstellt wurde.", + "store_web_verify_title": "Datei verifizieren", + "update_apply": "Jetzt installieren", + "update_applying": "Lade herunter...", + "update_available": "verfügbar", + "update_check": "Auf Updates prüfen", + "update_checking": "Prüfe...", + "update_error": "Fehler", + "update_none": "Bereits aktuell", + "update_restarting": "Starte neu..." } diff --git a/web/translations/en.json b/web/translations/en.json index 61c5c86..b08bf41 100644 --- a/web/translations/en.json +++ b/web/translations/en.json @@ -1,291 +1,327 @@ { - "header_status_standby": "Ready", - "header_status_printing": "Printing", - "header_status_complete": "Complete", - "header_status_error": "Error", - "kobra_free": "Ready", - "kobra_busy": "Busy", - "kobra_printing": "Printing", - "kobra_preheating": "Preheating", - "kobra_auto_leveling": "Auto Leveling", - "kobra_checking": "Checking", - "kobra_updated": "Updating", - "kobra_init": "Initializing", - "kobra_pausing": "Pausing...", - "kobra_paused": "Paused", - "kobra_resuming": "Resuming...", - "kobra_resumed": "Resumed", - "kobra_stopping": "Stopping...", - "kobra_stoped": "Stopped", - "kobra_finished": "Finished", - "kobra_failed": "Error", - "kobra_canceled": "Cancelled", - "kobra_offline": "Offline", - "nav_dashboard": "Dashboard", - "nav_print": "Print", - "nav_temps": "Temperatures", - "nav_motion": "Motion", - "nav_ams": "AMS", - "nav_extras": "Light / Fan", - "nav_console": "Console", - "card_progress": "Progress", - "card_temps": "Temperatures", - "card_light_fan": "Fan", - "card_speed": "Print Speed", - "card_cam": "Camera", - "lbl_elapsed": "Elapsed:", - "lbl_remaining": "Remaining:", - "lbl_slicer_time": "Slicer estimate:", - "lbl_layers": "Layer", - "lbl_zpos": "Z (mm)", - "speed_silent": "🐢 Silent", - "speed_normal": "⚡ Normal", - "speed_sport": "🚀 Sport", - "lbl_light": "💡 Light", - "lbl_feed": "Load", - "lbl_unload": "Unload", - "card_ace_dry": "ACE Drying", + "ace_dry_auto_refill": "Auto Refill", + "ace_dry_chart": "History (Temp/Humidity)", + "ace_dry_current_temp": "Temperature", + "ace_dry_dialog_cancel": "Cancel", + "ace_dry_dialog_confirm": "Confirm", + "ace_dry_dialog_custom_name": "Custom Name", + "ace_dry_dialog_reset_default": "Reset to Default", + "ace_dry_dialog_save_restart": "Save & Restart", + "ace_dry_dialog_temp": "Temperature (30-80°C)", + "ace_dry_dialog_time": "Rem. Time (h:m:s)", + "ace_dry_dialog_title": "Dryer Temp/Time Settings", "ace_dry_dryer": "Dryer", + "ace_dry_duration": "Duration (min)", + "ace_dry_enable": "Enable Drying", + "ace_dry_humidity": "Humidity", + "ace_dry_preset_abs_asa": "ABS / ASA", + "ace_dry_preset_custom": "Custom", + "ace_dry_preset_pa_pc": "PA / PC", + "ace_dry_preset_petg": "PETG", + "ace_dry_preset_pla": "PLA", + "ace_dry_preset_pla_plus": "PLA+", + "ace_dry_preset_tpu": "TPU", + "ace_dry_start": "▶ Start", "ace_dry_status_off": "Status: Off", "ace_dry_status_on": "Status: Active", "ace_dry_status_remaining": "Remaining", - "ace_dry_humidity": "Humidity", - "ace_dry_current_temp": "Temperature", - "ace_dry_chart": "History (Temp/Humidity)", - "ace_dry_temp": "Temperature (°C)", - "ace_dry_duration": "Duration (min)", - "ace_dry_start": "▶ Start", "ace_dry_stop": "■ Stop", - "ace_dry_auto_refill": "Auto Refill", - "ace_dry_enable": "Enable Drying", + "ace_dry_temp": "Temperature (°C)", "ace_dry_temp_line": "Drying Temperature", "ace_dry_time_line": "Drying Time", "ace_dry_ui_pending": "(UI only, backend next)", - "ace_dry_dialog_title": "Dryer Temp/Time Settings", - "ace_dry_dialog_temp": "Temperature (30-80°C)", - "ace_dry_dialog_time": "Rem. Time (h:m:s)", - "ace_dry_dialog_confirm": "Confirm", - "ace_dry_dialog_cancel": "Cancel", - "ace_dry_dialog_save_restart": "Save & Restart", - "ace_dry_dialog_custom_name": "Custom Name", - "ace_dry_dialog_reset_default": "Reset to Default", - "ace_dry_preset_pla": "PLA", - "ace_dry_preset_pla_plus": "PLA+", - "ace_dry_preset_petg": "PETG", - "ace_dry_preset_tpu": "TPU", - "ace_dry_preset_abs_asa": "ABS / ASA", - "ace_dry_preset_pa_pc": "PA / PC", - "ace_dry_preset_custom": "Custom", - "cam_placeholder": "📷 Camera not started", - "cam_stream_unavailable": "Stream unavailable", + "add_printer": "Add printer", + "ams_empty": "Empty", + "ams_no_data": "No AMS data received", + "apd_cancel": "Cancel", + "apd_confirm": "Add", + "apd_err_ip": "Please enter an IP address", + "apd_fetching": "Fetching data from printer…", + "apd_lbl_ip": "Printer IP", + "apd_lbl_name": "Name (optional)", + "apd_placeholder_name": "e.g. Kobra X Living Room", + "apd_success": "Printer added, bridge restarting…", + "apd_title": "Add printer", "btn_cam_start": "▶ Camera", + "btn_cam_start2": "▶ Start", "btn_cam_stop": "◼ Camera", + "btn_cam_stop2": "◼ Stop", + "btn_cancel": "✕ Stop", + "btn_cancel_generic": "Cancel", + "btn_confirm_generic": "Confirm", + "btn_connect": "⚡ Connect", + "btn_delete": "Delete", + "btn_disable_motors": "Motors Off", + "btn_disconnect": "✕ Disconnect", + "btn_home_all": "Home All", + "btn_home_xy": "Home XY", + "btn_home_z": "Home Z", "btn_pause": "⏸ Pause", "btn_resume": "▶ Resume", - "btn_cancel": "✕ Stop", - "label_nozzle": "Nozzle", + "cam_placeholder": "📷 Camera not started", + "cam_stream_unavailable": "Stream unavailable", + "card_ace_dry": "ACE Drying", + "card_ams": "Filament", + "card_cam": "Camera", + "card_light_fan": "Fan", + "card_progress": "Progress", + "card_speed": "Print Speed", + "card_temps": "Temperatures", + "confirm_cancel": "Really cancel the print?", + "fd_cancel": "Cancel", + "fd_no_matching_material": "No matching material", + "fd_no_slots_msg": "No loaded AMS slots.{br}Start print anyway?", + "fd_objects_hint": "Skip objects (optional):", + "fd_objects_toggle": "Skip objects", + "fd_options_title": "Print Options", + "fd_print": "▶ Print", + "fd_slot": "Slot", + "fd_slots_hint": "Assign GCode channel to AMS slot:", + "fd_title": "Slot Assignment", + "fd_used": "USED", + "file_cancel_btn": "✕ Cancel", + "file_ready_btn": "▶ Start Print", + "file_slots_btn": "🎨 Select Slots", + "header_status_complete": "Complete", + "header_status_error": "Error", + "header_status_printing": "Printing", + "header_status_standby": "Ready", + "hint_ip_no_port": "IP address only, no port (e.g. 192.168.1.102)", + "kobra_auto_leveling": "Auto Leveling", + "kobra_busy": "Busy", + "kobra_canceled": "Cancelled", + "kobra_checking": "Checking", + "kobra_failed": "Error", + "kobra_finished": "Finished", + "kobra_free": "Ready", + "kobra_init": "Initializing", + "kobra_offline": "Offline", + "kobra_paused": "Paused", + "kobra_pausing": "Pausing...", + "kobra_preheating": "Preheating", + "kobra_printing": "Printing", + "kobra_resumed": "Resumed", + "kobra_resuming": "Resuming...", + "kobra_stoped": "Stopped", + "kobra_stopping": "Stopping...", + "kobra_updated": "Updating", "label_bed": "Bed", "label_fan": "🌀 Fan", "label_light": "💡 Light", - "label_on_off": "On / Off", - "label_speed": "Speed", - "panel_print_title": "Print Control", - "panel_print_btn_pause": "⏸ Pause", - "panel_print_btn_resume": "▶ Resume", - "panel_print_btn_cancel": "✕ Cancel", - "panel_print_temps_live": "Temperatures (Live)", - "label_set": "Set", + "label_nozzle": "Nozzle", "label_off": "Off", - "panel_temps_nozzle": "Nozzle", - "panel_temps_bed": "Heated Bed", - "panel_temps_chart": "History (last 60 readings)", - "label_target_c": "Target:", - "panel_motion_xy": "XY Axes", - "panel_motion_z": "Z Axis", - "label_step": "Step size:", - "btn_home_z": "Home Z", - "btn_home_xy": "Home XY", - "btn_home_all": "Home All", - "btn_disable_motors": "Motors Off", - "panel_ams_title": "Filament", - "card_ams": "Filament", - "ams_no_data": "No AMS data received", + "label_on_off": "On / Off", + "label_set": "Set", "label_slot": "Slot", - "ams_empty": "Empty", - "panel_extras_light": "Light", - "panel_extras_fan": "Fan", - "panel_extras_camera": "Camera", - "btn_cam_start2": "▶ Start", - "btn_cam_stop2": "◼ Stop", - "panel_console_title": "Event Log", - "log_light_on": "Light on", - "log_light_off": "Light off", - "log_fan": "Fan →", - "log_nozzle": "Nozzle →", - "log_bed": "Bed →", + "label_speed": "Speed", + "label_step": "Step size:", + "label_target_c": "Target:", + "lbl_conn_error": "Connection error:", + "lbl_elapsed": "Elapsed:", + "lbl_feed": "Load", + "lbl_layers": "Layer", + "lbl_light": "💡 Light", + "lbl_remaining": "Remaining:", + "lbl_slicer_time": "Slicer estimate:", + "lbl_spoolman_sync_rate": "Sync rate (s, 0=off)", + "lbl_spoolman_url": "Server URL", + "lbl_unload": "Unload", + "lbl_zpos": "Z (mm)", + "log_auto": "⬇ Auto", "log_axis": "Axis", - "log_home": "Home", - "log_home_all": "Home All", + "log_bed": "Bed →", "log_cam_start": "Camera started:", "log_cam_stop": "Camera stopped", - "log_poll_error": "Poll error:", + "log_clear": "✕ Clear", + "log_delete_failed": "Delete failed", + "log_dir_all": "All", + "log_dir_label": "Dir:", + "log_dir_rx": "RX", + "log_dir_tx": "TX", + "log_download": "⬇ Download", "log_error": "Error:", - "confirm_cancel": "Really cancel the print?", - "settings_title": "Settings", - "settings_connection": "Connection", - "settings_print": "Print Settings", - "settings_poll": "Poll Interval (seconds)", + "log_fan": "Fan →", + "log_filter_placeholder": "Filter…", + "log_home": "Home", + "log_home_all": "Home All", + "log_light_off": "Light off", + "log_light_on": "Light on", + "log_lvl_err": "⛔ Errors", + "log_lvl_label": "Level:", + "log_lvl_warn": "⚠ Warn", + "log_nozzle": "Nozzle →", + "log_poll_error": "Poll error:", + "log_print_action": "Print:", + "log_print_start": "Print start:", + "log_topic_ams": "AMS", + "log_topic_info": "Info", + "log_topic_label": "Topic:", + "log_topic_print": "Print", + "log_topic_status": "Status", + "modal_sec_obico": "Obico", + "modal_sec_spoolman": "Spoolman", + "nav_ams": "AMS", + "nav_browser": "Browser", + "nav_console": "Console", + "nav_dashboard": "Dashboard", + "nav_extras": "Light / Fan", + "nav_motion": "Motion", + "nav_print": "Print", + "nav_printers": "Printers", "nav_settings": "Settings", - "settings_cat_display": "Appearance", - "settings_cat_filament": "Filament", - "settings_cat_language": "Language", - "settings_cat_theme": "Toggle light / dark", - "settings_filament_mapping": "Filament profile mapping (per slot)", - "settings_filament_mapping_save": "Save mapping", - "settings_visible_vendors": "Visible vendors (profile dropdown)", - "settings_visible_vendors_hint": "Only these vendors appear in the slot profile dropdown. Nothing selected = show all. \"Generic\" and your own profiles are always visible.", - "settings_visible_vendors_save": "Save selection", - "progress_action_print": "Print", - "progress_action_slots": "Map slots", - "progress_action_clear": "Clear", - "settings_version": "Version", - "settings_save": "Save & Restart", - "settings_printer_name": "Printer Name", - "settings_printer_ip": "Printer IP", - "settings_mqtt_port": "MQTT Port", - "settings_username": "MQTT Username", - "settings_password": "MQTT Password", - "settings_device_id": "Device ID", - "settings_mode_id": "Mode ID", - "hint_ip_no_port": "IP address only, no port (e.g. 192.168.1.102)", - "settings_default_slot": "Default Slot (single color)", - "settings_slot_auto": "Auto (all loaded slots)", - "settings_auto_leveling": "Auto-Leveling Default", - "fd_options_title": "Print Options", - "print_auto_leveling": "Auto-Leveling", - "settings_file_ready_mode": "Start Print Behavior", - "settings_file_ready_banner": "Print Bar", - "settings_file_ready_dialog": "Print Dialog", - "settings_camera_on_print": "Turn camera on at print start", - "settings_web_upload_warning": "Show warning when printing web uploads", - "update_check": "Check for Updates", - "update_checking": "Checking...", - "update_available": "available", - "update_none": "Already up to date", - "update_apply": "Install Now", - "update_applying": "Downloading...", - "update_restarting": "Restarting...", - "update_error": "Error", - "btn_connect": "⚡ Connect", - "btn_disconnect": "✕ Disconnect", - "lbl_conn_error": "Connection error:", - "slot_edit_title": "Edit Slot", - "slot_edit_color": "Color", - "slot_edit_material": "Material", - "slot_edit_load": "⬇ Load", - "slot_edit_unload": "⬆ Unload", - "slot_edit_save": "💾 Save", - "slot_edit_custom": "e.g. PLA, PETG, ABS…", - "slot_edit_ok": "AMS Slot", - "slot_edit_profile": "OrcaSlicer profile", - "slot_edit_profile_hint": "Sent on OrcaSlicer sync as the specific brand instead of just \"Generic\"", - "slot_edit_profile_default": "— Generic (default) —", - "orca_profile_section": "OrcaSlicer Profiles", + "nav_temps": "Temperatures", + "orca_profile_done": "Imported", + "orca_profile_dropmsg": "Drop here or click", + "orca_profile_help_html": "Upload a ZIP of your OrcaSlicer filament folder or single .json files.
In OrcaSlicer: Help → Show Configuration Folder → user/<id>/filament/", "orca_profile_hint": "Import your own OrcaSlicer filament profiles (open the user dir via Help → Show Configuration Folder)", "orca_profile_import_btn": "Import profiles", "orca_profile_import_link": "★ Import own profiles…", "orca_profile_import_title": "Import your OrcaSlicer profiles", - "orca_profile_help_html": "Upload a ZIP of your OrcaSlicer filament folder or single .json files.
In OrcaSlicer: Help → Show Configuration Folder → user/<id>/filament/", - "orca_profile_dropmsg": "Drop here or click", "orca_profile_list_label": "Currently imported", - "orca_profile_user_label": "Own profiles", - "orca_profile_user_empty": "– none –", - "orca_profile_uploading": "Uploading…", - "orca_profile_done": "Imported", + "orca_profile_section": "OrcaSlicer Profiles", "orca_profile_skipped": "skipped", - "log_dir_all": "All", - "log_dir_rx": "RX", - "log_dir_tx": "TX", - "log_dir_label": "Dir:", - "log_lvl_label": "Level:", - "log_lvl_err": "⛔ Errors", - "log_lvl_warn": "⚠ Warn", - "log_topic_label": "Topic:", - "log_topic_ams": "AMS", - "log_topic_print": "Print", - "log_topic_info": "Info", - "log_topic_status": "Status", - "log_download": "⬇ Download", - "log_auto": "⬇ Auto", - "log_clear": "✕ Clear", - "log_filter_placeholder": "Filter…", - "file_ready_btn": "▶ Start Print", - "file_slots_btn": "🎨 Select Slots", - "file_cancel_btn": "✕ Cancel", - "nav_printers": "Printers", - "skip_title": "✂ Skip objects", - "skip_hint": "Uncheck objects you no longer want to print:", - "skip_btn_label": "Objects", - "skip_no_objects": "No objects in this print.", + "orca_profile_uploading": "Uploading…", + "orca_profile_user_empty": "– none –", + "orca_profile_user_label": "Own profiles", + "panel_ams_title": "Filament", + "panel_browser_title": "File Browser", + "panel_console_title": "Event Log", + "panel_extras_camera": "Camera", + "panel_extras_fan": "Fan", + "panel_extras_light": "Light", + "panel_motion_xy": "XY Axes", + "panel_motion_z": "Z Axis", + "panel_print_btn_cancel": "✕ Cancel", + "panel_print_btn_pause": "⏸ Pause", + "panel_print_btn_resume": "▶ Resume", + "panel_print_temps_live": "Temperatures (Live)", + "panel_print_title": "Print Control", + "panel_temps_bed": "Heated Bed", + "panel_temps_chart": "History (last 60 readings)", + "panel_temps_nozzle": "Nozzle", + "print_auto_leveling": "Auto-Leveling", + "printers_active": "● active", + "printers_current": "Current printer", + "printers_empty_hint": "No printer set up yet.", + "printers_loading": "Loading…", + "printers_none": "No printers configured.", + "printers_remove": "Remove printer", + "printers_remove_confirm": "Remove printer \"{name}\"? The bridge will restart.", + "printers_switch": "Switch →", + "progress_action_clear": "Clear", + "progress_action_print": "Print", + "progress_action_slots": "Map slots", + "settings_auto_leveling": "Auto-Leveling Default", + "settings_auto_leveling_label": "Auto-Leveling before print", + "settings_btn_tooltip": "Settings", + "settings_camera_on_print": "Turn camera on at print start", + "settings_cat_connection": "Connection", + "settings_cat_display": "Appearance", + "settings_cat_filament": "Filament", + "settings_cat_language": "Language", + "settings_cat_printer": "Printer", + "settings_cat_system": "System", + "settings_cat_theme": "Toggle light / dark", + "settings_connection": "Connection", + "settings_default_slot": "Default Slot (single color)", + "settings_device_id": "Device ID", + "settings_device_id_hint": "32 hex characters", + "settings_device_id_placeholder": "32 hex characters", + "settings_filament_mapping": "Filament profile mapping (per slot)", + "settings_filament_mapping_hint": "Fixed Orca profile per AMS slot. On slicer sync, the bridge sends this profile instead of \"Generic\".", + "settings_filament_mapping_label": "Filament profile mapping (per slot)", + "settings_filament_mapping_save": "Save mapping", + "settings_filament_mapping_save_label": "Save mapping", + "settings_file_ready_banner": "Print bar", + "settings_file_ready_dialog": "Print dialog", + "settings_file_ready_mode": "After upload: Start print behavior", + "settings_integrations": "Integrations", + "settings_language": "Language", + "settings_mode_id": "Mode ID", + "settings_mode_id_placeholder": "20030", + "settings_mqtt_port": "MQTT Port", + "settings_mqtt_username_placeholder": "userXXXXXXXX", + "settings_orca_profiles_import": "Import profiles", + "settings_orca_profiles_label": "OrcaSlicer Profiles", + "settings_password": "MQTT Password", + "settings_poll": "Poll Interval (seconds)", + "settings_poll_interval_hint": "How often the bridge queries printer status", + "settings_poll_interval_label": "Poll Interval (seconds)", + "settings_print": "Print Settings", + "settings_printer_ip": "Printer IP", + "settings_printer_name": "Printer Name", + "settings_printer_name_placeholder": "e.g. Kobra X Left", + "settings_save": "Save & Restart", + "settings_slot_auto": "Auto (all loaded slots)", + "settings_theme_toggle": "Toggle light / dark", + "settings_title": "Settings", + "settings_username": "MQTT Username", + "settings_vendor_filter_placeholder": "Search vendors…", + "settings_version": "Version", + "settings_visible_vendors": "Visible vendors (profile dropdown)", + "settings_visible_vendors_hint": "Only these vendors appear in the slot profile dropdown. Nothing selected = show all. \"Generic\" and your own profiles are always visible.", + "settings_visible_vendors_label": "Visible vendors (profile dropdown)", + "settings_visible_vendors_save": "Save selection", + "settings_visible_vendors_save_label": "Save selection", + "settings_web_upload_warning": "Show warning when printing web uploads", + "sf_all": "All", + "sf_err": "✗ Failed", + "sf_new": "New", + "sf_ok": "✓ Completed", "skip_already": "skipped", + "skip_btn_label": "Objects", "skip_cancel": "Cancel", "skip_confirm": "Skip", + "skip_confirm_btn": "Skip", + "skip_hint": "Uncheck objects you no longer want to print:", + "skip_no_objects": "No objects in this print.", "skip_select_at_least_one": "Please pick at least one object.", "skip_sending": "Sending …", "skip_success": "Objects will be skipped.", - "fd_objects_hint": "Skip objects (optional):", - "fd_objects_toggle": "Skip objects", - "fd_slots_hint": "Assign GCode channel to AMS slot:", - "fd_cancel": "Cancel", - "fd_print": "▶ Print", - "fd_no_slots_msg": "No loaded AMS slots.{br}Start print anyway?", - "fd_slot": "Slot", - "fd_no_matching_material": "No matching material", - "fd_used": "USED", - "add_printer": "Add printer", - "apd_lbl_ip": "Printer IP", - "apd_lbl_name": "Name (optional)", - "apd_placeholder_name": "e.g. Kobra X Living Room", - "apd_cancel": "Cancel", - "apd_confirm": "Add", - "apd_fetching": "Fetching data from printer…", - "apd_success": "Printer added, bridge restarting…", - "apd_err_ip": "Please enter an IP address", - "printers_remove": "Remove printer", - "printers_remove_confirm": "Remove printer \"{name}\"? The bridge will restart.", - "printers_active": "● active", - "printers_switch": "Switch →", - "printers_current": "Current printer", - "printers_loading": "Loading…", - "printers_none": "No printers configured.", - "printers_empty_hint": "No printer set up yet.", - "nav_browser": "Browser", - "panel_browser_title": "File Browser", - "store_search_placeholder": "🔍 Search…", - "store_empty": "No files uploaded yet.", - "store_refresh": "↻ Refresh", - "store_print": "▶ Print", - "store_download": "⬇ Download", - "store_delete_confirm": "Delete file?", - "store_print_confirm": "Print file?", - "store_web_verify_title": "Verify file", - "store_web_verify_msg": "Please verify this file was made for Anycubic Kobra X.", - "store_web_verify_confirm": "Confirm", - "store_web_verify_abort": "Abort", - "store_no_results": "No files found.", - "store_never": "never printed", - "store_estimate": "Estimate", - "store_upload_label_prefix": "Drag GCode here or ", - "store_upload_label_browse": "browse", - "store_upload_busy": "⏳ Uploading…", - "store_upload_success": "✓ {file}", - "store_upload_error": "✗ {error}", - "store_upload_only_gcode": "✗ Only GCode files allowed (.gcode, .3mf, .bgcode)", - "sf_all": "All", - "sf_ok": "✓ Completed", - "sf_err": "✗ Failed", - "sf_new": "New", + "skip_title": "✂ Skip objects", + "slot_edit_color": "Color", + "slot_edit_custom": "e.g. PLA, PETG, ABS…", + "slot_edit_load": "⬇ Load", + "slot_edit_material": "Material", + "slot_edit_ok": "AMS Slot", + "slot_edit_profile": "OrcaSlicer profile", + "slot_edit_profile_default": "— Generic (default) —", + "slot_edit_profile_hint": "Sent on OrcaSlicer sync as the specific brand instead of just \"Generic\"", + "slot_edit_save": "💾 Save", + "slot_edit_title": "Edit Slot", + "slot_edit_unload": "⬆ Unload", + "speed_normal": "⚡ Normal", + "speed_silent": "🐢 Silent", + "speed_sport": "🚀 Sport", "ss_date": "↓ Date", + "ss_dur": "⏱ Print time", "ss_name": "A–Z Name", - "ss_dur": "⏱ Print time" + "store_delete_confirm": "Delete file?", + "store_download": "⬇ Download", + "store_empty": "No files uploaded yet.", + "store_estimate": "Estimate", + "store_never": "never printed", + "store_no_results": "No files found.", + "store_print": "▶ Print", + "store_print_confirm": "Print file?", + "store_refresh": "↻ Refresh", + "store_search_placeholder": "🔍 Search…", + "store_upload_busy": "⏳ Uploading…", + "store_upload_error": "✗ {error}", + "store_upload_label_browse": "browse", + "store_upload_label_prefix": "Drag GCode here or ", + "store_upload_only_gcode": "✗ Only GCode files allowed (.gcode, .3mf, .bgcode)", + "store_upload_success": "✓ {file}", + "store_web_verify_abort": "Cancel", + "store_web_verify_confirm": "Confirm", + "store_web_verify_msg": "Please verify this file was made for Anycubic Kobra X.", + "store_web_verify_title": "Verify file", + "update_apply": "Install Now", + "update_applying": "Downloading...", + "update_available": "available", + "update_check": "Check for Updates", + "update_checking": "Checking...", + "update_error": "Error", + "update_none": "Already up to date", + "update_restarting": "Restarting..." } diff --git a/web/translations/es.json b/web/translations/es.json index 822cf4b..d418799 100644 --- a/web/translations/es.json +++ b/web/translations/es.json @@ -1,291 +1,327 @@ { - "header_status_standby": "Listo", - "header_status_printing": "Imprimiendo", - "header_status_complete": "Completado", - "header_status_error": "Error", - "kobra_free": "Listo", - "kobra_busy": "Ocupado", - "kobra_printing": "Imprimiendo", - "kobra_preheating": "Precalentando", - "kobra_auto_leveling": "Autonivelado", - "kobra_checking": "Comprobando", - "kobra_updated": "Actualizando", - "kobra_init": "Inicializando", - "kobra_pausing": "Pausando...", - "kobra_paused": "Pausado", - "kobra_resuming": "Reanudando...", - "kobra_resumed": "Reanudado", - "kobra_stopping": "Deteniendo...", - "kobra_stoped": "Detenido", - "kobra_finished": "Finalizado", - "kobra_failed": "Error", - "kobra_canceled": "Cancelado", - "kobra_offline": "Desconectada", - "nav_dashboard": "Panel", - "nav_print": "Impresión", - "nav_temps": "Temperaturas", - "nav_motion": "Movimiento", - "nav_ams": "AMS", - "nav_extras": "Luz / Ventilador", - "nav_console": "Consola", - "card_progress": "Progreso", - "card_temps": "Temperaturas", - "card_light_fan": "Ventilador", - "card_speed": "Velocidad de impresión", - "card_cam": "Cámara", - "lbl_elapsed": "Transcurrido:", - "lbl_remaining": "Restante:", - "lbl_slicer_time": "Estimación del slicer:", - "lbl_layers": "Capa", - "lbl_zpos": "Z (mm)", - "speed_silent": "🐢 Silencioso", - "speed_normal": "⚡ Normal", - "speed_sport": "🚀 Sport", - "lbl_light": "💡 Luz", - "lbl_feed": "Cargar", - "lbl_unload": "Descargar", - "card_ace_dry": "Secado ACE", + "ace_dry_auto_refill": "Relleno automático", + "ace_dry_chart": "Historial (Temp/Humedad)", + "ace_dry_current_temp": "Temperatura", + "ace_dry_dialog_cancel": "Cancelar", + "ace_dry_dialog_confirm": "Confirmar", + "ace_dry_dialog_custom_name": "Nombre personalizado", + "ace_dry_dialog_reset_default": "Restablecer valores predeterminados", + "ace_dry_dialog_save_restart": "Guardar y reiniciar", + "ace_dry_dialog_temp": "Temperatura (30-80°C)", + "ace_dry_dialog_time": "Tiempo restante (h:m:s)", + "ace_dry_dialog_title": "Ajustes de temp/tiempo del secador", "ace_dry_dryer": "Secador", + "ace_dry_duration": "Duración (min)", + "ace_dry_enable": "Activar secado", + "ace_dry_humidity": "Humedad", + "ace_dry_preset_abs_asa": "ABS / ASA", + "ace_dry_preset_custom": "Personalizado", + "ace_dry_preset_pa_pc": "PA / PC", + "ace_dry_preset_petg": "PETG", + "ace_dry_preset_pla": "PLA", + "ace_dry_preset_pla_plus": "PLA+", + "ace_dry_preset_tpu": "TPU", + "ace_dry_start": "▶ Iniciar", "ace_dry_status_off": "Estado: Apagado", "ace_dry_status_on": "Estado: Activo", "ace_dry_status_remaining": "Restante", - "ace_dry_humidity": "Humedad", - "ace_dry_current_temp": "Temperatura", - "ace_dry_chart": "Historial (Temp/Humedad)", - "ace_dry_temp": "Temperatura (°C)", - "ace_dry_duration": "Duración (min)", - "ace_dry_start": "▶ Iniciar", "ace_dry_stop": "■ Parar", - "ace_dry_auto_refill": "Relleno automático", - "ace_dry_enable": "Activar secado", + "ace_dry_temp": "Temperatura (°C)", "ace_dry_temp_line": "Temperatura de secado", "ace_dry_time_line": "Tiempo de secado", "ace_dry_ui_pending": "(solo UI, backend después)", - "ace_dry_dialog_title": "Ajustes de temp/tiempo del secador", - "ace_dry_dialog_temp": "Temperatura (30-80°C)", - "ace_dry_dialog_time": "Tiempo restante (h:m:s)", - "ace_dry_dialog_confirm": "Confirmar", - "ace_dry_dialog_cancel": "Cancelar", - "ace_dry_dialog_save_restart": "Guardar y reiniciar", - "ace_dry_dialog_custom_name": "Nombre personalizado", - "ace_dry_dialog_reset_default": "Restablecer valores predeterminados", - "cam_placeholder": "📷 Cámara no iniciada", - "cam_stream_unavailable": "Stream no disponible", + "add_printer": "Añadir impresora", + "ams_empty": "Vacío", + "ams_no_data": "No se recibieron datos de AMS", + "apd_cancel": "Cancelar", + "apd_confirm": "Agregar", + "apd_err_ip": "Introduce una dirección IP", + "apd_fetching": "Obteniendo datos de la impresora…", + "apd_lbl_ip": "IP de impresora", + "apd_lbl_name": "Nombre (opcional)", + "apd_placeholder_name": "p. ej. Kobra X Sala", + "apd_success": "Impresora añadida, reiniciando bridge…", + "apd_title": "Agregar impresora", "btn_cam_start": "▶ Cámara", + "btn_cam_start2": "▶ Iniciar", "btn_cam_stop": "◼ Cámara", + "btn_cam_stop2": "◼ Detener", + "btn_cancel": "✕ Detener", + "btn_cancel_generic": "Cancelar", + "btn_confirm_generic": "Confirmar", + "btn_connect": "⚡ Conectar", + "btn_delete": "Eliminar", + "btn_disable_motors": "Motores apagados", + "btn_disconnect": "✕ Desconectar", + "btn_home_all": "Home All", + "btn_home_xy": "Home XY", + "btn_home_z": "Home Z", "btn_pause": "⏸ Pausa", "btn_resume": "▶ Reanudar", - "btn_cancel": "✕ Detener", - "label_nozzle": "Boquilla", + "cam_placeholder": "📷 Cámara no iniciada", + "cam_stream_unavailable": "Stream no disponible", + "card_ace_dry": "Secado ACE", + "card_ams": "Filamento", + "card_cam": "Cámara", + "card_light_fan": "Ventilador", + "card_progress": "Progreso", + "card_speed": "Velocidad de impresión", + "card_temps": "Temperaturas", + "confirm_cancel": "¿Realmente cancelar la impresión?", + "fd_cancel": "Cancelar", + "fd_no_matching_material": "No hay material compatible", + "fd_no_slots_msg": "No hay slots AMS cargados.{br}¿Iniciar impresión de todos modos?", + "fd_objects_hint": "Omitir objetos (opcional):", + "fd_objects_toggle": "Omitir objetos", + "fd_options_title": "Opciones", + "fd_print": "▶ Imprimir", + "fd_slot": "Ranura", + "fd_slots_hint": "Asignar canal GCode a la ranura AMS:", + "fd_title": "Asignación de ranura", + "fd_used": "USADO", + "file_cancel_btn": "✕ Cancelar", + "file_ready_btn": "▶ Iniciar impresión", + "file_slots_btn": "🎨 Seleccionar ranuras", + "header_status_complete": "Completado", + "header_status_error": "Error", + "header_status_printing": "Imprimiendo", + "header_status_standby": "Listo", + "hint_ip_no_port": "Solo dirección IP, sin puerto (p. ej. 192.168.1.102)", + "kobra_auto_leveling": "Autonivelado", + "kobra_busy": "Ocupado", + "kobra_canceled": "Cancelado", + "kobra_checking": "Comprobando", + "kobra_failed": "Error", + "kobra_finished": "Finalizado", + "kobra_free": "Listo", + "kobra_init": "Inicializando", + "kobra_offline": "Desconectada", + "kobra_paused": "Pausado", + "kobra_pausing": "Pausando...", + "kobra_preheating": "Precalentando", + "kobra_printing": "Imprimiendo", + "kobra_resumed": "Reanudado", + "kobra_resuming": "Reanudando...", + "kobra_stoped": "Detenido", + "kobra_stopping": "Deteniendo...", + "kobra_updated": "Actualizando", "label_bed": "Cama", "label_fan": "🌀 Ventilador", "label_light": "💡 Luz", - "label_on_off": "Encendido / Apagado", - "label_speed": "Velocidad", - "panel_print_title": "Control de impresión", - "panel_print_btn_pause": "⏸ Pausa", - "panel_print_btn_resume": "▶ Reanudar", - "panel_print_btn_cancel": "✕ Cancelar", - "panel_print_temps_live": "Temperaturas (en vivo)", - "label_set": "Set", + "label_nozzle": "Boquilla", "label_off": "Apagado", - "panel_temps_nozzle": "Boquilla", - "panel_temps_bed": "Cama caliente", - "panel_temps_chart": "Historial (últimas 60 lecturas)", - "label_target_c": "Objetivo:", - "panel_motion_xy": "Ejes XY", - "panel_motion_z": "Eje Z", - "label_step": "Tamaño del paso:", - "btn_home_z": "Home Z", - "btn_home_xy": "Home XY", - "btn_home_all": "Home All", - "btn_disable_motors": "Motores apagados", - "panel_ams_title": "Filamento", - "card_ams": "Filamento", - "ams_no_data": "No se recibieron datos de AMS", + "label_on_off": "Encendido / Apagado", + "label_set": "Set", "label_slot": "Ranura", - "ams_empty": "Vacío", - "panel_extras_light": "Luz", - "panel_extras_fan": "Ventilador", - "panel_extras_camera": "Cámara", - "btn_cam_start2": "▶ Iniciar", - "btn_cam_stop2": "◼ Detener", - "panel_console_title": "Registro de eventos", - "log_light_on": "Luz encendida", - "log_light_off": "Luz apagada", - "log_fan": "Ventilador →", - "log_nozzle": "Boquilla →", - "log_bed": "Cama →", + "label_speed": "Velocidad", + "label_step": "Tamaño del paso:", + "label_target_c": "Objetivo:", + "lbl_conn_error": "Error de conexión:", + "lbl_elapsed": "Transcurrido:", + "lbl_feed": "Cargar", + "lbl_layers": "Capa", + "lbl_light": "💡 Luz", + "lbl_remaining": "Restante:", + "lbl_slicer_time": "Estimación del slicer:", + "lbl_spoolman_sync_rate": "Tasa de sincronización (s, 0=desact.)", + "lbl_spoolman_url": "URL del servidor", + "lbl_unload": "Descargar", + "lbl_zpos": "Z (mm)", + "log_auto": "⬇ Auto", "log_axis": "Eje", - "log_home": "Home", - "log_home_all": "Home All", + "log_bed": "Cama →", "log_cam_start": "Cámara iniciada:", "log_cam_stop": "Cámara detenida", - "log_poll_error": "Error de sondeo:", + "log_clear": "✕ Limpiar", + "log_delete_failed": "Error al eliminar", + "log_dir_all": "Todos", + "log_dir_label": "Dirección:", + "log_dir_rx": "RX", + "log_dir_tx": "TX", + "log_download": "⬇ Descargar", "log_error": "Error:", - "confirm_cancel": "¿Realmente cancelar la impresión?", - "settings_title": "Configuración", - "settings_connection": "Conexión", - "settings_print": "Ajustes de impresión", - "settings_poll": "Intervalo de sondeo (segundos)", + "log_fan": "Ventilador →", + "log_filter_placeholder": "Filtrar…", + "log_home": "Home", + "log_home_all": "Home All", + "log_light_off": "Luz apagada", + "log_light_on": "Luz encendida", + "log_lvl_err": "⛔ Errores", + "log_lvl_label": "Nivel:", + "log_lvl_warn": "⚠ Avisos", + "log_nozzle": "Boquilla →", + "log_poll_error": "Error de sondeo:", + "log_print_action": "Impresión:", + "log_print_start": "Inicio de impresión:", + "log_topic_ams": "AMS", + "log_topic_info": "Info", + "log_topic_label": "Tema:", + "log_topic_print": "Impresión", + "log_topic_status": "Estado", + "modal_sec_obico": "Obico", + "modal_sec_spoolman": "Spoolman", + "nav_ams": "AMS", + "nav_browser": "Explorador", + "nav_console": "Consola", + "nav_dashboard": "Panel", + "nav_extras": "Luz / Ventilador", + "nav_motion": "Movimiento", + "nav_print": "Impresión", + "nav_printers": "Impresoras", "nav_settings": "Ajustes", - "settings_cat_display": "Apariencia", - "settings_cat_filament": "Filamento", - "settings_cat_language": "Idioma", - "settings_cat_theme": "Alternar claro / oscuro", - "settings_filament_mapping": "Asignación de perfil de filamento (por ranura)", - "settings_filament_mapping_save": "Guardar asignación", - "settings_visible_vendors": "Fabricantes visibles (lista de perfiles)", - "settings_visible_vendors_hint": "Solo estos fabricantes aparecen en la lista de perfiles de ranura. Nada seleccionado = mostrar todos. «Generic» y tus propios perfiles siempre son visibles.", - "settings_visible_vendors_save": "Guardar selección", - "progress_action_print": "Imprimir", - "progress_action_slots": "Asignar ranuras", - "progress_action_clear": "Vaciar", - "settings_version": "Versión", - "settings_save": "Guardar y reiniciar", - "settings_printer_name": "Nombre de impresora", - "settings_printer_ip": "IP de impresora", - "settings_mqtt_port": "MQTT Port", - "settings_username": "Usuario MQTT", - "settings_password": "Contraseña MQTT", - "settings_device_id": "ID del dispositivo", - "settings_mode_id": "ID de modo", - "hint_ip_no_port": "Solo dirección IP, sin puerto (p. ej. 192.168.1.102)", - "settings_default_slot": "Ranura predeterminada (un color)", - "settings_slot_auto": "Auto (todos los slots cargados)", - "settings_auto_leveling": "Autonivelado antes de imprimir", - "settings_camera_on_print": "Encender cámara al iniciar impresión", - "settings_web_upload_warning": "Mostrar advertencia al imprimir subidas web", - "update_check": "Buscar actualizaciones", - "update_checking": "Comprobando...", - "update_available": "disponible", - "update_none": "Ya actualizado", - "update_apply": "Instalar ahora", - "update_applying": "Descargando...", - "update_restarting": "Reiniciando...", - "update_error": "Error", - "btn_connect": "⚡ Conectar", - "btn_disconnect": "✕ Desconectar", - "lbl_conn_error": "Error de conexión:", - "slot_edit_title": "Editar slot", - "slot_edit_color": "Color", - "slot_edit_material": "Material", - "slot_edit_load": "⬇ Cargar", - "slot_edit_unload": "⬆ Descargar", - "slot_edit_save": "💾 Guardar", - "slot_edit_custom": "p. ej. PLA, PETG, ABS…", - "slot_edit_ok": "Ranura AMS", - "slot_edit_profile": "Perfil de OrcaSlicer", - "slot_edit_profile_hint": "Envía al sincronizar con OrcaSlicer la marca concreta en lugar de solo \"Generic\"", - "slot_edit_profile_default": "— Genérico (Predeterminado) —", - "orca_profile_section": "Perfiles de OrcaSlicer", + "nav_temps": "Temperaturas", + "orca_profile_done": "Importado", + "orca_profile_dropmsg": "Suelta aquí o haz clic", + "orca_profile_help_html": "Sube un ZIP de tu carpeta de filamentos de OrcaSlicer o archivos .json sueltos.
En OrcaSlicer: Help → Show Configuration Folder → user/<id>/filament/", "orca_profile_hint": "Importa tus propios perfiles de filamento de OrcaSlicer (abre el directorio del usuario vía Help → Show Configuration Folder)", "orca_profile_import_btn": "Importar perfiles", "orca_profile_import_link": "★ Importar perfiles propios…", "orca_profile_import_title": "Importar tus perfiles de OrcaSlicer", - "orca_profile_help_html": "Sube un ZIP de tu carpeta de filamentos de OrcaSlicer o archivos .json sueltos.
En OrcaSlicer: Help → Show Configuration Folder → user/<id>/filament/", - "orca_profile_dropmsg": "Suelta aquí o haz clic", "orca_profile_list_label": "Actualmente importados", - "orca_profile_user_label": "Perfiles propios", - "orca_profile_user_empty": "– ninguno –", - "orca_profile_uploading": "Subiendo…", - "orca_profile_done": "Importado", + "orca_profile_section": "Perfiles de OrcaSlicer", "orca_profile_skipped": "omitido", - "log_dir_all": "Todos", - "log_lvl_label": "Nivel:", - "file_ready_btn": "▶ Iniciar impresión", - "file_slots_btn": "🎨 Seleccionar ranuras", - "file_cancel_btn": "✕ Cancelar", - "nav_printers": "Impresoras", - "skip_title": "✂ Omitir objetos", - "skip_hint": "Deselecciona los objetos que ya no quieras imprimir:", - "skip_btn_label": "Objetos", - "skip_no_objects": "No hay objetos en esta impresión.", + "orca_profile_uploading": "Subiendo…", + "orca_profile_user_empty": "– ninguno –", + "orca_profile_user_label": "Perfiles propios", + "panel_ams_title": "Filamento", + "panel_browser_title": "Explorador de archivos", + "panel_console_title": "Registro de eventos", + "panel_extras_camera": "Cámara", + "panel_extras_fan": "Ventilador", + "panel_extras_light": "Luz", + "panel_motion_xy": "Ejes XY", + "panel_motion_z": "Eje Z", + "panel_print_btn_cancel": "✕ Cancelar", + "panel_print_btn_pause": "⏸ Pausa", + "panel_print_btn_resume": "▶ Reanudar", + "panel_print_temps_live": "Temperaturas (en vivo)", + "panel_print_title": "Control de impresión", + "panel_temps_bed": "Cama caliente", + "panel_temps_chart": "Historial (últimas 60 lecturas)", + "panel_temps_nozzle": "Boquilla", + "print_auto_leveling": "Autonivelado para esta impresión", + "printers_active": "● activa", + "printers_current": "Impresora actual", + "printers_empty_hint": "Aún no hay impresora configurada.", + "printers_loading": "Cargando…", + "printers_none": "No hay impresoras configuradas.", + "printers_remove": "Eliminar impresora", + "printers_remove_confirm": "¿Eliminar impresora \"{name}\"? El bridge se reiniciará.", + "printers_switch": "Cambiar →", + "progress_action_clear": "Vaciar", + "progress_action_print": "Imprimir", + "progress_action_slots": "Asignar ranuras", + "settings_auto_leveling": "Autonivelado antes de imprimir", + "settings_auto_leveling_label": "Autonivelado antes de imprimir", + "settings_btn_tooltip": "Ajustes", + "settings_camera_on_print": "Encender cámara al iniciar impresión", + "settings_cat_connection": "Conexión", + "settings_cat_display": "Apariencia", + "settings_cat_filament": "Filamento", + "settings_cat_language": "Idioma", + "settings_cat_printer": "Impresora", + "settings_cat_system": "Sistema", + "settings_cat_theme": "Alternar claro / oscuro", + "settings_connection": "Conexión", + "settings_default_slot": "Ranura predeterminada (un color)", + "settings_device_id": "ID del dispositivo", + "settings_device_id_hint": "32 caracteres hexadecimales", + "settings_device_id_placeholder": "32 caracteres hexadecimales", + "settings_filament_mapping": "Asignación de perfil de filamento (por ranura)", + "settings_filament_mapping_hint": "Perfil Orca fijo por ranura AMS. Al sincronizar con el slicer, el bridge envía este perfil en lugar de \"Generic\".", + "settings_filament_mapping_label": "Asignación de perfil de filamento (por ranura)", + "settings_filament_mapping_save": "Guardar asignación", + "settings_filament_mapping_save_label": "Guardar asignación", + "settings_file_ready_banner": "Barra de impresión", + "settings_file_ready_dialog": "Diálogo de impresión", + "settings_file_ready_mode": "Después de carga: Comportamiento de inicio de impresión", + "settings_integrations": "Integraciones", + "settings_language": "Idioma", + "settings_mode_id": "ID de modo", + "settings_mode_id_placeholder": "20030", + "settings_mqtt_port": "MQTT Port", + "settings_mqtt_username_placeholder": "userXXXXXXXX", + "settings_orca_profiles_import": "Importar perfiles", + "settings_orca_profiles_label": "Perfiles de OrcaSlicer", + "settings_password": "Contraseña MQTT", + "settings_poll": "Intervalo de sondeo (segundos)", + "settings_poll_interval_hint": "Con qué frecuencia el bridge consulta el estado de la impresora", + "settings_poll_interval_label": "Intervalo de sondeo (segundos)", + "settings_print": "Ajustes de impresión", + "settings_printer_ip": "IP de impresora", + "settings_printer_name": "Nombre de impresora", + "settings_printer_name_placeholder": "p. ej. Kobra X Sala", + "settings_save": "Guardar y reiniciar", + "settings_slot_auto": "Auto (todos los slots cargados)", + "settings_theme_toggle": "Alternar claro / oscuro", + "settings_title": "Configuración", + "settings_username": "Usuario MQTT", + "settings_vendor_filter_placeholder": "Buscar fabricantes…", + "settings_version": "Versión", + "settings_visible_vendors": "Fabricantes visibles (lista de perfiles)", + "settings_visible_vendors_hint": "Solo estos fabricantes aparecen en la lista de perfiles de ranura. Nada seleccionado = mostrar todos. «Generic» y tus propios perfiles siempre son visibles.", + "settings_visible_vendors_label": "Fabricantes visibles (lista de perfiles)", + "settings_visible_vendors_save": "Guardar selección", + "settings_visible_vendors_save_label": "Guardar selección", + "settings_web_upload_warning": "Mostrar advertencia al imprimir subidas web", + "sf_all": "Todos", + "sf_err": "✗ Fallido", + "sf_new": "Nuevo", + "sf_ok": "✓ Completado", "skip_already": "omitido", + "skip_btn_label": "Objetos", + "skip_cancel": "Cancelar", + "skip_confirm": "Omitir", + "skip_confirm_btn": "Omitir", + "skip_hint": "Deselecciona los objetos que ya no quieras imprimir:", + "skip_no_objects": "No hay objetos en esta impresión.", "skip_select_at_least_one": "Selecciona al menos un objeto.", "skip_sending": "Enviando …", "skip_success": "Se omitirán los objetos.", - "fd_objects_hint": "Omitir objetos (opcional):", - "fd_objects_toggle": "Omitir objetos", - "fd_slots_hint": "Asignar canal GCode a la ranura AMS:", - "fd_cancel": "Cancelar", - "fd_print": "▶ Imprimir", - "fd_no_slots_msg": "No hay slots AMS cargados.{br}¿Iniciar impresión de todos modos?", - "fd_slot": "Ranura", - "fd_no_matching_material": "No hay material compatible", - "fd_used": "USADO", - "add_printer": "Añadir impresora", - "apd_lbl_ip": "IP de impresora", - "apd_lbl_name": "Nombre (opcional)", - "apd_placeholder_name": "p. ej. Kobra X Sala", - "apd_cancel": "Cancelar", - "apd_confirm": "Añadir", - "apd_fetching": "Obteniendo datos de la impresora…", - "apd_success": "Impresora añadida, reiniciando bridge…", - "apd_err_ip": "Introduce una dirección IP", - "printers_remove": "Eliminar impresora", - "printers_remove_confirm": "¿Eliminar impresora \"{name}\"? El bridge se reiniciará.", - "printers_active": "● activa", - "printers_switch": "Cambiar →", - "printers_current": "Impresora actual", - "printers_loading": "Cargando…", - "printers_none": "No hay impresoras configuradas.", - "printers_empty_hint": "Aún no hay impresora configurada.", - "nav_browser": "Explorador", - "panel_browser_title": "Explorador de archivos", - "store_search_placeholder": "🔍 Buscar…", - "store_empty": "Aún no hay archivos subidos.", - "store_refresh": "↻ Actualizar", - "store_print": "▶ Imprimir", - "store_download": "⬇ Descargar", - "store_delete_confirm": "¿Eliminar archivo?", - "store_print_confirm": "¿Imprimir archivo?", - "store_web_verify_title": "Verificar archivo", - "store_web_verify_msg": "Verifica que este archivo fue creado para Anycubic Kobra X.", - "store_web_verify_confirm": "Confirmar", - "store_web_verify_abort": "Abortar", - "store_no_results": "No se encontraron archivos.", - "store_never": "nunca impreso", - "store_estimate": "Estimación", - "store_upload_label_prefix": "Arrastra el GCode aquí o ", - "store_upload_label_browse": "buscar", - "store_upload_busy": "⏳ Subiendo…", - "store_upload_success": "✓ {file}", - "store_upload_error": "✗ {error}", - "store_upload_only_gcode": "✗ Solo se permiten archivos GCode (.gcode, .3mf, .bgcode)", - "sf_all": "Todos", - "sf_ok": "✓ Completado", - "sf_err": "✗ Fallido", - "sf_new": "Nuevo", + "skip_title": "✂ Omitir objetos", + "slot_edit_color": "Color", + "slot_edit_custom": "p. ej. PLA, PETG, ABS…", + "slot_edit_load": "⬇ Cargar", + "slot_edit_material": "Material", + "slot_edit_ok": "Ranura AMS", + "slot_edit_profile": "Perfil de OrcaSlicer", + "slot_edit_profile_default": "— Genérico (Predeterminado) —", + "slot_edit_profile_hint": "Envía al sincronizar con OrcaSlicer la marca concreta en lugar de solo \"Generic\"", + "slot_edit_save": "💾 Guardar", + "slot_edit_title": "Editar slot", + "slot_edit_unload": "⬆ Descargar", + "speed_normal": "⚡ Normal", + "speed_silent": "🐢 Silencioso", + "speed_sport": "🚀 Sport", "ss_date": "↓ Fecha", - "ss_name": "A–Z Nombre", "ss_dur": "⏱ Tiempo de impresión", - "ace_dry_preset_pla": "PLA", - "ace_dry_preset_pla_plus": "PLA+", - "ace_dry_preset_petg": "PETG", - "ace_dry_preset_tpu": "TPU", - "ace_dry_preset_abs_asa": "ABS / ASA", - "ace_dry_preset_pa_pc": "PA / PC", - "ace_dry_preset_custom": "Personalizado", - "fd_options_title": "Opciones", - "print_auto_leveling": "Autonivelado para esta impresión", - "settings_file_ready_mode": "Iniciar diálogo de impresión", - "settings_file_ready_banner": "Barra de impresión", - "settings_file_ready_dialog": "Diálogo de impresión", - "log_dir_rx": "RX", - "log_dir_tx": "TX", - "log_dir_label": "Dirección:", - "log_lvl_err": "⛔ Errores", - "log_lvl_warn": "⚠ Avisos", - "log_topic_label": "Tema:", - "log_topic_ams": "AMS", - "log_topic_print": "Impresión", - "log_topic_info": "Info", - "log_topic_status": "Estado", - "log_download": "⬇ Descargar", - "log_auto": "⬇ Auto", - "log_clear": "✕ Limpiar", - "log_filter_placeholder": "Filtrar…", - "skip_cancel": "Cancelar", - "skip_confirm": "Omitir" + "ss_name": "A–Z Nombre", + "store_delete_confirm": "¿Eliminar archivo?", + "store_download": "⬇ Descargar", + "store_empty": "Aún no hay archivos subidos.", + "store_estimate": "Estimación", + "store_never": "nunca impreso", + "store_no_results": "No se encontraron archivos.", + "store_print": "▶ Imprimir", + "store_print_confirm": "¿Imprimir archivo?", + "store_refresh": "↻ Actualizar", + "store_search_placeholder": "🔍 Buscar…", + "store_upload_busy": "⏳ Subiendo…", + "store_upload_error": "✗ {error}", + "store_upload_label_browse": "buscar", + "store_upload_label_prefix": "Arrastra el GCode aquí o ", + "store_upload_only_gcode": "✗ Solo se permiten archivos GCode (.gcode, .3mf, .bgcode)", + "store_upload_success": "✓ {file}", + "store_web_verify_abort": "Cancelar", + "store_web_verify_confirm": "Confirmar", + "store_web_verify_msg": "Verifica que este archivo fue hecho para Anycubic Kobra X.", + "store_web_verify_title": "Verificar archivo", + "update_apply": "Instalar ahora", + "update_applying": "Descargando...", + "update_available": "disponible", + "update_check": "Buscar actualizaciones", + "update_checking": "Comprobando...", + "update_error": "Error", + "update_none": "Ya actualizado", + "update_restarting": "Reiniciando..." } diff --git a/web/translations/fr.json b/web/translations/fr.json index 01fc6f6..863ba44 100644 --- a/web/translations/fr.json +++ b/web/translations/fr.json @@ -1,291 +1,327 @@ { - "header_status_standby": "Prêt", - "header_status_printing": "Impression", - "header_status_complete": "Terminé", - "header_status_error": "Erreur", - "kobra_free": "Disponible", - "kobra_busy": "Occupé", - "kobra_printing": "Impression", - "kobra_preheating": "Préchauffage", - "kobra_auto_leveling": "Mise à niveau auto", - "kobra_checking": "Vérification", - "kobra_updated": "Mise à jour", - "kobra_init": "Initialisation", - "kobra_pausing": "Pause en cours…", - "kobra_paused": "En pause", - "kobra_resuming": "Reprise en cours…", - "kobra_resumed": "Repris", - "kobra_stopping": "Arrêt en cours…", - "kobra_stoped": "Arrêté", - "kobra_finished": "Terminé", - "kobra_failed": "Erreur", - "kobra_canceled": "Annulé", - "kobra_offline": "Hors ligne", - "nav_dashboard": "Tableau de bord", - "nav_print": "Impression", - "nav_temps": "Températures", - "nav_motion": "Mouvement", - "nav_ams": "AMS", - "nav_extras": "Lumière / Ventilateur", - "nav_console": "Console", - "card_progress": "Progression", - "card_temps": "Températures", - "card_light_fan": "Ventilateur", - "card_speed": "Vitesse d'impression", - "card_cam": "Caméra", - "lbl_elapsed": "Écoulé :", - "lbl_remaining": "Restant :", - "lbl_slicer_time": "Estimation slicer :", - "lbl_layers": "Couche", - "lbl_zpos": "Z (mm)", - "speed_silent": "🐢 Silencieux", - "speed_normal": "⚡ Normal", - "speed_sport": "🚀 Sport", - "lbl_light": "💡 Lumière", - "lbl_feed": "Charger", - "lbl_unload": "Décharger", - "card_ace_dry": "Séchage ACE", + "ace_dry_auto_refill": "Remplissage auto", + "ace_dry_chart": "Historique (Temp/Humidité)", + "ace_dry_current_temp": "Température", + "ace_dry_dialog_cancel": "Annuler", + "ace_dry_dialog_confirm": "Confirmer", + "ace_dry_dialog_custom_name": "Nom personnalisé", + "ace_dry_dialog_reset_default": "Réinitialiser", + "ace_dry_dialog_save_restart": "Enregistrer et redémarrer", + "ace_dry_dialog_temp": "Température (30-80°C)", + "ace_dry_dialog_time": "Temps restant (h:m:s)", + "ace_dry_dialog_title": "Réglages Temp/Durée du séchoir", "ace_dry_dryer": "Séchoir", + "ace_dry_duration": "Durée (min)", + "ace_dry_enable": "Activer le séchage", + "ace_dry_humidity": "Humidité", + "ace_dry_preset_abs_asa": "ABS / ASA", + "ace_dry_preset_custom": "Personnalisé", + "ace_dry_preset_pa_pc": "PA / PC", + "ace_dry_preset_petg": "PETG", + "ace_dry_preset_pla": "PLA", + "ace_dry_preset_pla_plus": "PLA+", + "ace_dry_preset_tpu": "TPU", + "ace_dry_start": "▶ Démarrer", "ace_dry_status_off": "Statut : Arrêté", "ace_dry_status_on": "Statut : Actif", "ace_dry_status_remaining": "Restant", - "ace_dry_humidity": "Humidité", - "ace_dry_current_temp": "Température", - "ace_dry_chart": "Historique (Temp/Humidité)", - "ace_dry_temp": "Température (°C)", - "ace_dry_duration": "Durée (min)", - "ace_dry_start": "▶ Démarrer", "ace_dry_stop": "■ Arrêter", - "ace_dry_auto_refill": "Remplissage auto", - "ace_dry_enable": "Activer le séchage", + "ace_dry_temp": "Température (°C)", "ace_dry_temp_line": "Température de séchage", "ace_dry_time_line": "Durée de séchage", "ace_dry_ui_pending": "(Interface seule, backend suivant)", - "ace_dry_dialog_title": "Réglages Temp/Durée du séchoir", - "ace_dry_dialog_temp": "Température (30-80°C)", - "ace_dry_dialog_time": "Temps restant (h:m:s)", - "ace_dry_dialog_confirm": "Confirmer", - "ace_dry_dialog_cancel": "Annuler", - "ace_dry_dialog_save_restart": "Enregistrer et redémarrer", - "ace_dry_dialog_custom_name": "Nom personnalisé", - "ace_dry_dialog_reset_default": "Réinitialiser", - "cam_placeholder": "📷 Caméra non démarrée", - "cam_stream_unavailable": "Flux indisponible", + "add_printer": "Ajouter une imprimante", + "ams_empty": "Vide", + "ams_no_data": "Aucune donnée AMS reçue", + "apd_cancel": "Annuler", + "apd_confirm": "Ajouter", + "apd_err_ip": "Veuillez saisir une adresse IP", + "apd_fetching": "Récupération des données de l'imprimante…", + "apd_lbl_ip": "IP de l'imprimante", + "apd_lbl_name": "Nom (optionnel)", + "apd_placeholder_name": "ex. Kobra X Salon", + "apd_success": "Imprimante ajoutée, redémarrage du bridge…", + "apd_title": "Ajouter une imprimante", "btn_cam_start": "▶ Caméra", + "btn_cam_start2": "▶ Démarrer", "btn_cam_stop": "◼ Caméra", + "btn_cam_stop2": "◼ Arrêter", + "btn_cancel": "✕ Arrêter", + "btn_cancel_generic": "Annuler", + "btn_confirm_generic": "Confirmer", + "btn_connect": "⚡ Connecter", + "btn_delete": "Supprimer", + "btn_disable_motors": "Moteurs Off", + "btn_disconnect": "✕ Déconnecter", + "btn_home_all": "Origine Tout", + "btn_home_xy": "Origine XY", + "btn_home_z": "Origine Z", "btn_pause": "⏸ Pause", "btn_resume": "▶ Reprendre", - "btn_cancel": "✕ Arrêter", - "label_nozzle": "Buse", + "cam_placeholder": "📷 Caméra non démarrée", + "cam_stream_unavailable": "Flux indisponible", + "card_ace_dry": "Séchage ACE", + "card_ams": "Filament", + "card_cam": "Caméra", + "card_light_fan": "Ventilateur", + "card_progress": "Progression", + "card_speed": "Vitesse d'impression", + "card_temps": "Températures", + "confirm_cancel": "Vraiment annuler l'impression ?", + "fd_cancel": "Annuler", + "fd_no_matching_material": "Aucun matériau correspondant", + "fd_no_slots_msg": "Aucun slot AMS chargé.{br}Lancer l'impression quand même ?", + "fd_objects_hint": "Ignorer des objets (optionnel) :", + "fd_objects_toggle": "Ignorer des objets", + "fd_options_title": "Options", + "fd_print": "▶ Imprimer", + "fd_slot": "Slot", + "fd_slots_hint": "Associer le canal GCode au slot AMS :", + "fd_title": "Attribution de fente", + "fd_used": "UTILISÉ", + "file_cancel_btn": "✕ Annuler", + "file_ready_btn": "▶ Lancer l'impression", + "file_slots_btn": "🎨 Choisir les slots", + "header_status_complete": "Terminé", + "header_status_error": "Erreur", + "header_status_printing": "Impression", + "header_status_standby": "Prêt", + "hint_ip_no_port": "Adresse IP uniquement, sans port (ex. 192.168.1.102)", + "kobra_auto_leveling": "Mise à niveau auto", + "kobra_busy": "Occupé", + "kobra_canceled": "Annulé", + "kobra_checking": "Vérification", + "kobra_failed": "Erreur", + "kobra_finished": "Terminé", + "kobra_free": "Disponible", + "kobra_init": "Initialisation", + "kobra_offline": "Hors ligne", + "kobra_paused": "En pause", + "kobra_pausing": "Pause en cours…", + "kobra_preheating": "Préchauffage", + "kobra_printing": "Impression", + "kobra_resumed": "Repris", + "kobra_resuming": "Reprise en cours…", + "kobra_stoped": "Arrêté", + "kobra_stopping": "Arrêt en cours…", + "kobra_updated": "Mise à jour", "label_bed": "Plateau", "label_fan": "🌀 Ventilateur", "label_light": "💡 Lumière", - "label_on_off": "On / Off", - "label_speed": "Vitesse", - "panel_print_title": "Contrôle impression", - "panel_print_btn_pause": "⏸ Pause", - "panel_print_btn_resume": "▶ Reprendre", - "panel_print_btn_cancel": "✕ Annuler", - "panel_print_temps_live": "Températures (en direct)", - "label_set": "Définir", + "label_nozzle": "Buse", "label_off": "Éteint", - "panel_temps_nozzle": "Buse", - "panel_temps_bed": "Plateau chauffant", - "panel_temps_chart": "Historique (60 dernières valeurs)", - "label_target_c": "Cible :", - "panel_motion_xy": "Axes XY", - "panel_motion_z": "Axe Z", - "label_step": "Pas :", - "btn_home_z": "Origine Z", - "btn_home_xy": "Origine XY", - "btn_home_all": "Origine Tout", - "btn_disable_motors": "Moteurs Off", - "panel_ams_title": "Filament", - "card_ams": "Filament", - "ams_no_data": "Aucune donnée AMS reçue", + "label_on_off": "On / Off", + "label_set": "Définir", "label_slot": "Slot", - "ams_empty": "Vide", - "panel_extras_light": "Lumière", - "panel_extras_fan": "Ventilateur", - "panel_extras_camera": "Caméra", - "btn_cam_start2": "▶ Démarrer", - "btn_cam_stop2": "◼ Arrêter", - "panel_console_title": "Journal d'événements", - "log_light_on": "Lumière allumée", - "log_light_off": "Lumière éteinte", - "log_fan": "Ventilateur →", - "log_nozzle": "Buse →", - "log_bed": "Plateau →", + "label_speed": "Vitesse", + "label_step": "Pas :", + "label_target_c": "Cible :", + "lbl_conn_error": "Erreur de connexion :", + "lbl_elapsed": "Écoulé :", + "lbl_feed": "Charger", + "lbl_layers": "Couche", + "lbl_light": "💡 Lumière", + "lbl_remaining": "Restant :", + "lbl_slicer_time": "Estimation slicer :", + "lbl_spoolman_sync_rate": "Taux de sync. (s, 0=désact.)", + "lbl_spoolman_url": "URL du serveur", + "lbl_unload": "Décharger", + "lbl_zpos": "Z (mm)", + "log_auto": "⬇ Auto", "log_axis": "Axe", - "log_home": "Origine", - "log_home_all": "Origine Tout", + "log_bed": "Plateau →", "log_cam_start": "Caméra démarrée :", "log_cam_stop": "Caméra arrêtée", - "log_poll_error": "Erreur de sondage :", + "log_clear": "✕ Effacer", + "log_delete_failed": "Échec de la suppression", + "log_dir_all": "Tout", + "log_dir_label": "Sens :", + "log_dir_rx": "RX", + "log_dir_tx": "TX", + "log_download": "⬇ Télécharger", "log_error": "Erreur :", - "confirm_cancel": "Vraiment annuler l'impression ?", - "settings_title": "Paramètres", - "settings_connection": "Connexion", - "settings_print": "Paramètres d'impression", - "settings_poll": "Intervalle de sondage (secondes)", + "log_fan": "Ventilateur →", + "log_filter_placeholder": "Filtrer…", + "log_home": "Origine", + "log_home_all": "Origine Tout", + "log_light_off": "Lumière éteinte", + "log_light_on": "Lumière allumée", + "log_lvl_err": "⛔ Erreurs", + "log_lvl_label": "Niveau :", + "log_lvl_warn": "⚠ Avert.", + "log_nozzle": "Buse →", + "log_poll_error": "Erreur de sondage :", + "log_print_action": "Impression :", + "log_print_start": "Début de l'impression :", + "log_topic_ams": "AMS", + "log_topic_info": "Info", + "log_topic_label": "Sujet :", + "log_topic_print": "Impression", + "log_topic_status": "Statut", + "modal_sec_obico": "Obico", + "modal_sec_spoolman": "Spoolman", + "nav_ams": "AMS", + "nav_browser": "Navigateur", + "nav_console": "Console", + "nav_dashboard": "Tableau de bord", + "nav_extras": "Lumière / Ventilateur", + "nav_motion": "Mouvement", + "nav_print": "Impression", + "nav_printers": "Imprimantes", "nav_settings": "Paramètres", - "settings_cat_display": "Apparence", - "settings_cat_filament": "Filament", - "settings_cat_language": "Langue", - "settings_cat_theme": "Basculer clair / sombre", - "settings_filament_mapping": "Mappage du profil de filament (par emplacement)", - "settings_filament_mapping_save": "Enregistrer le mappage", - "settings_visible_vendors": "Fabricants visibles (liste des profils)", - "settings_visible_vendors_hint": "Seuls ces fabricants apparaissent dans la liste des profils d'emplacement. Rien de sélectionné = tout afficher. « Generic » et vos propres profils sont toujours visibles.", - "settings_visible_vendors_save": "Enregistrer la sélection", - "progress_action_print": "Imprimer", - "progress_action_slots": "Affecter les emplacements", - "progress_action_clear": "Vider", - "settings_version": "Version", - "settings_save": "Enregistrer et redémarrer", - "settings_printer_name": "Nom de l'imprimante", - "settings_printer_ip": "IP de l'imprimante", - "settings_mqtt_port": "Port MQTT", - "settings_username": "Nom d'utilisateur MQTT", - "settings_password": "Mot de passe MQTT", - "settings_device_id": "ID de l'appareil", - "settings_mode_id": "ID du mode", - "hint_ip_no_port": "Adresse IP uniquement, sans port (ex. 192.168.1.102)", - "settings_default_slot": "Slot par défaut (couleur unique)", - "settings_slot_auto": "Auto (tous les slots chargés)", - "settings_auto_leveling": "Mise à niveau auto avant impression", - "settings_camera_on_print": "Activer la caméra au démarrage de l'impression", - "settings_web_upload_warning": "Afficher un avertissement lors de l'impression de fichiers web", - "update_check": "Vérifier les mises à jour", - "update_checking": "Vérification…", - "update_available": "disponible", - "update_none": "Déjà à jour", - "update_apply": "Installer maintenant", - "update_applying": "Téléchargement…", - "update_restarting": "Redémarrage…", - "update_error": "Erreur", - "btn_connect": "⚡ Connecter", - "btn_disconnect": "✕ Déconnecter", - "lbl_conn_error": "Erreur de connexion :", - "slot_edit_title": "Modifier le slot", - "slot_edit_color": "Couleur", - "slot_edit_material": "Matériau", - "slot_edit_load": "⬇ Charger", - "slot_edit_unload": "⬆ Décharger", - "slot_edit_save": "💾 Enregistrer", - "slot_edit_custom": "ex. PLA, PETG, ABS…", - "slot_edit_ok": "Slot AMS", - "slot_edit_profile": "Profil OrcaSlicer", - "slot_edit_profile_hint": "Envoyé lors de la synchronisation OrcaSlicer comme marque spécifique au lieu de \"Générique\"", - "slot_edit_profile_default": "— Générique (défaut) —", - "orca_profile_section": "Profils OrcaSlicer", + "nav_temps": "Températures", + "orca_profile_done": "Importé", + "orca_profile_dropmsg": "Déposez ici ou cliquez", + "orca_profile_help_html": "Déposez un ZIP de votre dossier filament OrcaSlicer ou des fichiers .json individuels.
Dans OrcaSlicer : Aide → Afficher le dossier de configuration → user/<id>/filament/", "orca_profile_hint": "Importez vos propres profils de filament OrcaSlicer (ouvrez le dossier utilisateur via Aide → Afficher le dossier de configuration)", "orca_profile_import_btn": "Importer des profils", "orca_profile_import_link": "★ Importer mes profils…", "orca_profile_import_title": "Importer vos profils OrcaSlicer", - "orca_profile_help_html": "Déposez un ZIP de votre dossier filament OrcaSlicer ou des fichiers .json individuels.
Dans OrcaSlicer : Aide → Afficher le dossier de configuration → user/<id>/filament/", - "orca_profile_dropmsg": "Déposez ici ou cliquez", "orca_profile_list_label": "Profils importés", - "orca_profile_user_label": "Mes profils", - "orca_profile_user_empty": "– aucun –", - "orca_profile_uploading": "Envoi en cours…", - "orca_profile_done": "Importé", + "orca_profile_section": "Profils OrcaSlicer", "orca_profile_skipped": "ignoré", - "log_dir_all": "Tout", - "log_lvl_label": "Niveau :", - "file_ready_btn": "▶ Lancer l'impression", - "file_slots_btn": "🎨 Choisir les slots", - "file_cancel_btn": "✕ Annuler", - "nav_printers": "Imprimantes", - "skip_title": "✂ Ignorer des objets", - "skip_hint": "Décochez les objets que vous ne souhaitez plus imprimer :", - "skip_btn_label": "Objets", - "skip_no_objects": "Aucun objet dans cette impression.", + "orca_profile_uploading": "Envoi en cours…", + "orca_profile_user_empty": "– aucun –", + "orca_profile_user_label": "Mes profils", + "panel_ams_title": "Filament", + "panel_browser_title": "Explorateur de fichiers", + "panel_console_title": "Journal d'événements", + "panel_extras_camera": "Caméra", + "panel_extras_fan": "Ventilateur", + "panel_extras_light": "Lumière", + "panel_motion_xy": "Axes XY", + "panel_motion_z": "Axe Z", + "panel_print_btn_cancel": "✕ Annuler", + "panel_print_btn_pause": "⏸ Pause", + "panel_print_btn_resume": "▶ Reprendre", + "panel_print_temps_live": "Températures (en direct)", + "panel_print_title": "Contrôle impression", + "panel_temps_bed": "Plateau chauffant", + "panel_temps_chart": "Historique (60 dernières valeurs)", + "panel_temps_nozzle": "Buse", + "print_auto_leveling": "Mise à niveau auto pour cette impression", + "printers_active": "● actif", + "printers_current": "Imprimante actuelle", + "printers_empty_hint": "Aucune imprimante configurée.", + "printers_loading": "Chargement…", + "printers_none": "Aucune imprimante configurée.", + "printers_remove": "Supprimer l'imprimante", + "printers_remove_confirm": "Supprimer l'imprimante \"{name}\" ? Le bridge va redémarrer.", + "printers_switch": "Changer →", + "progress_action_clear": "Vider", + "progress_action_print": "Imprimer", + "progress_action_slots": "Affecter les emplacements", + "settings_auto_leveling": "Mise à niveau auto avant impression", + "settings_auto_leveling_label": "Mise à niveau auto avant impression", + "settings_btn_tooltip": "Paramètres", + "settings_camera_on_print": "Activer la caméra au démarrage de l'impression", + "settings_cat_connection": "Connexion", + "settings_cat_display": "Apparence", + "settings_cat_filament": "Filament", + "settings_cat_language": "Langue", + "settings_cat_printer": "Imprimante", + "settings_cat_system": "Système", + "settings_cat_theme": "Basculer clair / sombre", + "settings_connection": "Connexion", + "settings_default_slot": "Slot par défaut (couleur unique)", + "settings_device_id": "ID de l'appareil", + "settings_device_id_hint": "32 caractères hexadécimaux", + "settings_device_id_placeholder": "32 caractères hexadécimaux", + "settings_filament_mapping": "Mappage du profil de filament (par emplacement)", + "settings_filament_mapping_hint": "Profil Orca fixe par emplacement AMS. Lors de la synchronisation du slicer, le bridge envoie ce profil au lieu de « Generic ».", + "settings_filament_mapping_label": "Mappage du profil de filament (par emplacement)", + "settings_filament_mapping_save": "Enregistrer le mappage", + "settings_filament_mapping_save_label": "Enregistrer le mappage", + "settings_file_ready_banner": "Barre d'impression", + "settings_file_ready_dialog": "Dialogue d'impression", + "settings_file_ready_mode": "Après téléchargement : Comportement de démarrage d'impression", + "settings_integrations": "Intégrations", + "settings_language": "Langue", + "settings_mode_id": "ID du mode", + "settings_mode_id_placeholder": "20030", + "settings_mqtt_port": "Port MQTT", + "settings_mqtt_username_placeholder": "userXXXXXXXX", + "settings_orca_profiles_import": "Importer des profils", + "settings_orca_profiles_label": "Profils OrcaSlicer", + "settings_password": "Mot de passe MQTT", + "settings_poll": "Intervalle de sondage (secondes)", + "settings_poll_interval_hint": "Fréquence à laquelle le bridge interroge l'état de l'imprimante", + "settings_poll_interval_label": "Intervalle de sondage (secondes)", + "settings_print": "Paramètres d'impression", + "settings_printer_ip": "IP de l'imprimante", + "settings_printer_name": "Nom de l'imprimante", + "settings_printer_name_placeholder": "p. ex. Kobra X Salon", + "settings_save": "Enregistrer et redémarrer", + "settings_slot_auto": "Auto (tous les slots chargés)", + "settings_theme_toggle": "Basculer clair / sombre", + "settings_title": "Paramètres", + "settings_username": "Nom d'utilisateur MQTT", + "settings_vendor_filter_placeholder": "Rechercher des fabricants…", + "settings_version": "Version", + "settings_visible_vendors": "Fabricants visibles (liste des profils)", + "settings_visible_vendors_hint": "Seuls ces fabricants apparaissent dans la liste des profils d'emplacement. Rien de sélectionné = tout afficher. « Generic » et vos propres profils sont toujours visibles.", + "settings_visible_vendors_label": "Fabricants visibles (liste des profils)", + "settings_visible_vendors_save": "Enregistrer la sélection", + "settings_visible_vendors_save_label": "Enregistrer la sélection", + "settings_web_upload_warning": "Afficher un avertissement lors de l'impression de fichiers web", + "sf_all": "Tout", + "sf_err": "✗ Échoués", + "sf_new": "Nouveau", + "sf_ok": "✓ Terminés", "skip_already": "ignoré", + "skip_btn_label": "Objets", + "skip_cancel": "Annuler", + "skip_confirm": "Ignorer", + "skip_confirm_btn": "Ignorer", + "skip_hint": "Décochez les objets que vous ne souhaitez plus imprimer :", + "skip_no_objects": "Aucun objet dans cette impression.", "skip_select_at_least_one": "Veuillez sélectionner au moins un objet.", "skip_sending": "Envoi …", "skip_success": "Les objets seront ignorés.", - "fd_objects_hint": "Ignorer des objets (optionnel) :", - "fd_objects_toggle": "Ignorer des objets", - "fd_slots_hint": "Associer le canal GCode au slot AMS :", - "fd_cancel": "Annuler", - "fd_print": "▶ Imprimer", - "fd_no_slots_msg": "Aucun slot AMS chargé.{br}Lancer l'impression quand même ?", - "fd_slot": "Slot", - "fd_no_matching_material": "Aucun matériau correspondant", - "fd_used": "UTILISÉ", - "add_printer": "Ajouter une imprimante", - "apd_lbl_ip": "IP de l'imprimante", - "apd_lbl_name": "Nom (optionnel)", - "apd_placeholder_name": "ex. Kobra X Salon", - "apd_cancel": "Annuler", - "apd_confirm": "Ajouter", - "apd_fetching": "Récupération des données de l'imprimante…", - "apd_success": "Imprimante ajoutée, redémarrage du bridge…", - "apd_err_ip": "Veuillez saisir une adresse IP", - "printers_remove": "Supprimer l'imprimante", - "printers_remove_confirm": "Supprimer l'imprimante \"{name}\" ? Le bridge va redémarrer.", - "printers_active": "● actif", - "printers_switch": "Changer →", - "printers_current": "Imprimante actuelle", - "printers_loading": "Chargement…", - "printers_none": "Aucune imprimante configurée.", - "printers_empty_hint": "Aucune imprimante configurée.", - "nav_browser": "Navigateur", - "panel_browser_title": "Explorateur de fichiers", - "store_search_placeholder": "🔍 Rechercher…", - "store_empty": "Aucun fichier uploadé.", - "store_refresh": "↻ Actualiser", - "store_print": "▶ Imprimer", - "store_download": "⬇ Télécharger", - "store_delete_confirm": "Supprimer le fichier ?", - "store_print_confirm": "Imprimer le fichier ?", - "store_web_verify_title": "Vérifier le fichier", - "store_web_verify_msg": "Veuillez vérifier que ce fichier a été créé pour l'Anycubic Kobra X.", - "store_web_verify_confirm": "Confirmer", - "store_web_verify_abort": "Annuler", - "store_no_results": "Aucun fichier trouvé.", - "store_never": "jamais imprimé", - "store_estimate": "Estimation", - "store_upload_label_prefix": "Déposez un GCode ici ou ", - "store_upload_label_browse": "parcourir", - "store_upload_busy": "⏳ Envoi en cours…", - "store_upload_success": "✓ {file}", - "store_upload_error": "✗ {error}", - "store_upload_only_gcode": "✗ Seuls les fichiers GCode sont autorisés (.gcode, .3mf, .bgcode)", - "sf_all": "Tout", - "sf_ok": "✓ Terminés", - "sf_err": "✗ Échoués", - "sf_new": "Nouveau", + "skip_title": "✂ Ignorer des objets", + "slot_edit_color": "Couleur", + "slot_edit_custom": "ex. PLA, PETG, ABS…", + "slot_edit_load": "⬇ Charger", + "slot_edit_material": "Matériau", + "slot_edit_ok": "Slot AMS", + "slot_edit_profile": "Profil OrcaSlicer", + "slot_edit_profile_default": "— Générique (défaut) —", + "slot_edit_profile_hint": "Envoyé lors de la synchronisation OrcaSlicer comme marque spécifique au lieu de \"Générique\"", + "slot_edit_save": "💾 Enregistrer", + "slot_edit_title": "Modifier le slot", + "slot_edit_unload": "⬆ Décharger", + "speed_normal": "⚡ Normal", + "speed_silent": "🐢 Silencieux", + "speed_sport": "🚀 Sport", "ss_date": "↓ Date", - "ss_name": "A–Z Nom", "ss_dur": "⏱ Durée d'impression", - "ace_dry_preset_pla": "PLA", - "ace_dry_preset_pla_plus": "PLA+", - "ace_dry_preset_petg": "PETG", - "ace_dry_preset_tpu": "TPU", - "ace_dry_preset_abs_asa": "ABS / ASA", - "ace_dry_preset_pa_pc": "PA / PC", - "ace_dry_preset_custom": "Personnalisé", - "fd_options_title": "Options", - "print_auto_leveling": "Mise à niveau auto pour cette impression", - "settings_file_ready_mode": "Démarrer le dialogue d'impression", - "settings_file_ready_banner": "Barre d'impression", - "settings_file_ready_dialog": "Dialogue d'impression", - "log_dir_rx": "RX", - "log_dir_tx": "TX", - "log_dir_label": "Sens :", - "log_lvl_err": "⛔ Erreurs", - "log_lvl_warn": "⚠ Avert.", - "log_topic_label": "Sujet :", - "log_topic_ams": "AMS", - "log_topic_print": "Impression", - "log_topic_info": "Info", - "log_topic_status": "Statut", - "log_download": "⬇ Télécharger", - "log_auto": "⬇ Auto", - "log_clear": "✕ Effacer", - "log_filter_placeholder": "Filtrer…", - "skip_cancel": "Annuler", - "skip_confirm": "Ignorer" + "ss_name": "A–Z Nom", + "store_delete_confirm": "Supprimer le fichier ?", + "store_download": "⬇ Télécharger", + "store_empty": "Aucun fichier uploadé.", + "store_estimate": "Estimation", + "store_never": "jamais imprimé", + "store_no_results": "Aucun fichier trouvé.", + "store_print": "▶ Imprimer", + "store_print_confirm": "Imprimer le fichier ?", + "store_refresh": "↻ Actualiser", + "store_search_placeholder": "🔍 Rechercher…", + "store_upload_busy": "⏳ Envoi en cours…", + "store_upload_error": "✗ {error}", + "store_upload_label_browse": "parcourir", + "store_upload_label_prefix": "Déposez un GCode ici ou ", + "store_upload_only_gcode": "✗ Seuls les fichiers GCode sont autorisés (.gcode, .3mf, .bgcode)", + "store_upload_success": "✓ {file}", + "store_web_verify_abort": "Annuler", + "store_web_verify_confirm": "Confirmer", + "store_web_verify_msg": "Veuillez vérifier que ce fichier a été créé pour Anycubic Kobra X.", + "store_web_verify_title": "Vérifier le fichier", + "update_apply": "Installer maintenant", + "update_applying": "Téléchargement…", + "update_available": "disponible", + "update_check": "Vérifier les mises à jour", + "update_checking": "Vérification…", + "update_error": "Erreur", + "update_none": "Déjà à jour", + "update_restarting": "Redémarrage…" } diff --git a/web/translations/it.json b/web/translations/it.json index 56ed376..4c50faa 100644 --- a/web/translations/it.json +++ b/web/translations/it.json @@ -1,291 +1,327 @@ { - "header_status_standby": "Pronto", - "header_status_printing": "In stampa", - "header_status_complete": "Completato", - "header_status_error": "Errore", - "kobra_free": "Pronto", - "kobra_busy": "Occupato", - "kobra_printing": "In stampa", - "kobra_preheating": "Preriscaldamento", - "kobra_auto_leveling": "Livellamento automatico", - "kobra_checking": "Verifica", - "kobra_updated": "Aggiornamento", - "kobra_init": "Inizializzazione", - "kobra_pausing": "Pausa in corso...", - "kobra_paused": "In pausa", - "kobra_resuming": "Ripresa...", - "kobra_resumed": "Ripreso", - "kobra_stopping": "Arresto...", - "kobra_stoped": "Arrestato", - "kobra_finished": "Finito", - "kobra_failed": "Errore", - "kobra_canceled": "Annullato", - "kobra_offline": "Offline", - "nav_dashboard": "Dashboard", - "nav_print": "Stampa", - "nav_temps": "Temperature", - "nav_motion": "Movimento", - "nav_ams": "AMS", - "nav_extras": "Luce / Ventola", - "nav_console": "Console", - "card_progress": "Avanzamento", - "card_temps": "Temperature", - "card_light_fan": "Ventola", - "card_speed": "Velocità di stampa", - "card_cam": "Camera", - "lbl_elapsed": "Trascorso:", - "lbl_remaining": "Rimanente:", - "lbl_slicer_time": "Stima slicer:", - "lbl_layers": "Layer", - "lbl_zpos": "Z (mm)", - "speed_silent": "🐢 Silenzioso", - "speed_normal": "⚡ Normale", - "speed_sport": "🚀 Sport", - "lbl_light": "💡 Luce", - "lbl_feed": "Carica", - "lbl_unload": "Rimuovi", - "card_ace_dry": "Essiccazione ACE", + "ace_dry_auto_refill": "Ricarica automatica", + "ace_dry_chart": "Cronologia (Temp/Umidità)", + "ace_dry_current_temp": "Temperatura", + "ace_dry_dialog_cancel": "Annulla", + "ace_dry_dialog_confirm": "Conferma", + "ace_dry_dialog_custom_name": "Nome personalizzato", + "ace_dry_dialog_reset_default": "Ripristina predefiniti", + "ace_dry_dialog_save_restart": "Salva e riavvia", + "ace_dry_dialog_temp": "Temperatura (30-80°C)", + "ace_dry_dialog_time": "Tempo rim. (h:m:s)", + "ace_dry_dialog_title": "Impostazioni Temp/Tempo essiccatore", "ace_dry_dryer": "Essiccatore", + "ace_dry_duration": "Durata (min)", + "ace_dry_enable": "Abilita essiccazione", + "ace_dry_humidity": "Umidità", + "ace_dry_preset_abs_asa": "ABS / ASA", + "ace_dry_preset_custom": "Personalizzato", + "ace_dry_preset_pa_pc": "PA / PC", + "ace_dry_preset_petg": "PETG", + "ace_dry_preset_pla": "PLA", + "ace_dry_preset_pla_plus": "PLA+", + "ace_dry_preset_tpu": "TPU", + "ace_dry_start": "▶ Avvia", "ace_dry_status_off": "Stato: Spento", "ace_dry_status_on": "Stato: Attivo", "ace_dry_status_remaining": "Rimanente", - "ace_dry_humidity": "Umidità", - "ace_dry_current_temp": "Temperatura", - "ace_dry_chart": "Cronologia (Temp/Umidità)", - "ace_dry_temp": "Temperatura (°C)", - "ace_dry_duration": "Durata (min)", - "ace_dry_start": "▶ Avvia", "ace_dry_stop": "■ Ferma", - "ace_dry_auto_refill": "Ricarica automatica", - "ace_dry_enable": "Abilita essiccazione", + "ace_dry_temp": "Temperatura (°C)", "ace_dry_temp_line": "Temperatura di essiccazione", "ace_dry_time_line": "Tempo di essiccazione", "ace_dry_ui_pending": "(Solo interfaccia, backend a seguire)", - "ace_dry_dialog_title": "Impostazioni Temp/Tempo essiccatore", - "ace_dry_dialog_temp": "Temperatura (30-80°C)", - "ace_dry_dialog_time": "Tempo rim. (h:m:s)", - "ace_dry_dialog_confirm": "Conferma", - "ace_dry_dialog_cancel": "Annulla", - "ace_dry_dialog_save_restart": "Salva e riavvia", - "ace_dry_dialog_custom_name": "Nome personalizzato", - "ace_dry_dialog_reset_default": "Ripristina predefiniti", - "ace_dry_preset_pla": "PLA", - "ace_dry_preset_pla_plus": "PLA+", - "ace_dry_preset_petg": "PETG", - "ace_dry_preset_tpu": "TPU", - "ace_dry_preset_abs_asa": "ABS / ASA", - "ace_dry_preset_pa_pc": "PA / PC", - "ace_dry_preset_custom": "Personalizzato", - "cam_placeholder": "📷 Camera non avviata", - "cam_stream_unavailable": "Flusso video non disponibile", + "add_printer": "Aggiungi stampante", + "ams_empty": "Vuoto", + "ams_no_data": "Nessun dato ricevuto dall' AMS", + "apd_cancel": "Annulla", + "apd_confirm": "Aggiungi", + "apd_err_ip": "Inserisci un indirizzo IP", + "apd_fetching": "Recupero dati dalla stampante…", + "apd_lbl_ip": "IP stampante", + "apd_lbl_name": "Nome (opzionale)", + "apd_placeholder_name": "es. Kobra X Soggiorno", + "apd_success": "Stampante aggiunta, riavvio del bridge in corso…", + "apd_title": "Aggiungi stampante", "btn_cam_start": "▶ Camera", + "btn_cam_start2": "▶ Avvia", "btn_cam_stop": "◼ Camera", + "btn_cam_stop2": "◼ Ferma", + "btn_cancel": "✕ Stop", + "btn_cancel_generic": "Annulla", + "btn_confirm_generic": "Conferma", + "btn_connect": "⚡ Connetti", + "btn_delete": "Elimina", + "btn_disable_motors": "Spegni motori", + "btn_disconnect": "✕ Disconnetti", + "btn_home_all": "Home generale", + "btn_home_xy": "Home XY", + "btn_home_z": "Home Z", "btn_pause": "⏸ Pausa", "btn_resume": "▶ Riprendi", - "btn_cancel": "✕ Stop", - "label_nozzle": "Ugello", + "cam_placeholder": "📷 Camera non avviata", + "cam_stream_unavailable": "Flusso video non disponibile", + "card_ace_dry": "Essiccazione ACE", + "card_ams": "Filamento", + "card_cam": "Camera", + "card_light_fan": "Ventola", + "card_progress": "Avanzamento", + "card_speed": "Velocità di stampa", + "card_temps": "Temperature", + "confirm_cancel": "Annullare davvero la stampa?", + "fd_cancel": "Annulla", + "fd_no_matching_material": "Nessun materiale corrispondente", + "fd_no_slots_msg": "Nessuno slot AMS caricato.{br}Avviare comunque la stampa?", + "fd_objects_hint": "Salta oggetti (opzionale):", + "fd_objects_toggle": "Salta oggetti", + "fd_options_title": "Opzioni di stampa", + "fd_print": "▶ Stampa", + "fd_slot": "Slot", + "fd_slots_hint": "Assegna il canale GCode allo slot AMS:", + "fd_title": "Assegnazione slot", + "fd_used": "USATO", + "file_cancel_btn": "✕ Annulla", + "file_ready_btn": "▶ Avvia stampa", + "file_slots_btn": "🎨 Seleziona slot", + "header_status_complete": "Completato", + "header_status_error": "Errore", + "header_status_printing": "In stampa", + "header_status_standby": "Pronto", + "hint_ip_no_port": "Solo indirizzo IP, senza porta (es. 192.168.1.102)", + "kobra_auto_leveling": "Livellamento automatico", + "kobra_busy": "Occupato", + "kobra_canceled": "Annullato", + "kobra_checking": "Verifica", + "kobra_failed": "Errore", + "kobra_finished": "Finito", + "kobra_free": "Pronto", + "kobra_init": "Inizializzazione", + "kobra_offline": "Offline", + "kobra_paused": "In pausa", + "kobra_pausing": "Pausa in corso...", + "kobra_preheating": "Preriscaldamento", + "kobra_printing": "In stampa", + "kobra_resumed": "Ripreso", + "kobra_resuming": "Ripresa...", + "kobra_stoped": "Arrestato", + "kobra_stopping": "Arresto...", + "kobra_updated": "Aggiornamento", "label_bed": "Piatto", "label_fan": "🌀 Ventola", "label_light": "💡 Luce", - "label_on_off": "On / Off", - "label_speed": "Velocità", - "panel_print_title": "Controllo stampa", - "panel_print_btn_pause": "⏸ Pausa", - "panel_print_btn_resume": "▶ Riprendi", - "panel_print_btn_cancel": "✕ Annulla", - "panel_print_temps_live": "Temperature (In tempo reale)", - "label_set": "Imposta", + "label_nozzle": "Ugello", "label_off": "Off", - "panel_temps_nozzle": "Ugello", - "panel_temps_bed": "Piatto riscaldato", - "panel_temps_chart": "Cronologia (ultime 60 letture)", - "label_target_c": "Target:", - "panel_motion_xy": "Assi XY", - "panel_motion_z": "Asse Z", - "label_step": "Ampiezza passo:", - "btn_home_z": "Home Z", - "btn_home_xy": "Home XY", - "btn_home_all": "Home generale", - "btn_disable_motors": "Spegni motori", - "panel_ams_title": "Filamento", - "card_ams": "Filamento", - "ams_no_data": "Nessun dato ricevuto dall' AMS", + "label_on_off": "On / Off", + "label_set": "Imposta", "label_slot": "Slot", - "ams_empty": "Vuoto", - "panel_extras_light": "Luce", - "panel_extras_fan": "Ventola", - "panel_extras_camera": "Camera", - "btn_cam_start2": "▶ Avvia", - "btn_cam_stop2": "◼ Ferma", - "panel_console_title": "Registro eventi", - "log_light_on": "Luce accesa", - "log_light_off": "Luce spenta", - "log_fan": "Ventola →", - "log_nozzle": "Ugello →", - "log_bed": "Piatto →", + "label_speed": "Velocità", + "label_step": "Ampiezza passo:", + "label_target_c": "Target:", + "lbl_conn_error": "Errore di connessione:", + "lbl_elapsed": "Trascorso:", + "lbl_feed": "Carica", + "lbl_layers": "Layer", + "lbl_light": "💡 Luce", + "lbl_remaining": "Rimanente:", + "lbl_slicer_time": "Stima slicer:", + "lbl_spoolman_sync_rate": "Frequenza sync (s, 0=disatt.)", + "lbl_spoolman_url": "URL server", + "lbl_unload": "Rimuovi", + "lbl_zpos": "Z (mm)", + "log_auto": "⬇ Auto", "log_axis": "Asse", - "log_home": "Home", - "log_home_all": "Home generale", + "log_bed": "Piatto →", "log_cam_start": "Camera avviata:", "log_cam_stop": "Camera arrestata", - "log_poll_error": "Errore di sincronizzazione:", + "log_clear": "✕ Cancella", + "log_delete_failed": "Eliminazione non riuscita", + "log_dir_all": "Tutti", + "log_dir_label": "Dir:", + "log_dir_rx": "RX", + "log_dir_tx": "TX", + "log_download": "⬇ Scarica", "log_error": "Errore:", - "confirm_cancel": "Annullare davvero la stampa?", - "settings_title": "Impostazioni", - "settings_connection": "Connessione", - "settings_print": "Impostazioni di stampa", - "settings_poll": "Intervallo di sincronizzazione (secondi)", + "log_fan": "Ventola →", + "log_filter_placeholder": "Filtra…", + "log_home": "Home", + "log_home_all": "Home generale", + "log_light_off": "Luce spenta", + "log_light_on": "Luce accesa", + "log_lvl_err": "⛔ Errori", + "log_lvl_label": "Livello:", + "log_lvl_warn": "⚠ Avvisi", + "log_nozzle": "Ugello →", + "log_poll_error": "Errore di sincronizzazione:", + "log_print_action": "Stampa:", + "log_print_start": "Inizio stampa:", + "log_topic_ams": "AMS", + "log_topic_info": "Info", + "log_topic_label": "Argomento:", + "log_topic_print": "Stampa", + "log_topic_status": "Stato", + "modal_sec_obico": "Obico", + "modal_sec_spoolman": "Spoolman", + "nav_ams": "AMS", + "nav_browser": "Browser", + "nav_console": "Console", + "nav_dashboard": "Dashboard", + "nav_extras": "Luce / Ventola", + "nav_motion": "Movimento", + "nav_print": "Stampa", + "nav_printers": "Stampanti", "nav_settings": "Impostazioni", - "settings_cat_display": "Aspetto", - "settings_cat_filament": "Filamento", - "settings_cat_language": "Lingua", - "settings_cat_theme": "Alterna chiaro / scuro", - "settings_filament_mapping": "Mappatura profilo filamento (per slot)", - "settings_filament_mapping_save": "Salva mappatura", - "settings_visible_vendors": "Produttori visibili (menu del profilo)", - "settings_visible_vendors_hint": "Solo questi produttori appariranno nel menu del profilo dello slot. Se non selezioni nulla = mostra tutti. I profili \"Generici\" e i tuoi personali sono sempre visibili.", - "settings_visible_vendors_save": "Salva selezione", - "progress_action_print": "Stampa", - "progress_action_slots": "Mappa slot", - "progress_action_clear": "Cancella", - "settings_version": "Versione", - "settings_save": "Salva e riavvia", - "settings_printer_name": "Nome stampante", - "settings_printer_ip": "IP stampante", - "settings_mqtt_port": "Porta MQTT", - "settings_username": "Nome utente MQTT", - "settings_password": "Password MQTT", - "settings_device_id": "ID dispositivo", - "settings_mode_id": "ID modalità", - "hint_ip_no_port": "Solo indirizzo IP, senza porta (es. 192.168.1.102)", - "settings_default_slot": "Slot predefinito (colore singolo)", - "settings_slot_auto": "Auto (tutti gli slot caricati)", - "settings_auto_leveling": "Livellamento automatico predefinito", - "fd_options_title": "Opzioni di stampa", - "print_auto_leveling": "Livellamento automatico", - "settings_file_ready_mode": "Comportamento all'avvio stampa", - "settings_file_ready_banner": "Barra di stampa", - "settings_file_ready_dialog": "Finestra di dialogo di stampa", - "settings_camera_on_print": "Attiva la camera all'avvio della stampa", - "settings_web_upload_warning": "Mostra un avviso quando si stampano caricamenti web", - "update_check": "Controlla aggiornamenti", - "update_checking": "Verifica in corso...", - "update_available": "disponibile", - "update_none": "Già aggiornato", - "update_apply": "Installa ora", - "update_applying": "Download in corso...", - "update_restarting": "Riavvio in corso...", - "update_error": "Errore", - "btn_connect": "⚡ Connetti", - "btn_disconnect": "✕ Disconnetti", - "lbl_conn_error": "Errore di connessione:", - "slot_edit_title": "Modifica slot", - "slot_edit_color": "Colore", - "slot_edit_material": "Materiale", - "slot_edit_load": "⬇ Carica", - "slot_edit_unload": "⬆ Rimuovi", - "slot_edit_save": "💾 Salva", - "slot_edit_custom": "es. PLA, PETG, ABS…", - "slot_edit_ok": "Slot AMS", - "slot_edit_profile": "Profilo OrcaSlicer", - "slot_edit_profile_hint": "Inviato durante la sincronizzazione con OrcaSlicer come marchio specifico invece di un semplice \"Generico\"", - "slot_edit_profile_default": "— Generico (predefinito) —", - "orca_profile_section": "Profili OrcaSlicer", + "nav_temps": "Temperature", + "orca_profile_done": "Importato", + "orca_profile_dropmsg": "Trascina qui o fai clic", + "orca_profile_help_html": "Carica un file ZIP della tua cartella filamenti di OrcaSlicer o file singoli .json.
In OrcaSlicer: Aiuto → Mostra cartella di configurazione → user/<id>/filament/", "orca_profile_hint": "Importa i tuoi profili di filamento OrcaSlicer (apri la cartella utente tramite Aiuto → Mostra cartella di configurazione)", "orca_profile_import_btn": "Importa profili", "orca_profile_import_link": "★ Importa i tuoi profili…", "orca_profile_import_title": "Importa i tuoi profili OrcaSlicer", - "orca_profile_help_html": "Carica un file ZIP della tua cartella filamenti di OrcaSlicer o file singoli .json.
In OrcaSlicer: Aiuto → Mostra cartella di configurazione → user/<id>/filament/", - "orca_profile_dropmsg": "Trascina qui o fai clic", "orca_profile_list_label": "Attualmente importati", - "orca_profile_user_label": "Profili personali", - "orca_profile_user_empty": "– nessuno –", - "orca_profile_uploading": "Caricamento in corso…", - "orca_profile_done": "Importato", + "orca_profile_section": "Profili OrcaSlicer", "orca_profile_skipped": "saltato", - "log_dir_all": "Tutti", - "log_dir_rx": "RX", - "log_dir_tx": "TX", - "log_dir_label": "Dir:", - "log_lvl_label": "Livello:", - "log_lvl_err": "⛔ Errori", - "log_lvl_warn": "⚠ Avvisi", - "log_topic_label": "Argomento:", - "log_topic_ams": "AMS", - "log_topic_print": "Stampa", - "log_topic_info": "Info", - "log_topic_status": "Stato", - "log_download": "⬇ Scarica", - "log_auto": "⬇ Auto", - "log_clear": "✕ Cancella", - "log_filter_placeholder": "Filtra…", - "file_ready_btn": "▶ Avvia stampa", - "file_slots_btn": "🎨 Seleziona slot", - "file_cancel_btn": "✕ Annulla", - "nav_printers": "Stampanti", - "skip_title": "✂ Salta oggetti", - "skip_hint": "Deseleziona gli oggetti che non vuoi più stampare:", - "skip_btn_label": "Oggetti", - "skip_no_objects": "Nessun oggetto in questa stampa.", + "orca_profile_uploading": "Caricamento in corso…", + "orca_profile_user_empty": "– nessuno –", + "orca_profile_user_label": "Profili personali", + "panel_ams_title": "Filamento", + "panel_browser_title": "Browser dei file", + "panel_console_title": "Registro eventi", + "panel_extras_camera": "Camera", + "panel_extras_fan": "Ventola", + "panel_extras_light": "Luce", + "panel_motion_xy": "Assi XY", + "panel_motion_z": "Asse Z", + "panel_print_btn_cancel": "✕ Annulla", + "panel_print_btn_pause": "⏸ Pausa", + "panel_print_btn_resume": "▶ Riprendi", + "panel_print_temps_live": "Temperature (In tempo reale)", + "panel_print_title": "Controllo stampa", + "panel_temps_bed": "Piatto riscaldato", + "panel_temps_chart": "Cronologia (ultime 60 letture)", + "panel_temps_nozzle": "Ugello", + "print_auto_leveling": "Livellamento automatico", + "printers_active": "● attiva", + "printers_current": "Stampante corrente", + "printers_empty_hint": "Nessuna stampante ancora configurata.", + "printers_loading": "Caricamento in corso…", + "printers_none": "Nessuna stampante configurata.", + "printers_remove": "Rimuovi stampante", + "printers_remove_confirm": "Rimuovere la stampante \"{name}\"? Il bridge si riavvierà.", + "printers_switch": "Cambia →", + "progress_action_clear": "Cancella", + "progress_action_print": "Stampa", + "progress_action_slots": "Mappa slot", + "settings_auto_leveling": "Livellamento automatico predefinito", + "settings_auto_leveling_label": "Livellamento automatico prima della stampa", + "settings_btn_tooltip": "Impostazioni", + "settings_camera_on_print": "Attiva la camera all'avvio della stampa", + "settings_cat_connection": "Connessione", + "settings_cat_display": "Aspetto", + "settings_cat_filament": "Filamento", + "settings_cat_language": "Lingua", + "settings_cat_printer": "Stampante", + "settings_cat_system": "Sistema", + "settings_cat_theme": "Alterna chiaro / scuro", + "settings_connection": "Connessione", + "settings_default_slot": "Slot predefinito (colore singolo)", + "settings_device_id": "ID dispositivo", + "settings_device_id_hint": "32 caratteri esadecimali", + "settings_device_id_placeholder": "32 caratteri esadecimali", + "settings_filament_mapping": "Mappatura profilo filamento (per slot)", + "settings_filament_mapping_hint": "Profilo Orca fisso per slot AMS. Durante la sincronizzazione dello slicer, il bridge invia questo profilo al posto di \"Generic\".", + "settings_filament_mapping_label": "Mappatura profilo filamento (per slot)", + "settings_filament_mapping_save": "Salva mappatura", + "settings_filament_mapping_save_label": "Salva mappatura", + "settings_file_ready_banner": "Barra di stampa", + "settings_file_ready_dialog": "Finestra di dialogo stampa", + "settings_file_ready_mode": "Dopo il caricamento: Comportamento di avvio stampa", + "settings_integrations": "Integrazioni", + "settings_language": "Lingua", + "settings_mode_id": "ID modalità", + "settings_mode_id_placeholder": "20030", + "settings_mqtt_port": "Porta MQTT", + "settings_mqtt_username_placeholder": "userXXXXXXXX", + "settings_orca_profiles_import": "Importa profili", + "settings_orca_profiles_label": "Profili OrcaSlicer", + "settings_password": "Password MQTT", + "settings_poll": "Intervallo di sincronizzazione (secondi)", + "settings_poll_interval_hint": "Con che frequenza il bridge interroga lo stato della stampante", + "settings_poll_interval_label": "Intervallo di sincronizzazione (secondi)", + "settings_print": "Impostazioni di stampa", + "settings_printer_ip": "IP stampante", + "settings_printer_name": "Nome stampante", + "settings_printer_name_placeholder": "p. es. Kobra X Sala", + "settings_save": "Salva e riavvia", + "settings_slot_auto": "Auto (tutti gli slot caricati)", + "settings_theme_toggle": "Attiva/disattiva chiaro / scuro", + "settings_title": "Impostazioni", + "settings_username": "Nome utente MQTT", + "settings_vendor_filter_placeholder": "Cerca produttori…", + "settings_version": "Versione", + "settings_visible_vendors": "Produttori visibili (menu del profilo)", + "settings_visible_vendors_hint": "Solo questi produttori appariranno nel menu del profilo dello slot. Se non selezioni nulla = mostra tutti. I profili \"Generici\" e i tuoi personali sono sempre visibili.", + "settings_visible_vendors_label": "Produttori visibili (menu del profilo)", + "settings_visible_vendors_save": "Salva selezione", + "settings_visible_vendors_save_label": "Salva selezione", + "settings_web_upload_warning": "Mostra un avviso quando si stampano caricamenti web", + "sf_all": "Tutti", + "sf_err": "✗ Fallito", + "sf_new": "Nuovo", + "sf_ok": "✓ Completato", "skip_already": "saltato", + "skip_btn_label": "Oggetti", "skip_cancel": "Annulla", "skip_confirm": "Salta", + "skip_confirm_btn": "Salta", + "skip_hint": "Deseleziona gli oggetti che non vuoi più stampare:", + "skip_no_objects": "Nessun oggetto in questa stampa.", "skip_select_at_least_one": "Seleziona almeno un oggetto.", "skip_sending": "Invio in corso …", "skip_success": "Gli oggetti verranno saltati.", - "fd_objects_hint": "Salta oggetti (opzionale):", - "fd_objects_toggle": "Salta oggetti", - "fd_slots_hint": "Assegna il canale GCode allo slot AMS:", - "fd_cancel": "Annulla", - "fd_print": "▶ Stampa", - "fd_no_slots_msg": "Nessuno slot AMS caricato.{br}Avviare comunque la stampa?", - "fd_slot": "Slot", - "fd_no_matching_material": "Nessun materiale corrispondente", - "fd_used": "USATO", - "add_printer": "Aggiungi stampante", - "apd_lbl_ip": "IP stampante", - "apd_lbl_name": "Nome (opzionale)", - "apd_placeholder_name": "es. Kobra X Soggiorno", - "apd_cancel": "Annulla", - "apd_confirm": "Aggiungi", - "apd_fetching": "Recupero dati dalla stampante…", - "apd_success": "Stampante aggiunta, riavvio del bridge in corso…", - "apd_err_ip": "Inserisci un indirizzo IP", - "printers_remove": "Rimuovi stampante", - "printers_remove_confirm": "Rimuovere la stampante \"{name}\"? Il bridge si riavvierà.", - "printers_active": "● attiva", - "printers_switch": "Cambia →", - "printers_current": "Stampante corrente", - "printers_loading": "Caricamento in corso…", - "printers_none": "Nessuna stampante configurata.", - "printers_empty_hint": "Nessuna stampante ancora configurata.", - "nav_browser": "Browser", - "panel_browser_title": "Browser dei file", - "store_search_placeholder": "🔍 Cerca…", - "store_empty": "Nessun file caricato.", - "store_refresh": "↻ Aggiorna", - "store_print": "▶ Stampa", - "store_download": "⬇ Scarica", - "store_delete_confirm": "Eliminare il file?", - "store_print_confirm": "Stampare il file?", - "store_web_verify_title": "Verifica file", - "store_web_verify_msg": "Verifica che questo file sia stato creato per Anycubic Kobra X.", - "store_web_verify_confirm": "Conferma", - "store_web_verify_abort": "Interrompi", - "store_no_results": "Nessun file trovato.", - "store_never": "mai stampato", - "store_estimate": "Stima", - "store_upload_label_prefix": "Trascina il GCode qui o ", - "store_upload_label_browse": "sfoglia", - "store_upload_busy": "⏳ Caricamento in corso…", - "store_upload_success": "✓ {file}", - "store_upload_error": "✗ {error}", - "store_upload_only_gcode": "✗ Sono consentiti solo file GCode (.gcode, .3mf, .bgcode)", - "sf_all": "Tutti", - "sf_ok": "✓ Completato", - "sf_err": "✗ Fallito", - "sf_new": "Nuovo", + "skip_title": "✂ Salta oggetti", + "slot_edit_color": "Colore", + "slot_edit_custom": "es. PLA, PETG, ABS…", + "slot_edit_load": "⬇ Carica", + "slot_edit_material": "Materiale", + "slot_edit_ok": "Slot AMS", + "slot_edit_profile": "Profilo OrcaSlicer", + "slot_edit_profile_default": "— Generico (predefinito) —", + "slot_edit_profile_hint": "Inviato durante la sincronizzazione con OrcaSlicer come marchio specifico invece di un semplice \"Generico\"", + "slot_edit_save": "💾 Salva", + "slot_edit_title": "Modifica slot", + "slot_edit_unload": "⬆ Rimuovi", + "speed_normal": "⚡ Normale", + "speed_silent": "🐢 Silenzioso", + "speed_sport": "🚀 Sport", "ss_date": "↓ Data", + "ss_dur": "⏱ Tempo di stampa", "ss_name": "Nome A–Z", - "ss_dur": "⏱ Tempo di stampa" -} \ No newline at end of file + "store_delete_confirm": "Eliminare il file?", + "store_download": "⬇ Scarica", + "store_empty": "Nessun file caricato.", + "store_estimate": "Stima", + "store_never": "mai stampato", + "store_no_results": "Nessun file trovato.", + "store_print": "▶ Stampa", + "store_print_confirm": "Stampare il file?", + "store_refresh": "↻ Aggiorna", + "store_search_placeholder": "🔍 Cerca…", + "store_upload_busy": "⏳ Caricamento in corso…", + "store_upload_error": "✗ {error}", + "store_upload_label_browse": "sfoglia", + "store_upload_label_prefix": "Trascina il GCode qui o ", + "store_upload_only_gcode": "✗ Sono consentiti solo file GCode (.gcode, .3mf, .bgcode)", + "store_upload_success": "✓ {file}", + "store_web_verify_abort": "Annulla", + "store_web_verify_confirm": "Conferma", + "store_web_verify_msg": "Verifica che questo file sia stato creato per Anycubic Kobra X.", + "store_web_verify_title": "Verifica file", + "update_apply": "Installa ora", + "update_applying": "Download in corso...", + "update_available": "disponibile", + "update_check": "Controlla aggiornamenti", + "update_checking": "Verifica in corso...", + "update_error": "Errore", + "update_none": "Già aggiornato", + "update_restarting": "Riavvio in corso..." +} diff --git a/web/translations/zh-cn.json b/web/translations/zh-cn.json index 8225ee0..7a29773 100644 --- a/web/translations/zh-cn.json +++ b/web/translations/zh-cn.json @@ -1,291 +1,327 @@ { - "header_status_standby": "就绪", - "header_status_printing": "打印中", - "header_status_complete": "完成", - "header_status_error": "错误", - "kobra_free": "就绪", - "kobra_busy": "忙碌", - "kobra_printing": "打印中", - "kobra_preheating": "预热中", - "kobra_auto_leveling": "自动调平", - "kobra_checking": "检查中", - "kobra_updated": "更新中", - "kobra_init": "初始化中", - "kobra_pausing": "暂停中...", - "kobra_paused": "已暂停", - "kobra_resuming": "恢复中...", - "kobra_resumed": "已恢复", - "kobra_stopping": "停止中...", - "kobra_stoped": "已停止", - "kobra_finished": "已完成", - "kobra_failed": "错误", - "kobra_canceled": "已取消", - "kobra_offline": "离线", - "nav_dashboard": "仪表盘", - "nav_print": "打印", - "nav_temps": "温度", - "nav_motion": "运动", - "nav_ams": "AMS", - "nav_extras": "灯光 / 风扇", - "nav_console": "控制台", - "card_progress": "进度", - "card_temps": "温度", - "card_light_fan": "风扇", - "card_speed": "打印速度", - "card_cam": "相机", - "lbl_elapsed": "已用时间:", - "lbl_remaining": "剩余时间:", - "lbl_slicer_time": "切片预估:", - "lbl_layers": "层", - "lbl_zpos": "Z (mm)", - "speed_silent": "🐢 静音", - "speed_normal": "⚡ 标准", - "speed_sport": "🚀 运动", - "lbl_light": "💡 灯光", - "lbl_feed": "进料", - "lbl_unload": "退料", - "card_ace_dry": "ACE 烘干", + "ace_dry_auto_refill": "自动补料", + "ace_dry_chart": "历史 (温度/湿度)", + "ace_dry_current_temp": "温度", + "ace_dry_dialog_cancel": "取消", + "ace_dry_dialog_confirm": "确认", + "ace_dry_dialog_custom_name": "自定义名称", + "ace_dry_dialog_reset_default": "恢复默认", + "ace_dry_dialog_save_restart": "保存并重启", + "ace_dry_dialog_temp": "温度 (30-80°C)", + "ace_dry_dialog_time": "剩余时间 (h:m:s)", + "ace_dry_dialog_title": "烘干温度/时间设置", "ace_dry_dryer": "烘干机", + "ace_dry_duration": "时长 (分钟)", + "ace_dry_enable": "启用烘干", + "ace_dry_humidity": "湿度", + "ace_dry_preset_abs_asa": "ABS / ASA", + "ace_dry_preset_custom": "自定义", + "ace_dry_preset_pa_pc": "PA / PC", + "ace_dry_preset_petg": "PETG", + "ace_dry_preset_pla": "PLA", + "ace_dry_preset_pla_plus": "PLA+", + "ace_dry_preset_tpu": "TPU", + "ace_dry_start": "▶ 启动", "ace_dry_status_off": "状态: 关闭", "ace_dry_status_on": "状态: 运行中", "ace_dry_status_remaining": "剩余", - "ace_dry_humidity": "湿度", - "ace_dry_current_temp": "温度", - "ace_dry_chart": "历史 (温度/湿度)", - "ace_dry_temp": "温度 (°C)", - "ace_dry_duration": "时长 (分钟)", - "ace_dry_start": "▶ 启动", "ace_dry_stop": "■ 停止", - "ace_dry_auto_refill": "自动补料", - "ace_dry_enable": "启用烘干", + "ace_dry_temp": "温度 (°C)", "ace_dry_temp_line": "烘干温度", "ace_dry_time_line": "烘干时间", "ace_dry_ui_pending": "(仅 UI,后端稍后支持)", - "ace_dry_dialog_title": "烘干温度/时间设置", - "ace_dry_dialog_temp": "温度 (30-80°C)", - "ace_dry_dialog_time": "剩余时间 (h:m:s)", - "ace_dry_dialog_confirm": "确认", - "ace_dry_dialog_cancel": "取消", - "ace_dry_dialog_save_restart": "保存并重启", - "ace_dry_dialog_custom_name": "自定义名称", - "ace_dry_dialog_reset_default": "恢复默认", - "cam_placeholder": "📷 相机未启动", - "cam_stream_unavailable": "视频流不可用", + "add_printer": "添加打印机", + "ams_empty": "空", + "ams_no_data": "未收到 AMS 数据", + "apd_cancel": "取消", + "apd_confirm": "添加", + "apd_err_ip": "请输入 IP 地址", + "apd_fetching": "正在从打印机获取数据…", + "apd_lbl_ip": "打印机 IP", + "apd_lbl_name": "名称 (可选)", + "apd_placeholder_name": "例如 Kobra X 客厅", + "apd_success": "打印机已添加,Bridge 正在重启…", + "apd_title": "添加打印机", "btn_cam_start": "▶ 相机", + "btn_cam_start2": "▶ 启动", "btn_cam_stop": "◼ 相机", + "btn_cam_stop2": "◼ 停止", + "btn_cancel": "✕ 停止", + "btn_cancel_generic": "取消", + "btn_confirm_generic": "确认", + "btn_connect": "⚡ 连接", + "btn_delete": "删除", + "btn_disable_motors": "关闭电机", + "btn_disconnect": "✕ 断开", + "btn_home_all": "全部回零", + "btn_home_xy": "回零 XY", + "btn_home_z": "回零 Z", "btn_pause": "⏸ 暂停", "btn_resume": "▶ 继续", - "btn_cancel": "✕ 停止", - "label_nozzle": "喷嘴", + "cam_placeholder": "📷 相机未启动", + "cam_stream_unavailable": "视频流不可用", + "card_ace_dry": "ACE 烘干", + "card_ams": "耗材", + "card_cam": "相机", + "card_light_fan": "风扇", + "card_progress": "进度", + "card_speed": "打印速度", + "card_temps": "温度", + "confirm_cancel": "确定要取消打印吗?", + "fd_cancel": "取消", + "fd_no_matching_material": "无匹配材料", + "fd_no_slots_msg": "没有已装载的 AMS 槽位。{br}仍要开始打印吗?", + "fd_objects_hint": "跳过对象 (可选):", + "fd_objects_toggle": "跳过对象", + "fd_options_title": "选项", + "fd_print": "▶ 打印", + "fd_slot": "槽位", + "fd_slots_hint": "将 GCode 通道分配到 AMS 槽位:", + "fd_title": "槽位分配", + "fd_used": "已用", + "file_cancel_btn": "✕ 取消", + "file_ready_btn": "▶ 开始打印", + "file_slots_btn": "🎨 选择槽位", + "header_status_complete": "完成", + "header_status_error": "错误", + "header_status_printing": "打印中", + "header_status_standby": "就绪", + "hint_ip_no_port": "仅填写 IP,不要端口 (例如 192.168.1.102)", + "kobra_auto_leveling": "自动调平", + "kobra_busy": "忙碌", + "kobra_canceled": "已取消", + "kobra_checking": "检查中", + "kobra_failed": "错误", + "kobra_finished": "已完成", + "kobra_free": "就绪", + "kobra_init": "初始化中", + "kobra_offline": "离线", + "kobra_paused": "已暂停", + "kobra_pausing": "暂停中...", + "kobra_preheating": "预热中", + "kobra_printing": "打印中", + "kobra_resumed": "已恢复", + "kobra_resuming": "恢复中...", + "kobra_stoped": "已停止", + "kobra_stopping": "停止中...", + "kobra_updated": "更新中", "label_bed": "热床", "label_fan": "🌀 风扇", "label_light": "💡 灯光", - "label_on_off": "开 / 关", - "label_speed": "速度", - "panel_print_title": "打印控制", - "panel_print_btn_pause": "⏸ 暂停", - "panel_print_btn_resume": "▶ 继续", - "panel_print_btn_cancel": "✕ 取消", - "panel_print_temps_live": "温度 (实时)", - "label_set": "设置", + "label_nozzle": "喷嘴", "label_off": "关闭", - "panel_temps_nozzle": "喷嘴", - "panel_temps_bed": "热床", - "panel_temps_chart": "历史 (最近 60 次读数)", - "label_target_c": "目标:", - "panel_motion_xy": "XY 轴", - "panel_motion_z": "Z 轴", - "label_step": "步进:", - "btn_home_z": "回零 Z", - "btn_home_xy": "回零 XY", - "btn_home_all": "全部回零", - "btn_disable_motors": "关闭电机", - "panel_ams_title": "耗材", - "card_ams": "耗材", - "ams_no_data": "未收到 AMS 数据", + "label_on_off": "开 / 关", + "label_set": "设置", "label_slot": "槽位", - "ams_empty": "空", - "panel_extras_light": "灯光", - "panel_extras_fan": "风扇", - "panel_extras_camera": "相机", - "btn_cam_start2": "▶ 启动", - "btn_cam_stop2": "◼ 停止", - "panel_console_title": "事件日志", - "log_light_on": "灯光已开", - "log_light_off": "灯光已关", - "log_fan": "风扇 →", - "log_nozzle": "喷嘴 →", - "log_bed": "热床 →", + "label_speed": "速度", + "label_step": "步进:", + "label_target_c": "目标:", + "lbl_conn_error": "连接错误:", + "lbl_elapsed": "已用时间:", + "lbl_feed": "进料", + "lbl_layers": "层", + "lbl_light": "💡 灯光", + "lbl_remaining": "剩余时间:", + "lbl_slicer_time": "切片预估:", + "lbl_spoolman_sync_rate": "同步频率(秒,0=关闭)", + "lbl_spoolman_url": "服务器地址", + "lbl_unload": "退料", + "lbl_zpos": "Z (mm)", + "log_auto": "⬇ 自动", "log_axis": "轴", - "log_home": "回零", - "log_home_all": "全部回零", + "log_bed": "热床 →", "log_cam_start": "相机已启动:", "log_cam_stop": "相机已停止", - "log_poll_error": "轮询错误:", + "log_clear": "✕ 清空", + "log_delete_failed": "删除失败", + "log_dir_all": "全部", + "log_dir_label": "方向:", + "log_dir_rx": "RX", + "log_dir_tx": "TX", + "log_download": "⬇ 下载", "log_error": "错误:", - "confirm_cancel": "确定要取消打印吗?", - "settings_title": "设置", - "settings_connection": "连接", - "settings_print": "打印设置", - "settings_poll": "轮询间隔(秒)", + "log_fan": "风扇 →", + "log_filter_placeholder": "筛选…", + "log_home": "回零", + "log_home_all": "全部回零", + "log_light_off": "灯光已关", + "log_light_on": "灯光已开", + "log_lvl_err": "⛔ 错误", + "log_lvl_label": "级别:", + "log_lvl_warn": "⚠ 警告", + "log_nozzle": "喷嘴 →", + "log_poll_error": "轮询错误:", + "log_print_action": "打印:", + "log_print_start": "打印开始:", + "log_topic_ams": "AMS", + "log_topic_info": "信息", + "log_topic_label": "主题:", + "log_topic_print": "打印", + "log_topic_status": "状态", + "modal_sec_obico": "Obico", + "modal_sec_spoolman": "Spoolman", + "nav_ams": "AMS", + "nav_browser": "浏览器", + "nav_console": "控制台", + "nav_dashboard": "仪表盘", + "nav_extras": "灯光 / 风扇", + "nav_motion": "运动", + "nav_print": "打印", + "nav_printers": "打印机", "nav_settings": "设置", - "settings_cat_display": "外观", - "settings_cat_filament": "耗材", - "settings_cat_language": "语言", - "settings_cat_theme": "切换浅色 / 深色", - "settings_filament_mapping": "耗材配置映射(每槽位)", - "settings_filament_mapping_save": "保存映射", - "settings_visible_vendors": "可见厂商(配置下拉框)", - "settings_visible_vendors_hint": "仅这些厂商会出现在槽位配置下拉框中。未选择 = 显示全部。“Generic”和您自己的配置始终可见。", - "settings_visible_vendors_save": "保存选择", - "progress_action_print": "打印", - "progress_action_slots": "分配槽位", - "progress_action_clear": "清除", - "settings_version": "版本", - "settings_save": "保存并重启", - "settings_printer_name": "打印机名称", - "settings_printer_ip": "打印机 IP", - "settings_mqtt_port": "MQTT 端口", - "settings_username": "MQTT 用户名", - "settings_password": "MQTT 密码", - "settings_device_id": "设备 ID", - "settings_mode_id": "模式 ID", - "hint_ip_no_port": "仅填写 IP,不要端口 (例如 192.168.1.102)", - "settings_default_slot": "默认槽位 (单色)", - "settings_slot_auto": "自动 (所有已装载槽位)", - "settings_auto_leveling": "打印前自动调平", - "settings_camera_on_print": "打印开始时开启相机", - "settings_web_upload_warning": "打印网页上传文件时显示警告", - "update_check": "检查更新", - "update_checking": "检查中...", - "update_available": "可用", - "update_none": "已是最新版本", - "update_apply": "立即安装", - "update_applying": "下载中...", - "update_restarting": "重启中...", - "update_error": "错误", - "btn_connect": "⚡ 连接", - "btn_disconnect": "✕ 断开", - "lbl_conn_error": "连接错误:", - "slot_edit_title": "编辑槽位", - "slot_edit_color": "颜色", - "slot_edit_material": "材料", - "slot_edit_load": "⬇ 进料", - "slot_edit_unload": "⬆ 退料", - "slot_edit_save": "💾 保存", - "slot_edit_custom": "例如 PLA, PETG, ABS…", - "slot_edit_ok": "AMS 槽位", - "slot_edit_profile": "OrcaSlicer 配置", - "slot_edit_profile_hint": "在 OrcaSlicer 同步时发送具体品牌,而不仅仅是“Generic”", - "slot_edit_profile_default": "— 通用 (默认) —", - "orca_profile_section": "OrcaSlicer 配置", + "nav_temps": "温度", + "orca_profile_done": "已导入", + "orca_profile_dropmsg": "拖到此处或点击", + "orca_profile_help_html": "上传 OrcaSlicer 耗材文件夹的 ZIP 或单个 .json 文件。
在 OrcaSlicer 中: Help → Show Configuration Folder → user/<id>/filament/", "orca_profile_hint": "导入你自己的 OrcaSlicer 耗材配置(在 Help → Show Configuration Folder 打开用户目录)", "orca_profile_import_btn": "导入配置", "orca_profile_import_link": "★ 导入自己的配置…", "orca_profile_import_title": "导入你的 OrcaSlicer 配置", - "orca_profile_help_html": "上传 OrcaSlicer 耗材文件夹的 ZIP 或单个 .json 文件。
在 OrcaSlicer 中: Help → Show Configuration Folder → user/<id>/filament/", - "orca_profile_dropmsg": "拖到此处或点击", "orca_profile_list_label": "已导入", - "orca_profile_user_label": "自己的配置", - "orca_profile_user_empty": "– 无 –", - "orca_profile_uploading": "上传中…", - "orca_profile_done": "已导入", + "orca_profile_section": "OrcaSlicer 配置", "orca_profile_skipped": "跳过", - "log_dir_all": "全部", - "log_lvl_label": "级别:", - "file_ready_btn": "▶ 开始打印", - "file_slots_btn": "🎨 选择槽位", - "file_cancel_btn": "✕ 取消", - "nav_printers": "打印机", - "skip_title": "✂ 跳过对象", - "skip_hint": "取消勾选不想继续打印的对象:", - "skip_btn_label": "对象", - "skip_no_objects": "此打印任务没有对象。", + "orca_profile_uploading": "上传中…", + "orca_profile_user_empty": "– 无 –", + "orca_profile_user_label": "自己的配置", + "panel_ams_title": "耗材", + "panel_browser_title": "文件浏览器", + "panel_console_title": "事件日志", + "panel_extras_camera": "相机", + "panel_extras_fan": "风扇", + "panel_extras_light": "灯光", + "panel_motion_xy": "XY 轴", + "panel_motion_z": "Z 轴", + "panel_print_btn_cancel": "✕ 取消", + "panel_print_btn_pause": "⏸ 暂停", + "panel_print_btn_resume": "▶ 继续", + "panel_print_temps_live": "温度 (实时)", + "panel_print_title": "打印控制", + "panel_temps_bed": "热床", + "panel_temps_chart": "历史 (最近 60 次读数)", + "panel_temps_nozzle": "喷嘴", + "print_auto_leveling": "本次打印自动调平", + "printers_active": "● 活动", + "printers_current": "当前打印机", + "printers_empty_hint": "尚未设置打印机。", + "printers_loading": "加载中…", + "printers_none": "未配置打印机。", + "printers_remove": "移除打印机", + "printers_remove_confirm": "移除打印机 \"{name}\"? Bridge 将重启。", + "printers_switch": "切换 →", + "progress_action_clear": "清除", + "progress_action_print": "打印", + "progress_action_slots": "分配槽位", + "settings_auto_leveling": "打印前自动调平", + "settings_auto_leveling_label": "打印前自动调平", + "settings_btn_tooltip": "设置", + "settings_camera_on_print": "打印开始时开启相机", + "settings_cat_connection": "连接", + "settings_cat_display": "外观", + "settings_cat_filament": "耗材", + "settings_cat_language": "语言", + "settings_cat_printer": "打印机", + "settings_cat_system": "系统", + "settings_cat_theme": "切换浅色 / 深色", + "settings_connection": "连接", + "settings_default_slot": "默认槽位 (单色)", + "settings_device_id": "设备 ID", + "settings_device_id_hint": "32 个十六进制字符", + "settings_device_id_placeholder": "32 个十六进制字符", + "settings_filament_mapping": "耗材配置映射(每槽位)", + "settings_filament_mapping_hint": "每个 AMS 槽位的固定 Orca 配置。在切片器同步时,Bridge 会发送此配置而不是“Generic”。", + "settings_filament_mapping_label": "耗材配置映射(每槽位)", + "settings_filament_mapping_save": "保存映射", + "settings_filament_mapping_save_label": "保存映射", + "settings_file_ready_banner": "打印栏", + "settings_file_ready_dialog": "打印对话框", + "settings_file_ready_mode": "上传后:开始打印行为", + "settings_integrations": "集成", + "settings_language": "语言", + "settings_mode_id": "模式 ID", + "settings_mode_id_placeholder": "20030", + "settings_mqtt_port": "MQTT 端口", + "settings_mqtt_username_placeholder": "userXXXXXXXX", + "settings_orca_profiles_import": "导入配置文件", + "settings_orca_profiles_label": "OrcaSlicer 配置文件", + "settings_password": "MQTT 密码", + "settings_poll": "轮询间隔(秒)", + "settings_poll_interval_hint": "Bridge 查询打印机状态的频率", + "settings_poll_interval_label": "轮询间隔(秒)", + "settings_print": "打印设置", + "settings_printer_ip": "打印机 IP", + "settings_printer_name": "打印机名称", + "settings_printer_name_placeholder": "例如 Kobra X 左", + "settings_save": "保存并重启", + "settings_slot_auto": "自动 (所有已装载槽位)", + "settings_theme_toggle": "切换浅色 / 深色", + "settings_title": "设置", + "settings_username": "MQTT 用户名", + "settings_vendor_filter_placeholder": "搜索厂商…", + "settings_version": "版本", + "settings_visible_vendors": "可见厂商(配置下拉框)", + "settings_visible_vendors_hint": "仅这些厂商会出现在槽位配置下拉框中。未选择 = 显示全部。“Generic”和您自己的配置始终可见。", + "settings_visible_vendors_label": "可见厂商(配置下拉框)", + "settings_visible_vendors_save": "保存选择", + "settings_visible_vendors_save_label": "保存选择", + "settings_web_upload_warning": "打印网页上传文件时显示警告", + "sf_all": "全部", + "sf_err": "✗ 失败", + "sf_new": "新", + "sf_ok": "✓ 已完成", "skip_already": "已跳过", + "skip_btn_label": "对象", + "skip_cancel": "取消", + "skip_confirm": "跳过", + "skip_confirm_btn": "跳过", + "skip_hint": "取消勾选不想继续打印的对象:", + "skip_no_objects": "此打印任务没有对象。", "skip_select_at_least_one": "请至少选择一个对象。", "skip_sending": "发送中 …", "skip_success": "对象将被跳过。", - "fd_objects_hint": "跳过对象 (可选):", - "fd_objects_toggle": "跳过对象", - "fd_slots_hint": "将 GCode 通道分配到 AMS 槽位:", - "fd_cancel": "取消", - "fd_print": "▶ 打印", - "fd_no_slots_msg": "没有已装载的 AMS 槽位。{br}仍要开始打印吗?", - "fd_slot": "槽位", - "fd_no_matching_material": "无匹配材料", - "fd_used": "已用", - "add_printer": "添加打印机", - "apd_lbl_ip": "打印机 IP", - "apd_lbl_name": "名称 (可选)", - "apd_placeholder_name": "例如 Kobra X 客厅", - "apd_cancel": "取消", - "apd_confirm": "添加", - "apd_fetching": "正在从打印机获取数据…", - "apd_success": "打印机已添加,Bridge 正在重启…", - "apd_err_ip": "请输入 IP 地址", - "printers_remove": "移除打印机", - "printers_remove_confirm": "移除打印机 \"{name}\"? Bridge 将重启。", - "printers_active": "● 活动", - "printers_switch": "切换 →", - "printers_current": "当前打印机", - "printers_loading": "加载中…", - "printers_none": "未配置打印机。", - "printers_empty_hint": "尚未设置打印机。", - "nav_browser": "浏览器", - "panel_browser_title": "文件浏览器", - "store_search_placeholder": "🔍 搜索…", - "store_empty": "尚未上传文件。", - "store_refresh": "↻ 刷新", - "store_print": "▶ 打印", - "store_download": "⬇ 下载", - "store_delete_confirm": "删除文件?", - "store_print_confirm": "打印文件?", - "store_web_verify_title": "验证文件", - "store_web_verify_msg": "请确认此文件是为 Anycubic Kobra X 创建的。", - "store_web_verify_confirm": "确认", - "store_web_verify_abort": "取消", - "store_no_results": "未找到文件。", - "store_never": "从未打印", - "store_estimate": "估算", - "store_upload_label_prefix": "将 GCode 拖到这里或 ", - "store_upload_label_browse": "浏览", - "store_upload_busy": "⏳ 上传中…", - "store_upload_success": "✓ {file}", - "store_upload_error": "✗ {error}", - "store_upload_only_gcode": "✗ 仅允许 GCode 文件 (.gcode, .3mf, .bgcode)", - "sf_all": "全部", - "sf_ok": "✓ 已完成", - "sf_err": "✗ 失败", - "sf_new": "新", + "skip_title": "✂ 跳过对象", + "slot_edit_color": "颜色", + "slot_edit_custom": "例如 PLA, PETG, ABS…", + "slot_edit_load": "⬇ 进料", + "slot_edit_material": "材料", + "slot_edit_ok": "AMS 槽位", + "slot_edit_profile": "OrcaSlicer 配置", + "slot_edit_profile_default": "— 通用 (默认) —", + "slot_edit_profile_hint": "在 OrcaSlicer 同步时发送具体品牌,而不仅仅是“Generic”", + "slot_edit_save": "💾 保存", + "slot_edit_title": "编辑槽位", + "slot_edit_unload": "⬆ 退料", + "speed_normal": "⚡ 标准", + "speed_silent": "🐢 静音", + "speed_sport": "🚀 运动", "ss_date": "↓ 日期", - "ss_name": "A–Z 名称", "ss_dur": "⏱ 打印时间", - "ace_dry_preset_pla": "PLA", - "ace_dry_preset_pla_plus": "PLA+", - "ace_dry_preset_petg": "PETG", - "ace_dry_preset_tpu": "TPU", - "ace_dry_preset_abs_asa": "ABS / ASA", - "ace_dry_preset_pa_pc": "PA / PC", - "ace_dry_preset_custom": "自定义", - "fd_options_title": "选项", - "print_auto_leveling": "本次打印自动调平", - "settings_file_ready_mode": "开始打印对话框", - "settings_file_ready_banner": "打印栏", - "settings_file_ready_dialog": "打印对话框", - "log_dir_rx": "RX", - "log_dir_tx": "TX", - "log_dir_label": "方向:", - "log_lvl_err": "⛔ 错误", - "log_lvl_warn": "⚠ 警告", - "log_topic_label": "主题:", - "log_topic_ams": "AMS", - "log_topic_print": "打印", - "log_topic_info": "信息", - "log_topic_status": "状态", - "log_download": "⬇ 下载", - "log_auto": "⬇ 自动", - "log_clear": "✕ 清空", - "log_filter_placeholder": "筛选…", - "skip_cancel": "取消", - "skip_confirm": "跳过" + "ss_name": "A–Z 名称", + "store_delete_confirm": "删除文件?", + "store_download": "⬇ 下载", + "store_empty": "尚未上传文件。", + "store_estimate": "估算", + "store_never": "从未打印", + "store_no_results": "未找到文件。", + "store_print": "▶ 打印", + "store_print_confirm": "打印文件?", + "store_refresh": "↻ 刷新", + "store_search_placeholder": "🔍 搜索…", + "store_upload_busy": "⏳ 上传中…", + "store_upload_error": "✗ {error}", + "store_upload_label_browse": "浏览", + "store_upload_label_prefix": "将 GCode 拖到这里或 ", + "store_upload_only_gcode": "✗ 仅允许 GCode 文件 (.gcode, .3mf, .bgcode)", + "store_upload_success": "✓ {file}", + "store_web_verify_abort": "取消", + "store_web_verify_confirm": "确认", + "store_web_verify_msg": "请验证此文件是为Anycubic Kobra X创建的。", + "store_web_verify_title": "验证文件", + "update_apply": "立即安装", + "update_applying": "下载中...", + "update_available": "可用", + "update_check": "检查更新", + "update_checking": "检查中...", + "update_error": "错误", + "update_none": "已是最新版本", + "update_restarting": "重启中..." }