shanshanzhong 7400137b3c
Some checks failed
Build and Release / Build (push) Has been cancelled
feat: 节点/服务器批量编辑 Sheet、Server 表单协议合并修复、设备类型解析
- 新增 NodeBatchSheet 与 ServerBatchSheet,支持批量选中后一键编辑公共字段
- Server 表单:引入 mergeProtocol / buildSanitizedProtocols,过滤空字符串避免 Zod 枚举校验失败;renderGroupCard 改为具名导出供批量 Sheet 复用;优化嵌套错误提示递归取第一条
- 新增 parseDeviceType 工具函数,从 User-Agent 解析设备平台(iPhone/Android/Mac 等)
- 用户列表:登录标识旁展示设备平台 Badge
- 注册安全设置表单:引入 Textarea 组件并完善字段布局
- 类型定义补充及 i18n 本地化更新

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 05:17:01 -07:00

131 lines
6.1 KiB
JSON

{
"all": "All",
"cancel": "Cancel",
"confirm": "Confirm",
"confirmDelete": "Are you sure you want to delete?",
"copy": "Copy",
"copySuccess": "Copied successfully",
"create": "Create",
"createSubscribe": "Create Subscription",
"createSuccess": "Create Successful",
"currentUserGroup": "Current User Group",
"defaultNodeGroup": "Default Node Group",
"delete": "Delete",
"nodeGroups": "Node Groups",
"nodes": "nodes",
"deleteSuccess": "Delete Successful",
"deleteWarning": "Data cannot be recovered after deletion. Please proceed with caution.",
"deviceLimit": "IP Limit",
"edit": "Edit",
"editSubscribe": "Edit Subscription",
"form": {
"annualReset": "Annual Reset",
"basic": "Basic",
"cancel": "Cancel",
"confirm": "Confirm",
"Day": "Day",
"deductionRatio": "Automatic/Manual Deduction Configuration",
"deductionRatioDescription": "Used for deduction. By default, the system adopts an automatic calculation algorithm. When a manual ratio is provided, the system calculates proportions based on the time and traffic ratio, ensuring the total equals 100%.",
"description": "Description",
"deviceLimit": "IP Limit",
"discount": "Discount",
"discount_price": "Discount Price",
"discountDescription": "Set discount based on unit price",
"discountPercent": "Discount Percentage",
"appleProductId": "Apple Product ID",
"Hour": "Hour",
"inventory": "Subscription Limit",
"language": "Language",
"languageDescription": "Leave empty for default without language restriction",
"languagePlaceholder": "Language identifier for the subscription, e.g., en-US, zh-CN",
"Minute": "Minute",
"Month": "Month",
"monthlyReset": "Monthly Reset",
"name": "Name",
"node": "Node",
"nodeGroup": "Node Group",
"nodeGroups": "Node Groups",
"nodeGroupsDescription": "Assign this product to multiple node groups. Users will get nodes from these groups.",
"nodeGroupsFirstSelectionDescription": "Select node groups for this product. The first selected group will be set as the default node group.",
"defaultNodeGroup": "Default Node Group",
"defaultNodeGroupDescription": "Select the default node group for this product. This will be automatically included in the backup node groups.",
"selectDefaultNodeGroup": "Select a default node group...",
"noDefaultNodeGroup": "No Default Node Group",
"backupNodeGroups": "Backup Node Groups",
"backupNodeGroupsDescription": "Select additional backup node groups. The default node group is automatically included.",
"nodes": "Linked Nodes",
"nodesDescription": "Select nodes for this subscription",
"nodesInGroup": "Nodes in this group:",
"nodesWithoutGroupsDescription": "Nodes without group assignment will be shown here (nodes that belong to groups are managed in the Node Groups section above)",
"noLimit": "No Limit",
"NoLimit": "No Limit",
"noReset": "No Reset",
"pricing": "Pricing",
"purchaseWithDiscount": "Allow Deduction",
"purchaseWithDiscountDescription": "Enable or disable unsubscribe functionality. After activation, the system will perform deduction processing according to the configured rules and proportions, and the remaining value will be returned to the balance",
"quota": "Purchase Limit",
"renewalReset": "Renewal Reset",
"renewalResetDescription": "Reset cycle upon renewal",
"replacement": "Reset Price (per time)",
"resetCycle": "Reset Cycle",
"resetOn1st": "Reset on the 1st",
"selectResetCycle": "Please select a reset cycle",
"selectUnitTime": "Please select a unit of time",
"showOriginalPrice": "Show Original Price",
"showOriginalPriceDescription": "When enabled, the subscription card will display both the original price and the discounted price to help users understand the discount amount",
"speedLimit": "Speed Limit ",
"traffic": "Traffic",
"trafficLimit": "Traffic Limit",
"trafficLimitRules": "Traffic Limit Rules",
"trafficLimitDescription": "Configure traffic-based speed limit rules. When traffic usage reaches the specified amount, the speed will be limited.",
"addTrafficLimitRule": "Add Traffic Limit Rule",
"statType": "Statistics Type",
"selectStatType": "Select type...",
"statTypeHour": "Hour",
"statTypeDay": "Day",
"statValue": "Time Value",
"trafficUsage": "Traffic Usage (GB)",
"speedLimitKb": "Speed Limit (kb)",
"unitPrice": "Unit Price",
"unitTime": "Unit Time",
"unlimitedInventory": "Unlimited (enter -1)",
"Year": "Year"
},
"groupMapping": "Group Mapping",
"groupMappingTitle": "Group Mapping",
"groupMappingUpdateFailed": "Failed to update group mapping",
"groupMappingUpdateSuccess": "Group mapping updated successfully",
"migrateUsers": "Migrate Users",
"migrateUsersTitle": "Migrate Users",
"migrateUsersDescription": "Migrate all users from the current user group to another group",
"migrateUsersWarning": "This will migrate {count} users from \"{group}\" to the target group. This action cannot be undone.",
"migrateUsersSuccess": "Successfully migrated {count} users to the target group",
"migrateUsersFailed": "Failed to migrate users",
"targetUserGroup": "Target User Group",
"selectTargetGroup": "Select a target group...",
"selectTargetGroupFirst": "Please select a target group first",
"cannotMigrateToSameGroup": "Cannot migrate to the same group",
"noSourceGroup": "No source group available",
"selectedGroup": "Selected Group",
"userCount": "User Count",
"migrating": "Migrating...",
"inventory": "Subscription Limit",
"language": "Language",
"loading": "Loading...",
"name": "Name",
"noMapping": "No mapping set",
"noNodes": "No nodes in this group",
"quota": "Purchase Limit/Time",
"replacement": "Reset Price/Time",
"save": "Save",
"selectGroupPlaceholder": "Select a group...",
"selectUserGroup": "Select User Group",
"sell": "Sell",
"show": "Display",
"sold": "Subscription Count",
"sortSuccess": "Sort completed successfully",
"traffic": "Traffic",
"unitPrice": "Unit Price",
"updateSuccess": "Update Successful"
}