Translate Python log messages + fix rhinopanel import in PROJECTS

- startup.py: all user-visible messages translated to English
- panel_base.py: icon/rendering log messages translated
- toolbar.py: display mode check messages translated
- Global: Panel registered/opened/listener-active across all modules
- Fix: elemente.py and other files with stale 'import rhinopanel'
  were missing from PROJECTS sync — now properly copied
This commit is contained in:
2026-06-06 11:38:20 +02:00
parent 375487c10c
commit b9f661cdb3
16 changed files with 63 additions and 63 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ def _on_begin_command(sender, e):
Rhino.UI.Panels.FocusPanel(guid)
except Exception: pass
if sc.sticky.get(_VERBOSE_KEY):
print("[BEGIN-CMD] Gestaltung-Panel geoeffnet/fokussiert")
print("[BEGIN-CMD] Gestaltung-Panel opened/fokussiert")
except Exception as ex:
print("[BEGIN-CMD] OpenPanel:", ex)
try:
+1 -1
View File
@@ -156,6 +156,6 @@ def install_curve_vertex_dots():
conduit = _VertexDotConduit()
conduit.Enabled = True
sc.sticky[_STICKY_CONDUIT] = conduit
print("[CURVE_DOTS] Vertex-Dot-Conduit aktiv")
print("[CURVE_DOTS] Vertex dot conduit active")
except Exception as ex:
print("[CURVE_DOTS] install:", ex)
+1 -1
View File
@@ -621,7 +621,7 @@ def _install_listeners(bridge):
except Exception as ex:
print("[DIMENSIONEN] select-events:", ex)
sc.sticky[flag] = True
print("[DIMENSIONEN] Listener aktiv (Idle + SelectObjects)")
print("[DIMENSIONEN] Listener active (Idle + SelectObjects)")
def _bridge_factory():
+1 -1
View File
@@ -18434,7 +18434,7 @@ def _install_listeners(bridge):
"cmd_begin": _on_command_begin,
"cmd_end": _on_command_end,
}
print("[ELEMENTE] Listener aktiv (Replace + Add + Delete + Select + Idle + Cmd)")
print("[ELEMENTE] Listener active (Replace + Add + Delete + Select + Idle + Cmd)")
# Schnitt-Doppelklick-Handler global registrieren — idempotent via
# sticky-Flag im schnitte-Modul, mehrfache Aufrufe bei Re-Loads
# raeumen den alten Handler vorher weg.
+1 -1
View File
@@ -3107,7 +3107,7 @@ def _install_layer_listener(bridge):
Rhino.RhinoDoc.LayerTableEvent += on_layer_event
sc.sticky["ebenen_layer_listener"] = True
print("[EBENEN] Layer-Listener aktiv")
print("[EBENEN] Layer-Listener active")
panel_base.register_and_open("ebenen", "Ebenen", PANEL_GUID_STR, _ebenen_bridge_factory,
+2 -2
View File
@@ -156,7 +156,7 @@ def _detect_dpi():
if dpi < 30.0 or dpi > 600.0:
print("[MASSSTAB] auto-detect: DPI {:.1f} ausserhalb 30..600 -> ignoriert".format(dpi))
return None
print("[MASSSTAB] DPI auto-detected: {:.1f} physisch (Bildschirm {:.0f}x{:.0f}px / {:.1f}x{:.1f}mm, logisch {:.0f}x{:.0f})".format(
print("[MASSSTAB] DPI auto-detected: {:.1f} physical (screen {:.0f}x{:.0f}px / ... logical {:.0f}x{:.0f})".format(
dpi, px, float(data.get("py") or 0),
mm, float(data.get("mh") or 0),
lpx, float(data.get("lpy") or 0)))
@@ -1061,7 +1061,7 @@ def _install_listeners(bridge):
Rhino.RhinoApp.Idle += on_idle
Rhino.RhinoDoc.ActiveDocumentChanged += on_view_change
sc.sticky[flag] = True
print("[MASSSTAB] Listener aktiv (Idle-Poll + Doc-Change)")
print("[MASSSTAB] Listener active (Idle-Poll + Doc-Change)")
def get_current_scale_ratio():
+1 -1
View File
@@ -865,4 +865,4 @@ def install_listeners():
return
sc.sticky["overrides_listeners"] = True
print("[OVERRIDES] Live-Update Listener aktiv (Add/Replace/LayerTable)")
print("[OVERRIDES] Live-Update Listener active (Add/Replace/LayerTable)")
+16 -16
View File
@@ -62,16 +62,16 @@ def print_startup_summary():
print("[STARTUP] ===== SUMMARY =====")
print("[STARTUP] Wall-time (first to last mark): {:.1f} ms".format(total_wall))
print("[STARTUP] Sum of measured work: {:.1f} ms".format(total_work))
# Top-10 nach Dauer
# Top-10 by duration
top = sorted(_TIMINGS, key=lambda x: -x[2])[:10]
print("[STARTUP] --- Top-10 nach Dauer ---")
print("[STARTUP] --- Top-10 by duration ---")
for phase, label, ms in top:
print("[STARTUP] {:7.1f} ms {} / {}".format(ms, phase, label))
# Aggregat nach Phase
# Aggregate by phase
by_phase = {}
for phase, _, ms in _TIMINGS:
by_phase[phase] = by_phase.get(phase, 0.0) + ms
print("[STARTUP] --- Aggregat nach Phase ---")
print("[STARTUP] --- Aggregate by phase ---")
for phase, ms in sorted(by_phase.items(), key=lambda x: -x[1]):
print("[STARTUP] {:7.1f} ms {}".format(ms, phase))
@@ -717,7 +717,7 @@ def make_panel_icon(name_or_letter, bg_hex):
if os.path.isfile(png_path):
icon_bmp = _try_load_png_white(png_path, size - 8)
if icon_bmp is not None: chosen_path = png_path
else: print("[panel_base] PNG geladen aber Bitmap None:",
else: print("[panel_base] PNG loaded but Bitmap is None:",
png_path)
# PNG-not-found ist normal: Fallback auf SVG dann Material-Font.
# Nur loggen wenn final ALLES failt (s.u.).
@@ -734,12 +734,12 @@ def make_panel_icon(name_or_letter, bg_hex):
size - 2*pad, size - 2*pad)
used_svg = True
used_material = True # → kein Letter-Fallback
print("[panel_base] Icon-Pfad: {}{}".format(
print("[panel_base] Icon path: {}{}".format(
name_or_letter, chosen_path))
except Exception as ex:
print("[panel_base] Icon-Composite Fehler:", ex)
print("[panel_base] Icon composite error:", ex)
except Exception as ex:
print("[panel_base] Icon-Pfad-Check:", ex)
print("[panel_base] Icon path check error:", ex)
# 1) Material-Icon-Font (wenn keine SVG vorhanden)
mat_cp = _MATERIAL_CODEPOINTS.get(name_or_letter)
@@ -759,7 +759,7 @@ def make_panel_icon(name_or_letter, bg_hex):
drawing.Colors.White)
used_material = True
except Exception as ex:
print("[panel_base] Material-Render Fehler:", ex)
print("[panel_base] Material render error:", ex)
used_material = False
# 2) Fallback: Buchstabe (erstes Zeichen bzw. eingegebener Buchstabe)
@@ -787,7 +787,7 @@ def make_panel_icon(name_or_letter, bg_hex):
tag, safe, bg_hex.lstrip("#")))
bmp.Save(path, drawing.ImageFormat.Png)
except Exception as ex:
print("[panel_base] Icon-Save:", ex)
print("[panel_base] Icon save error:", ex)
path = None
# WICHTIG: Mac Rhinos RegisterPanel meldet "expected Icon, got Icon"
# wenn wir Eto.Drawing.Icon uebergeben — die API erwartet
@@ -797,18 +797,18 @@ def make_panel_icon(name_or_letter, bg_hex):
try:
import System.Drawing as _sd
ic = _sd.Icon(path)
print("[panel_base] Icon erzeugt via System.Drawing.Icon(path) [{}]".format(tag))
print("[panel_base] Icon created via System.Drawing.Icon(path) [{}]".format(tag))
return ic
except Exception as ex:
print("[panel_base] System.Drawing.Icon(path) fehlgeschlagen:", ex)
print("[panel_base] System.Drawing.Icon(path) failed:", ex)
# System.Drawing.Bitmap als Fallback (manche RegisterPanel-Overloads akzeptieren Bitmap)
try:
import System.Drawing as _sd
bmp_sd = _sd.Bitmap(path)
print("[panel_base] Icon erzeugt via System.Drawing.Bitmap(path) [{}]".format(tag))
print("[panel_base] Icon created via System.Drawing.Bitmap(path) [{}]".format(tag))
return bmp_sd
except Exception as ex:
print("[panel_base] System.Drawing.Bitmap(path) fehlgeschlagen:", ex)
print("[panel_base] System.Drawing.Bitmap(path) failed:", ex)
# Eto.Drawing.Icon als letzter Versuch — falls Rhino-Version anders ist
try:
ic = drawing.Icon(path)
@@ -909,7 +909,7 @@ def register_and_open(mode, caption, guid_str, bridge_factory, icon_spec=None, m
registered = True
registered_with_icon = with_icon
if with_icon:
print("[{}] Panel mit Icon registriert ({})".format(
print("[{}] Panel registered with icon ({})".format(
mode.upper(), type(arg).__name__))
break
except Exception as ex:
@@ -936,7 +936,7 @@ def register_and_open(mode, caption, guid_str, bridge_factory, icon_spec=None, m
guid = sc.sticky.get(sticky_guid, System.Guid(guid_str))
RhinoUI.Panels.OpenPanel(guid)
_t_mark("OpenPanel", mode, t_open)
print("[{}] Panel geoeffnet".format(mode.upper()))
print("[{}] Panel opened".format(mode.upper()))
except Exception as ex:
print("[{}] OpenPanel fehlgeschlagen: {}".format(mode.upper(), ex))
_t_mark("register_and_open", mode, t_outer)
+1 -1
View File
@@ -406,6 +406,6 @@ def install_handlers():
handler.Enabled = True
sc.sticky[_STICKY_CONDUIT] = conduit
sc.sticky[_STICKY_HANDLER] = handler
print("[SCHNITT_GRIPS] Endpoint-Conduit + Mouse-Handler aktiv")
print("[SCHNITT_GRIPS] Endpoint conduit + mouse handler active")
except Exception as ex:
print("[SCHNITT_GRIPS] install:", ex)
+1 -1
View File
@@ -593,7 +593,7 @@ def install_double_click_handler():
h = _SchnittDoubleClickHandler()
h.Enabled = True
sc.sticky["_dossier_schnitt_dblclick_handler"] = h
print("[SCHNITT] Doppelklick-Handler aktiv")
print("[SCHNITT] Double-click handler active")
except Exception as ex:
print("[SCHNITT] install_double_click_handler:", ex)
+27 -27
View File
@@ -29,7 +29,7 @@ if not sc.sticky.get("_dossier_startup_scheduled"):
import _startup_splash as _splash_first
_splash_first.show()
except Exception as _ex_splash:
print("[STARTUP] splash early:", _ex_splash)
print("[STARTUP] splash error:", _ex_splash)
# DIAGNOSE — welcher Python-Engine laeuft hier wirklich? Einmalig beim Start.
print("[STARTUP] Python: {}".format(sys.version))
@@ -107,7 +107,7 @@ def _assign_default_display_modes(doc):
try:
from Rhino.Display import DisplayModeDescription
except Exception as ex:
print("[STARTUP] view-modes: DMD nicht verfuegbar:", ex); return
print("[STARTUP] view-modes: DMD not available:", ex); return
# Mode-Lookup per Name
mode_plan = mode_3d = None
@@ -119,10 +119,10 @@ def _assign_default_display_modes(doc):
elif n == "Dossier 3D": mode_3d = dm
except Exception: pass
except Exception as ex:
print("[STARTUP] view-modes: Mode-List:", ex); return
print("[STARTUP] view-modes: mode list error:", ex); return
if mode_plan is None and mode_3d is None:
print("[STARTUP] view-modes: keine Dossier-Modes registriert — skip")
print("[STARTUP] view-modes: no Dossier display modes found — skip")
return
n_set = 0
@@ -150,7 +150,7 @@ def _assign_default_display_modes(doc):
try:
doc.Strings.SetString(_DOC_FLAG_VIEW_MODES, "1")
except Exception: pass
print("[STARTUP] view-modes: {} Viewport(s) gesetzt".format(n_set))
print("[STARTUP] view-modes: {} viewport(s) set".format(n_set))
_DOC_FLAG_VIEW_MAXIMIZED = "dossier_top_view_maximized"
@@ -176,15 +176,15 @@ def _maximize_top_view(doc):
break
except Exception: pass
if top_view is None:
print("[STARTUP] view-max: kein Top-Viewport gefunden")
print("[STARTUP] view-max: no Top viewport found")
return
try:
top_view.Maximized = True
doc.Views.ActiveView = top_view
doc.Views.Redraw()
print("[STARTUP] view-max: Top-Viewport maximiert")
print("[STARTUP] view-max: Top viewport maximized")
except Exception as ex:
print("[STARTUP] view-max set:", ex); return
print("[STARTUP] view-max set error:", ex); return
try:
doc.Strings.SetString(_DOC_FLAG_VIEW_MAXIMIZED, "1")
except Exception: pass
@@ -213,7 +213,7 @@ def _check_doc_unit(doc):
target_unit_str = rhinopanel.get_project_unit(doc)
target_unit_enum = rhinopanel.get_project_unit_enum(doc)
except Exception as ex:
print("[STARTUP] unit-check: project-setting lesen:", ex)
print("[STARTUP] unit-check: project setting read error:", ex)
return
if target_unit_enum is None: return
try:
@@ -255,9 +255,9 @@ def _check_doc_unit(doc):
except Exception as ex:
print("[STARTUP] unit-convert RunScript:", ex)
else:
print("[STARTUP] User hat Unit-Umstellung verweigertDoc bleibt {}".format(current))
print("[STARTUP] User declined unit changedoc stays {}".format(current))
except Exception as ex:
print("[STARTUP] unit-check dialog:", ex)
print("[STARTUP] unit-check dialog error:", ex)
def _on_doc_opened(sender, e):
@@ -281,9 +281,9 @@ def _hint_dossier_ui():
manuell laden kann. Rhino merkt sich die Anordnung dann persistent."""
if not os.path.isfile(_UI_FILE):
return
print("[STARTUP] DOSSIERUI gefunden: {}".format(_UI_FILE))
print("[STARTUP] Einmalig laden: Window -> Window Layout -> Open -> obige Datei")
print("[STARTUP] Anordnung bleibt danach ueber Rhino-Restarts erhalten.")
print("[STARTUP] DOSSIERUI found: {}".format(_UI_FILE))
print("[STARTUP] Load once: Window -> Window Layout -> Open -> file above")
print("[STARTUP] Layout persists across Rhino restarts.")
def _load_all(sender, e):
@@ -293,7 +293,7 @@ def _load_all(sender, e):
except Exception:
pass
# Splash wird ganz oben in startup.py (vor diesem Idle) gezeigt.
print("[STARTUP] Lade DOSSIER-Panels...")
print("[STARTUP] Loading DOSSIER panels...")
# Migration einmal fuer das beim Start aktive Doc
_migrate_active_doc()
# Und Listener fuer spaeter geoeffnete Docs registrieren
@@ -311,13 +311,13 @@ def _load_all(sender, e):
if config and isinstance(config.get("modules"), list):
enabled_ids = [m for m in config["modules"] if m in _MODULE_TO_PY]
unknown = [m for m in config["modules"] if m not in _MODULE_TO_PY]
print("[STARTUP] Projekt: '{}'".format(config.get("name") or "?"))
print("[STARTUP] Aktivierte Module: {}".format(", ".join(enabled_ids) or "(keine)"))
print("[STARTUP] Project: '{}'".format(config.get("name") or "?"))
print("[STARTUP] Active modules: {}".format(", ".join(enabled_ids) or "(keine)"))
if unknown:
print("[STARTUP] Unbekannte Modul-IDs in Config: {}".format(unknown))
print("[STARTUP] Unknown module IDs in config: {}".format(unknown))
else:
enabled_ids = _ALL_MODULES
print("[STARTUP] Keine dossier.project.json — alle Module laden")
print("[STARTUP] No dossier.project.json — loading all modules")
# massstab.py wird als Library mitgeladen (von oberleiste/ausschnitte/...)
# und braucht hier nicht mehr als eigenstaendiges Panel zu erscheinen.
# Imports messen — das ist der grosse Block der bisher unmeasured war
@@ -331,7 +331,7 @@ def _load_all(sender, e):
_pb._t_mark("import", mod_id, _t_imp)
print("[STARTUP] {} ({}) OK".format(mod_id, py_name))
except Exception as ex:
print("[STARTUP] {} ({}) FEHLER: {}".format(mod_id, py_name, ex))
print("[STARTUP] {} ({}) ERROR: {}".format(mod_id, py_name, ex))
# Text-Editor Doppelklick-Hook fuer DOSSIER-Texte
_t_te = _t.time()
try:
@@ -346,7 +346,7 @@ def _load_all(sender, e):
_assign_default_display_modes(Rhino.RhinoDoc.ActiveDoc)
_pb._t_mark("post_init", "view_modes", _t_vm)
except Exception as ex:
print("[STARTUP] view-modes assign:", ex)
print("[STARTUP] view-modes assign error:", ex)
# Top-View maximieren (= einzige aktive View statt 4-View Default)
try:
_maximize_top_view(Rhino.RhinoDoc.ActiveDoc)
@@ -359,7 +359,7 @@ def _load_all(sender, e):
_check_doc_unit(Rhino.RhinoDoc.ActiveDoc)
_pb._t_mark("post_init", "unit_check", _t_uc)
except Exception as ex:
print("[STARTUP] unit-check active doc:", ex)
print("[STARTUP] unit-check active doc error:", ex)
# Aliases + Shortcuts (Defaults aus rhino/aliases/shortcuts_default.json
# + User-Overrides aus dossier_settings.json) registrieren. Idempotent —
# SetMacro/SetMacro ueberschreibt vorhandene Eintraege. Wenn Bridge noch
@@ -374,7 +374,7 @@ def _load_all(sender, e):
.format(_na, _nf, _nc, _ns))
_pb._t_mark("post_init", "aliases", _t_al)
except Exception as ex:
print("[STARTUP] alias-loader:", ex)
print("[STARTUP] alias-loader error:", ex)
# BeginCommand-Hook: Gestaltung-Panel oeffnen bei Drawing-Commands
try:
import begin_cmd_hook
@@ -413,18 +413,18 @@ def _load_all(sender, e):
with open(os.path.join(marker_dir, "plugin_loaded.flag"), "w") as f:
f.write("ok")
except Exception as ex:
print("[STARTUP] marker schreiben:", ex)
print("[STARTUP] marker write error:", ex)
import threading
threading.Timer(2.0, _write_marker).start()
print("[STARTUP] Fertig")
print("[STARTUP] Done")
# Idempotency-Guard: wenn beide Pfade gleichzeitig feuern (C#-Plugin OnLoad
# UND legacy StartupCommands-XML), nur das erste registriert den Idle-Loader.
# Verhindert doppelte Panel-Registrierung + doppelte Listener.
if sc.sticky.get("_dossier_startup_scheduled"):
print("[STARTUP] schon geplant — skip (parallel-aufruf)")
print("[STARTUP] already scheduled — skip (parallel call)")
else:
sc.sticky["_dossier_startup_scheduled"] = True
Rhino.RhinoApp.Idle += _load_all
print("[STARTUP] geplant - laedt sobald Rhino idle ist")
print("[STARTUP] scheduled — loads when Rhino is idle")
+1 -1
View File
@@ -2108,7 +2108,7 @@ def _install_selection_listener(bridge):
Rhino.RhinoDoc.AddRhinoObject += on_add
Rhino.RhinoDoc.ModifyObjectAttributes += on_modify_attrs
sc.sticky[flag] = True
print("[GESTALTUNG] Listener aktiv (Selection + Hatch-Live-Update + Ebene-Auto-Fill + Layer-Sync)")
print("[GESTALTUNG] Listener active (Selection + Hatch-Live-Update + Ebene-Auto-Fill + Layer-Sync)")
def _bridge_factory():
+1 -1
View File
@@ -64,7 +64,7 @@ def _ensure_double_click_hook():
if not sc.sticky.get("dossier_text_idle_registered"):
Rhino.RhinoApp.Idle += _on_idle_check_pending_edit
sc.sticky["dossier_text_idle_registered"] = True
print("[TEXT-HOOK] Doppelklick-Hook installiert")
print("[TEXT-HOOK] Double-click hook installed")
except Exception as ex:
print("[TEXT-HOOK] install:", ex)
+6 -6
View File
@@ -361,7 +361,7 @@ def _ensure_dossier_display_mode(target_name, target_guid, template_basename,
# und ALLE Modes nach Restart verschwinden lassen kann. User soll den
# Mode in Rhino bauen + per "Save As" -> templates/<basename> exportieren.
if not template_exists and target_name != "Dossier Plan":
print("[OBERLEISTE] {}: kein Template → skip (in Rhino bauen, "
print("[OBERLEISTE] {}: no template → skip (in Rhino bauen, "
"Display-Mode -> Save As -> {})".format(
target_name, template_ini_path))
return False
@@ -380,7 +380,7 @@ def _ensure_dossier_display_mode(target_name, target_guid, template_basename,
# loeschen + reloaden wenn er das Template neu laden will.
# Vermeidet delete-loop wenn das Template ini-Werte hat die mein
# alter check als "falsch" einstufte.
print("[OBERLEISTE] Plan-Mode: existing gefunden, keine Aktion (manuell loeschen fuer Refresh)")
print("[OBERLEISTE] Display mode: existing found, no action (delete manually to refresh)")
return True
# Sonst kein existing → vor dem Import alle Orphan-Modes mit unserer
# Guid ODER Namen "Dossier Plan" wegputzen (alte kaputte Versionen
@@ -880,7 +880,7 @@ def _apply_window_layout_impl(name):
print("[OBERLEISTE] API-Kandidaten gefunden:", len(api_candidates),
[(c, m) for c, m, _ in api_candidates])
else:
print("[OBERLEISTE] Keine Rhino.UI-API-Kandidaten (Mac Rhino "
print("[OBERLEISTE] No Rhino.UI API candidates (Mac Rhino "
"exposed das nicht statisch). Falle auf Scripted Commands.")
# Args zum Probieren: GUID zuerst (falls vorhanden) dann Name.
# Beide als 1-arg Tuple. Doppelte Klammern haben in der alten Version
@@ -930,7 +930,7 @@ def _apply_window_layout_impl(name):
]
for cmd in cmd_candidates:
if _try_cmd(cmd):
print("[OBERLEISTE] Command erfolgreich, Stop.")
print("[OBERLEISTE] Command succeeded, stopping.")
return True
print("[OBERLEISTE] apply_window_layout: kein Weg hat funktioniert. "
@@ -1121,7 +1121,7 @@ def _list_all_command_names():
"Properties","Layer","Snap","Ortho","Planar","Save","SaveAs"):
names.add(n)
out = sorted(names)
print("[OBERLEISTE] {} Rhino-Commands fuer Autocomplete enumeriert".format(len(out)))
print("[OBERLEISTE] {} Rhino commands enumerated for autocomplete".format(len(out)))
return out
@@ -2280,7 +2280,7 @@ def _install_listeners(bridge):
try: Rhino.RhinoDoc.EndSaveDocument += on_end_save
except Exception as ex: print("[OBERLEISTE] EndSaveDocument-Hook:", ex)
sc.sticky[flag] = True
print("[OBERLEISTE] Listener aktiv")
print("[OBERLEISTE] Listener active")
def _bridge_factory():
+1 -1
View File
@@ -113,6 +113,6 @@ def install_handlers():
conduit = _TreppeEndpointConduit()
conduit.Enabled = True
sc.sticky[_STICKY_CONDUIT] = conduit
print("[TREPPE_GRIPS] Endpoint-Conduit aktiv")
print("[TREPPE_GRIPS] Endpoint conduit active")
except Exception as ex:
print("[TREPPE_GRIPS] install:", ex)
+1 -1
View File
@@ -354,6 +354,6 @@ def install_handlers():
handler.Enabled = True
sc.sticky[_STICKY_CONDUIT] = conduit
sc.sticky[_STICKY_HANDLER] = handler
print("[WAND_GRIPS] Endpoint-Conduit + Mouse-Handler aktiv")
print("[WAND_GRIPS] Endpoint conduit + mouse handler active")
except Exception as ex:
print("[WAND_GRIPS] install:", ex)