Compare commits

..

2 Commits

Author SHA1 Message Date
Owen Schwartz
70c10f56b6 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-17 09:56:51 -07:00
Owen Schwartz
c63f26c095 New translations en-us.json (Chinese Simplified)
[ci skip]
2026-06-17 07:48:43 -07:00
4 changed files with 38 additions and 91 deletions

View File

@@ -72,7 +72,7 @@
"siteManageSites": "管理站点",
"siteDescription": "创建和管理站点,启用与私人网络的连接",
"sitesBannerTitle": "连接任何网络",
"sitesBannerDescription": "站点是连接到远程网络的接,允许Pangolin用户提供资源访问,无论是公共还是私人。可以在任何可以运行二进制文件或容器的地方安装站点网络连接器Newt以建立连接。",
"sitesBannerDescription": "站点是到远程网络的接,使 Pangolin 能够向任何位置的用户提公共或私有的资源访问。你可以在任何能够运行二进制文件或容器的地方安装站点网络连接器Newt以建立连接。",
"sitesBannerButtonText": "安装站点",
"approvalsBannerTitle": "批准或拒绝设备访问",
"approvalsBannerDescription": "审核、批准或拒绝用户的设备访问请求。 当需要设备批准时,用户必须先获得管理员批准,然后他们的设备才能连接到您的组织资源。",
@@ -204,11 +204,11 @@
"proxyResourceTitle": "管理公共资源",
"proxyResourceDescription": "创建和管理可通过 Web 浏览器公开访问的资源",
"publicResourcesBannerTitle": "基于 Web 的公共访问",
"publicResourcesBannerDescription": "公共资源是 HTTPS 代理,可以通过网络浏览器在互联网上的任何人访问。与私人资源不同,它们不需要客户端软件,并且可以包含身份和上下文感知的访问策略。",
"publicResourcesBannerDescription": "公共资源是 HTTPS 代理,可供互联网上的任何人通过 Web 浏览器访问。与私人资源不同,它们不需要客户端软件,并且可以包含身份和上下文感知的访问策略。",
"clientResourceTitle": "管理私有资源",
"clientResourceDescription": "创建和管理只能通过连接客户端访问的资源",
"privateResourcesBannerTitle": "零信任的私人访问",
"privateResourcesBannerDescription": "私资源使用零信任安全,确保只允许明确授的用户和机器访问资源。可以连接用户设备或机器客户端通过安全的虚拟专用网络访问这些资源。",
"privateResourcesBannerTitle": "零信任私有访问",
"privateResourcesBannerDescription": "私资源用零信任安全机制,确保只有获得明确授的用户和机器才能访问。用户设备或机器客户端连接后,即可通过安全的虚拟专用网络访问这些资源。",
"resourcesSearch": "搜索资源...",
"resourceAdd": "添加资源",
"resourceErrorDelte": "删除资源时出错",
@@ -327,7 +327,7 @@
"passToAuth": "传递至认证",
"orgSettingsDescription": "配置组织设置",
"orgGeneralSettings": "组织设置",
"orgGeneralSettingsDescription": "管理机构的详细信息和配置",
"orgGeneralSettingsDescription": "管理组织的详细信息和配置",
"saveGeneralSettings": "保存常规设置",
"saveSettings": "保存设置",
"orgDangerZone": "危险区域",
@@ -381,7 +381,7 @@
"accessApprovalsDescription": "查看和管理待审批的组织访问权限",
"description": "描述",
"inviteTitle": "打开邀请",
"inviteDescription": "管理其他用户加入机构的邀请",
"inviteDescription": "管理其他用户加入组织的邀请",
"inviteSearch": "搜索邀请...",
"minutes": "分钟",
"hours": "小时",
@@ -425,12 +425,12 @@
"apiKeysDelete": "删除 API 密钥",
"apiKeysManage": "管理 API 密钥",
"apiKeysDescription": "API 密钥用于认证集成 API",
"provisioningKeysTitle": "置备密钥",
"provisioningKeysManage": "管理置备键",
"provisioningKeysTitle": "预配密钥",
"provisioningKeysManage": "管理预配密钥",
"provisioningKeysDescription": "置备密钥用于验证您组织的自动站点配置。",
"provisioningManage": "置备中",
"provisioningDescription": "管理预配键和审查等待批准的站点。",
"pendingSites": "待站点",
"provisioningManage": "预配",
"provisioningDescription": "管理预配密钥,并审核待批准的站点。",
"pendingSites": "待审批站点",
"siteApproveSuccess": "站点批准成功",
"siteApproveError": "批准站点出错",
"provisioningKeys": "置备键",
@@ -467,11 +467,11 @@
"provisioningKeysUpdateError": "更新预配键时出错",
"provisioningKeysUpdated": "置备密钥已更新",
"provisioningKeysUpdatedDescription": "您的更改已保存。",
"provisioningKeysBannerTitle": "站点置备密钥",
"provisioningKeysBannerDescription": "生成一个供应密钥,并将其与 Newt 连接器一起使用,在首次启动时自动创建站点 - 无需为每个站点设置单独的凭据。",
"provisioningKeysBannerTitle": "站点预配密钥",
"provisioningKeysBannerDescription": "生成预配密钥,并将其与 Newt 连接器配合使用,即可在首次启动时自动创建站点无需为每个站点单独配置凭据。",
"provisioningKeysBannerButtonText": "了解更多",
"pendingSitesBannerTitle": "待站点",
"pendingSitesBannerDescription": "使用供应密钥连接的站点将在此显示以供审核。",
"pendingSitesBannerTitle": "待审批站点",
"pendingSitesBannerDescription": "使用预配密钥连接的网站会在这里以供审核。",
"pendingSitesBannerButtonText": "了解更多",
"apiKeysSettings": "{apiKeyName} 设置",
"userTitle": "管理所有用户",
@@ -1059,7 +1059,7 @@
"network": "网络",
"manage": "管理",
"sitesNotFound": "未找到站点。",
"pangolinServerAdmin": "服务器管理 - Pangolin",
"pangolinServerAdmin": "服务器管理 - Pangolin",
"licenseTierProfessional": "专业许可证",
"licenseTierEnterprise": "企业许可证",
"licenseTierPersonal": "个人许可证",
@@ -1366,7 +1366,7 @@
"supportKeyBuy": "购买支持者密钥",
"logoutError": "注销错误",
"signingAs": "登录为",
"serverAdmin": "服务器管理",
"serverAdmin": "服务器管理",
"managedSelfhosted": "托管自托管",
"otpEnable": "启用双因子认证",
"otpDisable": "禁用双因子认证",
@@ -1536,8 +1536,8 @@
"sidebarSites": "站点",
"sidebarApprovals": "审批请求",
"sidebarResources": "资源",
"sidebarProxyResources": "公开",
"sidebarClientResources": "非公开的",
"sidebarProxyResources": "公开资源",
"sidebarClientResources": "私有资源",
"sidebarPolicies": "共享策略",
"sidebarResourcePolicies": "公共资源",
"sidebarAccessControl": "访问控制",
@@ -1549,15 +1549,15 @@
"sidebarRoles": "角色",
"sidebarShareableLinks": "可共享链接",
"sidebarApiKeys": "API密钥",
"sidebarProvisioning": "置备中",
"sidebarProvisioning": "预配",
"sidebarSettings": "设置",
"sidebarAllUsers": "所有用户",
"sidebarIdentityProviders": "身份提供商",
"sidebarLicense": "证书",
"sidebarClients": "客户端",
"sidebarUserDevices": "用户设备",
"sidebarMachineClients": "机",
"sidebarDomains": "域",
"sidebarMachineClients": "机器身份",
"sidebarDomains": "域",
"sidebarGeneral": "管理",
"sidebarLogAndAnalytics": "日志与分析",
"sidebarBluePrints": "蓝图",
@@ -1689,8 +1689,8 @@
"alertingTabHealthChecks": "健康检查",
"alertingRulesBannerTitle": "获取通知",
"alertingRulesBannerDescription": "每条规则都连接要监视的对象站点、健康检查或资源触发时间例如离线或不健康以及如何通过电子邮件、Webhooks 或集成将通知发送给团队。使用此列表创建、启用和管理这些规则。",
"alertingHealthChecksBannerTitle": "监视健康和资源",
"alertingHealthChecksBannerDescription": "健康检查是您一次定义的 HTTP 或 TCP 监控。然后可以将它们用作告警规则中的来源,以便目标变得正常或不正常时得到通知。资源的健康检查也会出现在此处。",
"alertingHealthChecksBannerTitle": "资源与健康监控",
"alertingHealthChecksBannerDescription": "通过 HTTP 或 TCP 检查目标状态,并在服务异常或恢复时发送通知。资源中配置的健康检查也会显示在这里。",
"standaloneHcTableTitle": "健康检查",
"standaloneHcSearchPlaceholder": "搜索健康检查…",
"standaloneHcAddButton": "创建健康检查",
@@ -1793,15 +1793,15 @@
"initialSetupTitle": "初始服务器设置",
"initialSetupDescription": "创建初始服务器管理员帐户。 只能存在一个服务器管理员。 您可以随时更改这些凭据。",
"createAdminAccount": "创建管理员帐户",
"setupErrorCreateAdmin": "创建服务器管理员账户时发生错误。",
"setupErrorCreateAdmin": "创建管理员账户时发生错误。",
"certificateStatus": "证书",
"certificateStatusAutoRefreshHint": "状态自动刷新。",
"loading": "加载中",
"loadingEllipsis": "加载中……",
"loadingAnalytics": "加载分析",
"restart": "重启",
"domains": "域",
"domainsDescription": "创建和管理组织中可用的域",
"domains": "域",
"domainsDescription": "创建和管理组织中可用的域",
"domainsSearch": "搜索域...",
"domainAdd": "添加域",
"domainAddDescription": "注册一个新域名到组织",
@@ -2183,7 +2183,7 @@
"roleTextImportAppend": "附加到现有",
"roleTextImportMode": "导入模式",
"roleTextImportPreview": "预览",
"roleTextImportItemCount": "{count, plural, =0 {No items to import} one {1 item to import} other {# items to import}}",
"roleTextImportItemCount": "{count, plural, =0 {没有可导入的项目} one {1 个可导入项目} other {# 个可导入项目}}",
"roleTextImportTotalCount": "{existing} 个现有 + {imported} 个导入 = {total} 个总计",
"roleTextImportConfirm": "导入",
"roleTextImportInvalidFile": "不支持的文件类型",
@@ -2235,8 +2235,8 @@
"resourceEditDomain": "编辑域名",
"siteName": "站点名称",
"proxyPort": "端口",
"resourcesTableProxyResources": "公开",
"resourcesTableClientResources": "非公开的",
"resourcesTableProxyResources": "公开资源",
"resourcesTableClientResources": "私有资源",
"resourcesTableNoProxyResourcesFound": "未找到代理资源。",
"resourcesTableNoInternalResourcesFound": "未找到内部资源。",
"resourcesTableDestination": "目标",
@@ -2925,7 +2925,7 @@
"logRetentionRequestDescription": "保留请求日志的时间",
"logRetentionAccessLabel": "访问日志保留",
"logRetentionAccessDescription": "保留访问日志的时间",
"logRetentionActionLabel": "动作日志保留",
"logRetentionActionLabel": "审计日志保留",
"logRetentionActionDescription": "保留操作日志的时间",
"logRetentionConnectionLabel": "连接日志保留",
"logRetentionConnectionDescription": "保留连接日志的时间",
@@ -2938,11 +2938,11 @@
"logRetentionForever": "永远的",
"logRetentionEndOfFollowingYear": "下一年结束",
"actionLogsDescription": "查看此机构执行的操作历史",
"accessLogsDescription": "查看此机构资源的访问认证请求",
"accessLogsDescription": "查看此组织资源的访问认证请求",
"connectionLogs": "连接日志",
"connectionLogsDescription": "查看此机构隧道的连接日志",
"sidebarLogsConnection": "连接日志",
"sidebarLogsStreaming": "流",
"sidebarLogsStreaming": "事件流",
"sourceAddress": "源地址",
"destinationAddress": "目的地址",
"duration": "期限",

