mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 06:40:45 +08:00
1836 lines
70 KiB
TypeScript
1836 lines
70 KiB
TypeScript
const en = {
|
|
common: {
|
|
help: "Help",
|
|
refresh: "Refresh",
|
|
refreshing: "Refreshing…",
|
|
query: "Search",
|
|
clearFilters: "Clear filters",
|
|
prevPage: "Previous",
|
|
nextPage: "Next",
|
|
perPage: "{{n}}/page",
|
|
pagerMeta: "{{total}} items · page {{page}}/{{pages}}",
|
|
opFailed: "Operation failed",
|
|
empty: "-",
|
|
cancel: "Cancel",
|
|
},
|
|
workbench: {
|
|
title: "Workbench",
|
|
modules: "Modules",
|
|
sections: "Sections",
|
|
moduleCount: "{{count}} modules",
|
|
backToWorkbench: "Back to Workbench",
|
|
openInNewTab: "Open in new tab",
|
|
openModule: "Open or switch to this module tab",
|
|
monitoring: "System integration",
|
|
operations: "Operations",
|
|
system: "System",
|
|
welcomeEyebrow: "Workbench",
|
|
welcomeTitle: "Welcome back, {{name}}",
|
|
welcomeSub: "Monitor sync, topology, and ops tasks from one place.",
|
|
today: "Today · {{date}}",
|
|
kpi: {
|
|
uptime: "API uptime",
|
|
health: "System health",
|
|
tasks: "Active tasks",
|
|
healthOk: "Schedulers healthy",
|
|
healthWarn: "Check schedulers",
|
|
healthUnknown: "Metrics unavailable",
|
|
},
|
|
statusTitle: "Runtime status",
|
|
announceTitle: "Announcements",
|
|
recentTitle: "Recent operations",
|
|
recentMore: "View all",
|
|
quickTitle: "Quick actions",
|
|
emptyRecent: "No recent audit entries.",
|
|
gauge: {
|
|
cpu: "CPU",
|
|
mem: "Memory",
|
|
storage: "Storage",
|
|
storageUsed: "Used",
|
|
storageUnavailable: "Unavailable",
|
|
cli: "CLI budget",
|
|
db: "DB pool",
|
|
webcrt: "WebCRT",
|
|
tasks: "Active tasks",
|
|
low: "Low load",
|
|
normal: "Normal",
|
|
high: "Busy",
|
|
},
|
|
quick: {
|
|
tasks: "Task overview",
|
|
logs: "Audit logs",
|
|
users: "User admin",
|
|
apiKeys: "API keys",
|
|
sessions: "Sessions",
|
|
},
|
|
announce: {
|
|
a1: "Dark workbench shell is live — other modules follow the same palette.",
|
|
a1Date: "2026-08-04",
|
|
a2: "LLDP collect supports pause / resume / stop; interrupted jobs resume after restart.",
|
|
a2Date: "2026-08-04",
|
|
a3: "Config sync and LLDP KPI boards refresh while jobs are running.",
|
|
a3Date: "2026-08-03",
|
|
},
|
|
recentCols: {
|
|
action: "Action",
|
|
module: "Module",
|
|
time: "Time",
|
|
user: "User",
|
|
},
|
|
cards: {
|
|
umeSync: "UME Sync",
|
|
network: "Network Management",
|
|
managedNe: "NE Management",
|
|
collect: "Batch Collect",
|
|
webcrt: "WebCRT",
|
|
topology: "Topology",
|
|
portTrafficWall: "Traffic wall",
|
|
users: "Users",
|
|
audit: "Audit",
|
|
apiKeys: "API Keys",
|
|
sessions: "Login sessions",
|
|
},
|
|
},
|
|
network: {
|
|
title: "Network Management",
|
|
nav: {
|
|
detail: "Network details",
|
|
tasks: "Monitoring tasks",
|
|
topologyMgmt: "Topology management",
|
|
devices: "Device list",
|
|
topology: "Topology",
|
|
lldpLinks: "LLDP",
|
|
topoClassify: "Classify / slices",
|
|
alarms: "Alarms",
|
|
configs: "Configurations",
|
|
webcrt: "WebCRT",
|
|
collectTasks: "Collection tasks",
|
|
configSync: "Config sync",
|
|
portTraffic: "Port traffic",
|
|
portTrafficWall: "Traffic wall",
|
|
},
|
|
collapseNav: "Collapse sidebar",
|
|
expandNav: "Expand sidebar",
|
|
placeholder: {
|
|
title: "Coming soon",
|
|
body: "This capability is not available yet.",
|
|
},
|
|
},
|
|
portTraffic: {
|
|
title: "Port traffic",
|
|
create: "Monitor device",
|
|
backList: "Back to list",
|
|
created: "Device monitoring added",
|
|
createFailed: "Create failed",
|
|
updated: "Saved",
|
|
interfacesSaved: "Interfaces updated",
|
|
started: "Started",
|
|
paused: "Paused",
|
|
stopped: "Stopped",
|
|
statusRunning: "Running",
|
|
statusPaused: "Paused",
|
|
statusStopped: "Stopped",
|
|
collecting: "Collecting",
|
|
deleted: "Deleted",
|
|
confirmDelete: "Delete this device monitoring and its samples?",
|
|
empty: "No devices monitored yet. Pick a NE and interfaces to start.",
|
|
wall: "Ops wall",
|
|
wallTitle: "Port traffic wall",
|
|
toDevices: "Manage devices",
|
|
wallEmpty: "No monitored devices yet. Add a device and pick interfaces first.",
|
|
fullscreen: "Fullscreen",
|
|
exitFullscreen: "Exit fullscreen",
|
|
board: "Board",
|
|
boardPick: "Select board",
|
|
boardPickHint: "Select or create a traffic wall board.",
|
|
boardEmpty: "No boards yet. Create one for cutover or duty monitoring.",
|
|
boardDefaultName: "Untitled board",
|
|
boardName: "Name",
|
|
boardCols: "Columns",
|
|
boardCreate: "New board",
|
|
boardEdit: "Edit layout",
|
|
boardSave: "Save",
|
|
boardCancel: "Cancel",
|
|
boardSaved: "Board saved",
|
|
boardCreated: "Board created",
|
|
boardDeleted: "Board deleted",
|
|
boardConfirmDelete: "Delete this board and its panels?",
|
|
boardUnsavedLeave: "You have unsaved changes. Leave anyway?",
|
|
boardOpenTab: "Open in new tab",
|
|
boardOpen: "Open wall",
|
|
boardListHint: "Open a board in its own browser tab; launching Network from the workbench will not refresh open walls.",
|
|
boardPanelCount: "Panels",
|
|
boardUpdated: "Updated",
|
|
boardClosedHint: "You can close this tab, or reopen from Network → Traffic wall list.",
|
|
boardAddPanel: "Add panel",
|
|
boardNoPanels: "No panels yet. Edit the board and add interfaces.",
|
|
boardPickDevice: "Select device",
|
|
boardPanelSettings: "Panel settings",
|
|
boardPanelTitle: "Title (optional)",
|
|
boardColSpan: "Column span",
|
|
boardPanelStale: "Interface missing or inactive. Please reselect.",
|
|
boardRetarget: "Reselect port",
|
|
edit: "Edit",
|
|
save: "Save",
|
|
start: "Start",
|
|
pause: "Pause",
|
|
stop: "Stop",
|
|
delete: "Delete",
|
|
wizStep1: "Device",
|
|
wizStep2: "Interfaces",
|
|
wizStep3: "Params",
|
|
step1: "Params",
|
|
step2: "NEs",
|
|
step3: "Interfaces",
|
|
step4: "Confirm",
|
|
prev: "Back",
|
|
next: "Next",
|
|
fieldTitle: "Task name",
|
|
titlePh: "e.g. Access uplinks",
|
|
titleRequired: "Task name is required",
|
|
portsRequired: "Select at least one interface",
|
|
interval: "Interval (sec)",
|
|
retention: "Retention (days)",
|
|
retentionHintWizard: "Use ≥8 days for week-over-week compare",
|
|
concurrency: "Concurrency",
|
|
note: "Note",
|
|
notePh: "Optional",
|
|
startNow: "Start after create",
|
|
neKeywordPh: "Name / IP / vendor",
|
|
deepLinkHint: "Opened from topology: NE {{ne}}{{ifname}}. Confirm selection, then continue.",
|
|
deepLinkIfname: ", interface {{ifname}}",
|
|
selectedNe: "{{count}} NE(s) selected",
|
|
selectedOneNe: "Selected",
|
|
selectedPorts: "{{count}} interface(s) selected",
|
|
pickNeFirst: "Select one NE first",
|
|
discover: "Discover interfaces",
|
|
discoverDetail: "Discover detail",
|
|
discoverCommand: "Command",
|
|
discoverRaw: "Raw log",
|
|
discoverOk: "Discover succeeded",
|
|
discoverFail: "Discover failed",
|
|
confirmCreate: "Start monitoring",
|
|
wallTask: "Task",
|
|
wallPort: "Interface",
|
|
wallDevice: "Device",
|
|
wallDeviceLabel: "Device",
|
|
pickPort: "Select interface",
|
|
range: "Range",
|
|
compare: "Compare",
|
|
compareOff: "Off",
|
|
compareDay: "Yesterday (same TOD)",
|
|
compareWeek: "Last week (same weekday)",
|
|
compareShift: "Previous window",
|
|
compareCustom: "Custom offset",
|
|
offsetHours: "Offset (hours)",
|
|
aheadHours: "Extend past now (hours)",
|
|
aheadHoursHint:
|
|
"Push the chart end past now. With period compare enabled, the overlay can show trend after the current clock; 0 ends at now.",
|
|
mapBaselineHint:
|
|
"Mapped baseline can be combined with period compare; turn on Yesterday yourself when you need that contrast.",
|
|
baseline: "Baseline",
|
|
baselineAt: "Baseline time",
|
|
baselineDevice: "Baseline device",
|
|
baselinePort: "Baseline interface",
|
|
seriesCurrentIn: "Current In",
|
|
seriesCurrentOut: "Current Out",
|
|
seriesBaselineIn: "Baseline In",
|
|
seriesBaselineOut: "Baseline Out",
|
|
mapBaselinePort: "Mapped baseline interface",
|
|
mapBaselineTask: "Mapped baseline task",
|
|
mapBaselineNone: "None",
|
|
retentionHint: "Week compare needs retention_days ≥ 8 or the baseline may be empty.",
|
|
collectNow: "Collect now",
|
|
collectStarted: "Collect triggered",
|
|
collectBusy: "Collect already running",
|
|
targetError: "Last interface error",
|
|
waitSamples: "Samples appear after the device runs; or click Collect now. Chart auto-refreshes.",
|
|
waitAfterError: "Collect failed — open Logs under Traffic monitoring for details, then Collect now.",
|
|
log: "Logs",
|
|
logTitle: "Collect logs",
|
|
logEmpty: "No log entries yet.",
|
|
logDevice: "Device",
|
|
logLevel: "Level",
|
|
logTime: "Time",
|
|
logMessage: "Message",
|
|
logClose: "Close",
|
|
logHasError: "Has error",
|
|
rebind: "Rebind NE",
|
|
rebindTitle: "Rebind network element",
|
|
rebindOk: "Rebound to selected NE; collect can resume",
|
|
rebindFailed: "Rebind failed",
|
|
rebindHint:
|
|
"Pick the correct NE and confirm. IPs may not be unique, and a matching IP does not mean the same device. History is kept.",
|
|
rebindCurrent: "Current binding",
|
|
rebindEmpty: "No NEs found — add the device back under inventory first.",
|
|
rebindSameIp: "Same IP",
|
|
rebindSameIpHint: "IP matches current monitor — still verify name and ID",
|
|
rebindSubmit: "Confirm rebind",
|
|
rebindConfirm: "Bind monitoring to {{ne}}? History samples are kept.",
|
|
err: {
|
|
managedNeNotFound:
|
|
"Managed NE not found (often deleted then re-created with a new id). Use Rebind NE and pick manually.",
|
|
targetErrors: "{{count}} interface(s) failed",
|
|
unsupportedVendor: "Unsupported vendor / device type",
|
|
invalidSource: "Invalid NE source",
|
|
rebindPickFirst: "Select an NE first",
|
|
rebindNeMissing: "Selected NE not found — refresh and try again",
|
|
rebindSourceMismatch: "NE source does not match this monitor device",
|
|
alreadyMonitored: "That NE is already monitored by another device entry",
|
|
},
|
|
kpiLatest: "latest",
|
|
kpiBw: "Bandwidth",
|
|
latestAt: "Latest sample",
|
|
hoverPoint: "Cursor",
|
|
wallLiveTitle: "Live traffic",
|
|
filterView: "View",
|
|
filterMap: "Mapped baseline",
|
|
yMode: "Y axis",
|
|
yModeAuto: "Auto (incl. baseline)",
|
|
yModeCurrent: "Fit current",
|
|
yModeUtil: "Utilization %",
|
|
kpi: {
|
|
tasks: "Tasks",
|
|
devices: "Devices",
|
|
running: "Running",
|
|
ports: "Interfaces",
|
|
samples24h: "Samples 24h",
|
|
},
|
|
col: {
|
|
title: "Task",
|
|
device: "Device",
|
|
status: "Status",
|
|
ports: "Interfaces",
|
|
interval: "Interval",
|
|
last: "Last collect",
|
|
actions: "Actions",
|
|
source: "Source",
|
|
name: "Device",
|
|
vendor: "Vendor",
|
|
ifname: "Interface",
|
|
bw: "BW",
|
|
upDown: "Admin / Phy / Prot",
|
|
admin: "Admin",
|
|
phy: "Phy",
|
|
prot: "Prot",
|
|
description: "Description",
|
|
},
|
|
},
|
|
lldpLinks: {
|
|
title: "LLDP links",
|
|
collectNow: "Collect now",
|
|
retryFailed: "Retry failed",
|
|
started: "LLDP collect started",
|
|
pause: "Pause",
|
|
resume: "Resume",
|
|
stop: "Stop",
|
|
confirmStop: "Stop this job and skip remaining NEs?",
|
|
paused: "Paused",
|
|
resumed: "Resumed",
|
|
stopped: "Collect stopped",
|
|
policyTitle: "Collect policy",
|
|
policySaved: "Policy saved",
|
|
enabled: "Enable scheduled collect",
|
|
autoAddUnmatched: "Auto-add unmatched neighbors as placeholders on discover",
|
|
autoAddUnmatchedHint:
|
|
"Shared by scheduled collect and canvas discover. Off = record unmatched only, no placeholder NE. Default on.",
|
|
intervalDays: "Interval (days)",
|
|
interval: "Collect interval",
|
|
intervalUnitDays: "days",
|
|
intervalUnitHours: "hours",
|
|
concurrency: "Concurrency",
|
|
historyKeep: "Jobs to keep",
|
|
scope: "Scope",
|
|
scopeAll: "All NEs (managed + UME)",
|
|
scopeSelected: "Selected NEs",
|
|
savePolicy: "Save policy",
|
|
selectedCount: "{{count}} selected",
|
|
targetKeywordPh: "Name / IP / vendor",
|
|
jobsTitle: "Collect jobs",
|
|
jobDetailTitle: "Job details",
|
|
expand: "Details",
|
|
edgesTitle: "Fabric links",
|
|
edgeKeywordPh: "Endpoint name or IP",
|
|
edgeStatusAll: "All statuses",
|
|
edgeStatusActive: "Active",
|
|
edgeStatusMissing: "Missing",
|
|
missCount: "Miss cycles",
|
|
replacedBy: "Replaced",
|
|
kpi: {
|
|
nodes: "Fabric nodes",
|
|
edges: "Active links",
|
|
missing: "Missing",
|
|
running: "In progress",
|
|
idle: "Idle",
|
|
last: "Last job",
|
|
nextDue: "Next due",
|
|
},
|
|
col: {
|
|
source: "Source",
|
|
name: "Device",
|
|
vendor: "Vendor",
|
|
trigger: "Trigger",
|
|
scope: "Scope",
|
|
status: "Status",
|
|
progress: "Progress",
|
|
edges: "Edges",
|
|
missingDelta: "Missing/purged",
|
|
started: "Started",
|
|
ended: "Ended",
|
|
neighbors: "Neighbors",
|
|
error: "Error",
|
|
aSide: "Side A",
|
|
bSide: "Side B",
|
|
aPort: "Port A",
|
|
bPort: "Port B",
|
|
lastSeen: "Last seen",
|
|
},
|
|
jobStatus: {
|
|
running: "Running",
|
|
pending: "Pending",
|
|
paused: "Paused",
|
|
done: "Done",
|
|
failed: "Failed",
|
|
cancelled: "Cancelled",
|
|
},
|
|
triggerMode: {
|
|
manual: "Manual",
|
|
schedule: "Scheduled",
|
|
topology: "Topology canvas",
|
|
retry_failed: "Retry failed",
|
|
},
|
|
jobScope: {
|
|
all: "All NEs",
|
|
ne_ids: "Selected NEs",
|
|
selected: "Selected NEs",
|
|
},
|
|
itemResult: {
|
|
ok: "OK",
|
|
warn: "Warn",
|
|
fail: "Fail",
|
|
},
|
|
edgeSource: {
|
|
lldp: "LLDP",
|
|
manual: "Manual",
|
|
stale: "Stale",
|
|
},
|
|
},
|
|
configSync: {
|
|
title: "Config sync",
|
|
syncNow: "Sync now",
|
|
retryFailed: "Retry failed",
|
|
pause: "Pause",
|
|
resume: "Resume",
|
|
stop: "Stop",
|
|
confirmStop: "Stop this cycle and cancel remaining NE tasks?",
|
|
started: "Sync cycle started",
|
|
paused: "Paused",
|
|
resumed: "Resumed",
|
|
stopped: "Sync cycle stopped",
|
|
policyTitle: "Sync policy",
|
|
policySaved: "Policy saved",
|
|
enabled: "Enable scheduled sync",
|
|
intervalDays: "Interval (days)",
|
|
concurrency: "Concurrency",
|
|
historyKeep: "Config versions to keep",
|
|
cycleKeep: "Jobs to keep",
|
|
scope: "Scope",
|
|
scopeAll: "All NEs",
|
|
scopeSelected: "Selected NEs",
|
|
savePolicy: "Save policy",
|
|
selectedCount: "{{count}} selected",
|
|
targetKeywordPh: "Name / IP / vendor",
|
|
cyclesTitle: "Sync cycles",
|
|
cyclesEmpty: "No sync cycles yet",
|
|
tasksTitle: "Cycle tasks",
|
|
taskKeywordPh: "Name / IP / message",
|
|
allStatus: "All statuses",
|
|
expand: "Details",
|
|
collapse: "Collapse",
|
|
kpi: {
|
|
snapshots: "Snapshots",
|
|
running: "In progress",
|
|
idle: "Idle",
|
|
last: "Last cycle",
|
|
nextDue: "Next due",
|
|
},
|
|
col: {
|
|
source: "Source",
|
|
name: "Device",
|
|
vendor: "Vendor",
|
|
trigger: "Trigger",
|
|
status: "Status",
|
|
progress: "Progress",
|
|
started: "Started",
|
|
ended: "Ended",
|
|
message: "Message",
|
|
actions: "Actions",
|
|
},
|
|
},
|
|
networkDevices: {
|
|
title: "Device list",
|
|
keywordPh: "Name / IP / ID",
|
|
allSource: "All sources",
|
|
empty: "No network elements.",
|
|
col: {
|
|
source: "Source",
|
|
name: "Name",
|
|
vendor: "Vendor",
|
|
deviceType: "Device type",
|
|
connect: "Connect",
|
|
},
|
|
},
|
|
networkConfigs: {
|
|
title: "Configurations",
|
|
keywordPh: "Name / IP / ID",
|
|
vendorPh: "Vendor",
|
|
allSource: "All sources",
|
|
empty: "No synced configs yet. Run Config sync first.",
|
|
view: "View",
|
|
export: "Export",
|
|
exportBoth: "Export all",
|
|
exportOk: "Config exported",
|
|
close: "Close",
|
|
tabSet: "Set format",
|
|
tabHier: "Hierarchical",
|
|
col: {
|
|
name: "Device",
|
|
vendor: "Vendor",
|
|
source: "Source",
|
|
size: "Size",
|
|
collected: "Collected",
|
|
},
|
|
},
|
|
layout: {
|
|
title: "UME Integration",
|
|
titleUme: "UME Sync",
|
|
titleNetwork: "Network Management",
|
|
titleManagedNe: "NE Management",
|
|
titleCollect: "Batch Collect",
|
|
titleWebcrt: "WebCRT",
|
|
titleTopology: "Topology",
|
|
titlePortTrafficWall: "Traffic wall",
|
|
titleUsers: "Users",
|
|
titleAudit: "Audit",
|
|
titleApiKeys: "API Keys",
|
|
titleSessions: "Login sessions",
|
|
navUme: "UME",
|
|
netxApi: "netx api",
|
|
oclawBridge: "oclaw WSS",
|
|
activeTasks: "Active {{count}}",
|
|
activeTasksHint: "Open Audit · Task overview",
|
|
language: "Language",
|
|
switchLanguage: "Switch language / 切换语言",
|
|
moreMenu: "More",
|
|
langZh: "中文",
|
|
langEn: "English",
|
|
},
|
|
auth: {
|
|
loginTitle: "Sign in",
|
|
username: "Username",
|
|
password: "Password",
|
|
login: "Sign in",
|
|
loggingIn: "Signing in…",
|
|
loginFailed: "Login failed",
|
|
logout: "Sign out",
|
|
sessionsTitle: "Login sessions",
|
|
sessionsHint: "Manage browser/device logins for this account. Revoked sessions must sign in again.",
|
|
sessionsEmpty: "No active sessions.",
|
|
revokeOtherSessions: "Revoke other sessions",
|
|
revokeSession: "Revoke",
|
|
sessionCurrent: "Current",
|
|
sessionRevoked: "Session revoked",
|
|
sessionsRevokedOthers: "Revoked {{count}} other session(s)",
|
|
revokeCurrentConfirm: "This is your current session; revoking it requires signing in again. Continue?",
|
|
colSession: "Session",
|
|
colLastSeen: "Last seen",
|
|
colCreated: "Created",
|
|
usersTitle: "User management",
|
|
usersHint: "Only admins can create and manage local accounts.",
|
|
addUser: "Add user",
|
|
role: "Role",
|
|
roleAdmin: "Admin",
|
|
roleUser: "User",
|
|
status: "Status",
|
|
active: "Active",
|
|
disabled: "Disabled",
|
|
enable: "Enable",
|
|
disable: "Disable",
|
|
actions: "Actions",
|
|
newPassword: "New password",
|
|
resetPassword: "Reset password",
|
|
userCreated: "User created",
|
|
userUpdated: "User updated",
|
|
auditTitle: "Audit log",
|
|
auditHintAdmin: "View login and operation records for all users.",
|
|
auditHintUser: "View your own operation records.",
|
|
filterUsername: "Filter username",
|
|
filterAction: "Filter action",
|
|
colTime: "Time",
|
|
colUser: "User",
|
|
colAction: "Action",
|
|
colMethod: "Method",
|
|
colPath: "Path",
|
|
colStatus: "Status",
|
|
colIp: "IP",
|
|
apiKeysTitle: "API Key management",
|
|
apiKeysHelp:
|
|
"The web UI uses login sessions, not API keys — keys are for MCP/scripts. Defaults on create: alarms:read + ne:read + ne:write + ne:exec; refine later with Edit scopes (takes effect immediately, no need to regenerate). Secret is shown once. Admins may issue for other users; scopes cannot exceed the owner's. Unused scopes are reserved for future MCP tools.",
|
|
tokenName: "Name",
|
|
expiresIn: "Expiry",
|
|
expire7d: "7 days",
|
|
expire30d: "30 days",
|
|
expire90d: "90 days",
|
|
expire365d: "1 year",
|
|
expireNever: "Never",
|
|
tokenOwner: "Owner",
|
|
tokenOwnerSelf: "Myself ({{user}})",
|
|
createToken: "Create key",
|
|
tokenCreated: "API key created",
|
|
tokenUpdated: "Scopes updated",
|
|
tokenRevoked: "Revoked",
|
|
tokenOnceHint: "Copy and store this secret now; it will not be shown again:",
|
|
copyToken: "Copy",
|
|
tokenCopied: "Copied",
|
|
tokenCopyFailed: "Copy failed",
|
|
expiresAt: "Expires",
|
|
lastUsed: "Last used",
|
|
tokenStatusActive: "Active",
|
|
tokenStatusExpired: "Expired",
|
|
tokenStatusRevoked: "Revoked",
|
|
revokeToken: "Revoke",
|
|
revokeConfirm: "Revoke this API key?",
|
|
editScopes: "Edit scopes",
|
|
saveScopes: "Save scopes",
|
|
scopesUnsetLegacy: "Unrestricted (same as owner)",
|
|
scopesCol: "Scopes",
|
|
scopesRequired: "Select at least one scope",
|
|
scopesNoneAvailable: "This owner has no grantable scopes",
|
|
scopeAlarmsRead: "alarms:read — Alarms read (netx MCP)",
|
|
scopeNeRead: "ne:read — NE / topology read (MCP)",
|
|
scopeNeWrite: "ne:write — NE / topology write / draw (MCP)",
|
|
scopeNeExec: "ne:exec — Managed NE CLI (netx MCP)",
|
|
scopeSql: "sql:query — UME SQL (netx MCP)",
|
|
scopeWebcrt: "webcrt:session — WebCRT (reserved MCP)",
|
|
scopeAdminUsers: "admin:users — User admin (reserved MCP)",
|
|
scopeOpsWrite: "ops:write — Ops write / subscriptions (reserved MCP)",
|
|
|
|
forceChangeTitle: "Change initial password",
|
|
forceChangeHint: "Account {{user}} is still using the default password. You must change it before continuing.",
|
|
oldPassword: "Current password",
|
|
confirmPassword: "Confirm new password",
|
|
savePassword: "Save new password",
|
|
savingPassword: "Saving…",
|
|
passwordTooShort: "New password must be at least 8 characters",
|
|
passwordMismatch: "New passwords do not match",
|
|
passwordMustChange: "New password must differ from the default/old password",
|
|
},
|
|
collect: {
|
|
create: {
|
|
title: "New collection job",
|
|
hint: "Configure commands and NEs, then create the job. Click Start in the job list to run collection.",
|
|
selectedTitle: "Selected NEs",
|
|
selectedEmpty: "Filter below and add NEs one by one.",
|
|
selectedCount: "{{count}} selected",
|
|
clearSelected: "Clear selection",
|
|
remove: "Remove",
|
|
pickTitle: "Eligible NEs",
|
|
pickHint: "All managed and UME inventory NEs are selectable (any connect status). UME uses CLI connect profile credentials.",
|
|
pickEmpty: "No matching NEs.",
|
|
filterKeyword: "Filter",
|
|
filterKeywordPh: "Name / IP / vendor / device type",
|
|
add: "Add",
|
|
addBatch: "Add selected ({{count}})",
|
|
added: "Added",
|
|
create: "Create job",
|
|
creating: "Creating…",
|
|
expand: "New",
|
|
collapse: "Close",
|
|
meta: "{{ne}} NE(s) selected · {{cmd}} command(s)",
|
|
},
|
|
eligible: {
|
|
title: "Eligible NEs",
|
|
hint: "All managed and UME inventory NEs are selectable (any connect status).",
|
|
empty: "No NEs.",
|
|
},
|
|
form: {
|
|
title: "Collection setup",
|
|
jobTitle: "Job title",
|
|
jobTitlePh: "Auto-generated if empty",
|
|
commands: "Commands (one per line, # for comments)",
|
|
commandsPh: "display version\ndisplay current-configuration",
|
|
commandsHint: "Commands run in order on each device; output is saved as a text log (legacy NetX format).",
|
|
meta: "{{ne}} NE(s) selected · {{cmd}} command(s)",
|
|
start: "Start collection",
|
|
starting: "Submitting…",
|
|
},
|
|
created: "Collection job created: {{id}}",
|
|
started: "Collection started: {{id}}",
|
|
paused: "Job paused",
|
|
restarted: "Collection restarted",
|
|
retryFailedDone: "Retrying failed devices",
|
|
deleted: "Job deleted",
|
|
nothingToRetry: "No failed devices to retry",
|
|
neBusy: "Some NEs are busy in another collection job; wait for it to finish before starting",
|
|
jobRunning: "This job is already running",
|
|
confirmDelete: "Delete this collection job and its log files?",
|
|
jobs: {
|
|
title: "Collection jobs",
|
|
col: {
|
|
title: "Job",
|
|
status: "Status",
|
|
progress: "Progress",
|
|
created: "Created",
|
|
lastRun: "Last run",
|
|
actions: "Actions",
|
|
},
|
|
ok: "ok",
|
|
fail: "fail",
|
|
expand: "Details",
|
|
collapse: "Hide",
|
|
detailTitle: "Job details",
|
|
pause: "Pause",
|
|
start: "Start",
|
|
starting: "Starting…",
|
|
restart: "Restart",
|
|
retryFailed: "Retry failed",
|
|
downloadResults: "Download results",
|
|
delete: "Delete",
|
|
autoRefresh: "Auto-refresh every 2s while jobs are running",
|
|
runsInProgress: "Some devices are still being collected…",
|
|
},
|
|
kpi: {
|
|
jobs: "Jobs",
|
|
running: "In progress",
|
|
idle: "Idle",
|
|
last: "Last job",
|
|
active: "Active jobs",
|
|
},
|
|
runs: {
|
|
status: "Status",
|
|
message: "Message",
|
|
download: "Log",
|
|
downloadFile: "Download",
|
|
filterStatus: "Status filter",
|
|
filterDevice: "Device filter",
|
|
deviceKeywordPh: "Name / IP",
|
|
allStatus: "All statuses",
|
|
},
|
|
},
|
|
managedNe: {
|
|
title: "Network Elements",
|
|
credsNotConfigured:
|
|
"NETX_CREDENTIAL_SECRET_KEY is not set. Configure a Fernet key in .env and restart the API to store passwords.",
|
|
add: "Add NE",
|
|
importBtn: "Import",
|
|
downloadTemplate: "Download template",
|
|
importing: "Importing…",
|
|
edit: "Edit",
|
|
delete: "Delete",
|
|
openTerminal: "Terminal",
|
|
confirmDelete:
|
|
"Delete this network element? If its Fabric node is managed-only (no UME binding), that node and its direct links will also be removed.",
|
|
batchDelete: "Batch delete",
|
|
batchDeleting: "Deleting…",
|
|
batchDeleteConfirm:
|
|
"Delete {{n}} selected network element(s)? Cannot be undone. Managed-only Fabric nodes cascade (node + direct links); nodes still bound to UME keep topology.",
|
|
batchDeleteDone: "Deleted {{n}} network element(s)",
|
|
batchDeleteSelectRequired: "Select network elements to delete",
|
|
keywordPh: "name / IP / user / tags",
|
|
allVendors: "All vendors",
|
|
allConnectStatus: "All connect status",
|
|
stats: {
|
|
title: "Overview",
|
|
total: "{{n}} NEs managed",
|
|
pass: "Connected",
|
|
fail: "Failed",
|
|
unknown: "Untested",
|
|
testing: "Testing",
|
|
batchProxy: "Batch add proxy",
|
|
batchTest: "Batch connect-test",
|
|
tagFilter: "Filter by tag",
|
|
all: "All",
|
|
allTag: "All (no tag filter)",
|
|
noTag: "No tags",
|
|
tagStats: "Top tags",
|
|
confirm: "Apply to {{n}} NE(s). Continue?",
|
|
proxyDone: "Proxy applied to {{n}} NE(s)",
|
|
testDone: "Connect-test submitted for {{n}} NE(s)",
|
|
loadingIds: "Loading…",
|
|
},
|
|
col: {
|
|
name: "Name",
|
|
vendor: "Vendor",
|
|
deviceType: "Device type",
|
|
source: "Source",
|
|
ip: "Management IP",
|
|
port: "Port",
|
|
protocol: "Protocol",
|
|
user: "Username",
|
|
password: "Password",
|
|
tags: "Tags",
|
|
remark: "Remark",
|
|
connect: "Connect",
|
|
testedAt: "Tested at",
|
|
actions: "Actions",
|
|
},
|
|
source: {
|
|
manual: "Manual",
|
|
ume_sync: "UME sync",
|
|
webcrt: "WebCRT",
|
|
lldp: "LLDP placeholder",
|
|
topology: "Topology placeholder",
|
|
},
|
|
connect: {
|
|
run: "Connectivity test",
|
|
running: "Testing…",
|
|
submitted: "Submitted tests for {{n}} device(s)",
|
|
retest: "Test again",
|
|
},
|
|
connectDetail: "Details",
|
|
connectDetailTitle: "Connectivity test log",
|
|
connectDetailEmpty:
|
|
"No log yet. Run a connectivity test first; failures store full errors and hop context (passwords excluded).",
|
|
umeSync: {
|
|
sync: "Sync UME NEs",
|
|
syncing: "Syncing…",
|
|
delete: "Delete UME NEs",
|
|
deleting: "Deleting…",
|
|
deleteConfirm:
|
|
"Delete all managed NEs created from UME sync? Cannot be undone. Fabric nodes that become fully orphaned (no UME left) are removed with their direct links.",
|
|
done: "UME sync done: {{inserted}} inserted, {{updated}} updated, {{deleted}} deleted, {{total}} inventory total",
|
|
deletedDone: "Deleted {{n}} UME-synced NEs",
|
|
},
|
|
account: {
|
|
batchAdd: "Batch add account",
|
|
batchByTag: "Batch account by tag",
|
|
batchTitle: "Batch add account",
|
|
batchHint: "Apply the account info below to {{n}} selected NE(s).",
|
|
batchByTagHint: "Apply the account info below to NEs under the selected tag; leave password blank to update only username.",
|
|
batchDone: "Account updated for {{n}} NE(s)",
|
|
selectRequired: "Select network elements first",
|
|
applying: "Applying…",
|
|
apply: "Apply to NEs",
|
|
usernameOrPasswordRequired: "Enter at least a username or a password",
|
|
passwordOptionalBatch: "leave blank to keep unchanged",
|
|
},
|
|
help:
|
|
"[Bulk import]\n" +
|
|
"· Required columns: device_type, ip, username, port, protocol, name, vendor. Download the template first.\n" +
|
|
"· password may be empty (required for direct login; optional for bastion-managed or batch proxy later).\n" +
|
|
"· Recommended flow: import NEs first, select rows, then use Batch add proxy.\n\n" +
|
|
"[Jump / bastion]\n" +
|
|
"· Bastion SSH username template: {hop_user}@{target_user}@{target_ip} (bastion host is separate IP or FQDN); CLI: ssh user@target@ip@bastion-host.\n" +
|
|
"· Bastion-managed: set Jump password (Vault); target password optional. Manual mode needs target password.\n" +
|
|
"· Jump host accepts IP (192.0.2.10) or domain (ssh-bastion.example.com). JumpServer/CBH often use port 2222; some sites use 22.\n\n" +
|
|
"[Connectivity / edit]\n" +
|
|
"· NETX_CREDENTIAL_SECRET_KEY required to store passwords.\n" +
|
|
"· Leave password blank on edit to keep unchanged; open Details after failed connect-test for hop context (no secrets).",
|
|
importResult: {
|
|
done: "Import done: {{inserted}} inserted, {{updated}} updated, {{failed}} failed row(s)",
|
|
},
|
|
form: {
|
|
requiredHint: "Fields marked with * are required",
|
|
nameConnectHint: "After a successful connectivity test, name is replaced with the device hostname",
|
|
createTitle: "Add network element",
|
|
editTitle: "Edit network element",
|
|
save: "Save",
|
|
saving: "Saving…",
|
|
cancel: "Cancel",
|
|
created: "Network element created",
|
|
updated: "Network element updated",
|
|
deleted: "Network element deleted",
|
|
passwordRequired: "Password is required",
|
|
passwordOptional: "leave blank to keep unchanged",
|
|
},
|
|
hop: {
|
|
sectionTitle: "Jump host / proxy",
|
|
type: "Jump type",
|
|
enable: "Connect to target via jump host",
|
|
vendor: {
|
|
zte: "ZTE device (CLI jump)",
|
|
huawei: "Huawei device (CLI jump)",
|
|
cisco: "Cisco device (CLI jump)",
|
|
linux: "Linux server (SSH tunnel)",
|
|
bastion: "Bastion host (SSH protocol proxy)",
|
|
},
|
|
zteHint: "Run ssh/telnet on the ZTE device to reach the target; target credentials use secondary auth.",
|
|
huaweiHint: "Run telnet / stelnet (SSH) on the Huawei hop; stelnet is SSH. Target credentials use secondary auth.",
|
|
ciscoHint: "Run Cisco ssh -vrf / telnet /vrf jump commands; target credentials use secondary auth.",
|
|
linuxHint: "SSH to the Linux bastion, then direct-tcpip tunnel to target IP:port (ProxyJump-style).",
|
|
bastionHint:
|
|
"SSH with composite username via bastion protocol proxy. Hop host may be an IP or FQDN. Examples: bastion-user@target-user@198.51.100.20@192.0.2.10 or bastion-user@target-user@198.51.100.20@ssh-bastion.example.com; password is the bastion/Vault password. JumpServer/CBH often use port 2222.",
|
|
targetAuthMode: "Target credentials",
|
|
targetAuthBastionManaged: "Bastion-managed (target password optional)",
|
|
targetAuthManual: "Manual (secondary auth after connect)",
|
|
targetAuthHint: "Bastion-managed needs only bastion password; manual mode requires target NE password.",
|
|
usernameTemplate: "SSH username template",
|
|
templateHintBastion:
|
|
"Default {hop_user}@{target_user}@{target_ip}. Bastion address (IP or FQDN) goes in Jump host. CLI example: ssh bastion-user@target-user@198.51.100.20@ssh-bastion.example.com.",
|
|
host: "Jump host",
|
|
hostPlaceholderBastion: "192.0.2.10 or ssh-bastion.example.com",
|
|
hostHintBastion:
|
|
"IP or FQDN. You can paste a full SSH destination (e.g. bastion-user@target-user@198.51.100.20@ssh-bastion.example.com); on blur it splits into jump username + host.",
|
|
port: "Jump port",
|
|
protocol: "Jump protocol",
|
|
protocolSshStelnet: "ssh (stelnet)",
|
|
username: "Jump username",
|
|
password: "Jump password",
|
|
vrf: "Mgmt VRF (optional)",
|
|
vpnInstance: "VPN-Instance (optional)",
|
|
vrfCisco: "VRF (optional, e.g. MGMT)",
|
|
commandTemplate: "Jump command template",
|
|
templateHint:
|
|
"ZTE CLI: telnet {target_ip}, telnet {target_ip} vrf {vrf}, ssh {target_ip}, ssh {target_ip} vrf {vrf}. Auto-suggested from jump protocol/VRF; same when left blank. Target credentials via secondary auth prompts.",
|
|
templateHintHuawei:
|
|
"Huawei CLI: telnet {target_ip}, telnet vpn-instance {vrf} {target_ip}, stelnet {target_ip}, stelnet {target_ip} -vpn-instance {vrf}. SSH protocol maps to stelnet. Auto-suggested when left blank.",
|
|
templateHintCisco:
|
|
"Cisco CLI: ssh {target_ip}, ssh -vrf {vrf} {target_ip}, telnet {target_ip}, telnet {target_ip} /vrf {vrf}. Auto-suggested when left blank.",
|
|
badge: {
|
|
zte: "ZTE hop",
|
|
huawei: "Huawei hop",
|
|
cisco: "Cisco hop",
|
|
linux: "Linux hop",
|
|
bastion: "Bastion",
|
|
},
|
|
hostRequired: "Jump host is required",
|
|
userRequired: "Jump username is required",
|
|
passwordRequired: "Jump password is required",
|
|
batchAdd: "Add proxy",
|
|
batchTitle: "Batch add jump proxy",
|
|
batchHint: "Apply the jump-host settings below to {{n}} selected NE(s) (overwrites existing proxy config).",
|
|
batchDone: "Proxy applied to {{n}} NE(s)",
|
|
selectRequired: "Select network elements first",
|
|
applying: "Applying…",
|
|
apply: "Apply to selected",
|
|
},
|
|
},
|
|
ume: {
|
|
token: {
|
|
title: "UME Token",
|
|
disconnected: "disconnected",
|
|
connected: "connected",
|
|
connectedRenew: "connected (renew required)",
|
|
expiresIn: "expires_in",
|
|
needsRenew: "renew / 0s",
|
|
preview: "preview",
|
|
refreshStatus: "Refresh status",
|
|
renewLogin: "Renew / login",
|
|
renewing: "Renewing…",
|
|
disconnect: "Disconnect token",
|
|
disconnecting: "Disconnecting…",
|
|
renewOkChanged: "Token renewed and updated",
|
|
renewOkSame: "Renew completed (unchanged)",
|
|
disconnectOk: "UME token disconnected",
|
|
renewHint: "Token missing expiry or expired. Use Renew / login or wait for background keepalive.",
|
|
},
|
|
subscription: {
|
|
title: "UME alarm subscription (WebSocket)",
|
|
help:
|
|
"Subscriptions must be created/cancelled manually. After establish (or on restart if a valid subscription exists in DB), the backend auto-connects WSS for live alarms. Pause/resume on runtime task alarms_current_ws_consumer stops/resumes WSS only (does not cancel the UME subscription).",
|
|
sub: "subscription",
|
|
subActive: "active",
|
|
subInactive: "inactive",
|
|
wssPaused: "paused",
|
|
wssModeBanner:
|
|
"Current alarms are maintained via WSS (mode: {{mode}}); scheduled REST full sync is paused. Use Sync current alarms below for full reconcile.",
|
|
serverLostBanner:
|
|
"UME server subscription is missing or expired; local state may still show active. Clear local record and re-subscribe.",
|
|
establish: "Establish subscription",
|
|
establishing: "Establishing…",
|
|
reestablish: "Clear local & re-subscribe",
|
|
reestablishing: "Re-subscribing…",
|
|
cancel: "Cancel subscription",
|
|
cancelling: "Cancelling…",
|
|
refreshStatus: "Refresh subscription",
|
|
clearLocalOnly: "Clear local only",
|
|
clearing: "Clearing…",
|
|
opFailed: "Subscription operation failed",
|
|
confirmClearDefault:
|
|
"UME alarm subscription no longer exists or has expired.\n\nClear local subscription record? You can establish again afterwards.",
|
|
confirmReestablish: "Clear local record and re-establish subscription on UME. Continue?",
|
|
titleLoginFirst: "Log in to UME token first",
|
|
titleReestablish: "Clear stale local record and re-establish on UME",
|
|
establishInvalid: "Establish did not return a valid id/uri",
|
|
establishExists: "Subscription already exists (WSS will stay/connect)",
|
|
establishOk: "Subscription established; WSS will connect",
|
|
clearLocalOk: "Local subscription cleared; you can establish again",
|
|
serverLostMsg: "UME subscription lost. Clear local record and re-subscribe?",
|
|
cancelFailed: "Cancel failed: subscription may still exist on UME",
|
|
cancelOkMissing: "Local cleared (UME subscription was already missing)",
|
|
cancelOk: "Subscription cancelled",
|
|
wsLogs: "WSS runtime log",
|
|
wsActivity: "Last activity {{time}}",
|
|
wsAutoRefresh: "Auto refresh",
|
|
wsLogsEmpty: "No logs yet (connect WSS after establishing subscription)",
|
|
},
|
|
keyAlert: {
|
|
title: "AI alarm monitor",
|
|
showPanel: "Details",
|
|
hidePanel: "Close",
|
|
help: "Exact match by notificationId, or substring match on alarm description (case-insensitive; nativeProbableCause, etc.). Optionally restrict to UME inventory ne_type values (multi-select; empty = all devices). Pushed via OClaw WebSocket. Shares NETX_OCLAW_ANALYZE_TOKEN.",
|
|
ws: "OClaw WSS",
|
|
wsConnected: "connected",
|
|
wsDisconnected: "disconnected",
|
|
wsDisabled: "disabled",
|
|
wsPaused: "paused",
|
|
publishedOk: "published ok",
|
|
publishedFail: "published fail",
|
|
queue: "queue",
|
|
matchType: "Match by",
|
|
matchNotificationId: "notificationId",
|
|
matchKeyword: "description keyword",
|
|
matchValuePhNotificationId: "Enter notificationId",
|
|
matchValuePhKeyword: "Enter keyword (case-insensitive)",
|
|
label: "Rule description",
|
|
labelPh: "Required, e.g. BGP Down",
|
|
neTypesLabel: "Device types (optional, multi-select)",
|
|
neTypesHint: "Leave empty to match all device types. Options come from synced UME Inventory ne_type.",
|
|
neTypesEmpty: "No device types yet — sync Inventory first",
|
|
neTypesAll: "All",
|
|
forwardOnClear: "Push on alarm clear",
|
|
forwardOnClearHelp: "Global switch for all monitor rules. By default only new/updated alarms are pushed; when enabled, clear notifications are also sent when UME reports alarms cleared.",
|
|
add: "Add rules",
|
|
adding: "Adding…",
|
|
delete: "Delete",
|
|
edit: "Edit",
|
|
editTitle: "Edit monitor rule",
|
|
save: "Save",
|
|
saving: "Saving…",
|
|
cancel: "Cancel",
|
|
editOk: "Rule updated",
|
|
pickFromAlarms: "Load alarm hints",
|
|
emptyRules: "No monitor rules yet",
|
|
colType: "type",
|
|
colMatch: "match",
|
|
colLabel: "description",
|
|
colNeTypes: "device types",
|
|
colForwardClear: "on clear",
|
|
colPublished: "published",
|
|
colAttempts: "attempts",
|
|
colLast: "last push",
|
|
colActions: "actions",
|
|
colMonitor: "monitor",
|
|
monitorOn: "on",
|
|
monitorOff: "off",
|
|
filterKeywordPh: "Filter match / label",
|
|
filterMatchAll: "All types",
|
|
filterEnabledAll: "All states",
|
|
filterEnabledOn: "Monitoring on",
|
|
filterEnabledOff: "Monitoring off",
|
|
addOk: "Monitor rule added",
|
|
deleteOk: "Deleted",
|
|
confirmDelete: "Delete this monitor rule?",
|
|
yes: "yes",
|
|
no: "no",
|
|
},
|
|
sync: {
|
|
title: "UME sync",
|
|
inventory: "Sync inventory",
|
|
alarmsCurrent: "Sync current alarms",
|
|
full: "Full sync",
|
|
failed: "Sync failed",
|
|
},
|
|
tasks: {
|
|
currentTitle: "Running jobs",
|
|
running: "running",
|
|
noRunning: "No running jobs",
|
|
runtimeTitle: "Background tasks",
|
|
runtimeOpFailed: "Background task operation failed",
|
|
noRuntime: "No background task status",
|
|
intervalTitle: "Configured sleep between loop iterations (clamped at process start)",
|
|
lastRunTitle: "Last finished sync for scheduled tasks; refreshed at each loop tick",
|
|
deletedTitle: "Reconcile deletes: inventory = NE rows; alarms_current = current alarm rows",
|
|
lastErrorCol: "last_error",
|
|
runtimeError: {
|
|
startup_alarm_sync_before_ws: "Starting up: syncing current alarms (WSS connects after completion)…",
|
|
startup_gate_waiting: "Startup REST snapshot pending; scheduled REST and WSS on standby",
|
|
wss_active_skip_rest: "WSS receiving live alarms; REST sync skipped",
|
|
pulling_alarms_current: "Pulling UME current alarms…",
|
|
alarms_sync_in_progress_skip: "Another current-alarm REST sync in progress; skipped",
|
|
pulling_inventory: "Pulling UME inventory…",
|
|
pulling_topology: "Pulling UME topology (nodes/links)…",
|
|
topology_sync_busy: "Topology sync already running; skipped",
|
|
ume_ws_disabled_no_base_url: "Disabled or UME_BASE_URL not configured",
|
|
oclaw_fwd_disabled: "Disabled or NETX_OCLAW_ALARM_WS / token / url not configured",
|
|
resumed_sync_soon: "Resumed: skipping debounce wait, sync soon",
|
|
resumed_wss_reconnect: "Resumed: reconnecting WSS soon",
|
|
resumed_oclaw_wss_reconnect: "Resumed: reconnecting OClaw WSS soon",
|
|
resumed: "Resumed",
|
|
keepalive_failed: "Token keepalive failed",
|
|
},
|
|
wsState: {
|
|
init: "Initializing",
|
|
connected: "Connected",
|
|
connecting: "Connecting",
|
|
disconnected: "Disconnected",
|
|
no_subscription: "No subscription",
|
|
waiting_token: "Waiting for token",
|
|
paused: "Paused",
|
|
error: "Connection error",
|
|
reconnecting: "Reconnecting",
|
|
subscription_lost: "UME subscription lost",
|
|
disabled_no_base_url: "Disabled or UME_BASE_URL not configured",
|
|
},
|
|
fwdState: {
|
|
paused: "Paused",
|
|
disabled: "Disabled",
|
|
connecting: "Connecting",
|
|
connected: "Connected",
|
|
connect_refused: "OClaw gateway down or port 8787 refused",
|
|
connect_timeout: "Timed out connecting to OClaw gateway",
|
|
auth_failed: "OClaw netx-bridge auth failed (check shared token)",
|
|
disconnected: "OClaw WSS disconnected",
|
|
},
|
|
runtimeTask: {
|
|
token_keepalive: "UME token keepalive",
|
|
alarms_current_auto_sync: "Current alarms auto sync",
|
|
alarms_current_ws_consumer: "UME alarm WSS",
|
|
oclaw_alarm_forwarder: "OClaw key-alert WSS",
|
|
inventory_auto_sync: "Inventory auto sync",
|
|
topology_auto_sync: "Topology auto sync",
|
|
},
|
|
},
|
|
syncStatus: {
|
|
title: "Sync history",
|
|
showPanel: "Details",
|
|
hidePanel: "Close",
|
|
empty: "No sync records",
|
|
summary: "{{total}} record(s), {{running}} running",
|
|
fabricGapTitle: "Topology dock is newer than Fabric / UME World",
|
|
fabricGapHint:
|
|
"Dock ME {{dock}}, Fabric UME {{fabric}}. Apply without pulling UME. Last status: {{status}}",
|
|
applyFabric: "Apply to topology",
|
|
applyingFabric: "Applying…",
|
|
applyFabricOk: "Applied to topology",
|
|
},
|
|
ne: {
|
|
title: "Network elements",
|
|
showPanel: "Details",
|
|
hidePanel: "Close",
|
|
keywordPh: "keyword(ne_id/ne_name/user_label/ip/host_name)",
|
|
clearTitle: "Clear keyword and reset to page 1",
|
|
expand: "Details",
|
|
collapse: "Close",
|
|
cliConnect: "CLI connect",
|
|
summary: "{{total}} inventory NE(s)",
|
|
},
|
|
tabs: {
|
|
main: "UME sync",
|
|
cli: "CLI connect",
|
|
},
|
|
cli: {
|
|
title: "UME CLI connection profile",
|
|
showPanel: "Details",
|
|
hidePanel: "Close",
|
|
hint: "Unified SSH credentials and hop/bastion for UME inventory NEs. OClaw MCP can exec show commands via ume_ne_id without per-device managed_ne entries.",
|
|
statusReady: "CLI profile is ready for UME NE command execution.",
|
|
statusNotReady: "Set target username and hop/bastion settings (if enabled).",
|
|
profileName: "Profile name",
|
|
targetUsername: "Target SSH username",
|
|
targetPassword: "Target SSH password",
|
|
passwordKeep: "Leave blank to keep unchanged",
|
|
newProfile: "New profile",
|
|
deleteConfirm: "Delete this CLI profile?",
|
|
deleted: "Profile deleted",
|
|
saved: "CLI profile saved",
|
|
connectTestTitle: "Sample NE connectivity test",
|
|
sampleNePh: "ume_ne_id (copy from NE list below)",
|
|
sampleNeRequired: "ume_ne_id is required",
|
|
connectTestSubmitted: "Connectivity test submitted",
|
|
connectTestWaiting: "Waiting for test result…",
|
|
connectTestRunning: "Connectivity test in progress…",
|
|
connectTestResult: "Test result",
|
|
existingProfiles: "Existing profiles",
|
|
default: "default",
|
|
},
|
|
alarms: {
|
|
title: "Current alarms",
|
|
movedHint: "Current alarm query moved to Network Management →",
|
|
showPanel: "Expand",
|
|
hidePanel: "Collapse",
|
|
keywordPh: "keyword(alarm key/cause/ne_name/host_name/ip…)",
|
|
hostNamePh: "host_name (contains)",
|
|
allSeverity: "All severities",
|
|
clearedAll: "is_cleared: all",
|
|
clearTitle: "Clear filters and reset to page 1",
|
|
filterByHost: "Filter by this host",
|
|
noHostName: "No host_name (sync inventory first)",
|
|
},
|
|
},
|
|
webcrt: {
|
|
title: "WebCRT",
|
|
deviceList: "Device list",
|
|
sessionManager: "Device list",
|
|
connect: "Connect",
|
|
hint: "Pick an NE and open an interactive terminal in the browser. Credentials stay on the server.",
|
|
hintCrt: "Click an NE on the left to open a terminal. Includes managed, Sessions, and UME; or use New Session for a quick login.",
|
|
filterKeyword: "Filter",
|
|
filterKeywordPh: "Filter by name / IP / tag",
|
|
empty: "No matching NEs. Switch source or refine the search.",
|
|
open: "Open terminal",
|
|
opening: "Connecting…",
|
|
opened: "Opened {{name}}",
|
|
disconnect: "Disconnect",
|
|
closed: "Session closed",
|
|
termPlaceholder: "No terminal session open",
|
|
sessionMeta: "{{name}} · {{ip}}",
|
|
source: {
|
|
all: "All",
|
|
managed: "Managed",
|
|
webcrt: "Sessions",
|
|
ume: "UME",
|
|
},
|
|
newSession: {
|
|
title: "New Session",
|
|
claimTitle: "Complete placeholder session",
|
|
claimHint:
|
|
"Enter a reachable host. Session name defaults to the placeholder name. On success, source becomes WebCRT.",
|
|
connect: "Connect",
|
|
connecting: "Connecting…",
|
|
protocol: "Protocol",
|
|
host: "Hostname",
|
|
port: "Port",
|
|
sessionName: "Session name",
|
|
sessionNamePh: "Optional; defaults to IP",
|
|
authTitle: "SSH Authentication",
|
|
savePassword: "Save password",
|
|
ipRequired: "Hostname is required",
|
|
userRequired: "Username is required",
|
|
passwordRequired: "Password is required",
|
|
},
|
|
status: {
|
|
idle: "Idle",
|
|
connecting: "Connecting",
|
|
connected: "Connected",
|
|
error: "Error",
|
|
closed: "Closed",
|
|
},
|
|
phase: {
|
|
creating: "Creating session",
|
|
authenticating: "Authenticating",
|
|
waitingPrompt: "Waiting for device prompt",
|
|
hint: "Slow devices may take more than 10 seconds",
|
|
},
|
|
tabMenu: {
|
|
close: "Close",
|
|
closeOthers: "Close others",
|
|
closeAll: "Close all",
|
|
copyIp: "Copy IP",
|
|
copyIpOk: "Copied {{ip}}",
|
|
copyIpEmpty: "No IP on this tab",
|
|
},
|
|
treeMenu: {
|
|
rename: "Rename",
|
|
renameLabel: "Session name",
|
|
renameSave: "Save",
|
|
renameRequired: "Session name is required",
|
|
renamed: "Session renamed",
|
|
delete: "Delete session",
|
|
deleteConfirm: "Delete session \"{{name}}\"? This cannot be undone.",
|
|
deleted: "Session deleted",
|
|
},
|
|
keywordHl: {
|
|
title: "Keyword Highlighting",
|
|
enabled: "Enabled",
|
|
newKeyword: "New keyword",
|
|
newKeywordPh: "Keyword or regex",
|
|
regex: "Regular expression",
|
|
add: "Add",
|
|
colKeyword: "Keyword",
|
|
colRegex: "Regex",
|
|
empty: "No keywords yet",
|
|
moveUp: "Move up",
|
|
moveDown: "Move down",
|
|
remove: "Remove",
|
|
caseSensitive: "Case sensitive",
|
|
color: "Text color",
|
|
saved: "Keyword highlighting saved",
|
|
},
|
|
actions: {
|
|
reconnect: "Reconnect",
|
|
recordLog: "Record log",
|
|
clear: "Clear",
|
|
copy: "Copy",
|
|
recording: "Recording",
|
|
recordingOn: "Log recording started",
|
|
recordingSaved: "Log saved",
|
|
copied: "Copied to clipboard",
|
|
copyEmpty: "Terminal is empty",
|
|
copyFailed: "Copy failed",
|
|
break: "Break",
|
|
breakSent: "Break sent",
|
|
broadcast: "Broadcast",
|
|
broadcastSent: "Sent to all sessions",
|
|
postLogin: "Post-login cmds",
|
|
},
|
|
favorites: "Favorites",
|
|
recent: "Recent",
|
|
favorite: "Toggle favorite",
|
|
encoding: "Encoding",
|
|
fontSize: "Font size",
|
|
theme: "Theme",
|
|
themeDark: "Dark",
|
|
themeLight: "Light",
|
|
colorScheme: "Color scheme",
|
|
backgroundColor: "Background",
|
|
foregroundColor: "Font color",
|
|
scheme: {
|
|
dark: "Deep blue (default)",
|
|
blackWhite: "Black on white",
|
|
whiteBlack: "White on black",
|
|
greenBlack: "Green on black",
|
|
amberBlack: "Amber on black",
|
|
custom: "Custom",
|
|
},
|
|
copyOnSelect: "Copy on select",
|
|
pasteDelay: "Paste max line wait",
|
|
pasteDelayOff: "No delay (bulk send)",
|
|
keepalive: "SSH keepalive",
|
|
keepaliveOff: "Off",
|
|
keepaliveSec: "{{n}} sec",
|
|
options: "Options",
|
|
globalSessionOptions: "Global Session Options",
|
|
sessionOptionsSave: "Save",
|
|
sessionOptionsCancel: "Cancel",
|
|
sessionOptionsSaved: "Global session options saved",
|
|
disconnectBanner: "Session disconnected",
|
|
disconnectBannerError: "Session error or connection lost",
|
|
broadcastPh: "Send to all tabs…",
|
|
buttonBarHint: "One per line: label|command",
|
|
postLoginPrompt: "Post-login commands (one per line, this device)",
|
|
postLoginSaved: "Post-login commands saved",
|
|
sftp: {
|
|
title: "SFTP",
|
|
refresh: "Refresh",
|
|
up: "Up",
|
|
upload: "Upload",
|
|
uploaded: "Upload complete",
|
|
uploading: "Upload {{done}}/{{total}} · {{name}} {{pct}}",
|
|
downloading: "Download {{done}}/{{total}} · {{name}} {{pct}}",
|
|
downloaded: "Downloaded {{count}} file(s)",
|
|
downloadPartial: "Downloaded {{ok}}, failed {{failed}}",
|
|
uploadPartial: "Uploaded {{ok}}, failed {{failed}}",
|
|
retrying: "Retrying {{name}} ({{attempt}}/{{max}})…",
|
|
cancel: "Cancel",
|
|
dropHint: "Drop to upload into current folder",
|
|
dropEmpty: "No uploadable files found",
|
|
mkdir: "New",
|
|
mkdirPrompt: "New folder name",
|
|
mkdirInvalid: "Invalid folder name (no / or ..)",
|
|
mkdirOk: "Folder created",
|
|
rename: "Rename",
|
|
renamePrompt: "New name",
|
|
renameInvalid: "Invalid name (no / or ..)",
|
|
renamed: "Renamed",
|
|
download: "Download",
|
|
chmod: "chmod",
|
|
chmodPrompt: "Mode (e.g. 755 or rwxr-xr-x)",
|
|
chmodOk: "Permissions updated",
|
|
chmodPartial: "chmod ok {{ok}}, failed {{failed}}",
|
|
delete: "Delete",
|
|
deleteConfirm: "Delete {{name}}?",
|
|
deleteRecursiveConfirm: "{{name}} includes folders; non-empty folders will be removed recursively. Continue?",
|
|
deletePartial: "Deleted {{ok}}, failed {{failed}}",
|
|
deleted: "Deleted",
|
|
selectedCount: "{{count}} selected",
|
|
empty: "This folder is empty",
|
|
listTruncated: "Folder is large; showing first {{count}} entries (limit {{max}})",
|
|
dir: "dir",
|
|
loading: "Loading…",
|
|
enterHint: "Click to select; Ctrl/Shift multi-select; double-click to open",
|
|
downloadHint: "Click to select; Ctrl/Shift multi-select; double-click to download",
|
|
colName: "Name",
|
|
colSize: "Size",
|
|
colMtime: "Modified",
|
|
colOwner: "Owner",
|
|
colGroup: "Group",
|
|
colMode: "Access",
|
|
resizeHint: "Drag to resize SFTP / terminal",
|
|
colResizeHint: "Drag to resize column",
|
|
},
|
|
term: {
|
|
findPh: "Find…",
|
|
findPrev: "Previous",
|
|
findNext: "Next",
|
|
findClose: "Close find",
|
|
copy: "Copy",
|
|
paste: "Paste",
|
|
pasteEmpty: "Clipboard is empty",
|
|
pasteFailed: "Cannot read clipboard (on HTTP use the paste box, or Ctrl+V)",
|
|
pasteBridgeHint:
|
|
"This page is not HTTPS, so the browser blocks clipboard reads. Press Ctrl+V in this box to send text to the terminal.",
|
|
pasteBridgePh: "Press Ctrl+V here…",
|
|
pasteBridgeCancel: "Cancel",
|
|
clear: "Clear",
|
|
pasting: "Pasting {{done}}/{{total}} lines…",
|
|
wsError: "[WebSocket error]",
|
|
wsClosed: "[WebSocket closed code={{code}}]",
|
|
sessionStatus: "[session {{state}}{{detail}}]",
|
|
outputTruncated: "[output truncated: {{count}} chunk(s) dropped]",
|
|
},
|
|
err: {
|
|
deviceType: "Unsupported device type",
|
|
ipConflictRestart: "Database still enforces unique IP; restart the netx API and retry",
|
|
sessionLimit: "Session limit reached; close other terminals first",
|
|
neNotFound: "Network element not found",
|
|
credsIncomplete: "Incomplete username/password on this NE",
|
|
authRejected: "Wrong username or password. Please try again.",
|
|
cliProfile: "UME NEs require a CLI connect profile (default account / hop)",
|
|
connectFailed: "Device login failed: {{detail}}",
|
|
sftpHop: "SFTP does not support hop devices yet (direct SSH only)",
|
|
sftpSsh: "SFTP requires SSH",
|
|
sftpNeedPassword: "SFTP needs a saved SSH password (one-shot dialog passwords are not reused for files)",
|
|
sftpUnsupported: "This SSH session has no SFTP channel (device may not offer it)",
|
|
sftpTooLarge: "File exceeds size limit (default 512MB)",
|
|
sftpChmodInvalid: "Invalid mode (use 755 or rwxr-xr-x)",
|
|
sftpAborted: "Transfer cancelled",
|
|
queueDropped: "Terminal output too fast; about {{count}} chunk(s) dropped — transcript may be incomplete",
|
|
websocket: "WebSocket connection failed",
|
|
},
|
|
},
|
|
topology: {
|
|
title: "Topology",
|
|
maps: "Maps",
|
|
tree: "Topology tree",
|
|
treeLoading: "Loading tree…",
|
|
treeLoadFailed: "Failed to load topology tree",
|
|
treeRetry: "Retry",
|
|
graphLoading: "Loading 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",
|
|
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/slices or a new map.",
|
|
truncatedFrozen: "This map membership is frozen; neighbors cannot be projected. Unfreeze in classify/slices 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",
|
|
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 selected ({{count}})",
|
|
removeSelected: "Remove selected ({{count}})",
|
|
openWebcrt: "Open terminal",
|
|
openNe: "NE details",
|
|
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",
|
|
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}}",
|
|
createNeBusy: "Creating…",
|
|
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)",
|
|
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)",
|
|
},
|
|
topoClassify: {
|
|
title: "Classify & slices",
|
|
openTopo: "Topology",
|
|
inventory: "NE inventory",
|
|
keywordPh: "Filter by name/IP",
|
|
filterRoleAll: "All roles",
|
|
filterRegionAll: "All regions",
|
|
filterUnmatchedOff: "No unmatched filter",
|
|
kindAny: "Role or region empty",
|
|
kindRole: "Role empty",
|
|
kindRegion: "Region empty",
|
|
filterLinkAll: "All link states",
|
|
filterLinkLinked: "Linked inventory",
|
|
filterLinkOrphaned: "Detached",
|
|
colLink: "Link",
|
|
linkManaged: "Managed",
|
|
linkUme: "UME",
|
|
linkBoth: "Managed+UME",
|
|
linkOrphaned: "Detached",
|
|
roleCore: "Core",
|
|
roleAggregation: "Aggregation",
|
|
roleAccess: "Access",
|
|
roleUnknown: "Unknown",
|
|
sourceManual: "Manual",
|
|
sourceUmeSync: "UME sync",
|
|
sourceLldp: "LLDP placeholder",
|
|
sourceTopology: "Topology placeholder",
|
|
sourceWebcrt: "WebCRT",
|
|
regexTitle: "Regex find",
|
|
patternPh: "Regex, e.g. ^CORE- or -BJ-",
|
|
fieldName: "Name",
|
|
fieldNameIp: "Name+IP",
|
|
findMatches: "Find matches",
|
|
matchOk: "Matched {{count}}; selected",
|
|
matchHint: "{{count}} matched",
|
|
assignRole: "Role only",
|
|
assignRegion: "Region only",
|
|
assignBoth: "Role + region",
|
|
clearRegion: "Clear region",
|
|
confirmAssign: "Confirm assign",
|
|
bulkConfirm: "Write tags to {{count}} selected/matched NE(s)?",
|
|
bulkOk: "Updated {{count}}",
|
|
selectedCount: "{{count}} selected",
|
|
selectPage: "Select page",
|
|
colNe: "NE",
|
|
colRole: "Role",
|
|
colRegion: "Region",
|
|
colActions: "Actions",
|
|
edit: "Edit",
|
|
save: "Save",
|
|
cancel: "Cancel",
|
|
delete: "Delete",
|
|
deleteSelected: "Delete nodes ({{count}})",
|
|
deleteConfirm:
|
|
"Delete {{count}} fabric node(s) (placements and edges)? Managed/UME inventory is not touched.",
|
|
deleteOk: "Deleted {{count}} node(s)",
|
|
deleteHint:
|
|
"Only orphaned or LLDP/WebCRT placeholder fabric nodes can be deleted; UME-only and real managed NEs cannot",
|
|
deleteBlocked: "UME-only or still linked to real managed inventory — cannot delete here",
|
|
rowSaved: "Saved",
|
|
loading: "Loading…",
|
|
empty: "No NEs.",
|
|
showSlices: "Show slice maps",
|
|
hideSlices: "Hide slice maps",
|
|
slices: "Slice maps",
|
|
pickRegion: "Pick region",
|
|
tplCore: "Core only",
|
|
tplCoreAgg: "Core + neighbor Agg",
|
|
tplAggAcc: "Agg + neighbor Access",
|
|
seedPhysical: "Also place Cores on physical overview",
|
|
slicePreview: "Preview slices",
|
|
sliceApply: "Generate maps",
|
|
sliceConfirm: "Create custom maps and freeze placements?",
|
|
sliceOk: "Created {{count}} slice map(s)",
|
|
sliceStats: "{{maps}} map(s) planned, {{overlap}} NE(s) on multiple maps",
|
|
nodeCount: "{{count}} NE(s)",
|
|
},
|
|
audit: {
|
|
title: "Audit & ops",
|
|
logsTitle: "Operation logs",
|
|
nav: {
|
|
tasks: "Task overview",
|
|
logs: "Operation logs",
|
|
},
|
|
tasks: {
|
|
title: "Task overview",
|
|
hint: "Live view of running or pending background work. Actor prefers recent audit entries; scheduled work shows as scheduler/system.",
|
|
empty: "No tasks to show right now.",
|
|
open: "Open",
|
|
inflight: "running {{n}}",
|
|
kpiActive: "Active / in-flight",
|
|
kpiTotal: "Total rows",
|
|
kpiKinds: "By kind",
|
|
kpiStatuses: "By status",
|
|
colKind: "Kind",
|
|
colTitle: "Task",
|
|
colStatus: "Status",
|
|
colActor: "Actor",
|
|
colTrigger: "Trigger",
|
|
colProgress: "Progress",
|
|
colStarted: "Started",
|
|
colUpdated: "Updated",
|
|
colLink: "Open",
|
|
kind: {
|
|
port_traffic: "Port traffic",
|
|
config_sync: "Config sync",
|
|
ne_collect: "Batch collect",
|
|
lldp_discover: "LLDP discover",
|
|
ume_sync: "UME sync",
|
|
ne_connect: "Connect test",
|
|
ume_runtime: "UME runtime",
|
|
webcrt: "WebCRT",
|
|
},
|
|
trigger: {
|
|
manual: "Manual",
|
|
schedule: "Schedule",
|
|
topology: "Topology",
|
|
system: "System",
|
|
retry_failed: "Retry failed",
|
|
},
|
|
status: {
|
|
collecting: "Collecting",
|
|
running: "Running",
|
|
testing: "Testing",
|
|
connecting: "Logging in",
|
|
ready: "Connected",
|
|
detached: "Detached (grace)",
|
|
pending: "Pending",
|
|
paused: "Paused",
|
|
idle: "Idle",
|
|
error: "Error",
|
|
failed: "Failed",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export default en;
|