Stub raus, vollständige Implementierung analog Unbound/Squid:
* Migration 0015: ntp_settings (single-row mit listen_addresses,
allow_acl, serve_clients, makestep, rtcsync) + ntp_pools (kind
pool|server, address, iburst/prefer, minpoll/maxpoll). Default
4 deutsche pool.ntp.org-Server seeded.
* Models DNSSettings/NTPPool, services/ntp Repo, handlers/ntp.go
REST /api/v1/ntp/{settings,pools} mit Auto-Restart nach Mutation.
* internal/chrony/chrony.cfg.tpl + chrony.go: Renderer schreibt
/etc/chrony/conf.d/edgeguard.conf direkt (analog unbound — distro
chrony.conf included conf.d automatisch). Listen-bind nur wenn
serve_clients=true; sonst port 0 (= Client-only).
* main.go: ntpRepo + chronyReloader injiziert.
* render.go: chrony als sechste generator.
* postinst:
- chrony als hard Depends im control file.
- Conf-Datei /etc/chrony/conf.d/edgeguard.conf wird als
edgeguard:edgeguard 0644 angelegt.
- Sudoers für systemctl reload + restart chrony.
* Auto-FW-Rule-Generator: udp/123 wenn serve_clients=true und
listen_addresses non-loopback enthält.
* Frontend /ntp: PageHeader + Quellen-Tab + Settings-Tab. Listen-
Addresses als Multi-Select aus Kernel-IPs (analog DNS).
* Sidebar-Eintrag unter Network.
* i18n DE/EN für ntp.* Block.
chrony.service hat kein 'reload' — Renderer ruft RestartService auf.
Verified: 4 default-pool-server connected (chronyc sources zeigt
sie nach erstem render).
Version 1.0.40.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
530 lines
22 KiB
JSON
530 lines
22 KiB
JSON
{
|
||
"app": {
|
||
"title": "EdgeGuard",
|
||
"subtitle": "Native reverse-proxy / VPN / firewall"
|
||
},
|
||
"nav": {
|
||
"dashboard": "Dashboard",
|
||
"domains": "Domains",
|
||
"backends": "Backends",
|
||
"routing": "Routing",
|
||
"networks": "Network interfaces",
|
||
"ipAddresses": "IP addresses",
|
||
"ssl": "SSL certificates",
|
||
"vpn": "VPN",
|
||
"wireguard": "WireGuard",
|
||
"forwardProxy": "Forward proxy",
|
||
"dns": "DNS",
|
||
"ntp": "Time (NTP)",
|
||
"firewall": "Firewall",
|
||
"cluster": "Cluster",
|
||
"settings": "Settings",
|
||
"section": {
|
||
"overview": "Overview",
|
||
"routing": "Routing",
|
||
"network": "Network",
|
||
"security": "Security",
|
||
"system": "System"
|
||
}
|
||
},
|
||
"fw": {
|
||
"title": "Firewall",
|
||
"intro": "Fortigate-style: rules built from zones × address objects/groups × services/service groups × action. NAT is separate. Top-down, first-match.",
|
||
"tabs": {
|
||
"rules": "Rules",
|
||
"nat": "NAT",
|
||
"zones": "Zones",
|
||
"addrObj": "Address objects",
|
||
"addrGrp": "Address groups",
|
||
"services": "Services",
|
||
"svcGrp": "Service groups"
|
||
},
|
||
"zone": {
|
||
"name": "Name",
|
||
"description": "Description",
|
||
"builtin": "built-in",
|
||
"builtinHint": "Built-in zones cannot be deleted — the renderer and anti-lockout rules depend on them.",
|
||
"builtinNameLocked": "Name is built-in — cannot be changed because existing rules and interfaces reference it.",
|
||
"namePattern": "Lowercase letters, digits, _ and -; must start with a letter, up to 32 chars.",
|
||
"add": "Add zone",
|
||
"edit": "Edit zone",
|
||
"deleteConfirm": "Really delete zone {{name}}?"
|
||
},
|
||
"ao": {
|
||
"name": "Name", "kind": "Kind", "value": "Value", "description": "Description",
|
||
"add": "Add address object", "edit": "Edit address object",
|
||
"deleteConfirm": "Really delete address object {{name}}?"
|
||
},
|
||
"ag": {
|
||
"name": "Name", "members": "Members", "description": "Description",
|
||
"add": "Add address group", "edit": "Edit address group",
|
||
"selectMembers": "Select address objects",
|
||
"deleteConfirm": "Really delete address group {{name}}?"
|
||
},
|
||
"svc": {
|
||
"name": "Name", "proto": "Protocol", "ports": "Ports",
|
||
"portStart": "Port (start)", "portEnd": "Port (end)",
|
||
"description": "Description", "builtinHint": "Built-in — not editable",
|
||
"add": "Add service", "edit": "Edit service",
|
||
"deleteConfirm": "Really delete service {{name}}?"
|
||
},
|
||
"sg": {
|
||
"name": "Name", "members": "Members", "description": "Description",
|
||
"add": "Add service group", "edit": "Edit service group",
|
||
"selectMembers": "Select services",
|
||
"deleteConfirm": "Really delete service group {{name}}?"
|
||
},
|
||
"rule": {
|
||
"name": "Name", "priority": "Priority", "enabled": "Enabled", "log": "Log",
|
||
"action": "Action", "src": "Source", "dst": "Destination", "service": "Service",
|
||
"srcZone": "Source zone", "dstZone": "Dest. zone",
|
||
"srcKind": "Source kind", "dstKind": "Dest. kind",
|
||
"object": "Address object", "group": "Address group",
|
||
"serviceKind": "Service kind", "serviceGroup": "Service group",
|
||
"comment": "Comment",
|
||
"add": "Add rule", "edit": "Edit rule",
|
||
"deleteConfirm": "Really delete this rule?"
|
||
},
|
||
"nat": {
|
||
"name": "Name", "priority": "Priority", "kind": "Kind", "enabled": "Enabled",
|
||
"match": "Match", "target": "Target",
|
||
"inZone": "Ingress zone", "outZone": "Egress zone", "proto": "Protocol",
|
||
"matchSrcCidr": "Source CIDR (match)", "matchDstCidr": "Dest. CIDR (match)",
|
||
"matchDstCidrHint": "empty = any dest IP (e.g. box's public IP)",
|
||
"dportStart": "Port (start)", "dportEnd": "Port (end)",
|
||
"targetAddr": "Target address", "targetPortStart": "Target port (start)", "targetPortEnd": "Target port (end)",
|
||
"comment": "Comment",
|
||
"add": "Add NAT rule", "edit": "Edit NAT rule",
|
||
"deleteConfirm": "Really delete this NAT rule?"
|
||
},
|
||
"sys": {
|
||
"title": "System rules (always active)",
|
||
"chain": "Chain", "match": "Match", "action": "Action", "note": "Note",
|
||
"policy": "Default policy",
|
||
"policyValue": "Input DROP — everything must be explicitly allowed.",
|
||
"order": "Evaluation",
|
||
"orderValue": "System rules first, then operator rules top-down (priority asc, first-match).",
|
||
"lockout": "Anti-lockout",
|
||
"lockoutValue": "SSH (22) and the management UI (443) are always reachable — even the operator can't accidentally lock themselves out."
|
||
}
|
||
},
|
||
"networks": {
|
||
"title": "Network interfaces",
|
||
"intro": "Manage WAN, LAN, VLAN and bond interfaces. Read-only kernel discovery above; declared configuration below — runtime apply via systemd-networkd lands in a later release.",
|
||
"systemDiscovered": "System interfaces (read-only)",
|
||
"addInterface": "Add interface",
|
||
"editInterface": "Edit interface",
|
||
"name": "Name",
|
||
"type": "Type",
|
||
"parent": "Parent interface",
|
||
"selectParent": "Select parent",
|
||
"vlan": "VLAN",
|
||
"vlanId": "VLAN ID",
|
||
"composition": "Composition",
|
||
"members": "Member interfaces",
|
||
"selectMembers": "Select physical interfaces",
|
||
"membersRequired": "At least one member interface is required",
|
||
"membersHintBridge": "A bridge joins multiple physical ports at L2 — typically two ports for a software switch.",
|
||
"membersHintBond": "A bond aggregates multiple physical ports into one logical link (LACP / active-backup).",
|
||
"role": "Zone",
|
||
"roleHint": "Zones are managed in Firewall → Zones. Custom zones (e.g. iot, guest) can be added there.",
|
||
"mtu": "MTU",
|
||
"active": "Active",
|
||
"description": "Description",
|
||
"actions": "Actions",
|
||
"deleteConfirm": "Really delete interface {{name}}?"
|
||
},
|
||
"ips": {
|
||
"title": "IP addresses",
|
||
"intro": "Addresses the kernel currently has (read-only above) plus addresses EdgeGuard additionally manages — including VIPs that follow the active cluster node on failover.",
|
||
"systemDiscovered": "Kernel addresses (read-only)",
|
||
"managedTitle": "Managed addresses",
|
||
"family": "Family",
|
||
"addAddress": "Add address",
|
||
"editAddress": "Edit address",
|
||
"interface": "Interface",
|
||
"selectInterface": "Select interface",
|
||
"address": "Address",
|
||
"prefix": "Prefix",
|
||
"vip": "VIP",
|
||
"vipFlag": "Mark as VIP",
|
||
"vipPriority": "VIP priority (cluster failover)",
|
||
"active": "Active",
|
||
"description": "Description",
|
||
"actions": "Actions",
|
||
"deleteConfirm": "Really delete address {{addr}}?"
|
||
},
|
||
"auth": {
|
||
"loginTitle": "Sign in",
|
||
"email": "Email",
|
||
"password": "Password",
|
||
"login": "Sign in",
|
||
"logout": "Sign out",
|
||
"loginFailed": "Sign-in failed",
|
||
"loggedInAs": "Signed in as"
|
||
},
|
||
"setup": {
|
||
"title": "First-time setup",
|
||
"intro": "Create the admin account, declare the public FQDN, and — optionally — paste a license key. Without one, a 30-day trial starts.",
|
||
"adminEmail": "Admin email",
|
||
"adminPassword": "Admin password",
|
||
"passwordRule": "At least 12 characters.",
|
||
"fqdn": "Public FQDN",
|
||
"acmeEmail": "ACME / Let's Encrypt email",
|
||
"licenseKey": "License key (optional)",
|
||
"submit": "Finish setup",
|
||
"successTitle": "Setup complete",
|
||
"successHint": "Redirecting you to sign-in."
|
||
},
|
||
"dashboard": {
|
||
"title": "Dashboard",
|
||
"welcomeHint": "Overview of all running EdgeGuard components."
|
||
},
|
||
"domains": {
|
||
"title": "Domains",
|
||
"intro": "Manage FQDNs that HAProxy terminates. Optional primary backend as catch-all; path-based routing via routing rules.",
|
||
"addDomain": "Add domain",
|
||
"editDomain": "Edit domain",
|
||
"name": "Name",
|
||
"active": "Active",
|
||
"primaryBackend": "Primary backend",
|
||
"primaryBackendHint": "Catch-all backend for requests with no matching routing rule. Optional — leave empty if all traffic is routed via routing rules.",
|
||
"selectBackend": "Select backend",
|
||
"noBackend": "no backend",
|
||
"httpToHttps": "HTTP→HTTPS",
|
||
"hsts": "HSTS",
|
||
"notes": "Notes",
|
||
"actions": "Actions",
|
||
"edit": "Edit",
|
||
"delete": "Delete",
|
||
"deleteConfirm": "Really delete domain {{name}}?"
|
||
},
|
||
"backends": {
|
||
"title": "Backends",
|
||
"intro": "Upstream servers HAProxy proxies to. Optional health-check path enables TCP + HTTP probes every 5s.",
|
||
"addBackend": "Add backend",
|
||
"editBackend": "Edit backend",
|
||
"name": "Name",
|
||
"scheme": "Scheme",
|
||
"address": "Address",
|
||
"port": "Port",
|
||
"target": "Target",
|
||
"healthCheck": "Health check path",
|
||
"active": "Active",
|
||
"usedBy": "Used by",
|
||
"noDomain": "no domain",
|
||
"attachedDomains": "Domains",
|
||
"attachedDomainsHint": "Domains that use this backend as their primary. Selecting domains here reconfigures them directly — same source of truth as the Domain modal's backend picker.",
|
||
"selectDomains": "Select domains",
|
||
"actions": "Actions",
|
||
"deleteConfirm": "Really delete backend {{name}}?"
|
||
},
|
||
"routing": {
|
||
"title": "Routing rules",
|
||
"intro": "Path-prefix → backend mapping per domain. Lowest priority wins; catch-all via domain.primary_backend.",
|
||
"addRule": "Add rule",
|
||
"editRule": "Edit rule",
|
||
"domain": "Domain",
|
||
"pathPrefix": "Path prefix",
|
||
"backend": "Backend",
|
||
"priority": "Priority",
|
||
"active": "Active",
|
||
"actions": "Actions",
|
||
"selectDomain": "Select domain",
|
||
"selectBackend": "Select backend",
|
||
"deleteConfirm": "Really delete this routing rule?"
|
||
},
|
||
"cluster": {
|
||
"title": "Cluster",
|
||
"intro": "{{count}} node(s) registered. Multi-node cluster (KeyDB Active-Active + PG streaming replication) coming in a later release.",
|
||
"id": "Node ID",
|
||
"fqdn": "FQDN",
|
||
"role": "Role",
|
||
"joinedAt": "Joined",
|
||
"self": "this node"
|
||
},
|
||
"ssl": {
|
||
"title": "SSL certificates",
|
||
"intro": "Manage TLS certs — let EdgeGuard issue them via Let's Encrypt or upload your own PEM. HAProxy reloads automatically after each change.",
|
||
"tabLE": "Let's Encrypt",
|
||
"tabUpload": "Custom certificate",
|
||
"leIntro": "Pick a domain, click Issue — EdgeGuard solves HTTP-01 over the ACME webroot, writes the PEM into /etc/edgeguard/tls/, and reloads HAProxy.",
|
||
"uploadIntro": "Upload your own certificate. Format: PEM-encoded. Cert + optional chain + private key. EdgeGuard validates cert/key match before writing.",
|
||
"uploadHint": "Tip: for Let's Encrypt renewals don't upload here — use the LE tab.",
|
||
"domain": "Domain",
|
||
"selectDomain": "Pick or type a domain",
|
||
"domainExtra": "Includes the management FQDN (from Setup), cluster nodes and operator domains. You can also type any other domain — as long as DNS resolves to this box.",
|
||
"fqdnHintMgmt": "management FQDN",
|
||
"fqdnHintCluster": "cluster · {{role}}",
|
||
"issuer": "Issuer",
|
||
"status": "Status",
|
||
"expiresIn": "Expires in",
|
||
"expiredAgo": "expired {{days}} days ago",
|
||
"actions": "Actions",
|
||
"issueButton": "Issue certificate",
|
||
"uploadButton": "Upload",
|
||
"issueSuccess": "Certificate issued + installed.",
|
||
"uploadSuccess": "Certificate uploaded + installed.",
|
||
"deleteConfirm": "Delete certificate for {{domain}}? HAProxy falls back to the default cert for this domain.",
|
||
"installedTitle": "Installed certificates",
|
||
"certPem": "Certificate (PEM)",
|
||
"chainPem": "Chain (PEM, optional)",
|
||
"keyPem": "Private key (PEM)"
|
||
},
|
||
"settings": {
|
||
"title": "Settings",
|
||
"intro": "System information and setup status. Editable values come in a later release.",
|
||
"systemInfo": "System",
|
||
"version": "Version",
|
||
"status": "Status",
|
||
"setupInfo": "Setup",
|
||
"adminEmail": "Admin email",
|
||
"fqdn": "FQDN",
|
||
"setupCompleted": "Setup completed"
|
||
},
|
||
"update": {
|
||
"available": "Update available: {{pkg}} {{installed}} → {{available}}",
|
||
"applyNow": "Apply now",
|
||
"applying": "Update in progress …",
|
||
"started": "Update has started — the server will restart shortly."
|
||
},
|
||
"wg": {
|
||
"title": "WireGuard",
|
||
"intro": "WireGuard VPN tunnels. Server mode = we listen for peers; client mode = we dial out to a fixed upstream. Private keys are encrypted at rest.",
|
||
"tabs": { "servers": "Server tunnels", "clients": "Client tunnels" },
|
||
"serverIntro": "Server tunnels host a peer roster — typically employee devices or branch sites. Each peer can be downloaded as a wg-quick.conf or scanned as a QR code.",
|
||
"clientIntro": "Client tunnels connect EdgeGuard to a remote WireGuard server (e.g. HQ datacenter). Allowed IPs control which traffic is routed through the tunnel.",
|
||
"iface": {
|
||
"name": "Name",
|
||
"namePattern": "wg followed by lowercase letters/digits/-, max 15 chars",
|
||
"nameExtra": "Suggested: wg0, wg1, wg-hq …",
|
||
"address": "Address (CIDR)",
|
||
"addressExtra": "Box's tunnel IP, e.g. 10.99.0.1/24 for a /24 pool",
|
||
"listenPort": "Listen port",
|
||
"publicKey": "Public key",
|
||
"privateKey": "Private key (paste)",
|
||
"privateKeyExtra": "Fill in only if not auto-generating — base64 32 bytes. Stored encrypted.",
|
||
"peerEndpoint": "Peer endpoint",
|
||
"peerPublicKey": "Peer public key",
|
||
"peerPSK": "Pre-shared key (PSK)",
|
||
"peerPSKExtra": "Optional extra layer",
|
||
"allowedIPs": "Allowed IPs",
|
||
"allowedIPsExtra": "What gets routed through the tunnel. Default = full tunnel.",
|
||
"keepalive": "Persistent keepalive (sec)",
|
||
"mtu": "MTU",
|
||
"zone": "Firewall zone",
|
||
"description": "Description",
|
||
"addServer": "Add server tunnel",
|
||
"editServer": "Edit server tunnel",
|
||
"addClient": "Add client tunnel",
|
||
"editClient": "Edit client tunnel",
|
||
"upstream": "Upstream peer",
|
||
"deleteConfirm": "Really delete tunnel {{name}}? wg-quick will be stopped.",
|
||
"keys": "Keys",
|
||
"generateExtra": "If on: server generates a fresh Curve25519 keypair on save.",
|
||
"generateOn": "Server-generated",
|
||
"generateOff": "Manual paste",
|
||
"editKeyWarning": "Warning: new keys invalidate all existing peer configs. Only change if intentional."
|
||
},
|
||
"peers": {
|
||
"button": "Peers",
|
||
"drawerTitle": "Peer roster"
|
||
},
|
||
"peer": {
|
||
"name": "Name",
|
||
"publicKey": "Public key",
|
||
"publicKeyExtra": "Generated by the peer device; only paste here if the peer already has a keypair.",
|
||
"allowedIPs": "Allowed IPs",
|
||
"allowedIPsExtra": "Which tunnel IPs this peer is allowed to use. Typically /32 = one IP.",
|
||
"keepalive": "Keepalive (sec)",
|
||
"keepaliveExtra": "0 = off. Recommended 25 behind NAT.",
|
||
"lastHandshake": "Last handshake",
|
||
"never": "never",
|
||
"description": "Description",
|
||
"add": "Add peer",
|
||
"edit": "Edit peer",
|
||
"deleteConfirm": "Really remove peer {{name}}?",
|
||
"keys": "Keys",
|
||
"generateExtra": "If on: server generates a keypair for this peer and can hand out the config / QR. If off: paste the peer's public key only — no config download.",
|
||
"pskExtra": "If on: server generates a 32-byte PSK for this peer.",
|
||
"pskOn": "Generate PSK",
|
||
"pskOff": "no PSK",
|
||
"downloadConf": "Download wg-quick.conf",
|
||
"qrTitle": "WireGuard QR",
|
||
"qrHint": "Scan with the WireGuard app (iOS/Android): \"Add tunnel\" → \"Scan QR code\". Replace the Endpoint placeholder in the downloaded conf before use.",
|
||
"online": "Online",
|
||
"offline": "Offline",
|
||
"traffic": "Traffic"
|
||
}
|
||
},
|
||
"dashboard": {
|
||
"title": "Dashboard",
|
||
"welcomeHint": "EdgeGuard overview — health, counts, live status of the major services.",
|
||
"kpi": {
|
||
"domains": "Domains",
|
||
"backends": "Backends",
|
||
"ifaces": "Interfaces",
|
||
"fwRules": "FW rules",
|
||
"natRules": "NAT rules",
|
||
"wg": "WG connections"
|
||
},
|
||
"wgCard": {
|
||
"title": "WireGuard",
|
||
"empty": "No WG tunnel configured yet."
|
||
},
|
||
"firewallCard": {
|
||
"title": "Firewall",
|
||
"zones": "Zones",
|
||
"activeRules": "{{rules}} active rules · {{nat}} NAT"
|
||
},
|
||
"sslCard": {
|
||
"title": "SSL certificates",
|
||
"total": "Managed certificates",
|
||
"expiringSoon": "{{count}} expiring soon (< 30 days)",
|
||
"allFresh": "All certs have > 30 days remaining."
|
||
},
|
||
"clusterCard": {
|
||
"title": "Cluster",
|
||
"nodes": "Nodes"
|
||
},
|
||
"routingCard": {
|
||
"title": "Routing",
|
||
"domains": "Domains",
|
||
"backends": "Backends",
|
||
"attached": "{{count}}/{{total}} domains have a primary backend"
|
||
},
|
||
"systemCard": {
|
||
"title": "System",
|
||
"version": "Version",
|
||
"api": "API",
|
||
"ifaces": "Interfaces",
|
||
"wg": "WireGuard"
|
||
}
|
||
},
|
||
"ntp": {
|
||
"title": "Time server (Chrony)",
|
||
"intro": "Chrony as time-sync daemon (NTP). Sources on top, listen/serve config on the settings tab. With 'serve_clients' on and LAN-IPs bound, the box itself becomes an NTP server for the LAN.",
|
||
"tabs": { "pools": "Sources", "settings": "Settings" },
|
||
"pool": {
|
||
"kind": "Type",
|
||
"kindPool": "pool — DNS round-robin (multiple servers from A records)",
|
||
"kindServer": "server — single host",
|
||
"address": "Address / host",
|
||
"addressExtra": "FQDN (for pool: 0.de.pool.ntp.org) or IP.",
|
||
"iburst": "iburst",
|
||
"prefer": "prefer",
|
||
"minpoll": "min-poll",
|
||
"maxpoll": "max-poll",
|
||
"options": "Options",
|
||
"description": "Description",
|
||
"add": "Add source",
|
||
"edit": "Edit source",
|
||
"deleteConfirm": "Really delete NTP source {{addr}}?"
|
||
},
|
||
"settings": {
|
||
"intro": "Global chrony settings. Saves reload chrony automatically.",
|
||
"serveClients": "Act as NTP server for clients",
|
||
"serveClientsExtra": "If off: chrony acts as client only (port 0). If on + listen IP: binds UDP/123.",
|
||
"listenAddresses": "Listen addresses",
|
||
"listenAddressesPlaceholder": "Pick IPs (or type)",
|
||
"listenAddressesExtra": "Which IPs chrony binds :123/UDP on. 127.0.0.1+::1 = local only; LAN IPs open for LAN clients (FW rule auto-generated).",
|
||
"allowACL": "Allow ACL (CIDRs)",
|
||
"allowACLExtra": "Who is allowed to ask for NTP time.",
|
||
"makestepSecs": "makestep secs",
|
||
"makestepSecsExtra": "Allow step (vs. slew) when offset > N seconds.",
|
||
"makestepLimit": "makestep limit",
|
||
"rtcsync": "Sync RTC with system time",
|
||
"rtcsyncExtra": "Keep hardware clock in sync every 11 min — after reboot time is roughly correct.",
|
||
"leapsectz": "Leap-sec TZ",
|
||
"leapsectzExtra": "Optional, e.g. 'right/UTC' for leap-sec via tzdata."
|
||
}
|
||
},
|
||
"dns": {
|
||
"title": "DNS (Unbound)",
|
||
"intro": "Unbound resolver on :53. Local zones (authoritative from DNS records) and forward zones (stub-zone to remote resolvers). Default forwarders catch everything else.",
|
||
"tabs": { "zones": "Zones", "settings": "Resolver settings" },
|
||
"zone": {
|
||
"name": "Zone name",
|
||
"nameExtra": "FQDN without leading/trailing dot — e.g. internal.netcell-it.de",
|
||
"type": "Type",
|
||
"typeLocal": "local — authoritative (records here)",
|
||
"typeForward": "forward — stub-zone to remote resolver",
|
||
"forwardTo": "Upstream resolvers",
|
||
"forwardToExtra": "Comma-separated IP list — e.g. '10.0.0.53, 8.8.8.8'",
|
||
"description": "Description",
|
||
"records": "Records …",
|
||
"add": "Add zone",
|
||
"edit": "Edit zone",
|
||
"deleteConfirm": "Really delete zone {{name}} and all its records?"
|
||
},
|
||
"record": {
|
||
"name": "Name",
|
||
"nameExtra": "Relative to zone (e.g. 'mailcow') or FQDN with trailing dot.",
|
||
"type": "Type",
|
||
"value": "Value",
|
||
"valueExtra": "RDATA in text form: A → IP, CNAME → FQDN, MX → 'priority host', TXT → 'string'.",
|
||
"ttl": "TTL (sec)",
|
||
"drawerTitle": "DNS records",
|
||
"add": "Add record",
|
||
"edit": "Edit record",
|
||
"deleteConfirm": "Really delete record {{name}}?"
|
||
},
|
||
"settings": {
|
||
"intro": "Global resolver settings. Saves reload Unbound automatically.",
|
||
"listenAddresses": "Listen addresses",
|
||
"listenAddressesPlaceholder": "Pick IPs (or type)",
|
||
"listenAddressesRequired": "At least one address required.",
|
||
"listenAddressesExtra": "Multi-select from kernel-discovered IPs. 127.0.0.1 + ::1 = local only; LAN iface IPs (e.g. 10.10.20.3) open the resolver to LAN clients. You can also type custom IPs (Enter).",
|
||
"listenPort": "Port",
|
||
"upstreamForwards": "Default forwarders",
|
||
"upstreamForwardsExtra": "Where everything not local goes. Default 1.1.1.1 + 9.9.9.9.",
|
||
"accessACL": "Access ACL (CIDRs)",
|
||
"accessACLExtra": "Who is allowed to use this resolver.",
|
||
"dnssec": "DNSSEC validation",
|
||
"qnameMin": "QName minimisation (privacy)",
|
||
"cacheMin": "Cache min-TTL",
|
||
"cacheMax": "Cache max-TTL"
|
||
}
|
||
},
|
||
"fwd": {
|
||
"title": "Forward proxy (Squid)",
|
||
"intro": "Squid-based forward proxy on :3128. ACLs are evaluated top-down by priority — first match wins. If no rule matches, the default permits only localnet (10/8, 172.16/12, 192.168/16).",
|
||
"helpTitle": "ACL ordering tip",
|
||
"helpBody": "Higher priority = evaluated first. Example: 'deny .badsite.com' (priority 200) before 'allow .com' (priority 100). Values can be lists (multiple lines), regex depending on acl_type.",
|
||
"name": "Name",
|
||
"nameExtra": "Squid-conformant identifier — lowercase + _, no spaces.",
|
||
"aclType": "Type",
|
||
"aclTypeExtra": "What Squid matches (source, domain, port, …).",
|
||
"value": "Value",
|
||
"valueExtra": "Format depends on type — IPs/CIDRs for src/dst, domain with leading dot for dstdomain (.example.com also matches sub.example.com), regex for *_regex types.",
|
||
"action": "Action",
|
||
"priority": "Priority",
|
||
"priorityExtra": "Higher = evaluated first.",
|
||
"comment": "Comment",
|
||
"add": "Add ACL",
|
||
"edit": "Edit ACL",
|
||
"deleteConfirm": "Really delete ACL {{name}}?"
|
||
},
|
||
"common": {
|
||
"yes": "Yes",
|
||
"no": "No",
|
||
"save": "Save",
|
||
"cancel": "Cancel",
|
||
"loading": "Loading …",
|
||
"error": "Error",
|
||
"edit": "Edit",
|
||
"delete": "Delete",
|
||
"deleteConfirm": "Really delete?",
|
||
"search": "Search …",
|
||
"totalRows": "{{count}} rows",
|
||
"active": "Active",
|
||
"inactive": "Inactive",
|
||
"noData": "No data",
|
||
"actions": "Actions",
|
||
"add": "Add",
|
||
"download": "Download",
|
||
"copy": "Copy",
|
||
"copied": "Copied"
|
||
}
|
||
}
|