View File

@@ -1,7 +1,4 @@
import {
getResourceRuleValueValidationError,
isValidUrlGlobPattern
} from "./validators";
import { isValidUrlGlobPattern } from "./validators";
import { assertEquals } from "@test/assert";
function runTests() {
@@ -239,43 +236,6 @@ function runTests() {
"Path with isolated percent sign should be invalid"
);
// ASN validation tests
assertEquals(
getResourceRuleValueValidationError("ASN", "AS15169"),
null,
"Standard ASN should be valid"
);
assertEquals(
getResourceRuleValueValidationError("ASN", " As15169 "),
null,
"Standard ASN should be valid with mixed case and whitespace"
);
assertEquals(
getResourceRuleValueValidationError("ASN", "ALL"),
null,
"ALL ASN selector should be valid"
);
assertEquals(
getResourceRuleValueValidationError("ASN", " all "),
null,
"ALL ASN selector should be valid with mixed case and whitespace"
);
assertEquals(
getResourceRuleValueValidationError("ASN", "AS0"),
null,
"AS0 alias should be valid"
);
assertEquals(
getResourceRuleValueValidationError("ASN", " as0 "),
null,
"AS0 alias should be valid with mixed case and whitespace"
);
assertEquals(
getResourceRuleValueValidationError("ASN", "not-an-asn"),
"Invalid ASN provided",
"Invalid ASN should return an error"
);
console.log("All tests passed!");
}

View File

@@ -100,10 +100,7 @@ export function getResourceRuleValueValidationError(
? null
: "Invalid country code provided";
case "ASN":
const normalizedValue = value.trim().toUpperCase();
return /^AS\d+$/.test(normalizedValue) ||
normalizedValue === "ALL" ||
normalizedValue === "AS0"
return /^AS\d+$/i.test(value.trim())
? null
: "Invalid ASN provided";
default:

View File

@@ -83,19 +83,9 @@ export function createPolicyRuleValueSchema(t: TranslateFn, match: string) {
{ message: t("rulesErrorInvalidCountryDescription") }
);
case "ASN":
return required.refine(
(value) => {
const normalizedValue = value.trim().toUpperCase();
return (
/^AS\d+$/.test(normalizedValue) ||
normalizedValue === "ALL" ||
normalizedValue === "AS0"
);
},
{
message: t("rulesErrorInvalidAsnDescription")
}
);
return required.refine((value) => /^AS\d+$/i.test(value.trim()), {
message: t("rulesErrorInvalidAsnDescription")
});
default:
return required;
}