mirror of
https://github.com/hansjone/netx.git
synced 2026-10-16 01:50:45 +08:00
Structure
- pages/ -> features/<domain>/{Page, components, hooks, lib}; 95 files moved,
333 imports rewritten, verified with tsc.
- services/api.ts -> services/api/<domain>.ts (250 exports preserved),
types.ts -> types/<domain>.ts, i18n zh/en -> locales/<lang>/<namespace>.ts
(2696 messages deep-equal before/after).
- ESLint rule: shared layers must not import features/.
Styles
- index.css (16k lines) split losslessly into styles/{base,layout,components,
pages,legacy,theme}; compiled CSS was byte-identical before tokenizing.
- ~930 hard-coded colors replaced by --nx-* tokens (theme/tokens.css); WebCRT
off-palette colors unified; fixed dark-on-dark text introduced by mapping.
- theme/theme.css: modern blue design language (rounded shapes, gradients,
unified buttons/fields/tables/modals), form-grid alignment fix, flat nav list
without tree indent, soft selected state instead of left accent bar.
Docs: WEB.md documents code structure and style rules.
Not touched: the large Biz*/Webcrt/Topology page components (to be split later).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
344 lines
15 KiB
TypeScript
344 lines
15 KiB
TypeScript
const topology = {
|
|
title: "Topology",
|
|
maps: "Maps",
|
|
tree: "Topology tree",
|
|
treeLoading: "Loading tree…",
|
|
treeLoadFailed: "Failed to load topology tree",
|
|
treeRetry: "Retry",
|
|
graphLoading: "Loading topology…",
|
|
graphLoadFailed: "Failed to load topology",
|
|
graphRefreshing: "Refreshing…",
|
|
canvasEmpty: "No NEs on this map yet",
|
|
canvasEmptyHint: "Use Add NE, or pick a region that already has devices.",
|
|
treeHint: "Top level is a Root (nav only); its unique Root Map is the canvas. Open the root map or a sub-region to edit devices.",
|
|
treeSearch: "Search NEs across maps",
|
|
treeSearchPh: "Name / IP",
|
|
treeSearchEmpty: "No matching NEs",
|
|
treeSearchNoViews: "Not on any map",
|
|
treeSearchNotOnMap: "This NE is not placed on any topology map yet",
|
|
locateNotOnCanvas:
|
|
"This NE is missing from the world-map sample and has no world coordinates. Open a region map instead.",
|
|
treeSearchViewCount: "{{count}} map(s)",
|
|
treeSearchTruncated: "Showing first 30 of {{total}}",
|
|
rootName: "Roots",
|
|
selectRegion: "Select a root or region",
|
|
openMap: "Open map",
|
|
openRegion: "Open",
|
|
kindPhysical: "Physical",
|
|
kindCustom: "Custom",
|
|
layerNodeHint: "{{count}} NE(s)",
|
|
layerNodeEmpty: "Click to create & open",
|
|
rootCanvasHint: "Pick a root from the left tree.",
|
|
regionCanvasHint: "Open the root map to edit devices; create sub-regions on that canvas.",
|
|
regionBrowseHint: "Root folder: unique root map below. Click to open.",
|
|
browserTitle: "Topology folder",
|
|
browserRegionSub: "{{count}} map(s)",
|
|
browserRegionsSub: "{{count}} item(s)",
|
|
browserEmptyMaps: "No root map under this root yet.",
|
|
addNe: "Add NE",
|
|
more: "More",
|
|
backUp: "Back",
|
|
newRegion: "New root",
|
|
newRegionName: "New root",
|
|
newRegionPrompt: "Root name",
|
|
newSubRegion: "New sub-region",
|
|
newSubRegionName: "New sub-region",
|
|
newSubRegionPrompt: "Sub-region name",
|
|
subRegionNotOnFlat: "The world map has no regions. Create sub-regions on World or a lower-level canvas.",
|
|
worldMapNoDirectNes: "Cannot add NEs on the world map — add them on a sub-region canvas.",
|
|
worldMapName: "World map",
|
|
worldMapOffline: "World map is temporarily offline",
|
|
rootMapName: "Root map",
|
|
worldHud: "World {{total}} · close-up {{cached}} · z{{zoom}} · {{lod}}",
|
|
worldEmptyCoords: "World map has no coordinates yet",
|
|
worldEmptyCoordsHint:
|
|
"Dock has {{dock}} NEs, but Fabric / world coords are empty. Apply without pulling UME.",
|
|
worldApply: "Apply to world map",
|
|
worldApplying: "Applying…",
|
|
worldApplyOk: "Applied to world map",
|
|
subRegionNeedParent: "Open a root map or region canvas first, then create a sub-region.",
|
|
regionCreated: "Created",
|
|
regionDeleted: "Deleted",
|
|
deleteRegion: "Delete",
|
|
deleteRegionConfirm: "Delete \"{{name}}\"? Its maps will also be deleted.",
|
|
deleteUmeWorldConfirm:
|
|
"Delete \"{{name}}\"? This cascades all UME regions and maps under it. A later UME topology apply may recreate it.",
|
|
renameRegion: "Rename",
|
|
renameRegionPrompt: "Name",
|
|
regionRenamed: "Renamed",
|
|
collapseRegion: "Collapse",
|
|
expandRegion: "Expand",
|
|
newCustom: "Custom map",
|
|
newCustomName: "Custom topology",
|
|
newCustomPrompt: "Custom map name",
|
|
folderHint: "Creating a root auto-creates its unique root map. Add sub-regions on that canvas.",
|
|
folderHintShort: "Root folder",
|
|
outsidePeers: "{{count}} outside peer(s) linked but not on this map",
|
|
outsidePeersView: "Off-map NEs {{count}}",
|
|
outsidePeersTitle: "Outside peers",
|
|
outsidePeersHint: "Linked to this map but not placed. Select and add only what you need.",
|
|
outsidePeersVia: "via {{name}}",
|
|
outsidePeersFilterPh: "Filter: name / IP / via",
|
|
outsidePeersEmpty: "No matching outside peers",
|
|
projectNeighbors: "Project neighbors",
|
|
projectedNeighbors: "Projected {{count}} neighbor(s) onto the map",
|
|
localBrowserOnly: "this browser only",
|
|
deleteEdgeConfirm:
|
|
"Remove selected link(s) from the canvas? They are deleted from Fabric only when you Save. LLDP may recreate them on the next collect.",
|
|
edgeDeleted: "Queued {{count}} link delete(s) — Save to apply",
|
|
discoverCancelled: "Discovery cancelled",
|
|
truncatedMembership: "Membership cap reached; some neighbors were not placed. Use classify or a new map.",
|
|
truncatedFrozen: "This map membership is frozen; neighbors cannot be projected. Unfreeze via classify workflow or create a new map.",
|
|
truncatedNodes: "Too many view nodes; display truncated. Narrow membership or create another map.",
|
|
truncatedEdges: "Too many edges; display truncated. Filter status or create another map.",
|
|
truncatedGeneric: "Graph data truncated. Narrow scope or create another map.",
|
|
deleteSelectionConfirm:
|
|
"Remove {{nodes}} NE(s) from this map and {{edges}} link(s)? Link deletes apply on Save; NE remove from map applies on Save.",
|
|
selectionDeleted: "Queued: remove {{nodes}} NE(s), delete {{edges}} link(s) — Save to apply",
|
|
newMap: "New",
|
|
newMapName: "New topology",
|
|
rename: "Rename",
|
|
renamePrompt: "Topology map name",
|
|
renameHint: "Double-click to rename",
|
|
renamed: "Topology map renamed",
|
|
deleteMap: "Delete map",
|
|
deleteMapConfirm: "Delete map \"{{name}}\"? Nodes and edges will be removed.",
|
|
emptyMaps: "No roots yet. Create a root first.",
|
|
palette: "NE library",
|
|
paletteHint: "Select multiple to add in batch, or drag one onto the canvas",
|
|
paletteDragHint: "Drag onto canvas to add",
|
|
selectAllVisible: "Select all visible",
|
|
addSelected: "Add selected ({{count}})",
|
|
addSelectedDone: "Added {{count}} NE(s)",
|
|
addingNe: "Adding…",
|
|
filterPh: "Type to filter: name / IP / vendor",
|
|
save: "Save",
|
|
saveDirty: "Save *",
|
|
unsavedConfirm: "You have unsaved changes. Discard and switch maps?",
|
|
saving: "Saving…",
|
|
saved: "Topology saved",
|
|
saveFailed: "Save failed: {{detail}}",
|
|
readOnlyBanner: "Read-only (ne:write scope required to edit)",
|
|
readOnlyHint: "Read-only — no write permission",
|
|
discoverTimeout: "Discovery timed out; check LLDP tasks for progress",
|
|
policySyncFailed: "Failed to sync LLDP policy; local toggle still applies to canvas discovery",
|
|
discover: "Discover links",
|
|
discovering: "Discovering…",
|
|
discoverOne: "Discover links",
|
|
discovered: "Discovery done: +{{added}} updated {{updated}} missing {{stale}}",
|
|
discoverFail: "Discovery failed: {{detail}}",
|
|
discoverOneNeedNe: "This node is not linked to a scannable NE",
|
|
selectMap: "Select or create a topology map",
|
|
renameNode: "Rename",
|
|
renameNodePrompt: "Node display name",
|
|
sourcePort: "Local port",
|
|
targetPort: "Remote port",
|
|
endpointA: "Endpoint A",
|
|
endpointB: "Endpoint B",
|
|
port: "port",
|
|
expandPhysicalLinks: "Expand physical links",
|
|
scaleBundleWidth: "Thicken bundles by link count",
|
|
linkMembers: "Physical members ({{count}})",
|
|
canvasHint:
|
|
"Left tree lists regions; add maps yourself, then open a map to edit devices with Add NE and save positions.",
|
|
selected: "Selected",
|
|
selectedEdge: "Selected edge",
|
|
selectedCount: "{{count}} selected",
|
|
toolModes: "Edit modes",
|
|
toolSelect: "Select",
|
|
toolPan: "Pan",
|
|
toolDrag: "Drag",
|
|
toolConnect: "Connect",
|
|
layout: "Layout",
|
|
layoutHierarchicalTb: "Hierarchical · top-bottom",
|
|
layoutHierarchicalLr: "Hierarchical · left-right",
|
|
layoutForce: "Force-directed",
|
|
layoutGrid: "Grid",
|
|
layoutRadial: "Radial",
|
|
layoutSelected: "Selected only (hierarchical)",
|
|
layoutNeedSelection: "Select nodes to lay out first",
|
|
align: "Align",
|
|
alignLeft: "Align left",
|
|
alignRight: "Align right",
|
|
alignTop: "Align top",
|
|
alignBottom: "Align bottom",
|
|
alignHCenter: "Align center X",
|
|
alignVCenter: "Align center Y",
|
|
alignHDistribute: "Distribute horizontally",
|
|
alignVDistribute: "Distribute vertically",
|
|
alignNeedSelection: "Select at least two nodes",
|
|
snapGrid: "Snap to grid",
|
|
autoLayoutDiscover: "Auto-layout after discover",
|
|
discoverAutoAddUnmatched: "Auto-add unmatched NEs as placeholders on discover",
|
|
discoverProjectNeighbors:
|
|
"After discover, project neighbors of scanned NEs onto the canvas (Save to keep permanently)",
|
|
undo: "Undo",
|
|
redo: "Redo",
|
|
discoverSelected: "Discover links ({{count}})",
|
|
removeSelected: "Remove selected ({{count}})",
|
|
openWebcrt: "Open terminal",
|
|
openNe: "NE details",
|
|
openAlarms: "View alarms",
|
|
noAlarmLink: "Cannot build an alarm filter for this node",
|
|
removeNode: "Remove from canvas",
|
|
deletePlaceholder: "Delete placeholder",
|
|
deletePlaceholderConfirm:
|
|
"Permanently delete this placeholder NE (inventory + Fabric links)? This cannot be undone with canvas Undo.",
|
|
deletePlaceholderDone: "Placeholder deleted",
|
|
removeEdge: "Delete edge",
|
|
nodeMenu: "Node",
|
|
paneMenu: "Canvas",
|
|
edgeMenu: "Edge",
|
|
createNe: "New NE",
|
|
createNeModeHint:
|
|
"Create a full managed NE, or a topology placeholder (credentials can be filled later).",
|
|
createNeManaged: "Managed NE",
|
|
createNeManagedHint: "Same full form as NE management; placed on the canvas after create.",
|
|
createNePlaceholder: "Placeholder NE",
|
|
createNePlaceholderHint: "Name/IP only; topology placeholder for sketching first.",
|
|
createNeTitle: "New topology placeholder NE",
|
|
createNeHint:
|
|
"Source is topology placeholder. Complete login via WebCRT, or promote in NE management.",
|
|
createNeName: "Name",
|
|
createNeNamePh: "e.g. SW-CORE-01",
|
|
createNeNameRequired: "NE name is required",
|
|
createNeIp: "IP (optional)",
|
|
createNeIpPh: "Can fill later during setup",
|
|
createNeDone: "Created placeholder {{name}}",
|
|
createManagedNeDone: "Created and placed {{name}}",
|
|
createManagedNePlaceFailed:
|
|
"{{name}} was created in inventory, but placing on the map failed: {{error}}. Add it again from NE management or the sidebar.",
|
|
createManagedNePosFailed:
|
|
"{{name}} is on the map, but could not move to the click position (kept default layout coords)",
|
|
createNeBusy: "Creating…",
|
|
connectTest: "Connectivity test",
|
|
connectTestSelected: "Connectivity test ({{count}})",
|
|
connectTestNeedManaged: "Node is not linked to a managed NE; cannot run connectivity test",
|
|
connectTestSkipped: "skipped {{count}} without managed link",
|
|
selectionMenu: "Selection",
|
|
edgeStyle: "Edge style",
|
|
edgeColor: "Color",
|
|
edgeLineStyle: "Line",
|
|
edgeLineSolid: "Solid",
|
|
edgeLineDashed: "Dashed",
|
|
edgeLineDotted: "Dotted",
|
|
edgeWidth: "Width",
|
|
edgeStyleReset: "Reset style",
|
|
edgeDefaults: "Default edge styles",
|
|
edgeDefaultsReset: "Factory reset",
|
|
noNeLink: "Not linked to a managed NE",
|
|
completeNeFirst:
|
|
"Login details are incomplete (vendor, hop/proxy, etc. belong in NE inventory). Complete the NE first, then open the terminal.",
|
|
edgeManual: "Manual",
|
|
edgeUme: "UME",
|
|
edgeDiscovered: "LLDP",
|
|
edgeStale: "Missing",
|
|
fit: "Fit view",
|
|
export: "Export",
|
|
exportSvg: "SVG vector",
|
|
exportXml: "XML data",
|
|
exporting: "Exporting…",
|
|
exportEmpty: "Nothing on the canvas to export",
|
|
exportedSvg: "SVG exported",
|
|
exportedXml: "XML exported",
|
|
exportFailed: "Export failed: {{detail}}",
|
|
liveSync: "Live sync",
|
|
liveSyncOn: "Syncing…",
|
|
liveSyncHint: "Poll the tree about every 5s and the open map every 3s (watch MCP create/draw). Off by default",
|
|
fullscreen: "Fullscreen",
|
|
exitFullscreen: "Exit fullscreen",
|
|
display: "Display",
|
|
canvasBg: "Canvas background",
|
|
canvasBgColor: "Background color",
|
|
canvasBgReset: "Reset default",
|
|
textColors: "Text colors",
|
|
textColorsReset: "Reset default",
|
|
labelColor: "NE name",
|
|
edgeLabelColor: "Link numbers",
|
|
vendorColors: "Vendor icon colors",
|
|
vendorColorsReset: "Reset default",
|
|
vendorTone: {
|
|
cisco: "Cisco",
|
|
huawei: "Huawei",
|
|
zte: "ZTE",
|
|
juniper: "Juniper",
|
|
nokia: "Nokia",
|
|
ericsson: "Ericsson",
|
|
h3c: "H3C",
|
|
ruijie: "Ruijie",
|
|
mikrotik: "MikroTik",
|
|
gray: "Unknown / unmanaged",
|
|
},
|
|
hideIp: "Hide IP",
|
|
hideVendor: "Hide vendor",
|
|
showPlaceholderBadge: "Show placeholder badge (TOPO/LLDP)",
|
|
showConnectStatus: "Show connect-status dots",
|
|
showAlarmOverlay: "Show alarm overlay",
|
|
showLevelColors: "Color by classify level",
|
|
levelUnmatched: "Unclassified",
|
|
level: {
|
|
external: "External",
|
|
core: "Core",
|
|
aggregation: "Aggregation",
|
|
access: "Access",
|
|
edge: "Edge",
|
|
},
|
|
hidePorts: "Hide ports",
|
|
edgeFlow: "Edge flow",
|
|
collapseSidebar: "Collapse sidebar",
|
|
expandSidebar: "Expand sidebar",
|
|
resizeSidebar: "Drag to resize sidebar",
|
|
hideAdded: "Hide added",
|
|
paletteEmpty: "No matching NEs.",
|
|
paletteHiddenAll: "Added NEs are hidden; uncheck to show them again.",
|
|
paletteSource: "NE source",
|
|
paletteManaged: "Managed",
|
|
paletteUme: "UME",
|
|
paletteLoading: "Loading…",
|
|
discoverReport: "Discovery progress",
|
|
discoverClose: "Close",
|
|
discoverCancel: "Cancel discovery",
|
|
discoverProgress: "Scanning {{count}} managed NE(s) on the map (serial LLDP; please wait)…",
|
|
discoverProgressLive: "Scanning {{index}}/{{total}}: {{name}}",
|
|
discoverSummary: "Scanned {{scanned}} · added {{added}} · updated {{updated}} · missing {{stale}} · failed {{failed}}",
|
|
discoverNeOk: "neighbors {{neighbors}} · added {{added}} · updated {{updated}}",
|
|
discoverNeFail: "Collect failed",
|
|
discoverUnmatched: "unmatched {{count}}",
|
|
discoverUnmatchedMore: "{{count}} more not listed",
|
|
discoverVendorRequired: "Vendor/device type missing; skipped LLDP command",
|
|
discoverParserStub: "Parser \"{{parser}}\" is still a stub; output was collected but neighbors were not parsed",
|
|
discoverNoTargets:
|
|
"No scannable NEs on the map. Add managed NEs, or UME NEs with a CLI connect profile.",
|
|
discoverViewDetail: "Detail",
|
|
discoverLinkCount: "{{count}} link(s)",
|
|
discoverLinksTitle: "Matched links ({{count}})",
|
|
discoverLinksEmpty: "No on-map peer links matched in this scan.",
|
|
discoverUnmatchedTitle: "Unmatched neighbors ({{count}})",
|
|
discoverUnmatchedEmpty: "No unmatched neighbors.",
|
|
discoverColPeer: "Peer NE",
|
|
discoverColRemote: "Neighbor",
|
|
discoverColLocalPort: "Local port",
|
|
discoverColRemotePort: "Remote port",
|
|
discoverColProtocol: "Protocol",
|
|
discoverColAction: "Result",
|
|
discoverLinkAdded: "Added",
|
|
discoverLinkUpdated: "Updated",
|
|
discoverLinkKeptManual: "Kept manual",
|
|
discoverLocatePeer: "Locate peer",
|
|
discoverLocateNe: "Locate NE",
|
|
discoverRawPreview: "Raw output preview (truncated when long; parsing uses full output)",
|
|
discoverGoLldp: "Details → LLDP links",
|
|
findNode: "Find",
|
|
findNodePh: "Type to search: name / IP / vendor",
|
|
findNoMatch: "No matching node on the canvas",
|
|
findMore: "{{count}} more matches…",
|
|
locateOnCanvas: "Click to locate on canvas",
|
|
openPortTraffic: "Open port traffic",
|
|
removeStale: "Clear missing ({{count}})",
|
|
removeStaleHint:
|
|
"Queue delete of red missing edges (applies on Save); scheduled collect also purges after 4 consecutive misses",
|
|
staleRemoved: "Queued {{count}} missing edge delete(s) — Save to apply",
|
|
connectHint: "Connect mode: drag from the NE center anchor to the target (Esc or Select to exit)",
|
|
};
|
|
|
|
export default topology;
|