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": "重启中..."
}