// Bilingual i18n dictionary for app.html
const APP_I18N = {
en: {
common: {
search: "Search…",
save: "Save",
cancel: "Cancel",
delete: "Delete",
online: "online",
offline: "offline",
signOut: "Sign out",
settings: "Settings",
language: "Language",
theme: "Theme",
light: "Light",
dark: "Dark",
backToSite: "Back to site",
upgrade: "Upgrade",
},
roles: {
owner: "Owner",
editor: "Editor",
reader: "Reader",
},
plans: { free: "Basic", pro: "Pro", enterprise: "Enterprise" },
nav: {
networks: "Network",
support: "Support",
},
networks: {
title: "Networks",
new: "New network",
name: "Name",
cidr: "CIDR",
plan: "Plan",
devices: "Devices",
lastActivity: "Last activity",
},
network: {
devicesTab: "Devices",
topologyTab: "Topology",
performanceTab: "Performance",
routesTab: "Routes",
dnsTab: "MagicDNS",
aclTab: "ACL",
qosTab: "QoS",
netflowTab: "Traffic",
auditTab: "Audit",
billingTab: "Billing",
settingsTab: "Settings",
ruleSrc: "src",
ruleDst: "dst",
ruleVia: "via",
ruleNat: "NAT",
ruleAction: "action",
ruleKind: "kind",
routesAdvTitle: "Route advertisements",
routesAdvHelp: "Each node (node:xxx) advertises CIDRs it can reach inside the mesh. Nodes install accepted advertisements as system routes.",
routesAdvBy: "advertised by",
routesAdvType: "type",
routesStatus: "status",
routesCidr: "route",
routesMasqTitle: "Masquerade rules",
routesMasqHelp: "Pin out-of-mesh traffic to a specific egress node. Src is node:xxx or a CIDR. Dst is anything NOT covered by an advertisement — L3: external CIDR; L7: hostname (wildcard / regex). Toggle NAT on the via node if needed.",
routesRule: "Rule",
aclTitle: "ACL rules",
aclRule: "Rule",
aclHelp: "Filter traffic. Src is node:xxx or CIDR. Dst is node:xxx, CIDR, or hostname (wildcard / regex — L7 only). Default deny. Top-down evaluation; first match wins.",
dnsHelp: "MagicDNS serves *.widewired hostnames from node gossip. No resolver config needed.",
qosHelp: "QoS rules tag matching flows with DSCP and enforce rate limits at each node. Applied at egress on the sending node.",
qosRules: "Rules",
qosAdd: "Rule",
qosMatch: "match",
qosDscp: "DSCP",
qosRate: "rate",
qosPriority: "priority",
netflowChart: "Throughput · last 60 min (Mbps)",
netflowProto: "Protocol mix",
netflowTop: "Top flows",
netflowPair: "pair",
netflowProtoCol: "proto/port",
netflowBytes: "bytes",
netflowFlows: "flows",
netflowSearch: "Search flows…",
netflowAllProto: "all protocols",
netflowAllPeer: "all nodes",
installCode: "Config code",
installCopy: "Copy",
installRegen: "Regenerate",
installExpiry: "Expires in 14:52",
auditTitle: "Audit log",
auditAllActions: "all actions",
auditTimestamp: "timestamp",
auditAction: "action",
auditSubject: "subject",
auditActor: "actor",
auditIp: "ip",
devicesTitle: "Devices",
exportCsv: "Export CSV",
approve: "Approve",
revoke: "Revoke",
pending: "pending",
deviceColumns: ["name", "ip", "os", "status", "last seen"],
membersTitle: "Members",
membersHelp: "Invite users to this network. Each member gets a per-network role: Owner manages billing & settings, Editor edits config, Reader has read-only access.",
addressTitle: "Network CIDR",
addressHelp: "The network CIDR defines the IP pool assigned to nodes. Changing the CIDR re-addresses every node on next handshake.",
addressNetwork: "Network",
addressUsable: "Usable",
addressHosts: "hosts",
addressUsed: "Assigned",
settingsGeneral: "General",
tokensTitle: "API tokens",
deleteBody: "Deleting this network removes all devices, ACL, DNS, NetFlow history, and invoices. This cannot be undone.",
},
topology: {
graph: "Graph",
},
matrix: {
title: "Connectivity matrix",
legend: ["direct", "user_relay", "managed_relay", "unreachable"],
selected: "selected",
rtt: "rtt",
loss: "loss",
path: "path",
hint: "Click a cell to inspect the pair. Hover for RTT.",
},
members: {
invite: "Invite",
member: "member",
role: "Role",
joined: "Joined",
lastSeen: "Last seen",
inviteEmail: "Email",
inviteRole: "Role",
sendInvite: "Send invite",
},
billing: {
invoices: "Invoices",
invoiceDate: "Date",
invoiceAmount: "Amount",
invoiceItem: "Item",
invoiceStatus: "Status",
invoiceDownload: "PDF",
current: "current",
downgrade: "Downgrade",
freeBlurb: "Up to 10 devices · community support",
proBlurb: "Up to 100 devices · managed_relay · IPSec bridge",
entBlurb: "Unlimited devices · SSO · audit export · SLA",
infoTitle: "Billing information",
company: "Company",
taxId: "Tax ID / VAT",
address1: "Street address",
city: "City",
postal: "Postal code",
country: "Country",
email: "Billing email",
method: "Payment method",
update: "Update",
},
tokens: {
accountHint: "Account-level token. Authenticates as your user across every network you can access. Treat it like a password.",
networkHint: "Network-level token. Scoped to this network only — it cannot read or modify any other network.",
add: "Token",
revoke: "revoke",
colName: "name",
colToken: "token",
colScopes: "scopes",
colCreated: "created",
colExpires: "expires",
},
settings: {
title: "Settings",
account: "Account",
name: "Name",
email: "Email",
mfa: "Multi-factor authentication",
mfaOn: "Enabled",
configure: "Configure",
password: "Password",
passwordHint: "Last changed 2026-02-04",
changePassword: "Change password",
dangerZone: "Danger zone",
deleteBody: "Deleting your account removes you from every network. Networks you solely own will be archived. This cannot be undone.",
deleteMe: "Delete my account",
tokensTitle: "API tokens",
},
support: {
newTicket: "New ticket",
opened: "opened",
subject: "subject",
state: "state",
lastUpdate: "last update",
},
},
zh: {
common: {
search: "搜索…",
save: "保存",
cancel: "取消",
delete: "删除",
online: "在线",
offline: "离线",
signOut: "退出登录",
settings: "设置",
language: "语言",
theme: "主题",
light: "浅色",
dark: "深色",
backToSite: "返回官网",
upgrade: "升级",
},
roles: {
owner: "所有者",
editor: "编辑",
reader: "只读",
},
plans: { free: "基础版", pro: "专业版", enterprise: "企业版" },
nav: {
networks: "网络",
support: "支持",
},
networks: {
title: "网络",
new: "新建网络",
name: "名称",
cidr: "网段",
plan: "计划",
devices: "设备",
lastActivity: "最近活动",
},
network: {
devicesTab: "设备",
topologyTab: "拓扑",
performanceTab: "性能",
routesTab: "路由",
dnsTab: "MagicDNS",
aclTab: "ACL",
qosTab: "QoS",
netflowTab: "流量",
auditTab: "审计",
billingTab: "账单",
settingsTab: "设置",
ruleSrc: "来源",
ruleDst: "目标",
ruleVia: "出口",
ruleNat: "NAT",
ruleAction: "动作",
ruleKind: "类型",
routesAdvTitle: "路由宣告",
routesAdvHelp: "每个节点(node:xxx)宣告它在网内可达的网段。被接受的宣告会作为系统路由安装到各 node。",
routesAdvBy: "宣告设备",
routesAdvType: "类型",
routesStatus: "状态",
routesCidr: "网段",
routesMasqTitle: "伪装规则",
routesMasqHelp: "将网外流量固定到指定出口节点。来源为 node:xxx 或 CIDR;目标为不在路由宣告范围内的对象 —— L3:外部网段;L7:域名(通配符或正则)。需要时在出口节点开启 NAT。",
routesRule: "规则",
aclTitle: "ACL 规则",
aclRule: "规则",
aclHelp: "过滤流量。来源为 node:xxx 或 CIDR;目标为 node:xxx、CIDR 或域名(通配符 / 正则,仅 L7)。默认拒绝;规则按顺序匹配,命中即停。",
dnsHelp: "MagicDNS 通过 node gossip 服务 *.widewired 主机名,客户端无需配置解析器。",
qosHelp: "QoS 规则为匹配的流打 DSCP 标记,并在每个 node 上执行速率限制。在发送端出方向生效。",
qosRules: "规则",
qosAdd: "规则",
qosMatch: "匹配",
qosDscp: "DSCP",
qosRate: "速率",
qosPriority: "优先级",
netflowChart: "吞吐 · 近 60 分钟(Mbps)",
netflowProto: "协议分布",
netflowTop: "头部流量",
netflowPair: "通信对",
netflowProtoCol: "协议/端口",
netflowBytes: "字节数",
netflowFlows: "流数",
netflowSearch: "搜索流量…",
netflowAllProto: "全部协议",
netflowAllPeer: "全部 node",
installCode: "配置码",
installCopy: "复制",
installRegen: "重新生成",
installExpiry: "14:52 后失效",
auditTitle: "审计日志",
auditAllActions: "全部动作",
auditTimestamp: "时间",
auditAction: "动作",
auditSubject: "对象",
auditActor: "操作人",
auditIp: "IP",
devicesTitle: "设备",
exportCsv: "导出 CSV",
approve: "批准",
revoke: "撤销",
pending: "待审批",
deviceColumns: ["名称", "IP", "系统", "状态", "最后在线"],
membersTitle: "成员",
membersHelp: "邀请用户加入本网络。每位成员拥有网络内角色:所有者可管理账单与设置,编辑可修改配置,只读仅可查看。",
addressTitle: "网络 CIDR",
addressHelp: "网段定义了分配给 node 的 IP 池。修改网段后,各 node 将在下次握手时重新分配地址。",
addressNetwork: "网络",
addressUsable: "可用",
addressHosts: "主机数",
addressUsed: "已分配",
settingsGeneral: "基本",
tokensTitle: "API Token",
deleteBody: "删除本网络将移除所有设备、ACL、DNS、NetFlow 历史与发票。此操作不可撤销。",
},
topology: {
graph: "拓扑图",
},
matrix: {
title: "连通矩阵",
legend: ["直连", "自有中继", "托管中继", "不可达"],
selected: "选中",
rtt: "RTT",
loss: "丢包",
path: "路径",
hint: "点击单元格查看详情。悬停查看 RTT。",
},
members: {
invite: "邀请",
member: "成员",
role: "角色",
joined: "加入时间",
lastSeen: "最后在线",
inviteEmail: "邮箱",
inviteRole: "角色",
sendInvite: "发送邀请",
},
billing: {
invoices: "发票",
invoiceDate: "日期",
invoiceAmount: "金额",
invoiceItem: "项目",
invoiceStatus: "状态",
invoiceDownload: "PDF",
current: "当前",
downgrade: "降级",
freeBlurb: "最多 10 台设备 · 社区支持",
proBlurb: "最多 100 台设备 · 托管中继 · IPSec 桥接",
entBlurb: "无限设备 · SSO · 审计导出 · SLA",
infoTitle: "账单信息",
company: "公司名称",
taxId: "税号 / VAT",
address1: "详细地址",
city: "城市",
postal: "邮编",
country: "国家 / 地区",
email: "账单邮箱",
method: "支付方式",
update: "更新",
},
tokens: {
accountHint: "账号级 Token。以你账号身份访问所有可见网络,请像保管密码一样妥善保管。",
networkHint: "网络级 Token。仅作用于本网络,无法读取或修改其他网络。",
add: "Token",
revoke: "撤销",
colName: "名称",
colToken: "Token",
colScopes: "权限",
colCreated: "创建时间",
colExpires: "过期时间",
},
settings: {
title: "设置",
account: "账号",
name: "姓名",
email: "邮箱",
mfa: "多因素认证",
mfaOn: "已启用",
configure: "配置",
password: "密码",
passwordHint: "上次修改 2026-02-04",
changePassword: "修改密码",
dangerZone: "危险操作",
deleteBody: "删除账号后你将被移出所有网络。由你独自拥有的网络将被归档。此操作不可撤销。",
deleteMe: "删除我的账号",
tokensTitle: "API Token",
},
support: {
newTicket: "新建工单",
opened: "创建时间",
subject: "主题",
state: "状态",
lastUpdate: "最近更新",
},
},
};
window.APP_I18N = APP_I18N;