Files
ryan 497edfd564 refactor(i18n): fragments 为唯一源,主包改为生成物
- 一次性回灌:主包最新内容(含 565 个未同步键)全量写回 6 个 fragment 文件,fragments 成为完整唯一源;新增 core fragment(common/docs/home 等 9 个此前仅存在于主包的命名空间)
- merge-i18n-fragments.mjs 改为从零重建主包(不再以主包为基础),重建结果与原主包语义零差异
- 主包 messages/{zh-CN,en}.json 移出跟踪并加入 .gitignore
- 生成接入入口:predev/prebuild/prebuild:embed/precheck:i18n 钩子 + Makefile code-check 与 checks.sh vitest 前置生成
- 修复既有漂移:configVersions.title 现以 fragments(Config versions)为准
2026-08-16 22:38:50 +08:00

674 lines
28 KiB
JSON

{
"dashboard": {
"title": "Overview",
"generatedAt": "Generated at {time}",
"refresh": "Refresh",
"loadingTitle": "Loading overview",
"loadingDesc": "Aggregating node health, traffic, and capacity metrics...",
"loadFailed": "Failed to load overview: {error}",
"emptyTitle": "No overview data",
"emptyDesc": "The system is running, but there is no aggregated overview to show yet.",
"requestFailed": "Request failed. Please try again later.",
"stats": {
"requests24h": "24h requests",
"requestsMeta": "24h unique visitors {visitors} · errors {errors} · estimated QPS {qps}",
"clusterCapacity": "Cluster capacity",
"avgMemoryHighLoad": "Avg memory {memory} · high-load nodes CPU {cpu} / memory {memoryNodes} / storage {storage}",
"nodeOverview": "Node overview",
"onlineOf": "/ {total} online",
"pending": "Pending {count}",
"unhealthyOffline": "Unhealthy {unhealthy} · offline {offline}"
},
"world": {
"title": "Global stage",
"description": "Summarizes node distribution, source-country heat, and recent runtime status.",
"legendSource": "Source",
"legendHealthy": "Healthy",
"legendPressure": "Under load",
"legendUnhealthy": "Unhealthy",
"modeVisitorSource": "Visitor sources",
"modeNodeCoords": "Node coordinates",
"modeCoverage": "Coverage signal",
"onlineCoverage": "Online coverage",
"onlineHint": "{online}/{total} online",
"runHealth": "Runtime health",
"unhealthyCount": "{count} unhealthy",
"requests24h": "24h requests",
"qpsReported": "QPS {qps} · {count} nodes reporting",
"nodeCoords": "Node coordinates",
"sourceCountries": "{count} source countries",
"fallbackPins": "Preset pins are used when coordinates are missing",
"avgCpu": "Avg CPU",
"highCount": "{count} high",
"avgMemory": "Avg memory",
"highStorage": "High storage",
"offlinePending": "{offline} offline · {pending} pending",
"mapPreparing": "Preparing map",
"mapPreparingDesc": "Loads when it enters the viewport",
"noNodesOverlay": "No nodes yet. Geographic distribution will appear after nodes join."
},
"map": {
"sourceRequests": "Source requests in the last 24 hours {count}",
"presetPin": "Preset pin",
"requestsErrors": "Requests {requests} · errors {errors}",
"eventsStatus": "Active events {events} · node status {status}",
"openrestyStatus": "OpenResty status {status}",
"loadFailed": "Failed to load world map",
"loading": "Loading world map",
"loadFailedDesc": "The ECharts world map failed to register. Refresh and try again.",
"loadingDesc": "Initializing the world map after the first screen is ready.",
"measuring": "Measuring map container size..."
},
"trafficTrend": {
"title": "24-hour request trend",
"description": "Hourly request totals and 2xx/4xx/5xx counts to spot abnormal status spikes.",
"summaryHint": "Last 24 hours",
"requests": "Requests",
"status2xx": "2xx requests",
"status4xx": "4xx requests",
"status5xx": "5xx requests"
},
"capacityTrend": {
"title": "24-hour capacity trend",
"description": "Hourly CPU and memory usage to see whether cluster capacity stays tight.",
"avgCpu": "Avg CPU",
"avgMemory": "Avg memory"
},
"trafficCapacity": {
"title": "24-hour traffic and capacity trend",
"networkHint": "Last 24 hours · from access logs",
"received": "Data received",
"provided": "Data served",
"capacityHint": "Last 24 hours · host capacity · average"
},
"distributions": {
"sourceTitle": "Source distribution",
"sourceDesc": "Top source countries over the last 24 hours.",
"sourceEmpty": "No source distribution data",
"statusTitle": "Status code distribution",
"statusDesc": "Check whether successful responses still dominate and whether errors are rising.",
"statusEmpty": "No status code distribution",
"httpLabel": "HTTP {code}",
"domainTitle": "Top Domain",
"domainDesc": "See which domains concentrate most of the traffic.",
"domainEmpty": "No domain distribution"
},
"nodeHealth": {
"title": "Node health",
"description": "Sorted by active incidents and resource pressure.",
"openNodes": "Open nodes",
"emptyTitle": "No nodes",
"emptyDesc": "After nodes join, this list will show health and capacity summaries.",
"colNode": "Node",
"colStatus": "Status",
"colCpuMem": "CPU / Memory",
"colReqErr": "Requests / Errors",
"colEvents": "Active incidents",
"colHeartbeat": "Last heartbeat",
"colActions": "Actions",
"noGeo": "Map point not configured",
"wsConnected": "WS connected",
"na": "N/A",
"detail": "Details"
},
"nodeRank": {
"title": "Top nodes",
"traffic": "Highest traffic",
"trafficEmpty": "No traffic ranking",
"pressure": "Highest capacity pressure",
"pressureEmpty": "No capacity pressure data"
}
},
"nodes": {
"title": "Nodes",
"applyLogs": "Apply logs",
"create": "Add node",
"listTitle": "Node list",
"refreshNow": "Refresh now",
"loadingList": "Loading nodes...",
"emptyAll": "No nodes yet. Create one to get started.",
"emptyFilter": "No nodes match the current filter",
"updated": "Node updated",
"created": "Node created",
"deleted": "Node deleted",
"deleteTitle": "Delete node",
"deleteDesc": "Delete node “{name}”? You will need to recreate and rejoin it.",
"deleting": "Deleting...",
"confirmDelete": "Delete",
"edit": "Edit",
"delete": "Delete",
"refresh": "Refresh",
"detail": "Details",
"na": "N/A",
"wsConnected": "WS connected",
"wsEstablished": "WebSocket connection established",
"requestFailed": "Request failed. Please try again later.",
"unknown": "Unknown",
"running": "Running",
"liveConfig": "Live config",
"notApplied": "Not applied",
"enabled": "Enabled",
"manual": "Manual",
"lockedSuffix": " (locked)",
"noGeo": "Map point not configured",
"notConfigured": "Not configured",
"ipLine": "IP: {ip}",
"locationLine": "Location: {location}",
"backToList": "Back to nodes",
"missingId": "Missing node ID. Open details from the node list.",
"loadingDetail": "Loading node details...",
"notFound": "Node not found. It may have been deleted or the ID is invalid.",
"syncing": "Syncing...",
"forceSync": "Force sync",
"dispatching": "Dispatching...",
"viewUpgrade": "View upgrade",
"tabOverview": "Overview",
"tabManage": "Status & deploy",
"kpiNodeId": "Node ID",
"kpiLastSeen": "Last heartbeat",
"kpiCurrentConfig": "Current config",
"filter": {
"all": "All nodes",
"descAll": "Showing all nodes.",
"descRelay": "Showing Relay nodes only.",
"descTunnel": "Showing Tunnel nodes only.",
"descEdge": "Showing Edge nodes only."
},
"status": {
"online": "Online",
"pending": "Pending",
"offline": "Offline",
"running": "Running",
"wsConnected": "WS connected"
},
"apply": {
"success": "Success",
"warning": "Warning",
"failed": "Failed",
"none": "N/A"
},
"health": {
"healthy": "Healthy",
"unhealthy": "Unhealthy",
"unknown": "Unknown"
},
"relative": {
"justNow": "Just now",
"minutesAgo": "{count} minutes ago",
"hoursAgo": "{count} hours ago",
"daysAgo": "{count} days ago",
"monthsAgo": "{count} months ago"
},
"uptime": {
"daysHours": "{days}d {hours}h",
"hoursMinutes": "{hours}h {minutes}m",
"minutes": "{minutes}m"
},
"channel": {
"preview": "preview",
"stable": "stable"
},
"table": {
"node": "Node",
"status": "Status",
"version": "Version",
"runHealth": "Runtime health",
"currentVersion": "Current version",
"latestApply": "Latest apply",
"lastSeen": "Last heartbeat",
"actions": "Actions"
},
"editor": {
"editTitle": "Edit node",
"createTitle": "Add node",
"description": "After creating a node, open its details for a dedicated token and deploy command.",
"nodeType": "Node type",
"typeEdge": "Edge node",
"typeRelay": "Relay node",
"typeTunnel": "Tunnel node",
"name": "Node name",
"namePlaceholder": "e.g. edge-hk-01",
"ip": "Node IP",
"ipPlaceholder": "Optional; reported automatically after join",
"lockIp": "Lock IP",
"lockIpDesc": "When enabled, the control plane will not overwrite the IP",
"autoUpdate": "Auto-update Agent",
"autoUpdateDesc": "When enabled, the node pulls stable updates automatically",
"bindPort": "Bind port",
"vhostPort": "VHost port",
"manualGeo": "Manual map point",
"manualGeoDesc": "Used on the overview map",
"geoName": "Location name",
"latitude": "Latitude",
"longitude": "Longitude",
"saving": "Saving...",
"saveEdit": "Save changes",
"createAction": "Add node",
"errName": "Enter a node name",
"errLockIp": "A node IP is required when IP is locked",
"errBindPort": "Enter a valid bind port",
"errVhostPort": "Enter a valid VHost port"
},
"install": {
"edgeTitle": "Edge node deploy",
"edgeDesc": "Use the Agent Token to join an edge node to the control plane.",
"relayTitle": "Relay deploy command",
"relayDesc": "Use the Discovery Token to join an frps relay node to the control plane.",
"tunnelTitle": "Tunnel deploy command",
"tunnelDesc": "Use the Tunnel Token to join an openflared client to the control plane.",
"agentToken": "Agent Token",
"discoveryToken": "Discovery Token",
"tunnelToken": "Tunnel Token",
"scriptLabel": "One-line script (Linux / macOS)",
"dockerLabel": "Docker container deploy",
"copyFailed": "Copy failed. Select the command text manually.",
"copiedScript": "Deploy script copied",
"copiedDocker": "Docker deploy command copied",
"copyScript": "Copy script",
"copyDocker": "Copy Docker",
"nodeId": "Node ID",
"serverUrl": "Server URL (control plane)",
"serverUrlHint": "The script and container will use this address to reach the OpenFlare control plane.",
"noToken": "This node has no access token yet. Refresh later.",
"needServerUrl": "Enter a valid Server URL to generate the deploy command."
},
"update": {
"title": "Agent upgrade",
"description": "Check GitHub releases and dispatch an upgrade. The node runs it after the next heartbeat.",
"currentVersion": "Current version",
"channel": "Release channel",
"updateStatus": "Update status",
"waitingPreview": "Waiting for preview update",
"waitingUpdate": "Waiting for update",
"notRequested": "Not dispatched",
"checking": "Checking releases...",
"hasUpdate": "Update available",
"upToDate": "Already up to date",
"previewRelease": "Preview release",
"stableRelease": "Stable release",
"targetVersion": "Target version",
"notFound": "Not found",
"publishedAt": "Published",
"noNotes": "No release notes",
"viewRelease": "View release",
"checkStable": "Check stable",
"checkPreview": "Check preview",
"upgradePreview": "Upgrade to preview",
"upgradeStable": "Upgrade to stable"
},
"edge": {
"upgrade": "Upgrade Agent",
"restartOpenresty": "Restart OpenResty",
"runStatus": "Runtime status",
"runStatusDesc": "Node online state and OpenResty health",
"openrestyHealth": "OpenResty health",
"lastSeen": "Last heartbeat",
"ip": "IP address",
"geo": "Map point",
"syncTitle": "Config sync",
"syncDesc": "Version catch-up and latest apply result",
"currentVersion": "Current config version",
"latestApply": "Latest apply",
"latestApplyAt": "Latest apply time",
"agentVersion": "Agent version",
"nginxVersion": "Nginx version",
"autoUpdate": "Auto update",
"runtimeMessages": "Runtime messages",
"runtimeMessagesDesc": "Status notes reported by OpenResty and Agent",
"openrestyMessage": "OpenResty status message",
"noExtraError": "No extra error reported.",
"restartPending": "Waiting for the node to restart OpenResty after the next heartbeat.",
"kpiAgent": "Agent version",
"connectionHint": "Current OpenResty connections",
"toastUpdated": "Node updated",
"toastForceSync": "Force-sync dispatched to node {name}",
"toastRestart": "OpenResty restart dispatched to node {name}",
"toastUpgrade": "{channel} upgrade dispatched to node {name}",
"toastDeleted": "Node deleted"
},
"relay": {
"upgrade": "Upgrade Relay",
"runStatus": "Relay runtime",
"runStatusDesc": "frps online state and load summary",
"health": "Relay health",
"connections": "Active connections / proxies",
"portsTitle": "Network ports",
"portsDesc": "frps control plane and HTTP vhost settings",
"bindPort": "Control bind port",
"vhostPort": "VHost HTTP port",
"agentAddr": "Agent access address",
"relayVersion": "Relay version",
"frpsVersion": "frps core version",
"webuiTitle": "FRPS WebUI",
"webuiDesc": "Enable the built-in frps web console and set its listen port",
"enableWebui": "Enable web console",
"enableWebuiHint": "When on, the node starts the built-in frps admin service.",
"webuiPort": "Web console port",
"webuiPortPlaceholder": "e.g. 17500",
"actualPort": "Currently listening on {port} (takes effect on the next heartbeat; default is bind port + 500).",
"openWebui": "Open FRPS WebUI",
"copiedLink": "Link copied",
"copyLink": "Copy link",
"webuiDisabled": "WebUI is disabled or the bind port is not set.",
"metadata": "Node metadata",
"createdAt": "Created",
"updatedAt": "Updated",
"kpiFrps": "frps core",
"connectionHint": "Relay active connections",
"invalidPort": "Port must be between 1 and 65535",
"portSaveFailed": "Failed to update port",
"toastPortSaved": "FRPS WebUI port updated",
"toastUpdated": "Relay node updated",
"toastWebui": "FRPS WebUI setting updated",
"toastForceSync": "Force-sync dispatched to relay {name}",
"toastUpgrade": "{channel} upgrade dispatched to relay {name}",
"toastDeleted": "Relay node deleted",
"deleteTitle": "Delete relay node",
"deleteDesc": "Delete relay node “{name}”? You will need to recreate and rejoin it."
},
"tunnel": {
"upgrade": "Upgrade openflared",
"runStatus": "Tunnel runtime",
"runStatusDesc": "openflared connection and online state",
"flaredStatus": "flared status",
"autoUpdate": "Auto update",
"syncTitle": "Config sync",
"syncDesc": "Tunnel client config catch-up",
"currentVersion": "Current config version",
"latestApply": "Latest apply",
"latestApplyAt": "Latest apply time",
"fileCount": "Synced files",
"fileCountValue": "{count}",
"upgradeStatus": "Upgrade status",
"credentials": "Join credentials",
"credentialsDesc": "Token required by the tunnel client",
"tunnelToken": "Tunnel Token",
"createdAt": "Created",
"updatedAt": "Updated",
"kpiOpenflared": "openflared",
"connectionHint": "Tunnel concurrent connections",
"toastUpdated": "Tunnel node updated",
"toastForceSync": "Force-sync dispatched to tunnel {name}",
"toastUpgrade": "{channel} upgrade dispatched to tunnel {name}",
"toastDeleted": "Tunnel node deleted",
"deleteTitle": "Delete tunnel node",
"deleteDesc": "Delete tunnel node “{name}”? You will need to recreate and rejoin it."
},
"obs": {
"hostname": "Hostname",
"os": "Operating system",
"kernelArch": "Kernel / arch",
"uptime": "Uptime",
"cpu": "CPU",
"cpuCores": "{count} cores",
"totalMemory": "Total memory",
"totalStorage": "Total storage",
"reportedAt": "Reported at",
"eventsTitle": "Health event timeline",
"eventsDesc": "Keeps active and recovered events to help judge runtime health.",
"cleanupLogs": "Clean logs",
"filterAll": "All events",
"filterActive": "Active",
"filterResolved": "Recovered",
"filterEmpty": "No health events for this filter.",
"noMessage": "No detailed message",
"firstTriggered": "First triggered:",
"lastTriggered": "Last triggered:",
"resolvedAt": "Recovered:",
"noEvents": "This node has not reported any health events yet.",
"cleaned": "Cleaned {count} health event logs",
"nothingToClean": "No health event logs to clean",
"loading": "Loading observability data...",
"diag": "Runtime diagnosis",
"activeIssues": "{count} active incidents",
"stable": "Stable",
"noActiveEvents": "No active health events",
"systemCore": "System core",
"uptimeFromProfile": "From the node system profile",
"profileTitle": "System profile",
"profileDesc": "Host and hardware info reported by the node",
"noProfile": "The node has joined but has not reported a full system profile yet.",
"noProfileLong": "The node has joined but has not reported a full system profile yet.",
"snapshotTitle": "Live resource snapshot",
"snapshotDesc": "Latest metrics report",
"realtimeResources": "Live resources",
"memory": "Memory",
"storage": "Storage",
"connections": "Connections",
"snapshotAgo": "Snapshot {time}",
"noSnapshot": "The node has joined but has not reported a resource snapshot yet.",
"noSnapshotLong": "The node has joined but has not reported a resource snapshot yet.",
"cleanupTitle": "Clean health event logs",
"cleanupDesc": "This deletes all health diagnosis history recorded for this node on the control plane. New events will still be reported.",
"cleaning": "Cleaning...",
"confirmCleanup": "Clean",
"windowRequests": "Window requests",
"windowVisitorsHint": "Window unique visitors {visitors} · error rate {rate}%",
"noWindowSummary": "No request window summary",
"capacityPressure": "Capacity pressure",
"needsAttention": "Needs attention",
"normalRange": "Normal",
"cpuStorage": "CPU {cpu} · storage {storage}",
"noResourceSnapshot": "No resource snapshot",
"sourceSignal": "Source signal",
"requestTimes": "{count} requests",
"noSourceDist": "No source distribution data",
"systemInfo": "System info",
"networkTraffic": "Network traffic",
"noActiveIssue": "No active incidents",
"openrestyConn": "OpenResty connections",
"currentConn": "Current connections:",
"throughputHint": "See access-log trends for business throughput (served / received)",
"windowVisitors": "Window unique visitors",
"reqQps": "Requests {requests} · estimated QPS {qps}",
"noTrafficSummary": "No window traffic summary",
"windowErrors": "Window errors",
"errorRate": "Error rate {rate}%",
"noErrorSummary": "No error-rate summary",
"noNetworkSnapshot": "The node has joined but has not reported a network traffic snapshot yet.",
"trafficTrendDesc": "Hourly request and error counts for this node.",
"capacityTrendDesc": "CPU and memory usage for this node over 24 hours.",
"structureTitle": "Request structure",
"structureDesc": "Last 24 hours: which status codes and domains concentrate traffic and errors.",
"mainStatus": "Top status code",
"times": "{count} times",
"noStatusDist": "No status code distribution",
"topDomain": "Top Domain",
"noDomainDist": "No domain distribution",
"resolvedEvents": "Recovered events",
"resolvedHint": "Health events recovered in the last 24 hours",
"statusDist": "Status code distribution",
"distEmpty": "No distribution data",
"unknownLabel": "Unknown"
},
"networkTrend": {
"title": "24-hour network trend",
"description": "Hourly data served / received from access logs; summary is the last-24h total.",
"summaryHint": "Last 24 hours",
"received": "Data received",
"provided": "Data served"
},
"diskIo": {
"title": "24-hour disk IO trend",
"description": "Hourly disk read/write rate (B/s) to spot log amplification, cache jitter, or disk pressure.",
"summaryHint": "Last 24 hours · average rate",
"read": "Disk read",
"write": "Disk write"
}
},
"performance": {
"title": "Performance",
"description": "Manage global OpenResty performance settings. Saving enters the unified config publish flow.",
"preview": "View config preview",
"saved": "Performance settings saved",
"saveFailed": "Save failed",
"loadingAuth": "Loading permissions...",
"forbiddenTitle": "Insufficient permissions",
"forbiddenDesc": "Only administrators can access performance settings.",
"loading": "Loading performance settings...",
"runtimeTitle": "Connections and events",
"runtimeDesc": "Workers, timeouts, and request body size",
"proxyTitle": "Proxy buffers and timeouts",
"proxyDesc": "Upstream connections, buffers, and WebSocket/HTTP3 switches",
"gzipTitle": "Compression",
"cacheTitle": "Cache",
"cacheDesc": "Single-node reverse-proxy cache",
"errors": {
"workerProcesses": "worker_processes must be auto or an integer greater than 0",
"timeouts": "Timeout and connection values must be integers greater than 0",
"statusCode": "Default server return status must be between 100 and 999",
"bodySize": "Invalid client_max_body_size format",
"headerBuffers": "large_client_header_buffers must look like \"4 16k\"",
"proxyTimeouts": "Proxy timeouts must be integers greater than 0 seconds",
"proxyBuffers": "proxy_buffers must look like \"16 16k\"",
"bufferSize": "Buffer sizes must be integers or values with k/m/g units",
"gzipMinLength": "gzip_min_length must be an integer greater than 0",
"gzipLevel": "gzip_comp_level must be between 1 and 9",
"cachePath": "proxy_cache_path is required when cache is enabled",
"cacheFormat": "Invalid cache levels, inactive, max_size, or lock_timeout format",
"cacheKey": "A cache key template is required when cache is enabled"
}
},
"applyLogs": {
"title": "Apply logs",
"description": "Inspect successful, warning, and failed config applies. Filter by node_id.",
"refresh": "Refresh",
"clear": "Clear logs",
"backToNodes": "Back to nodes",
"totalRecords": "Total records",
"currentPage": "Current page",
"totalPages": "Total pages",
"pageNodes": "Nodes on this page",
"nodeId": "Node ID",
"nodePlaceholder": "Filter apply logs by node_id",
"pageSize": "Page size",
"pageSizeOption": "{count}",
"filter": "Filter",
"reset": "Reset filters",
"emptyTitle": "No apply logs",
"emptyDesc": "No apply records match the current filters.",
"colNodeId": "Node ID",
"colVersion": "Version",
"colResult": "Result",
"colChecksum": "Checksum",
"colTime": "Time",
"colMessage": "Message",
"colActions": "Actions",
"detail": "Details",
"pageInfo": "Page {current} / {total}, {count} records.",
"prev": "Previous",
"next": "Next",
"loadFailed": "Load failed",
"cleared": "Apply logs cleared",
"clearedDesc": "Deleted {count} records",
"clearFailed": "Failed to clear apply logs",
"unknownError": "Unknown error",
"clearTitle": "Clear all apply logs?",
"clearDesc": "This deletes all {count} apply log records and cannot be undone. Nodes will continue to report new apply results.",
"clearing": "Clearing...",
"confirmClear": "Clear",
"success": "Success",
"warning": "Warning",
"failed": "Failed",
"sheetTitle": "Apply log details",
"sheetDesc": "Full result and checksum details for this apply log.",
"versionBadge": "Version: {version}",
"createdAt": "Created",
"targetChecksum": "Target Checksum",
"mainChecksum": "Main config digest",
"routeChecksum": "Route config digest",
"supportFiles": "Support files",
"message": "Message",
"close": "Close"
},
"configVersions": {
"title": "Release versions",
"description": "Browse historical snapshots, preview pending diffs, and reactivate an older version when needed.",
"refresh": "Refresh",
"cleanupOld": "Clean",
"viewDiff": "Diff",
"forcePublish": "Force publish",
"previewPublish": "Publish",
"emptyTitle": "No history",
"emptyDesc": "There are no published versions yet. Publish a config first.",
"colVersion": "Version",
"colStatus": "Status",
"colAuthor": "Created by",
"colChecksum": "Checksum",
"colCreatedAt": "Created",
"colActions": "Actions",
"active": "Active",
"history": "History",
"system": "System",
"snapshot": "Snapshot",
"activate": "Activate",
"loadFailed": "Load failed",
"previewLoadFailed": "Failed to load preview",
"diffLoadFailed": "Failed to load diff",
"publishSuccess": "Published",
"publishSuccessDesc": "Version {version}",
"publishFailed": "Publish failed",
"activateSuccess": "Activated",
"activateSuccessDesc": "Version {version}",
"activateFailed": "Activate failed",
"cleanupDone": "Cleanup complete",
"cleanupDoneDesc": "Deleted {count} historical snapshots",
"cleanupFailed": "Cleanup failed",
"unknownError": "Unknown error",
"confirmPublishTitle": "Publish config",
"confirmPublishDesc": "This creates a new version from the pending config and marks it active. Nodes will pull the update next.",
"confirmPublish": "Publish",
"confirmForceTitle": "Force publish",
"confirmForceDesc": "This ignores the change check and immediately creates a new version. Confirm you really need to republish.",
"confirmActivateTitle": "Activate version",
"confirmActivateDesc": "Set version {version} as the active version?",
"confirmActivate": "Activate",
"previewTitle": "Publish preview",
"previewDesc": "Rendered pending config and support files.",
"loadingPreview": "Loading preview...",
"routeCount": "{count} routes",
"websiteCount": "{count} websites",
"mainConfig": "Main config",
"routeConfig": "Route config",
"supportFiles": "Support files ({count})",
"noSupportFiles": "This publish has no extra support files.",
"noChanges": "Pending routes match the active version, so it cannot be published again.",
"close": "Close",
"publishing": "Publishing...",
"diffTitle": "Config diff",
"diffDesc": "Differences between the pending config and the active version.",
"loadingDiff": "Loading diff...",
"activeVersion": "Active version",
"none": "None",
"addedDomains": "Added domains",
"removedDomains": "Removed domains",
"modifiedDomains": "Modified domains",
"itemCount": "{count}",
"noChange": "No changes",
"emptyValue": "empty",
"mainChanged": "Main config changed",
"mainUnchanged": "Main config unchanged",
"wafChanged": "WAF changed",
"wafUnchanged": "WAF unchanged",
"websiteDelta": "Websites {from} → {to}",
"optionKey": "Option",
"activeValue": "Active value",
"pendingValue": "Pending value",
"noOptionChanges": "No OpenResty option changes.",
"snapshotTitle": "Version snapshot",
"snapshotVersion": "Version {version}",
"snapshotDesc": "Full snapshot of this historical config version.",
"loadingSnapshot": "Loading snapshot...",
"createdBy": "Created by",
"createdAt": "Created",
"snapshotLoadFailed": "Failed to load version snapshot",
"cleanupTitle": "Clean historical snapshots",
"cleanupDesc": "Delete older snapshots. The currently active version is always protected.",
"keepCount": "Keep latest snapshots",
"keepHint": "Default 10, minimum 3.",
"keepMin": "Keep at least 3 historical snapshots",
"cleaning": "Cleaning...",
"confirmCleanup": "Clean"
}
}