Browser-BIM (cad): semantisches Modell, abgeleitete 2D/3D-Sichten, Zeichenwerkzeuge
Standalone-Browser-Port von DOSSIER. Enthaelt das semantische Modell mit Plan-/3D-Ableitung, Zeichen- und Editierwerkzeuge, Rhino-artiges Befehlssystem, dockbares Panel-System, Resource-Manager, DXF/.lin/.pat-Import, i18n (de/en) sowie Projektdokumentation und Probe-Harness.
This commit is contained in:
+500
@@ -0,0 +1,500 @@
|
||||
// Deutsches Wörterbuch (Default-Sprache). Die Werte hier sind EXAKT die bisher
|
||||
// sichtbaren UI-Texte — die i18n-Umstellung darf optisch nichts ändern.
|
||||
//
|
||||
// Identifier/Keys sind englisch und namespaced wie bei DOSSIER
|
||||
// (z. B. `topbar.grundriss`); nur die Werte sind übersetzbarer Text.
|
||||
// Platzhalter in geschweiften Klammern (`{name}`) werden von t(...) ersetzt.
|
||||
|
||||
export const de = {
|
||||
// ── Marke / Topbar ───────────────────────────────────────────────────────
|
||||
"brand.tag": "Dokumentmodell",
|
||||
|
||||
"topbar.viewGroup": "Ansicht",
|
||||
"topbar.grundriss": "Grundriss",
|
||||
"topbar.perspektive": "Perspektive",
|
||||
|
||||
"view3d.group": "Ansicht 3D",
|
||||
"view3d.front": "Front",
|
||||
"view3d.front.hint": "Frontalansicht von vorne",
|
||||
"view3d.top": "Oben",
|
||||
"view3d.top.hint": "Draufsicht (senkrecht von oben)",
|
||||
"view3d.side": "Seite",
|
||||
"view3d.side.hint": "Seitenansicht (90° zur Front)",
|
||||
"view3d.perspective": "Perspektive",
|
||||
"view3d.perspective.hint": "Freie Perspektive (3/4-Blick)",
|
||||
"view3d.iso": "Isometrie",
|
||||
"view3d.iso.hint": "Isometrische Ansicht (gleichwinklig von vorne-oben-rechts)",
|
||||
"view3d.camera": "Kamera",
|
||||
"view3d.camera.hint": "Kamera-Einstellungen (Sichtwinkel)",
|
||||
"view3d.fov": "Sichtwinkel",
|
||||
"view3d.fov.hint": "Sichtwinkel (FOV) der Perspektivkamera in Grad",
|
||||
|
||||
"topbar.detailGroup": "Detailgrad",
|
||||
"topbar.detail": "Detailgrad",
|
||||
"topbar.detail.hint": "Detailgrad der Plandarstellung (Symbole, Schraffuren, Linien)",
|
||||
"topbar.detail.hintDisabled": "Detailgrad wirkt im Grundriss (in der Perspektive noch nicht)",
|
||||
"topbar.detail.grob": "grob",
|
||||
"topbar.detail.mittel": "mittel",
|
||||
"topbar.detail.fein": "fein",
|
||||
|
||||
"topbar.scaleGroup": "Massstab und Zoom",
|
||||
"topbar.scale": "Massstab",
|
||||
"topbar.scale.apply": "Papier-Massstab 1:N anwenden",
|
||||
"topbar.scale.custom": "frei …",
|
||||
"topbar.scale.live": "Aktueller Papier-Massstab (live)",
|
||||
"topbar.scale.prompt": "Massstab eingeben (z. B. 1:35 oder 35):",
|
||||
"topbar.zoom100": "100%",
|
||||
"topbar.zoom100.hint": "Zoom exakt auf den gewählten Massstab 1:{n}",
|
||||
"topbar.fit": "Einpassen",
|
||||
"topbar.fit.hint": "Auf Plan einpassen",
|
||||
"topbar.fitSelection": "Auswahl",
|
||||
"topbar.fitSelection.hint": "Auf Auswahl einpassen (sonst auf Plan)",
|
||||
"topbar.zoom.current": "Aktueller Zoom",
|
||||
|
||||
"topbar.renderGroup": "Render-Modus",
|
||||
"topbar.render.shaded": "Schattiert",
|
||||
"topbar.render.shaded.hint": "Schattiert",
|
||||
"topbar.render.wireframe": "Draht",
|
||||
"topbar.render.wireframe.hint": "Drahtgitter",
|
||||
"topbar.render.hidden": "Kanten",
|
||||
"topbar.render.hidden.hint": "Verdeckte Kanten (Hidden-Line)",
|
||||
"topbar.render.hintDisabled": "Render-Modus wirkt in der Perspektive",
|
||||
// Darstellungsart (kontextabhängiger Dropdown): Grundriss = Farbig/SW,
|
||||
// Perspektive = Schattiert/Weiss/Draht/Kanten.
|
||||
"display.style": "Darstellung",
|
||||
"display.style.group": "Darstellungsart",
|
||||
"display.style.hint": "Darstellungsart der aktiven Ansicht",
|
||||
"display.style.color": "Farbig",
|
||||
"display.style.mono": "Schwarz-Weiss",
|
||||
"display.style.shaded": "Schattiert",
|
||||
"display.style.white": "Weiss",
|
||||
"display.style.wireframe": "Drahtgitter",
|
||||
"display.style.hidden": "Kanten",
|
||||
|
||||
"topbar.referenceLinesGroup": "Referenzlinien",
|
||||
"topbar.referenceLines": "Referenzlinien",
|
||||
"topbar.referenceLines.hint": "Referenzlinien (Wandachsen) ein-/ausblenden",
|
||||
"topbar.referenceLines.hintDisabled": "Referenzlinien wirken im Grundriss",
|
||||
|
||||
"topbar.resources": "Ressourcen",
|
||||
"topbar.resources.hint": "Ressourcen-Fenster ein-/ausblenden",
|
||||
|
||||
// ── Layout-Menü (Topbar) ─────────────────────────────────────────────────
|
||||
"layout.title": "Layout",
|
||||
"layout.placeholder": "Layout …",
|
||||
"layout.saveCurrent": "+ Aktuelles speichern …",
|
||||
"layout.loadGroup": "Laden",
|
||||
"layout.deleteGroup": "Löschen",
|
||||
"layout.savePrompt": "Layout speichern als:",
|
||||
|
||||
// ── Sichtbarkeits-Kombinationen (Topbar) ─────────────────────────────────
|
||||
"combo.layers": "Ebenen-Komb.",
|
||||
"combo.drawings": "Zeichn.-Komb.",
|
||||
"combo.placeholder": "Kombination …",
|
||||
"combo.saveCurrent": "+ Aktuelle speichern …",
|
||||
"combo.loadGroup": "Laden",
|
||||
"combo.deleteGroup": "Löschen",
|
||||
"combo.layers.title": "Ebenenkombinationen",
|
||||
"combo.drawings.title": "Zeichnungskombinationen",
|
||||
"combo.layers.savePrompt": "Ebenenkombination speichern als:",
|
||||
"combo.drawings.savePrompt": "Zeichnungskombination speichern als:",
|
||||
|
||||
// ── Zeichenwerkzeuge (Topbar-Werkzeugleiste + Statushinweise) ────────────
|
||||
"tool.group": "Werkzeuge",
|
||||
"tool.select": "Auswahl",
|
||||
"tool.wall": "Wand",
|
||||
"tool.line": "Linie",
|
||||
"tool.polyline": "Polylinie",
|
||||
"tool.rect": "Rechteck",
|
||||
"tool.select.hint": "Auswahl — Elemente klicken/aufziehen",
|
||||
"tool.wall.firstPoint": "Wand: ersten Achspunkt setzen",
|
||||
"tool.wall.nextPoint": "Wand: nächsten Punkt — Doppelklick/Rechtsklick beendet",
|
||||
"tool.line.firstPoint": "Linie: Startpunkt setzen",
|
||||
"tool.line.secondPoint": "Linie: Endpunkt setzen",
|
||||
"tool.polyline.firstPoint": "Polylinie: ersten Punkt setzen",
|
||||
"tool.polyline.nextPoint": "Polylinie: nächster Punkt — Klick auf Start schließt, Doppelklick beendet",
|
||||
"tool.rect.firstCorner": "Rechteck: erste Ecke setzen",
|
||||
"tool.rect.secondCorner": "Rechteck: gegenüberliegende Ecke setzen",
|
||||
"tool.wallType": "Wandtyp",
|
||||
"tool.layer": "Ebene",
|
||||
"tool.layer.hint": "Aktive Ebene — alles Gezeichnete kommt auf diese Kategorie",
|
||||
"tool.floorOnlyDisabled": "Wand nur auf einem Geschoss zeichenbar",
|
||||
"tool.snap": "Fang",
|
||||
"tool.snap.hint": "Fang an Endpunkten/Raster; Shift = Ortho, Ctrl = Fang aus",
|
||||
"snap.enabled": "Fang aktiv",
|
||||
"snap.endpoint": "Endpunkt",
|
||||
"snap.midpoint": "Mittelpunkt",
|
||||
"snap.intersection": "Schnittpunkt",
|
||||
"snap.onEdge": "Auf Kante (Lot)",
|
||||
"snap.grid": "Raster",
|
||||
"snap.ortho": "Ortho (Shift)",
|
||||
"snap.gridSize": "Rasterweite (m)",
|
||||
"snap.angleStep": "Winkelraster",
|
||||
|
||||
// ── Transformation (Bewegen/Spiegeln/Drehen) + Modusleiste ───────────────
|
||||
"transform.bar": "Transformation",
|
||||
"transform.cancel": "Abbrechen (Esc)",
|
||||
"transform.countPrompt": "Anzahl Kopien:",
|
||||
"transform.move": "Bewegen (M)",
|
||||
"transform.mirror": "Spiegeln (S)",
|
||||
"transform.rotate": "Drehen (D)",
|
||||
"transform.mode.move": "Bewegen",
|
||||
"transform.mode.copy": "Kopie",
|
||||
"transform.mode.array": "N Kopien",
|
||||
"transform.mode.distribute": "Verteilen",
|
||||
"transform.hint.move.0": "Basispunkt klicken",
|
||||
"transform.hint.move.1": "Zielpunkt klicken",
|
||||
"transform.hint.rotate.0": "Drehzentrum klicken",
|
||||
"transform.hint.rotate.1": "Bezugspunkt (Startwinkel) klicken",
|
||||
"transform.hint.rotate.2": "Zielwinkel klicken",
|
||||
"transform.hint.mirror.0": "Erster Punkt der Spiegelachse",
|
||||
"transform.hint.mirror.1": "Zweiter Punkt der Spiegelachse",
|
||||
|
||||
// ── Linien-Darstellung (Display/Print) ───────────────────────────────────
|
||||
"topbar.lineModeGroup": "Linien-Darstellung",
|
||||
"topbar.lineMode.display": "Display",
|
||||
"topbar.lineMode.print": "Print",
|
||||
"topbar.lineMode.display.hint": "Display: alle Linien als konstante Haarlinie (ruhiges Arbeiten)",
|
||||
"topbar.lineMode.print.hint": "Print: echte mm-Strichstärken (Papier-/Druckbild)",
|
||||
|
||||
// ── Statusleiste ─────────────────────────────────────────────────────────
|
||||
"status.selection": "Auswahl",
|
||||
"status.selectionN": "Auswahl: {n} {noun}",
|
||||
"status.wall": "Wand",
|
||||
"status.walls": "Wände",
|
||||
"status.xy": "X/Y",
|
||||
"status.unit": "Einheit",
|
||||
"status.scale": "Massstab",
|
||||
"status.zoom": "Zoom",
|
||||
"status.floor": "Geschoss",
|
||||
"status.layer": "Ebene",
|
||||
"status.none": "—",
|
||||
|
||||
// ── Navigator-Panels ─────────────────────────────────────────────────────
|
||||
"nav.drawingLevels": "Zeichnungsebenen",
|
||||
"nav.layers": "Ebenen",
|
||||
"nav.tools": "Werkzeuge",
|
||||
"nav.attributes": "Attribute",
|
||||
"nav.objectInfo": "Objekt-Info",
|
||||
|
||||
// Attribute-Palette (AttributesPanel)
|
||||
"attr.title": "Attribute",
|
||||
"attr.empty": "Keine Auswahl",
|
||||
"attr.stroke": "Stift",
|
||||
"attr.color": "Farbe",
|
||||
"attr.weight": "Strichstärke (mm)",
|
||||
"attr.lineStyle": "Linienstil",
|
||||
"attr.fill": "Füllung",
|
||||
"attr.fillColor": "Füllfarbe",
|
||||
"attr.clearFill": "Füllfarbe entfernen",
|
||||
"attr.hatch": "Schraffur",
|
||||
"attr.none": "keine",
|
||||
"attr.inheritedFromLayer": "Wände erben die Strichstärke aus der Ebene",
|
||||
"attr.fillNeedsClosed": "Füllung nur für geschlossene Formen",
|
||||
"attr.size": "Maße",
|
||||
"attr.width": "Breite",
|
||||
"attr.height": "Höhe",
|
||||
|
||||
// Objekt-Info-Palette (ObjectInfoPanel)
|
||||
"objinfo.title": "Objekt-Info",
|
||||
"objinfo.empty": "Kein Objekt gewählt",
|
||||
"objinfo.refpoint": "Bezugspunkt",
|
||||
"objinfo.setRefpoint": "Bezugspunkt wählen",
|
||||
"objinfo.x": "X",
|
||||
"objinfo.y": "Y",
|
||||
"objinfo.z": "Z",
|
||||
"objinfo.zHint": "2D-Ebene – keine Höhe am Element",
|
||||
"objinfo.dimensions": "Maße",
|
||||
"objinfo.width": "Breite",
|
||||
"objinfo.height": "Höhe",
|
||||
"objinfo.type": "Typ",
|
||||
"objinfo.kind.wall": "Wand",
|
||||
"objinfo.kind.drawing2d": "2D-Objekt",
|
||||
"objinfo.kind.door": "Tür",
|
||||
// ── Wand-Attribute (Object-Info-Panel) ──────────────────────────────────
|
||||
"objinfo.wall.section": "Wand",
|
||||
"objinfo.wall.refLine": "Referenzlinie",
|
||||
"objinfo.wall.refLine.left": "Außen (links)",
|
||||
"objinfo.wall.refLine.center": "Mitte",
|
||||
"objinfo.wall.refLine.right": "Innen (rechts)",
|
||||
"objinfo.wall.buildup": "Aufbau",
|
||||
"objinfo.wall.single": "Einschichtig",
|
||||
"objinfo.wall.multi": "Mehrschichtig",
|
||||
"objinfo.wall.thickness": "Dicke",
|
||||
"objinfo.wall.preset": "Wandaufbau",
|
||||
"objinfo.wall.presetLabel": "{name} · {thickness} m",
|
||||
"objinfo.wall.refFloor": "Referenzgeschoss",
|
||||
"objinfo.wall.linkAbove": "An oberes Geschoss binden",
|
||||
"objinfo.wall.bottom": "Unterkante (UK)",
|
||||
"objinfo.wall.top": "Oberkante (OK)",
|
||||
"objinfo.wall.anchorFloor": "An Geschoss gebunden",
|
||||
"objinfo.wall.anchorCustom": "Eigene Höhe",
|
||||
"objinfo.wall.height": "Höhe",
|
||||
"objinfo.wall.floorAboveNone": "Kein oberes Geschoss",
|
||||
"levels.addFloor": "+ Geschoss",
|
||||
"levels.addDrawing": "+ Zeichnung",
|
||||
"layers.addCategory": "+ Ebene",
|
||||
"nav.visibility": "Sichtbarkeit",
|
||||
"nav.hide": "Ausblenden",
|
||||
"nav.show": "Einblenden",
|
||||
"nav.categoryVisible": "{name} sichtbar",
|
||||
"nav.categorySelect": "{name} als aktive Ebene wählen (Zeichen-Ziel)",
|
||||
|
||||
// ── Badges (Art einer Zeichnungsebene) ───────────────────────────────────
|
||||
"badge.floor": "Geschoss",
|
||||
"badge.section": "Schnitt",
|
||||
"badge.elevation": "Ansicht",
|
||||
"badge.drawing": "Zeichnung",
|
||||
|
||||
// ── Darstellungsmodus-Umschalter ─────────────────────────────────────────
|
||||
"display.title": "Darstellungsmodus",
|
||||
"display.all_force": "Alle anzeigen",
|
||||
"display.all": "Ausgewählte",
|
||||
"display.active": "Nur aktive",
|
||||
"display.grey": "Andere grau",
|
||||
"display.grey_locked": "Andere grau & gesperrt",
|
||||
|
||||
// ── Dock ─────────────────────────────────────────────────────────────────
|
||||
"dock.resize": "Breite anpassen",
|
||||
"dock.dock": "Andocken",
|
||||
"dock.close": "Schließen",
|
||||
"dock.float": "Lösen",
|
||||
"dock.redock": "Andocken",
|
||||
"dock.resizePanel": "Größe ändern",
|
||||
"dock.dropLeft": "Links andocken",
|
||||
"dock.dropRight": "Rechts andocken",
|
||||
|
||||
// ── Kontextmenü (Einträge) ───────────────────────────────────────────────
|
||||
"ctx.layerSettings": "Ebeneneinstellungen…",
|
||||
"ctx.addSubLayer": "Sub-Ebene hinzufügen…",
|
||||
"ctx.assignSelection": "Selektion hierher übertragen",
|
||||
"ctx.assignSelection.disabled": "Keine Wand ausgewählt — zuerst im Grundriss/3D eine Wand anklicken.",
|
||||
"ctx.duplicate": "Duplizieren",
|
||||
"ctx.copyProps": "Eigenschaften kopieren",
|
||||
"ctx.pasteProps": "Eigenschaften einfügen",
|
||||
"ctx.pasteProps.disabled": "Zwischenablage leer — zuerst „Eigenschaften kopieren“.",
|
||||
"ctx.delete": "Löschen",
|
||||
"ctx.delete.lastLayer": "Die letzte Ebene kann nicht gelöscht werden.",
|
||||
"ctx.delete.lastLevel": "Die letzte Zeichnungsebene kann nicht gelöscht werden.",
|
||||
"ctx.levelSettings": "Einstellungen…",
|
||||
"ctx.fitSelection": "Auf Auswahl einpassen",
|
||||
"ctx.clearSelection": "Auswahl aufheben",
|
||||
"ctx.fit": "Ansicht einpassen",
|
||||
"ctx.noWallHit": "Keine Wand getroffen",
|
||||
"ctx.noWallHit.hint": "Rechtsklick auf eine Wand wählt sie und zeigt Wand-Aktionen.",
|
||||
|
||||
// Kontextmenü-Titel je Quelle.
|
||||
"ctx.title.level": "Zeichnungsebene",
|
||||
"ctx.title.wall": "Wand",
|
||||
"ctx.title.view": "Ansicht",
|
||||
|
||||
// ── Inline-Editor (Ebene / Geschoss) ─────────────────────────────────────
|
||||
"editor.close": "Schließen",
|
||||
"editor.layerTitle": "Ebene {code}",
|
||||
"editor.name": "Name",
|
||||
"editor.color": "Farbe",
|
||||
"editor.lineWeight": "Linienstärke",
|
||||
"editor.floorHeight": "Geschosshöhe",
|
||||
"editor.cutHeight": "Schnitthöhe",
|
||||
"editor.unit.mm": "mm",
|
||||
"editor.unit.m": "m",
|
||||
"editor.noHeightDrawing": "Für Zeichnungen gibt es keine Geschoss-/Schnitthöhe.",
|
||||
"editor.noHeightSection": "Für Schnitte/Ansichten gibt es keine Geschoss-/Schnitthöhe.",
|
||||
|
||||
// ── Hauptinhalt (Panes / Eigenschaften) ──────────────────────────────────
|
||||
"content.perspektiveTitle": "Perspektive · {name}",
|
||||
"content.grundrissTitle": "Grundriss · {name}",
|
||||
"content.grundrissLegend": "Grundriss · {name} · Schnitthöhe {cutHeight}",
|
||||
"content.drawingTitle": "Zeichnung · {name}",
|
||||
"content.drawingCanvas": "Zeichenfläche",
|
||||
"content.drawingLegend": "Freie 2D-Zeichnung",
|
||||
"props.floorHeight": "Geschosshöhe",
|
||||
"props.cutHeight": "Schnitthöhe",
|
||||
"props.okff": "OKFF",
|
||||
"props.okffValue": "+{value} m",
|
||||
|
||||
// ── Stub (Schnitt / Ansicht) ─────────────────────────────────────────────
|
||||
"stub.section": "Schnitt",
|
||||
"stub.elevation": "Ansicht",
|
||||
"stub.note": "{kind} — abgeleitete Projektion folgt in einer späteren Phase",
|
||||
|
||||
// ── Default-Namen neuer Elemente ─────────────────────────────────────────
|
||||
"default.floorName": "Geschoss {n}",
|
||||
"default.drawingName": "Zeichnung {n}",
|
||||
"default.categoryName": "Neue Ebene",
|
||||
"default.subCategoryName": "Neue Sub-Ebene",
|
||||
"default.componentName": "Neues Bauteil",
|
||||
"default.hatchName": "Neue Schraffur",
|
||||
"default.lineStyleName": "Neuer Linienstil",
|
||||
"default.hatchNone": "Ohne",
|
||||
"default.copySuffixLevel": "{name} Kopie",
|
||||
"default.copySuffixLayer": "{name} KOPIE",
|
||||
"default.wallTypeSingle": "Wand {thickness} m",
|
||||
|
||||
// ── Warnungen (Lösch-Schutz) ─────────────────────────────────────────────
|
||||
"alert.layerInUse": "Ebene „{code} {name}\" wird von Bauteilen verwendet und kann nicht gelöscht werden.",
|
||||
"alert.componentInUse": "Bauteil „{name}\" wird von einem Wandtyp verwendet und kann nicht gelöscht werden.",
|
||||
"alert.hatchInUse": "Schraffur „{name}\" wird von einem Bauteil verwendet und kann nicht gelöscht werden.",
|
||||
"alert.lineStyleInUse": "Linienstil „{name}\" wird von einer Schraffur verwendet und kann nicht gelöscht werden.",
|
||||
|
||||
// ── Ressourcen-Manager ───────────────────────────────────────────────────
|
||||
"resources.title": "Ressourcen",
|
||||
"resources.label": "Ressourcen-Manager",
|
||||
"resources.close": "Schließen",
|
||||
"resources.tab.components": "Bauteile",
|
||||
"resources.tab.hatches": "Schraffuren",
|
||||
"resources.tab.lines": "Linien",
|
||||
"resources.add": "Neu",
|
||||
"resources.import.lin": "⤓ .lin importieren",
|
||||
"resources.import.pat": "⤓ .pat importieren",
|
||||
|
||||
// Bauteile.
|
||||
"resources.components.hint": "Höhere Priorität läuft am Stoß durch (verschneidet zuerst); niedrigere stößt seitlich an.",
|
||||
"resources.components.empty": "Noch keine Bauteile.",
|
||||
"resources.components.placeholder": "Bauteil",
|
||||
"resources.col.name": "Name",
|
||||
"resources.col.color": "Farbe",
|
||||
"resources.col.hatch": "Schraffur",
|
||||
"resources.col.prio": "Prio",
|
||||
"resources.col.prio.hint": "Höhere Priorität läuft am Stoß durch",
|
||||
"resources.col.texture": "Textur",
|
||||
"resources.delete.component": "Bauteil „{name}\" löschen",
|
||||
|
||||
// Schraffuren.
|
||||
"resources.hatches.hint": "Muster, Maßstab und Winkel steuern die Schnitt-Schraffur; der Linienstil bestimmt die Stärke der Musterlinien.",
|
||||
"resources.hatches.empty": "Noch keine Schraffuren.",
|
||||
"resources.hatches.placeholder": "Schraffur",
|
||||
"resources.col.pattern": "Muster",
|
||||
"resources.col.scale": "Maßstab",
|
||||
"resources.col.angle": "Winkel °",
|
||||
"resources.col.lineStyle": "Linienstil",
|
||||
"resources.lineStyle.none": "— ohne —",
|
||||
"resources.delete.hatch": "Schraffur „{name}\" löschen",
|
||||
|
||||
// Schraffur-Muster.
|
||||
"pattern.none": "Ohne",
|
||||
"pattern.solid": "Vollfläche",
|
||||
"pattern.insulation": "Wärmedämmung",
|
||||
"pattern.diagonal": "Diagonal",
|
||||
"pattern.crosshatch": "Kreuzschraffur",
|
||||
|
||||
// Linien.
|
||||
"resources.lines.hint": "Strichstärke in Millimetern (Paper-Space). Strichmuster: durchgezogen, gestrichelt oder gepunktet.",
|
||||
"resources.lines.empty": "Noch keine Linienstile.",
|
||||
"resources.lines.placeholder": "Linienstil",
|
||||
"resources.col.weight": "Stärke (mm)",
|
||||
"resources.col.stroke": "Strich",
|
||||
"resources.col.preview": "Vorschau",
|
||||
"resources.delete.lineStyle": "Linienstil „{name}\" löschen",
|
||||
"resources.texture.empty": "—",
|
||||
|
||||
// Strichmuster.
|
||||
"dash.solid": "Durchgezogen",
|
||||
"dash.dashed": "Gestrichelt",
|
||||
"dash.dotted": "Gepunktet",
|
||||
|
||||
// ── Command-Line / Befehle (Rhino-artiges Befehlssystem) ──────────────────
|
||||
"cmd.aria": "Befehlszeile",
|
||||
"cmd.idle.prompt": "Befehl:",
|
||||
"cmd.idle.placeholder": "Befehl eingeben … (Tab)",
|
||||
"cmd.line.label": "Linie",
|
||||
"cmd.line.start": "Startpunkt der Linie:",
|
||||
"cmd.line.end": "Endpunkt der Linie:",
|
||||
"cmd.polyline.label": "Polylinie",
|
||||
"cmd.polyline.start": "Startpunkt:",
|
||||
"cmd.polyline.next": "Nächster Punkt:",
|
||||
"cmd.polyline.close": "Schliessen",
|
||||
"cmd.polyline.undo": "Zurück",
|
||||
"cmd.rect.label": "Rechteck",
|
||||
"cmd.rect.first": "Erste Ecke:",
|
||||
"cmd.rect.second": "Gegenüberliegende Ecke:",
|
||||
"cmd.circle.label": "Kreis",
|
||||
"cmd.circle.center": "Mittelpunkt:",
|
||||
"cmd.circle.radius": "Radius:",
|
||||
// Editierbefehle (Tier 1): Move/Copy/Offset operieren auf der Auswahl.
|
||||
"cmd.move.label": "Verschieben",
|
||||
"cmd.move.base": "Basispunkt:",
|
||||
"cmd.move.target": "Zielpunkt:",
|
||||
"cmd.move.empty": "Nichts gewählt (erst Objekte wählen).",
|
||||
"cmd.copy.label": "Kopieren",
|
||||
"cmd.copy.base": "Basispunkt:",
|
||||
"cmd.copy.target": "Zielpunkt (Enter beendet):",
|
||||
"cmd.copy.empty": "Nichts gewählt (erst Objekte wählen).",
|
||||
"cmd.offset.label": "Versatz",
|
||||
"cmd.offset.pick": "Kurve wählen:",
|
||||
"cmd.offset.side": "Seite oder Distanz:",
|
||||
// Editier-Werkzeuge Split / Join / Segment-Löschen (Tastatur: Ctrl+S / Ctrl+J /
|
||||
// Alt+Klick). Labels für Befehlsleiste/Menüs.
|
||||
"edit.split.label": "Teilen",
|
||||
"edit.join.label": "Verbinden",
|
||||
"edit.cutSegment.label": "Segment löschen",
|
||||
// Tab-Feld-Zyklus (Präzisionseingabe): geordnete Zahlenfelder je Schritt.
|
||||
"cmd.field.length": "Länge",
|
||||
"cmd.field.angle": "Winkel",
|
||||
"cmd.field.width": "Breite",
|
||||
"cmd.field.height": "Höhe",
|
||||
"cmd.field.radius": "Radius",
|
||||
"cmd.field.distance": "Distanz",
|
||||
|
||||
// ── Befehle: Import / Gelände ────────────────────────────────────────────
|
||||
"cmd.import.label": "Importieren",
|
||||
"cmd.import.prompt": "DXF-Datei wählen …",
|
||||
"cmd.terrain.label": "Gelände",
|
||||
"cmd.terrain.prompt": "Gelände aus Konturen erzeugen …",
|
||||
|
||||
// ── Site-/Kontext-Panel (SitePanel) ──────────────────────────────────────
|
||||
"nav.site": "Gelände",
|
||||
"site.title": "Gelände & Kontext",
|
||||
"site.import": "⤓ DXF importieren",
|
||||
"site.generateTerrain": "Gelände erzeugen",
|
||||
"site.contourSet": "Kontur-Satz",
|
||||
"site.empty": "Kein Kontext geladen. Importiere eine DXF-Datei (Höhenlinien oder Mesh).",
|
||||
"site.delete": "Entfernen",
|
||||
"site.type.mesh": "Mesh",
|
||||
"site.type.contours": "Konturen",
|
||||
"site.type.terrain": "Gelände",
|
||||
"site.dwgHint": "DWG? Zuerst mit dem gratis ODA File Converter in DXF umwandeln.",
|
||||
"site.terrainFailed": "Kein Gelände erzeugbar (zu wenige/kollineare Konturpunkte).",
|
||||
|
||||
// ── Import-Dialog (ImportDialog) ─────────────────────────────────────────
|
||||
"import.title": "DXF importieren",
|
||||
"import.close": "Schließen",
|
||||
"import.file": "Datei",
|
||||
"import.summary.heading": "Inhalt",
|
||||
"import.summary.contours": "{n} Konturen",
|
||||
"import.summary.meshes": "{n} Meshes",
|
||||
"import.summary.layers": "Layer: {layers}",
|
||||
"import.summary.noLayers": "keine Layer-Namen",
|
||||
"import.summary.empty": "Keine importierbare 2D-Geometrie gefunden.",
|
||||
"import.target.heading": "Ziel-Zeichnungsebene",
|
||||
"import.target.existing": "In bestehende Zeichnungsebene importieren",
|
||||
"import.target.new": "Neue Zeichnung anlegen",
|
||||
"import.target.newNamePlaceholder": "Name der neuen Zeichnung",
|
||||
"import.layers.heading": "Ebenen-Handling (DXF-Layer)",
|
||||
"import.layers.asCategories": "DXF-Layer als Kategorien übernehmen",
|
||||
"import.layers.toActive": "Alles auf die aktive Kategorie ({code})",
|
||||
"import.mesh.heading": "Meshes",
|
||||
"import.mesh.asContext": "Meshes als Kontext-Geometrie (3D) importieren",
|
||||
"import.mesh.note": "Meshes sind keine 2D-Zeichnung — sie landen in der Kontext-Schicht.",
|
||||
"import.dwg.heading": "DWG-Datei",
|
||||
"import.dwg.loading": "DWG wird gelesen …",
|
||||
"import.dwg.hint":
|
||||
"DWG konnte nicht gelesen werden. Wandle die Datei alternativ mit dem gratis ODA File Converter in DXF um und importiere die DXF-Datei.",
|
||||
"import.confirm": "Importieren",
|
||||
"import.cancel": "Abbrechen",
|
||||
"import.badge.floor": "Geschoss",
|
||||
"import.badge.section": "Schnitt",
|
||||
"import.badge.elevation": "Ansicht",
|
||||
"import.badge.drawing": "Zeichnung",
|
||||
|
||||
// ── Drag & Drop (App-weiter Datei-Drop) ──────────────────────────────────
|
||||
"drop.hint": "DXF/DWG-Datei hier ablegen",
|
||||
|
||||
// ── Fehler-Boundary ──────────────────────────────────────────────────────
|
||||
"error.console": "Unerwarteter Fehler:",
|
||||
"error.title": "Etwas ist schiefgelaufen",
|
||||
"error.body": "Ein unerwarteter Fehler ist aufgetreten. Details in der Konsole.",
|
||||
"error.reload": "Neu laden",
|
||||
} as const;
|
||||
|
||||
export type TranslationKey = keyof typeof de;
|
||||
+490
@@ -0,0 +1,490 @@
|
||||
// English dictionary — proves translatability. Same keys as de.ts; only the
|
||||
// values differ. Identifiers/keys stay English (DOSSIER namespacing); values are
|
||||
// the translated, user-visible text.
|
||||
|
||||
import type { TranslationKey } from "./de";
|
||||
|
||||
export const en: Record<TranslationKey, string> = {
|
||||
// Brand / Topbar.
|
||||
"brand.tag": "Document model",
|
||||
|
||||
"topbar.viewGroup": "View",
|
||||
"topbar.grundriss": "Plan",
|
||||
"topbar.perspektive": "Perspective",
|
||||
|
||||
"view3d.group": "3D view",
|
||||
"view3d.front": "Front",
|
||||
"view3d.front.hint": "Front view (frontal)",
|
||||
"view3d.top": "Top",
|
||||
"view3d.top.hint": "Top view (straight down)",
|
||||
"view3d.side": "Side",
|
||||
"view3d.side.hint": "Side view (90° to front)",
|
||||
"view3d.perspective": "Perspective",
|
||||
"view3d.perspective.hint": "Free perspective (3/4 view)",
|
||||
"view3d.iso": "Isometric",
|
||||
"view3d.iso.hint": "Isometric view (equiangular from front-top-right)",
|
||||
"view3d.camera": "Camera",
|
||||
"view3d.camera.hint": "Camera settings (field of view)",
|
||||
"view3d.fov": "Field of view",
|
||||
"view3d.fov.hint": "Field of view (FOV) of the perspective camera in degrees",
|
||||
|
||||
"topbar.detailGroup": "Detail level",
|
||||
"topbar.detail": "Detail level",
|
||||
"topbar.detail.hint": "Detail level of the plan (symbols, hatches, lines)",
|
||||
"topbar.detail.hintDisabled": "Detail level applies in the plan (not yet in perspective)",
|
||||
"topbar.detail.grob": "coarse",
|
||||
"topbar.detail.mittel": "medium",
|
||||
"topbar.detail.fein": "fine",
|
||||
|
||||
"topbar.scaleGroup": "Scale and zoom",
|
||||
"topbar.scale": "Scale",
|
||||
"topbar.scale.apply": "Apply paper scale 1:N",
|
||||
"topbar.scale.custom": "custom …",
|
||||
"topbar.scale.live": "Current paper scale (live)",
|
||||
"topbar.scale.prompt": "Enter scale (e.g. 1:35 or 35):",
|
||||
"topbar.zoom100": "100%",
|
||||
"topbar.zoom100.hint": "Zoom exactly to the chosen scale 1:{n}",
|
||||
"topbar.fit": "Fit",
|
||||
"topbar.fit.hint": "Fit to plan",
|
||||
"topbar.fitSelection": "Selection",
|
||||
"topbar.fitSelection.hint": "Fit to selection (otherwise to plan)",
|
||||
"topbar.zoom.current": "Current zoom",
|
||||
|
||||
"topbar.renderGroup": "Render mode",
|
||||
"topbar.render.shaded": "Shaded",
|
||||
"topbar.render.shaded.hint": "Shaded",
|
||||
"topbar.render.wireframe": "Wire",
|
||||
"topbar.render.wireframe.hint": "Wireframe",
|
||||
"topbar.render.hidden": "Edges",
|
||||
"topbar.render.hidden.hint": "Hidden line",
|
||||
"topbar.render.hintDisabled": "Render mode applies in perspective",
|
||||
// Display style (context-dependent dropdown): plan = Color/Mono,
|
||||
// perspective = Shaded/White/Wireframe/Hidden.
|
||||
"display.style": "Display",
|
||||
"display.style.group": "Display style",
|
||||
"display.style.hint": "Display style of the active view",
|
||||
"display.style.color": "Color",
|
||||
"display.style.mono": "Black & white",
|
||||
"display.style.shaded": "Shaded",
|
||||
"display.style.white": "White",
|
||||
"display.style.wireframe": "Wireframe",
|
||||
"display.style.hidden": "Hidden line",
|
||||
|
||||
"topbar.referenceLinesGroup": "Reference lines",
|
||||
"topbar.referenceLines": "Reference lines",
|
||||
"topbar.referenceLines.hint": "Show/hide reference lines (wall axes)",
|
||||
"topbar.referenceLines.hintDisabled": "Reference lines apply in the plan",
|
||||
|
||||
"topbar.resources": "Resources",
|
||||
"topbar.resources.hint": "Show/hide the resources window",
|
||||
|
||||
// Layout menu.
|
||||
"layout.title": "Layout",
|
||||
"layout.placeholder": "Layout …",
|
||||
"layout.saveCurrent": "+ Save current …",
|
||||
"layout.loadGroup": "Load",
|
||||
"layout.deleteGroup": "Delete",
|
||||
"layout.savePrompt": "Save layout as:",
|
||||
|
||||
// Visibility combinations (topbar).
|
||||
"combo.layers": "Layer comb.",
|
||||
"combo.drawings": "Drawing comb.",
|
||||
"combo.placeholder": "Combination …",
|
||||
"combo.saveCurrent": "+ Save current …",
|
||||
"combo.loadGroup": "Load",
|
||||
"combo.deleteGroup": "Delete",
|
||||
"combo.layers.title": "Layer combinations",
|
||||
"combo.drawings.title": "Drawing combinations",
|
||||
"combo.layers.savePrompt": "Save layer combination as:",
|
||||
"combo.drawings.savePrompt": "Save drawing combination as:",
|
||||
|
||||
// Drawing tools (topbar toolbar + status hints).
|
||||
"tool.group": "Tools",
|
||||
"tool.select": "Select",
|
||||
"tool.wall": "Wall",
|
||||
"tool.line": "Line",
|
||||
"tool.polyline": "Polyline",
|
||||
"tool.rect": "Rectangle",
|
||||
"tool.select.hint": "Select — click/drag elements",
|
||||
"tool.wall.firstPoint": "Wall: set first axis point",
|
||||
"tool.wall.nextPoint": "Wall: next point — double/right-click to finish",
|
||||
"tool.line.firstPoint": "Line: set start point",
|
||||
"tool.line.secondPoint": "Line: set end point",
|
||||
"tool.polyline.firstPoint": "Polyline: set first point",
|
||||
"tool.polyline.nextPoint": "Polyline: next point — click start to close, double-click to finish",
|
||||
"tool.rect.firstCorner": "Rectangle: set first corner",
|
||||
"tool.rect.secondCorner": "Rectangle: set opposite corner",
|
||||
"tool.wallType": "Wall type",
|
||||
"tool.layer": "Layer",
|
||||
"tool.layer.hint": "Active layer — everything drawn goes onto this category",
|
||||
"tool.floorOnlyDisabled": "Walls can only be drawn on a floor",
|
||||
"tool.snap": "Snap",
|
||||
"tool.snap.hint": "Snap to endpoints/grid; Shift = ortho, Ctrl = snap off",
|
||||
"snap.enabled": "Snap on",
|
||||
"snap.endpoint": "Endpoint",
|
||||
"snap.midpoint": "Midpoint",
|
||||
"snap.intersection": "Intersection",
|
||||
"snap.onEdge": "On edge (perp.)",
|
||||
"snap.grid": "Grid",
|
||||
"snap.ortho": "Ortho (Shift)",
|
||||
"snap.gridSize": "Grid size (m)",
|
||||
"snap.angleStep": "Angle step",
|
||||
|
||||
// Transform (move/mirror/rotate) + mode bar.
|
||||
"transform.bar": "Transform",
|
||||
"transform.cancel": "Cancel (Esc)",
|
||||
"transform.countPrompt": "Number of copies:",
|
||||
"transform.move": "Move (M)",
|
||||
"transform.mirror": "Mirror (S)",
|
||||
"transform.rotate": "Rotate (D)",
|
||||
"transform.mode.move": "Move",
|
||||
"transform.mode.copy": "Copy",
|
||||
"transform.mode.array": "N copies",
|
||||
"transform.mode.distribute": "Distribute",
|
||||
"transform.hint.move.0": "Click base point",
|
||||
"transform.hint.move.1": "Click destination point",
|
||||
"transform.hint.rotate.0": "Click rotation centre",
|
||||
"transform.hint.rotate.1": "Click reference point (start angle)",
|
||||
"transform.hint.rotate.2": "Click target angle",
|
||||
"transform.hint.mirror.0": "First point of mirror axis",
|
||||
"transform.hint.mirror.1": "Second point of mirror axis",
|
||||
|
||||
// Line display (Display/Print).
|
||||
"topbar.lineModeGroup": "Line display",
|
||||
"topbar.lineMode.display": "Display",
|
||||
"topbar.lineMode.print": "Print",
|
||||
"topbar.lineMode.display.hint": "Display: all lines as constant hairlines (calm editing)",
|
||||
"topbar.lineMode.print.hint": "Print: real mm line weights (paper/print look)",
|
||||
|
||||
// Status bar.
|
||||
"status.selection": "Selection",
|
||||
"status.selectionN": "Selection: {n} {noun}",
|
||||
"status.wall": "wall",
|
||||
"status.walls": "walls",
|
||||
"status.xy": "X/Y",
|
||||
"status.unit": "Unit",
|
||||
"status.scale": "Scale",
|
||||
"status.zoom": "Zoom",
|
||||
"status.floor": "Floor",
|
||||
"status.layer": "Layer",
|
||||
"status.none": "—",
|
||||
|
||||
// Navigator panels.
|
||||
"nav.drawingLevels": "Drawing levels",
|
||||
"nav.layers": "Layers",
|
||||
"nav.tools": "Tools",
|
||||
"nav.attributes": "Attributes",
|
||||
"nav.objectInfo": "Object Info",
|
||||
|
||||
// Attribute-Palette (AttributesPanel)
|
||||
"attr.title": "Attributes",
|
||||
"attr.empty": "No selection",
|
||||
"attr.stroke": "Pen",
|
||||
"attr.color": "Color",
|
||||
"attr.weight": "Line weight (mm)",
|
||||
"attr.lineStyle": "Line style",
|
||||
"attr.fill": "Fill",
|
||||
"attr.fillColor": "Fill color",
|
||||
"attr.clearFill": "Remove fill color",
|
||||
"attr.hatch": "Hatch",
|
||||
"attr.none": "none",
|
||||
"attr.inheritedFromLayer": "Walls inherit line weight from the layer",
|
||||
"attr.fillNeedsClosed": "Fill only for closed shapes",
|
||||
"attr.size": "Size",
|
||||
"attr.width": "Width",
|
||||
"attr.height": "Height",
|
||||
|
||||
// Objekt-Info-Palette (ObjectInfoPanel)
|
||||
"objinfo.title": "Object Info",
|
||||
"objinfo.empty": "No object selected",
|
||||
"objinfo.refpoint": "Reference point",
|
||||
"objinfo.setRefpoint": "Set reference point",
|
||||
"objinfo.x": "X",
|
||||
"objinfo.y": "Y",
|
||||
"objinfo.z": "Z",
|
||||
"objinfo.zHint": "2D layer – elements have no height",
|
||||
"objinfo.dimensions": "Dimensions",
|
||||
"objinfo.width": "Width",
|
||||
"objinfo.height": "Height",
|
||||
"objinfo.type": "Type",
|
||||
"objinfo.kind.wall": "Wall",
|
||||
"objinfo.kind.drawing2d": "2D object",
|
||||
"objinfo.kind.door": "Door",
|
||||
// ── Wall attributes (object info panel) ──────────────────────────────────
|
||||
"objinfo.wall.section": "Wall",
|
||||
"objinfo.wall.refLine": "Reference line",
|
||||
"objinfo.wall.refLine.left": "Exterior (left)",
|
||||
"objinfo.wall.refLine.center": "Center",
|
||||
"objinfo.wall.refLine.right": "Interior (right)",
|
||||
"objinfo.wall.buildup": "Build-up",
|
||||
"objinfo.wall.single": "Single layer",
|
||||
"objinfo.wall.multi": "Multi layer",
|
||||
"objinfo.wall.thickness": "Thickness",
|
||||
"objinfo.wall.preset": "Wall style",
|
||||
"objinfo.wall.presetLabel": "{name} · {thickness} m",
|
||||
"objinfo.wall.refFloor": "Reference floor",
|
||||
"objinfo.wall.linkAbove": "Bind to floor above",
|
||||
"objinfo.wall.bottom": "Bottom (UK)",
|
||||
"objinfo.wall.top": "Top (OK)",
|
||||
"objinfo.wall.anchorFloor": "Bound to floor",
|
||||
"objinfo.wall.anchorCustom": "Custom height",
|
||||
"objinfo.wall.height": "Height",
|
||||
"objinfo.wall.floorAboveNone": "No floor above",
|
||||
"levels.addFloor": "+ Floor",
|
||||
"levels.addDrawing": "+ Drawing",
|
||||
"layers.addCategory": "+ Layer",
|
||||
"nav.visibility": "Visibility",
|
||||
"nav.hide": "Hide",
|
||||
"nav.show": "Show",
|
||||
"nav.categoryVisible": "{name} visible",
|
||||
"nav.categorySelect": "Make {name} the active layer (drawing target)",
|
||||
|
||||
// Badges.
|
||||
"badge.floor": "Floor",
|
||||
"badge.section": "Section",
|
||||
"badge.elevation": "Elevation",
|
||||
"badge.drawing": "Drawing",
|
||||
|
||||
// Display mode select.
|
||||
"display.title": "Display mode",
|
||||
"display.all_force": "Show all",
|
||||
"display.all": "Selected",
|
||||
"display.active": "Active only",
|
||||
"display.grey": "Others grey",
|
||||
"display.grey_locked": "Others grey & locked",
|
||||
|
||||
// Dock.
|
||||
"dock.resize": "Adjust width",
|
||||
"dock.dock": "Dock",
|
||||
"dock.close": "Close",
|
||||
"dock.float": "Float",
|
||||
"dock.redock": "Dock",
|
||||
"dock.resizePanel": "Resize",
|
||||
"dock.dropLeft": "Dock left",
|
||||
"dock.dropRight": "Dock right",
|
||||
|
||||
// Context menu.
|
||||
"ctx.layerSettings": "Layer settings…",
|
||||
"ctx.addSubLayer": "Add sub-layer…",
|
||||
"ctx.assignSelection": "Assign selection here",
|
||||
"ctx.assignSelection.disabled": "No wall selected — first click a wall in the plan/3D.",
|
||||
"ctx.duplicate": "Duplicate",
|
||||
"ctx.copyProps": "Copy properties",
|
||||
"ctx.pasteProps": "Paste properties",
|
||||
"ctx.pasteProps.disabled": "Clipboard empty — first use “Copy properties”.",
|
||||
"ctx.delete": "Delete",
|
||||
"ctx.delete.lastLayer": "The last layer cannot be deleted.",
|
||||
"ctx.delete.lastLevel": "The last drawing level cannot be deleted.",
|
||||
"ctx.levelSettings": "Settings…",
|
||||
"ctx.fitSelection": "Fit to selection",
|
||||
"ctx.clearSelection": "Clear selection",
|
||||
"ctx.fit": "Fit view",
|
||||
"ctx.noWallHit": "No wall hit",
|
||||
"ctx.noWallHit.hint": "Right-clicking a wall selects it and shows wall actions.",
|
||||
|
||||
"ctx.title.level": "Drawing level",
|
||||
"ctx.title.wall": "Wall",
|
||||
"ctx.title.view": "View",
|
||||
|
||||
// Inline editor.
|
||||
"editor.close": "Close",
|
||||
"editor.layerTitle": "Layer {code}",
|
||||
"editor.name": "Name",
|
||||
"editor.color": "Color",
|
||||
"editor.lineWeight": "Line weight",
|
||||
"editor.floorHeight": "Floor height",
|
||||
"editor.cutHeight": "Cut height",
|
||||
"editor.unit.mm": "mm",
|
||||
"editor.unit.m": "m",
|
||||
"editor.noHeightDrawing": "Drawings have no floor/cut height.",
|
||||
"editor.noHeightSection": "Sections/elevations have no floor/cut height.",
|
||||
|
||||
// Main content.
|
||||
"content.perspektiveTitle": "Perspective · {name}",
|
||||
"content.grundrissTitle": "Plan · {name}",
|
||||
"content.grundrissLegend": "Plan · {name} · Cut height {cutHeight}",
|
||||
"content.drawingTitle": "Drawing · {name}",
|
||||
"content.drawingCanvas": "Drawing canvas",
|
||||
"content.drawingLegend": "Free 2D drawing",
|
||||
"props.floorHeight": "Floor height",
|
||||
"props.cutHeight": "Cut height",
|
||||
"props.okff": "FFL",
|
||||
"props.okffValue": "+{value} m",
|
||||
|
||||
// Stub.
|
||||
"stub.section": "Section",
|
||||
"stub.elevation": "Elevation",
|
||||
"stub.note": "{kind} — derived projection follows in a later phase",
|
||||
|
||||
// Default names.
|
||||
"default.floorName": "Floor {n}",
|
||||
"default.drawingName": "Drawing {n}",
|
||||
"default.categoryName": "New layer",
|
||||
"default.subCategoryName": "New sub-layer",
|
||||
"default.componentName": "New component",
|
||||
"default.hatchName": "New hatch",
|
||||
"default.lineStyleName": "New line style",
|
||||
"default.hatchNone": "None",
|
||||
"default.copySuffixLevel": "{name} copy",
|
||||
"default.copySuffixLayer": "{name} COPY",
|
||||
"default.wallTypeSingle": "Wall {thickness} m",
|
||||
|
||||
// Alerts.
|
||||
"alert.layerInUse": "Layer “{code} {name}” is used by components and cannot be deleted.",
|
||||
"alert.componentInUse": "Component “{name}” is used by a wall type and cannot be deleted.",
|
||||
"alert.hatchInUse": "Hatch “{name}” is used by a component and cannot be deleted.",
|
||||
"alert.lineStyleInUse": "Line style “{name}” is used by a hatch and cannot be deleted.",
|
||||
|
||||
// Resource manager.
|
||||
"resources.title": "Resources",
|
||||
"resources.label": "Resource manager",
|
||||
"resources.close": "Close",
|
||||
"resources.tab.components": "Components",
|
||||
"resources.tab.hatches": "Hatches",
|
||||
"resources.tab.lines": "Lines",
|
||||
"resources.add": "New",
|
||||
"resources.import.lin": "⤓ Import .lin",
|
||||
"resources.import.pat": "⤓ Import .pat",
|
||||
|
||||
"resources.components.hint": "Higher priority runs through at the join (intersects first); lower butts against the side.",
|
||||
"resources.components.empty": "No components yet.",
|
||||
"resources.components.placeholder": "Component",
|
||||
"resources.col.name": "Name",
|
||||
"resources.col.color": "Color",
|
||||
"resources.col.hatch": "Hatch",
|
||||
"resources.col.prio": "Prio",
|
||||
"resources.col.prio.hint": "Higher priority runs through at the join",
|
||||
"resources.col.texture": "Texture",
|
||||
"resources.delete.component": "Delete component “{name}”",
|
||||
|
||||
"resources.hatches.hint": "Pattern, scale and angle drive the section hatch; the line style sets the weight of the pattern lines.",
|
||||
"resources.hatches.empty": "No hatches yet.",
|
||||
"resources.hatches.placeholder": "Hatch",
|
||||
"resources.col.pattern": "Pattern",
|
||||
"resources.col.scale": "Scale",
|
||||
"resources.col.angle": "Angle °",
|
||||
"resources.col.lineStyle": "Line style",
|
||||
"resources.lineStyle.none": "— none —",
|
||||
"resources.delete.hatch": "Delete hatch “{name}”",
|
||||
|
||||
"pattern.none": "None",
|
||||
"pattern.solid": "Solid",
|
||||
"pattern.insulation": "Insulation",
|
||||
"pattern.diagonal": "Diagonal",
|
||||
"pattern.crosshatch": "Crosshatch",
|
||||
|
||||
"resources.lines.hint": "Line weight in millimetres (paper space). Stroke: solid, dashed or dotted.",
|
||||
"resources.lines.empty": "No line styles yet.",
|
||||
"resources.lines.placeholder": "Line style",
|
||||
"resources.col.weight": "Weight (mm)",
|
||||
"resources.col.stroke": "Stroke",
|
||||
"resources.col.preview": "Preview",
|
||||
"resources.delete.lineStyle": "Delete line style “{name}”",
|
||||
"resources.texture.empty": "—",
|
||||
|
||||
"dash.solid": "Solid",
|
||||
"dash.dashed": "Dashed",
|
||||
"dash.dotted": "Dotted",
|
||||
|
||||
// Command line / commands (Rhino-style command system).
|
||||
"cmd.aria": "Command line",
|
||||
"cmd.idle.prompt": "Command:",
|
||||
"cmd.idle.placeholder": "Type a command … (Tab)",
|
||||
"cmd.line.label": "Line",
|
||||
"cmd.line.start": "Start of line:",
|
||||
"cmd.line.end": "End of line:",
|
||||
"cmd.polyline.label": "Polyline",
|
||||
"cmd.polyline.start": "Start point:",
|
||||
"cmd.polyline.next": "Next point:",
|
||||
"cmd.polyline.close": "Close",
|
||||
"cmd.polyline.undo": "Undo",
|
||||
"cmd.rect.label": "Rectangle",
|
||||
"cmd.rect.first": "First corner:",
|
||||
"cmd.rect.second": "Opposite corner:",
|
||||
"cmd.circle.label": "Circle",
|
||||
"cmd.circle.center": "Center:",
|
||||
"cmd.circle.radius": "Radius:",
|
||||
"cmd.move.label": "Move",
|
||||
"cmd.move.base": "Base point:",
|
||||
"cmd.move.target": "Target point:",
|
||||
"cmd.move.empty": "Nothing selected (select objects first).",
|
||||
"cmd.copy.label": "Copy",
|
||||
"cmd.copy.base": "Base point:",
|
||||
"cmd.copy.target": "Target point (Enter to finish):",
|
||||
"cmd.copy.empty": "Nothing selected (select objects first).",
|
||||
"cmd.offset.label": "Offset",
|
||||
"cmd.offset.pick": "Select curve:",
|
||||
"cmd.offset.side": "Side or distance:",
|
||||
// Edit tools Split / Join / Delete segment (keyboard: Ctrl+S / Ctrl+J /
|
||||
// Alt+Click). Labels for the command line / menus.
|
||||
"edit.split.label": "Split",
|
||||
"edit.join.label": "Join",
|
||||
"edit.cutSegment.label": "Delete segment",
|
||||
// Tab field cycle (precision input): ordered numeric fields per step.
|
||||
"cmd.field.length": "Length",
|
||||
"cmd.field.angle": "Angle",
|
||||
"cmd.field.width": "Width",
|
||||
"cmd.field.height": "Height",
|
||||
"cmd.field.radius": "Radius",
|
||||
"cmd.field.distance": "Distance",
|
||||
|
||||
// Commands: import / terrain.
|
||||
"cmd.import.label": "Import",
|
||||
"cmd.import.prompt": "Choose DXF file …",
|
||||
"cmd.terrain.label": "Terrain",
|
||||
"cmd.terrain.prompt": "Generate terrain from contours …",
|
||||
|
||||
// Site / context panel (SitePanel).
|
||||
"nav.site": "Terrain",
|
||||
"site.title": "Terrain & Context",
|
||||
"site.import": "⤓ Import DXF",
|
||||
"site.generateTerrain": "Generate terrain",
|
||||
"site.contourSet": "Contour set",
|
||||
"site.empty": "No context loaded. Import a DXF file (contour lines or mesh).",
|
||||
"site.delete": "Remove",
|
||||
"site.type.mesh": "Mesh",
|
||||
"site.type.contours": "Contours",
|
||||
"site.type.terrain": "Terrain",
|
||||
"site.dwgHint": "DWG? Convert it to DXF first with the free ODA File Converter.",
|
||||
"site.terrainFailed": "No terrain could be generated (too few/collinear contour points).",
|
||||
|
||||
// Import dialog.
|
||||
"import.title": "Import DXF",
|
||||
"import.close": "Close",
|
||||
"import.file": "File",
|
||||
"import.summary.heading": "Contents",
|
||||
"import.summary.contours": "{n} contours",
|
||||
"import.summary.meshes": "{n} meshes",
|
||||
"import.summary.layers": "Layers: {layers}",
|
||||
"import.summary.noLayers": "no layer names",
|
||||
"import.summary.empty": "No importable 2D geometry found.",
|
||||
"import.target.heading": "Target drawing level",
|
||||
"import.target.existing": "Import into existing drawing level",
|
||||
"import.target.new": "Create new drawing",
|
||||
"import.target.newNamePlaceholder": "New drawing name",
|
||||
"import.layers.heading": "Layer handling (DXF layers)",
|
||||
"import.layers.asCategories": "Keep DXF layers as categories",
|
||||
"import.layers.toActive": "Everything onto the active category ({code})",
|
||||
"import.mesh.heading": "Meshes",
|
||||
"import.mesh.asContext": "Import meshes as context geometry (3D)",
|
||||
"import.mesh.note": "Meshes are not 2D drawings — they go into the context layer.",
|
||||
"import.dwg.heading": "DWG file",
|
||||
"import.dwg.loading": "Reading DWG …",
|
||||
"import.dwg.hint":
|
||||
"DWG could not be read. Alternatively, convert the file to DXF with the free ODA File Converter, then import the DXF.",
|
||||
"import.confirm": "Import",
|
||||
"import.cancel": "Cancel",
|
||||
"import.badge.floor": "Floor",
|
||||
"import.badge.section": "Section",
|
||||
"import.badge.elevation": "Elevation",
|
||||
"import.badge.drawing": "Drawing",
|
||||
|
||||
// Drag & drop (app-wide file drop).
|
||||
"drop.hint": "Drop a DXF/DWG file here",
|
||||
|
||||
// Error boundary.
|
||||
"error.console": "Unexpected error:",
|
||||
"error.title": "Something went wrong",
|
||||
"error.body": "An unexpected error occurred. Details in the console.",
|
||||
"error.reload": "Reload",
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
// i18n-Schicht — eine einzige Übersetzungsfunktion `t(key, params?)` plus ein
|
||||
// optionaler React-Hook `useT`. Default-Sprache ist Deutsch; das deutsche
|
||||
// Wörterbuch (de.ts) hält die EXAKTEN bisherigen UI-Texte, sodass die Umstellung
|
||||
// optisch nichts ändert. en.ts beweist die Übersetzbarkeit.
|
||||
//
|
||||
// Bewusst minimal gehalten: ein modulweiter „current language" + Wörterbuch-
|
||||
// Lookup mit {param}-Interpolation. Kein Provider-Zwang — t(...) ist überall
|
||||
// direkt aufrufbar; useT() liefert dieselbe Funktion und re-rendert Komponenten
|
||||
// beim Sprachwechsel (subscribe), falls je ein Umschalter gebaut wird.
|
||||
//
|
||||
// Identifier/Keys bleiben englisch (DOSSIER-Namespacing); nur die Wörterbuch-
|
||||
// Werte sind übersetzbarer Text.
|
||||
|
||||
import { useSyncExternalStore } from "react";
|
||||
import { de } from "./de";
|
||||
import { en } from "./en";
|
||||
import type { TranslationKey } from "./de";
|
||||
|
||||
export type { TranslationKey } from "./de";
|
||||
|
||||
/** Unterstützte Sprachen. Default ist „de". */
|
||||
export type Language = "de" | "en";
|
||||
|
||||
/** Wörterbücher je Sprache. de ist die Quelle der Keys (Default-Sprache). */
|
||||
const DICTS: Record<Language, Record<TranslationKey, string>> = { de, en };
|
||||
|
||||
/** Werte für die Platzhalter-Interpolation (`{name}` → params.name). */
|
||||
export type TParams = Record<string, string | number>;
|
||||
|
||||
// ── Modulweiter Sprachzustand + Abonnenten (für useT) ──────────────────────
|
||||
|
||||
let currentLanguage: Language = "de";
|
||||
const listeners = new Set<() => void>();
|
||||
|
||||
/** Aktuell gewählte Sprache. */
|
||||
export function getLanguage(): Language {
|
||||
return currentLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sprache umschalten. Benachrichtigt abonnierte Komponenten (useT), damit sie
|
||||
* mit den neuen Texten neu rendern. (Noch kein UI-Umschalter — die Naht ist
|
||||
* aber vorhanden und verdrahtet.)
|
||||
*/
|
||||
export function setLanguage(lang: Language): void {
|
||||
if (lang === currentLanguage) return;
|
||||
currentLanguage = lang;
|
||||
for (const l of listeners) l();
|
||||
}
|
||||
|
||||
// ── Kern: Lookup + Interpolation ───────────────────────────────────────────
|
||||
|
||||
/** Ersetzt `{name}`-Platzhalter im Wert durch die übergebenen Parameter. */
|
||||
function interpolate(value: string, params?: TParams): string {
|
||||
if (!params) return value;
|
||||
return value.replace(/\{(\w+)\}/g, (match, name: string) =>
|
||||
name in params ? String(params[name]) : match,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Übersetzt einen Key in der aktuellen Sprache mit optionaler {param}-
|
||||
* Interpolation. Fehlt der Key in der gewählten Sprache, greift Deutsch als
|
||||
* Fallback; fehlt er auch dort, wird der Key selbst zurückgegeben (sichtbar,
|
||||
* damit fehlende Texte auffallen statt leer zu bleiben).
|
||||
*/
|
||||
export function t(key: TranslationKey | string, params?: TParams): string {
|
||||
const dict = DICTS[currentLanguage];
|
||||
const value =
|
||||
(dict as Record<string, string>)[key] ??
|
||||
(de as Record<string, string>)[key] ??
|
||||
key;
|
||||
return interpolate(value, params);
|
||||
}
|
||||
|
||||
// ── React-Hook ─────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Hook-Variante: liefert dieselbe `t`-Funktion, abonniert aber den
|
||||
* Sprachzustand, sodass die Komponente beim Sprachwechsel neu rendert. In den
|
||||
* meisten Komponenten reicht der direkte `t`-Import; useT() ist für den Fall
|
||||
* gedacht, dass ein Live-Sprachumschalter existiert.
|
||||
*/
|
||||
export function useT(): typeof t {
|
||||
useSyncExternalStore(
|
||||
(cb) => {
|
||||
listeners.add(cb);
|
||||
return () => listeners.delete(cb);
|
||||
},
|
||||
getLanguage,
|
||||
getLanguage,
|
||||
);
|
||||
return t;
|
||||
}
|
||||
Reference in New Issue
Block a user