From 02aa672b55c57670b7f9ba6322f5ac0d44c47e6e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 17:43:47 +0000 Subject: [PATCH 1/5] fix(platform-objects): translate the zh-CN object labels, options and help that shipped as English copies Claude-Session: https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN Co-authored-by: Claude --- .../translations/zh-CN.objects.generated.ts | 640 +++++++++--------- 1 file changed, 320 insertions(+), 320 deletions(-) diff --git a/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts b/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts index 805d2d11df2..24cfb9355b8 100644 --- a/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts +++ b/packages/platform-objects/src/apps/translations/zh-CN.objects.generated.ts @@ -97,11 +97,11 @@ export const zhCNObjects: NonNullable = { }, manager_id: { label: "经理", - help: "This user's direct manager. Forms the reporting chain the `own_and_reports` hierarchy scope walks (ADR-0057 / @objectstack/security-enterprise)." + help: "该用户的直属上级。构成 `own_and_reports` 层级范围所遍历的汇报链(ADR-0057 / @objectstack/security-enterprise)。" }, primary_business_unit_id: { label: "主属业务单元", - help: "The user's primary business unit — a denormalised projection of sys_business_unit_member.is_primary, maintained by plugin-sharing (ADR-0057 addendum D12). Lets a user-lookup filter candidates by business unit without traversing the membership junction. Do not edit directly; set it via business-unit membership." + help: "该用户的主属业务单元——sys_business_unit_member.is_primary 的去规范化投影,由 plugin-sharing 维护(ADR-0057 附录 D12)。使用户查找字段无需遍历成员关系关联表即可按业务单元筛选候选人。请勿直接编辑;请通过业务单元成员关系设置。" }, source: { label: "身份来源", @@ -334,16 +334,16 @@ export const zhCNObjects: NonNullable = { label: "过期时间" }, last_activity_at: { - label: "Last Activity At", - help: "Timestamp of the last request on this session; drives idle-timeout. System-managed." + label: "最后活动时间", + help: "该会话上最后一次请求的时间戳;用于判定空闲超时。由系统维护。" }, revoked_at: { - label: "Revoked At", - help: "When set, this session was revoked (idle / absolute-max / concurrent-cap / admin / organization membership ended). System-managed." + label: "撤销时间", + help: "设置后表示该会话已被撤销(空闲超时 / 绝对时长上限 / 并发数上限 / 管理员 / 组织成员关系终止)。由系统维护。" }, revoke_reason: { - label: "Revoke Reason", - help: "Why the session was revoked (idle_timeout, absolute_max, concurrent_cap, user_revoked, admin, organization_membership_ended, …)." + label: "撤销原因", + help: "会话被撤销的原因(idle_timeout、absolute_max、concurrent_cap、user_revoked、admin、organization_membership_ended 等)。" }, active_organization_id: { label: "当前组织" @@ -431,15 +431,15 @@ export const zhCNObjects: NonNullable = { }, access_token: { label: "访问令牌", - help: "Live OAuth access token issued by the provider — never returned on the data API (#7987); better-auth reads it back through the engine's privileged internal-field accessor" + help: "由提供方签发的有效 OAuth 访问令牌——数据 API 绝不返回该值(#7987);better-auth 通过引擎的特权内部字段访问器读回它" }, refresh_token: { label: "刷新令牌", - help: "Live OAuth refresh token — long-lived and not revoked by revoking an ObjectStack session; never returned on the data API (#7987)" + help: "有效的 OAuth 刷新令牌——长期有效,撤销 ObjectStack 会话不会使其失效;数据 API 绝不返回该值(#7987)" }, id_token: { label: "ID 令牌", - help: "OIDC ID token issued by the provider — never returned on the data API (#7987)" + help: "由提供方签发的 OIDC ID 令牌——数据 API 绝不返回该值(#7987)" }, access_token_expires_at: { label: "Access Token 过期时间" @@ -455,8 +455,8 @@ export const zhCNObjects: NonNullable = { help: "邮箱/密码提供方使用的密码哈希" }, previous_password_hashes: { - label: "Previous Password Hashes", - help: "JSON array of prior password hashes (bounded by password_history_count); reuse-prevention only. System-managed." + label: "历史密码哈希", + help: "以往密码哈希的 JSON 数组(数量上限为 password_history_count);仅用于防止重复使用。由系统维护。" } }, _views: { @@ -554,12 +554,12 @@ export const zhCNObjects: NonNullable = { help: "该组织计算日期边界所用的 IANA 时区(如 UTC、Asia/Shanghai)——所有未自行设置时区的业务单元都继承的根默认值。未设置表示 UTC。" }, parent_organization_id: { - label: "Parent Organization", - help: "Reporting/grouping parent. Grants NOTHING — visibility across organizations comes from membership, never from this reference (ADR-0105 D6)." + label: "上级组织", + help: "用于汇报 / 分组的上级。不授予任何权限——跨组织的可见性来自成员关系,绝不来自此引用(ADR-0105 D6)。" }, sort_order: { - label: "Sort Order", - help: "Display order among sibling organizations. Presentation only." + label: "排序", + help: "在同级组织中的显示顺序。仅用于展示。" }, id: { label: "组织 ID" @@ -633,17 +633,17 @@ export const zhCNObjects: NonNullable = { options: { owner: "所有者", admin: "管理员", - delegated_admin: "Delegated Admin", + delegated_admin: "受托管理员", member: "成员" } } }, _views: { mine: { - label: "My Memberships", + label: "我的组织", emptyState: { - title: "No organizations yet", - message: "You haven't joined any organizations." + title: "尚无组织", + message: "你尚未加入任何组织。" } } }, @@ -700,7 +700,7 @@ export const zhCNObjects: NonNullable = { options: { owner: "所有者", admin: "管理员", - delegated_admin: "Delegated Admin", + delegated_admin: "受托管理员", member: "成员" } }, @@ -726,12 +726,12 @@ export const zhCNObjects: NonNullable = { help: "接受邀请后可选分配的团队" }, business_unit_id: { - label: "Placement Business Unit", - help: "Business unit the invitee is placed under on acceptance (ADR-0105 D8). Must lie inside the issuer's delegated subtree." + label: "分配业务单元", + help: "受邀者接受邀请后被分配到的业务单元(ADR-0105 D8)。必须位于邀请发起人的委派子树内。" }, positions: { - label: "Placement Positions", - help: "sys_position names assigned on acceptance (ADR-0105 D8). Every position's permission sets must be allowlisted by the issuer's adminScope." + label: "分配岗位", + help: "接受邀请时分配的 sys_position 名称(ADR-0105 D8)。每个岗位的权限集都必须在邀请发起人的 adminScope 允许列表内。" } }, _views: { @@ -786,8 +786,8 @@ export const zhCNObjects: NonNullable = { help: "该团队所属的上级组织" }, member_count: { - label: "Member Count", - help: "Seat counter maintained by better-auth; do not write directly." + label: "成员数", + help: "由 better-auth 维护的席位计数;请勿直接写入。" }, id: { label: "团队 ID" @@ -845,8 +845,8 @@ export const zhCNObjects: NonNullable = { label: "用户" }, membership_key: { - label: "Membership Key", - help: "Derived membership digest maintained by better-auth; do not write directly." + label: "成员关系键", + help: "由 better-auth 维护的派生成员关系摘要;请勿直接写入。" } }, _actions: { @@ -1007,8 +1007,8 @@ export const zhCNObjects: NonNullable = { help: "拥有该 API 密钥的用户" }, active_organization_id: { - label: "Active Organization", - help: "Organization this key authenticates into — inherited from the minter at creation and established as the request’s active organization" + label: "当前组织", + help: "该密钥认证进入的组织——创建时继承自签发者,并被设为请求的当前组织" }, scopes: { label: "范围", @@ -1095,16 +1095,16 @@ export const zhCNObjects: NonNullable = { help: "JSON 序列化的备用恢复码" }, verified: { - label: "Verified", - help: "Whether the enrollment was confirmed with a valid TOTP code (managed by better-auth)" + label: "已验证", + help: "该启用记录是否已通过有效的 TOTP 验证码确认(由 better-auth 管理)" }, failed_verification_count: { - label: "Failed Verification Count", - help: "Consecutive failed 2FA verifications; reset on success. Maintained by better-auth." + label: "验证失败次数", + help: "连续 2FA 验证失败的次数;验证成功后重置。由 better-auth 维护。" }, locked_until: { - label: "Locked Until", - help: "Set when failed 2FA verifications cross the lockout threshold. Maintained by better-auth." + label: "锁定至", + help: "当 2FA 验证失败次数超过锁定阈值时设置。由 better-auth 维护。" } }, _views: { @@ -1291,8 +1291,8 @@ export const zhCNObjects: NonNullable = { help: "公开的 OAuth 客户端标识" }, client_discovery_id: { - label: "Client Discovery ID", - help: "Opaque identifier the provider uses to look this client up on the discovery path, kept apart from the public `client_id`" + label: "客户端发现 ID", + help: "提供方在发现路径上查找该客户端所用的不透明标识符,与公开的 `client_id` 相互独立" }, client_secret: { label: "客户端密钥", @@ -1339,8 +1339,8 @@ export const zhCNObjects: NonNullable = { help: "客户端可申请的 scopes 的 JSON 序列化列表" }, client_credentials_scopes: { - label: "Client-Credentials Scopes", - help: "JSON-serialized list of scopes the client may request on the client_credentials grant, where there is no user to consent — kept apart from `scopes`, which governs user-delegated grants" + label: "客户端凭据范围", + help: "客户端在 client_credentials 授权中可申请的 scopes 的 JSON 序列化列表(该授权下没有进行同意的用户)——与管理用户委托授权的 `scopes` 相互独立" }, subject_type: { label: "主体类型", @@ -1348,15 +1348,15 @@ export const zhCNObjects: NonNullable = { }, jwks: { label: "JWKS", - help: "Client JSON Web Key Set (for private_key_jwt / signed-request verification)" + help: "客户端的 JSON Web Key Set(用于 private_key_jwt / 签名请求验证)" }, jwks_uri: { label: "JWKS URI", - help: "URL of the client JSON Web Key Set" + help: "客户端 JSON Web Key Set 的 URL" }, dpop_bound_access_tokens: { - label: "DPoP-bound Access Tokens", - help: "Require access tokens issued to this client to be DPoP-bound (RFC 9449)" + label: "DPoP 绑定访问令牌", + help: "要求签发给该客户端的访问令牌必须绑定 DPoP(RFC 9449)" }, disabled: { label: "已禁用" @@ -1370,12 +1370,12 @@ export const zhCNObjects: NonNullable = { help: "允许客户端调用 OIDC end-session 端点" }, backchannel_logout_uri: { - label: "Back-channel Logout URI", - help: "OIDC back-channel logout endpoint of the client" + label: "后端通道登出 URI", + help: "客户端的 OIDC 后端通道登出端点" }, backchannel_logout_session_required: { - label: "Back-channel Logout Session Required", - help: "Whether the back-channel logout token must include a sid claim" + label: "后端通道登出需要会话", + help: "后端通道登出令牌是否必须包含 sid claim" }, software_id: { label: "软件 ID" @@ -1404,7 +1404,7 @@ export const zhCNObjects: NonNullable = { }, _views: { mine: { - label: "My Applications" + label: "我的应用" }, active: { label: "启用" @@ -1440,7 +1440,7 @@ export const zhCNObjects: NonNullable = { type: { label: "应用类型", options: { - web: "Web", + web: "Web 应用", native: "原生应用", "user-agent-based": "基于 User-Agent", public: "公共客户端" @@ -1509,16 +1509,16 @@ export const zhCNObjects: NonNullable = { help: "调用方提供的关联标识符" }, authorization_code_id: { - label: "Authorization Code ID", - help: "ID of the authorization-code grant this token originates from" + label: "授权码 ID", + help: "该令牌来源的授权码授权的 ID" }, resources: { - label: "Resources", - help: "JSON-serialized list of RFC 8707 resource indicators bound to this token" + label: "资源", + help: "绑定到该令牌的 RFC 8707 资源指示符的 JSON 序列化列表" }, requested_user_info_claims: { - label: "Requested UserInfo Claims", - help: "JSON-serialized list of OIDC claims requested for the userinfo endpoint" + label: "请求的 UserInfo claim", + help: "为 userinfo 端点请求的 OIDC claim 的 JSON 序列化列表" }, scopes: { label: "范围", @@ -1531,12 +1531,12 @@ export const zhCNObjects: NonNullable = { label: "创建时间" }, revoked: { - label: "Revoked At", - help: "Timestamp at which this access token was revoked" + label: "撤销时间", + help: "该访问令牌被撤销的时间戳" }, confirmation: { - label: "Confirmation", - help: "JSON RFC 7800 cnf claim (e.g. DPoP key thumbprint) binding this token to a key" + label: "确认信息", + help: "将该令牌绑定到某个密钥的 RFC 7800 cnf claim(JSON,如 DPoP 密钥指纹)" } } }, @@ -1569,16 +1569,16 @@ export const zhCNObjects: NonNullable = { help: "调用方提供的关联标识符" }, authorization_code_id: { - label: "Authorization Code ID", - help: "ID of the authorization-code grant this token chain originates from" + label: "授权码 ID", + help: "该令牌链来源的授权码授权的 ID" }, resources: { - label: "Resources", - help: "JSON-serialized list of RFC 8707 resource indicators bound to this token" + label: "资源", + help: "绑定到该令牌的 RFC 8707 资源指示符的 JSON 序列化列表" }, requested_user_info_claims: { - label: "Requested UserInfo Claims", - help: "JSON-serialized list of OIDC claims requested for the userinfo endpoint" + label: "请求的 UserInfo claim", + help: "为 userinfo 端点请求的 OIDC claim 的 JSON 序列化列表" }, scopes: { label: "范围", @@ -1595,24 +1595,24 @@ export const zhCNObjects: NonNullable = { help: "该刷新令牌被撤销的时间戳" }, rotated_at: { - label: "Rotated At", - help: "Timestamp at which this token was rotated (superseded by a new row)" + label: "轮换时间", + help: "该令牌被轮换(被新记录取代)的时间戳" }, rotation_replay_response: { - label: "Rotation Replay Response", - help: "Cached token response replayed when the old token is re-presented within the reuse interval" + label: "轮换重放响应", + help: "旧令牌在复用间隔内被再次出示时重放的缓存令牌响应" }, rotation_replay_expires_at: { - label: "Rotation Replay Expires At", - help: "End of the post-rotation reuse interval during which the replay response is served" + label: "轮换重放过期时间", + help: "轮换后复用间隔的结束时间,在此期间会返回重放响应" }, auth_time: { label: "认证时间", help: "该令牌链中用户最初完成认证的时间" }, confirmation: { - label: "Confirmation", - help: "JSON RFC 7800 cnf claim (e.g. DPoP key thumbprint) binding this token to a key" + label: "确认信息", + help: "将该令牌绑定到某个密钥的 RFC 7800 cnf claim(JSON,如 DPoP 密钥指纹)" } } }, @@ -1637,12 +1637,12 @@ export const zhCNObjects: NonNullable = { help: "调用方提供的关联标识符" }, resources: { - label: "Resources", - help: "JSON-serialized list of RFC 8707 resource indicators the consent covers" + label: "资源", + help: "该授权同意涵盖的 RFC 8707 资源指示符的 JSON 序列化列表" }, requested_user_info_claims: { - label: "Requested UserInfo Claims", - help: "JSON-serialized list of OIDC claims the user consented to expose" + label: "请求的 UserInfo claim", + help: "用户同意公开的 OIDC claim 的 JSON 序列化列表" }, scopes: { label: "范围", @@ -1657,103 +1657,103 @@ export const zhCNObjects: NonNullable = { } }, sys_oauth_resource: { - label: "OAuth Resource", - pluralLabel: "OAuth Resources", - description: "Registered OAuth protected resources (RFC 8707 resource indicators)", + label: "OAuth 资源", + pluralLabel: "OAuth 资源", + description: "已注册的 OAuth 受保护资源(RFC 8707 资源指示符)", fields: { id: { label: "ID" }, identifier: { - label: "Identifier", - help: "Resource indicator URI presented in the RFC 8707 resource parameter" + label: "标识", + help: "在 RFC 8707 resource 参数中出示的资源指示符 URI" }, name: { - label: "Name" + label: "名称" }, access_token_ttl: { - label: "Access Token TTL", - help: "Access-token lifetime in seconds for this resource (overrides the server default)" + label: "访问令牌 TTL", + help: "该资源的访问令牌有效期(秒),覆盖服务器默认值" }, refresh_token_ttl: { - label: "Refresh Token TTL", - help: "Refresh-token lifetime in seconds for this resource (overrides the server default)" + label: "刷新令牌 TTL", + help: "该资源的刷新令牌有效期(秒),覆盖服务器默认值" }, signing_algorithm: { - label: "Signing Algorithm", - help: "JWS algorithm used to sign access tokens for this resource" + label: "签名算法", + help: "为该资源签名访问令牌所用的 JWS 算法" }, signing_key_id: { - label: "Signing Key ID", - help: "Key id (kid) used to sign access tokens for this resource" + label: "签名密钥 ID", + help: "为该资源签名访问令牌所用的密钥 ID(kid)" }, allowed_scopes: { - label: "Allowed Scopes", - help: "JSON-serialized list of scopes clients may request for this resource" + label: "允许的范围", + help: "客户端可为该资源申请的 scopes 的 JSON 序列化列表" }, custom_claims: { - label: "Custom Claims", - help: "JSON object of extra claims stamped on access tokens for this resource" + label: "自定义 claim", + help: "附加到该资源访问令牌上的额外 claim 的 JSON 对象" }, dpop_bound_access_tokens_required: { - label: "DPoP Required", - help: "Require access tokens for this resource to be DPoP-bound (RFC 9449)" + label: "要求 DPoP", + help: "要求该资源的访问令牌必须绑定 DPoP(RFC 9449)" }, disabled: { - label: "Disabled" + label: "已禁用" }, policy_version: { - label: "Policy Version", - help: "Monotonic version of the resource token policy" + label: "策略版本", + help: "资源令牌策略的单调递增版本号" }, metadata: { - label: "Metadata", - help: "JSON object of additional resource metadata" + label: "元数据", + help: "附加资源元数据的 JSON 对象" }, created_at: { - label: "Created At" + label: "创建时间" }, updated_at: { - label: "Updated At" + label: "更新时间" } } }, sys_oauth_client_resource: { - label: "OAuth Client Resource", - pluralLabel: "OAuth Client Resources", - description: "Grants allowing an OAuth client to request tokens for a protected resource", + label: "OAuth 客户端资源", + pluralLabel: "OAuth 客户端资源", + description: "允许 OAuth 客户端为受保护资源申请令牌的授权", fields: { id: { label: "ID" }, client_id: { - label: "Client ID", - help: "Foreign key to sys_oauth_application.client_id" + label: "客户端 ID", + help: "指向 sys_oauth_application.client_id 的外键" }, resource_id: { - label: "Resource ID", - help: "Foreign key to sys_oauth_resource.identifier" + label: "资源 ID", + help: "指向 sys_oauth_resource.identifier 的外键" }, metadata: { - label: "Metadata", - help: "JSON object of additional grant metadata" + label: "元数据", + help: "附加授权元数据的 JSON 对象" }, created_at: { - label: "Created At" + label: "创建时间" } } }, sys_oauth_client_assertion: { - label: "OAuth Client Assertion", - pluralLabel: "OAuth Client Assertions", - description: "Consumed OAuth client-assertion JTIs (RFC 7523 replay prevention)", + label: "OAuth 客户端断言", + pluralLabel: "OAuth 客户端断言", + description: "已使用的 OAuth 客户端断言 JTI(RFC 7523 防重放)", fields: { id: { label: "ID" }, expires_at: { - label: "Expires At", - help: "Assertion expiry — rows past this instant are safe to prune" + label: "过期时间", + help: "断言过期时间——超过该时刻的记录可安全清理" } } }, @@ -1947,174 +1947,174 @@ export const zhCNObjects: NonNullable = { } }, sys_scim_connection_binding: { - label: "SCIM Connection Binding", - pluralLabel: "SCIM Connection Bindings", - description: "Lifecycle state for a SCIM provisioning connection, including its decommission state machine", + label: "SCIM 连接绑定", + pluralLabel: "SCIM 连接绑定", + description: "SCIM 预配连接的生命周期状态,包括其下线状态机", fields: { id: { label: "ID" }, connection_id: { - label: "Connection ID", - help: "Immutable SCIM connection identifier that scopes every provisioned resource" + label: "连接 ID", + help: "不可变的 SCIM 连接标识符,限定每个预配资源的范围" }, connection_key: { - label: "Connection Key", - help: "Derived connection uniqueness key maintained by @better-auth/scim; do not write directly." + label: "连接键", + help: "由 @better-auth/scim 维护的派生连接唯一键;请勿直接写入。" }, provisioning_domain_id: { - label: "Provisioning Domain", - help: "Application-owned boundary that receives provisioned resources (defaults to the connection id)" + label: "预配域", + help: "接收预配资源的应用自有边界(默认为连接 ID)" }, decommission_status: { - label: "Decommission Status", - help: "Connection lifecycle state: active | reconciling | complete" + label: "下线状态", + help: "连接生命周期状态:active | reconciling | complete" }, decommissioned_at: { - label: "Decommissioned At" + label: "下线时间" }, decommission_cursor_user_id: { - label: "Decommission Cursor User", - help: "Resumable reconciliation cursor maintained by the library" + label: "下线游标用户", + help: "由该库维护的可续传协调游标" }, decommission_reconciled_user_count: { - label: "Reconciled Users" + label: "已协调用户数" }, decommission_batch_count: { - label: "Decommission Batches" + label: "下线批次数" }, decommission_revision: { - label: "Decommission Revision", - help: "Optimistic-concurrency revision for the decommission state machine" + label: "下线修订版本", + help: "下线状态机的乐观并发修订版本" }, decommission_completed_at: { - label: "Decommission Completed At" + label: "下线完成时间" }, decommission_lease_id: { - label: "Decommission Lease", - help: "Single-worker reconciliation lease maintained by the library" + label: "下线租约", + help: "由该库维护的单工作进程协调租约" }, decommission_lease_expires_at: { - label: "Decommission Lease Expires At" + label: "下线租约过期时间" }, created_at: { - label: "Created At" + label: "创建时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_connection_credential: { - label: "SCIM Connection Credential", - pluralLabel: "SCIM Connection Credentials", - description: "Bearer credentials (one-way digests) that authenticate SCIM provisioning connections", + label: "SCIM 连接凭据", + pluralLabel: "SCIM 连接凭据", + description: "用于认证 SCIM 预配连接的 Bearer 凭据(单向摘要)", fields: { id: { label: "ID" }, connection_id: { - label: "Connection ID", - help: "The SCIM connection this credential authenticates (e.g. \"okta-prod\"); scopes every resource the IdP provisions with it" + label: "连接 ID", + help: "该凭据认证的 SCIM 连接(例如 “okta-prod”);限定 IdP 使用它预配的每个资源的范围" }, provisioning_domain_id: { - label: "Provisioning Domain", - help: "Application-owned boundary receiving provisioned resources; defaults to the connection id when absent" + label: "预配域", + help: "接收预配资源的应用自有边界;缺省时默认为连接 ID" }, organization_id: { - label: "Organization", - help: "Organization scope of this connection, when provisioning is org-scoped" + label: "组织", + help: "该连接的组织范围(预配为组织级时)" }, label: { - label: "Label", - help: "Operator-facing name for this credential (e.g. \"rotation 2026-Q3\")" + label: "标签", + help: "面向运维人员的凭据名称(例如 “rotation 2026-Q3”)" }, token_digest: { - label: "Token Digest", - help: "HMAC-SHA-256 (base64url) of the bearer, keyed by the deployment auth secret — one-way; the plaintext is shown once at mint and never stored." + label: "令牌摘要", + help: "Bearer 令牌的 HMAC-SHA-256(base64url),以部署的认证密钥为键——单向;明文仅在签发时显示一次,且绝不存储。" }, active: { - label: "Active", - help: "Revocation switch — an inactive credential is refused at verification" + label: "启用", + help: "撤销开关——未启用的凭据在验证时会被拒绝" }, expires_at: { - label: "Expires At", - help: "Optional hard expiry for staged credential rotation; an expired credential is refused" + label: "过期时间", + help: "用于分阶段凭据轮换的可选硬性过期时间;已过期的凭据会被拒绝" }, user_id: { - label: "Minted By", - help: "User who minted this credential" + label: "签发人", + help: "签发该凭据的用户" }, created_at: { - label: "Created At" + label: "创建时间" }, updated_at: { - label: "Updated At" + label: "更新时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_group: { - label: "SCIM Group", - pluralLabel: "SCIM Groups", - description: "IdP-pushed SCIM 2.0 groups, scoped per provisioning connection", + label: "SCIM 组", + pluralLabel: "SCIM 组", + description: "由 IdP 推送的 SCIM 2.0 组,按预配连接划分范围", fields: { id: { label: "ID" }, connection_id: { - label: "Connection ID" + label: "连接 ID" }, provisioning_domain_id: { - label: "Provisioning Domain" + label: "预配域" }, revision: { - label: "Revision", - help: "Optimistic-concurrency revision maintained by @better-auth/scim" + label: "修订版本", + help: "由 @better-auth/scim 维护的乐观并发修订版本" }, display_name: { - label: "Display Name", - help: "SCIM displayName as sent by the IdP" + label: "显示名称", + help: "IdP 发送的 SCIM displayName" }, display_name_key: { - label: "Display Name Key", - help: "Derived case-folded displayName uniqueness key maintained by @better-auth/scim; do not write directly." + label: "显示名称键", + help: "由 @better-auth/scim 维护的派生 displayName 唯一键(已做大小写折叠);请勿直接写入。" }, external_id: { - label: "External ID", - help: "IdP-assigned externalId, when the IdP sends one" + label: "外部 ID", + help: "IdP 分配的 externalId(当 IdP 发送时)" }, external_id_key: { - label: "External ID Key", - help: "Derived externalId uniqueness key maintained by @better-auth/scim; do not write directly." + label: "外部 ID 键", + help: "由 @better-auth/scim 维护的派生 externalId 唯一键;请勿直接写入。" }, order_key: { - label: "Order Key", - help: "Derived stable-pagination key maintained by @better-auth/scim; do not write directly." + label: "排序键", + help: "由 @better-auth/scim 维护的派生稳定分页键;请勿直接写入。" }, created_at: { - label: "Created At" + label: "创建时间" }, updated_at: { - label: "Updated At" + label: "更新时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_group_member: { - label: "SCIM Group Member", - pluralLabel: "SCIM Group Members", - description: "SCIM group membership rows pushed by the IdP (group ↔ provisioned user)", + label: "SCIM 组成员", + pluralLabel: "SCIM 组成员", + description: "由 IdP 推送的 SCIM 组成员关系记录(组 ↔ 预配的用户)", fields: { id: { label: "ID" @@ -2124,72 +2124,72 @@ export const zhCNObjects: NonNullable = { help: "记录标题:预配的用户及其所在组(读取时计算)" }, connection_id: { - label: "Connection ID" + label: "连接 ID" }, group_id: { - label: "Group" + label: "组" }, scim_user_id: { - label: "SCIM User" + label: "SCIM 用户" }, membership_key: { - label: "Membership Key", - help: "Derived membership uniqueness key maintained by @better-auth/scim; do not write directly." + label: "成员关系键", + help: "由 @better-auth/scim 维护的派生成员关系唯一键;请勿直接写入。" }, created_at: { - label: "Created At" + label: "创建时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_identity_tombstone: { - label: "SCIM Identity Tombstone", - pluralLabel: "SCIM Identity Tombstones", - description: "Tombstones of IdP-deleted SCIM identities, kept so a re-provision is recognized", + label: "SCIM 身份墓碑", + pluralLabel: "SCIM 身份墓碑", + description: "IdP 已删除的 SCIM 身份的墓碑记录,保留下来以便识别重新预配", fields: { id: { label: "ID" }, connection_id: { - label: "Connection ID" + label: "连接 ID" }, provisioning_domain_id: { - label: "Provisioning Domain" + label: "预配域" }, external_id: { - label: "External ID", - help: "The IdP-assigned externalId of the deleted identity" + label: "外部 ID", + help: "已删除身份的 IdP 分配 externalId" }, external_id_key: { - label: "External ID Key", - help: "Derived externalId uniqueness key maintained by @better-auth/scim; do not write directly." + label: "外部 ID 键", + help: "由 @better-auth/scim 维护的派生 externalId 唯一键;请勿直接写入。" }, user_id: { - label: "User", - help: "The platform user the deleted identity was linked to" + label: "用户", + help: "已删除身份所关联的平台用户" }, profile: { - label: "Final Profile", - help: "Serialized final SCIM profile at deletion time, maintained by @better-auth/scim" + label: "最终资料", + help: "删除时的最终 SCIM 资料(已序列化),由 @better-auth/scim 维护" }, deleted_at: { - label: "Deleted At" + label: "删除时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_projection_grant: { - label: "SCIM Projection Grant", - pluralLabel: "SCIM Projection Grants", - description: "Role/entitlement grants projected onto platform users by SCIM provisioning", + label: "SCIM 投影授权", + pluralLabel: "SCIM 投影授权", + description: "由 SCIM 预配投影到平台用户上的角色 / 权益授权", fields: { id: { label: "ID" @@ -2199,173 +2199,173 @@ export const zhCNObjects: NonNullable = { help: "记录标题:投射的角色及被授予该角色的用户(读取时计算)" }, connection_id: { - label: "Connection ID" + label: "连接 ID" }, provisioning_domain_id: { - label: "Provisioning Domain" + label: "预配域" }, scim_user_id: { - label: "SCIM User", - help: "The per-connection user projection this grant belongs to" + label: "SCIM 用户", + help: "该授权所属的按连接划分的用户投影" }, user_id: { - label: "User", - help: "The platform user the grant is projected onto" + label: "用户", + help: "该授权投影到的平台用户" }, source_kind: { - label: "Source Kind", - help: "What projected the grant (e.g. group, entitlement, attribute)" + label: "来源类型", + help: "投影出该授权的来源(例如 group、entitlement、attribute)" }, source_id: { - label: "Source ID", - help: "Identifier of the projecting source (e.g. the SCIM group id)" + label: "来源 ID", + help: "投影来源的标识符(例如 SCIM 组 ID)" }, source_value: { - label: "Source Value", - help: "Source attribute value, when the source kind carries one" + label: "来源值", + help: "来源属性值(当来源类型携带该值时)" }, role: { - label: "Role", - help: "The role/entitlement projected onto the user" + label: "角色", + help: "投影到该用户上的角色 / 权益" }, grant_key: { - label: "Grant Key", - help: "Derived grant uniqueness key maintained by @better-auth/scim; do not write directly." + label: "授权键", + help: "由 @better-auth/scim 维护的派生授权唯一键;请勿直接写入。" }, created_at: { - label: "Created At" + label: "创建时间" }, updated_at: { - label: "Updated At" + label: "更新时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_subject: { - label: "SCIM Subject", - pluralLabel: "SCIM Subjects", - description: "Per-user SCIM provisioning link — one row per user any SCIM connection provisions", + label: "SCIM 主体", + pluralLabel: "SCIM 主体", + description: "按用户划分的 SCIM 预配关联——任一 SCIM 连接预配的每个用户对应一行", fields: { id: { label: "ID" }, user_id: { - label: "User", - help: "The platform user this subject row tracks (unique — one row per user)" + label: "用户", + help: "该主体记录跟踪的平台用户(唯一——每个用户一行)" }, profile_source_id: { - label: "Profile Source", - help: "The sys_scim_user projection currently sourcing this user's profile" + label: "资料来源", + help: "当前为该用户提供资料的 sys_scim_user 投影" }, revision: { - label: "Revision", - help: "Optimistic-concurrency revision maintained by @better-auth/scim" + label: "修订版本", + help: "由 @better-auth/scim 维护的乐观并发修订版本" }, created_at: { - label: "Created At" + label: "创建时间" }, updated_at: { - label: "Updated At" + label: "更新时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, sys_scim_user: { - label: "SCIM User", - pluralLabel: "SCIM Users", - description: "Per-connection projection of an IdP-provisioned user (SCIM 2.0 /Users)", + label: "SCIM 用户", + pluralLabel: "SCIM 用户", + description: "IdP 预配用户的按连接投影(SCIM 2.0 /Users)", fields: { id: { label: "ID" }, connection_id: { - label: "Connection ID", - help: "SCIM connection that provisioned this user" + label: "连接 ID", + help: "预配该用户的 SCIM 连接" }, provisioning_domain_id: { - label: "Provisioning Domain" + label: "预配域" }, user_id: { - label: "User", - help: "The platform user this projection materialized as" + label: "用户", + help: "该投影所落地成的平台用户" }, connection_user_key: { - label: "Connection User Key", - help: "Derived (connection, user) uniqueness key maintained by @better-auth/scim; do not write directly." + label: "连接用户键", + help: "由 @better-auth/scim 维护的派生(连接, 用户)唯一键;请勿直接写入。" }, user_name: { - label: "User Name", - help: "SCIM userName as sent by the IdP" + label: "用户名", + help: "IdP 发送的 SCIM userName" }, user_name_key: { - label: "User Name Key", - help: "Derived case-folded userName uniqueness key maintained by @better-auth/scim; do not write directly." + label: "用户名键", + help: "由 @better-auth/scim 维护的派生 userName 唯一键(已做大小写折叠);请勿直接写入。" }, primary_email: { - label: "Primary Email" + label: "主邮箱" }, work_email_value_index: { - label: "Work Email Index", - help: "Derived lookup index maintained by @better-auth/scim; do not write directly." + label: "工作邮箱索引", + help: "由 @better-auth/scim 维护的派生查找索引;请勿直接写入。" }, email_value_index: { - label: "Email Index", - help: "Derived lookup index maintained by @better-auth/scim; do not write directly." + label: "邮箱索引", + help: "由 @better-auth/scim 维护的派生查找索引;请勿直接写入。" }, display_name: { - label: "Display Name" + label: "显示名称" }, formatted_name: { - label: "Formatted Name" + label: "格式化姓名" }, given_name: { - label: "Given Name" + label: "名" }, family_name: { - label: "Family Name" + label: "姓" }, serialized_emails: { - label: "Emails (serialized)", - help: "Canonical serialized SCIM emails list maintained by @better-auth/scim; do not write directly." + label: "邮箱(序列化)", + help: "由 @better-auth/scim 维护的规范化序列化 SCIM 邮箱列表;请勿直接写入。" }, serialized_attributes: { - label: "Attributes (serialized)", - help: "Canonical serialized SCIM attributes maintained by @better-auth/scim; do not write directly." + label: "属性(序列化)", + help: "由 @better-auth/scim 维护的规范化序列化 SCIM 属性;请勿直接写入。" }, external_id: { - label: "External ID", - help: "IdP-assigned externalId, when the IdP sends one" + label: "外部 ID", + help: "IdP 分配的 externalId(当 IdP 发送时)" }, external_id_key: { - label: "External ID Key", - help: "Derived externalId uniqueness key maintained by @better-auth/scim; do not write directly." + label: "外部 ID 键", + help: "由 @better-auth/scim 维护的派生 externalId 唯一键;请勿直接写入。" }, active: { - label: "Active", - help: "SCIM active flag — false means the IdP deactivated this user" + label: "启用", + help: "SCIM active 标志——为 false 表示 IdP 已停用该用户" }, order_key: { - label: "Order Key", - help: "Derived stable-pagination key maintained by @better-auth/scim; do not write directly." + label: "排序键", + help: "由 @better-auth/scim 维护的派生稳定分页键;请勿直接写入。" }, created_at: { - label: "Created At" + label: "创建时间" }, updated_at: { - label: "Updated At" + label: "更新时间" } }, _views: { all: { - label: "All" + label: "全部" } } }, @@ -2378,29 +2378,29 @@ export const zhCNObjects: NonNullable = { label: "通知 ID" }, topic: { - label: "Topic", - help: "Notification topic, e.g. task.assigned, collab.mention" + label: "主题", + help: "通知主题,例如 task.assigned、collab.mention" }, payload: { - label: "Payload", - help: "Template inputs carried to channels (title/body/url/actor/source/…)" + label: "负载", + help: "传递给各通道的模板输入(title/body/url/actor/source/…)" }, severity: { - label: "Severity", - help: "Severity hint for rendering / filtering", + label: "严重程度", + help: "用于渲染 / 筛选的严重程度提示", options: { - info: "info", - warning: "warning", - critical: "critical" + info: "信息", + warning: "警告", + critical: "严重" } }, suppressed_channels: { - label: "Suppressed Channels", - help: "Channels fan-out skipped because they are unavailable for this tenant, as [{channel, reason}]; reason is the closed set: transport_not_configured" + label: "已抑制的通道", + help: "因对该租户不可用而在扇出时被跳过的通道,格式为 [{channel, reason}];reason 为封闭集合:transport_not_configured" }, dedup_key: { - label: "Dedup Key", - help: "Idempotency key within a topic window; a repeat emit is a no-op" + label: "去重键", + help: "主题窗口内的幂等键;重复发出不产生任何效果" }, source_object: { label: "来源对象", @@ -2420,14 +2420,14 @@ export const zhCNObjects: NonNullable = { }, _views: { recent: { - label: "Recent", + label: "最近", emptyState: { - title: "No events", - message: "No notification events have been emitted." + title: "尚无事件", + message: "尚未发出任何通知事件。" } }, by_topic: { - label: "By Topic" + label: "按主题" } } }, @@ -2626,17 +2626,17 @@ export const zhCNObjects: NonNullable = { help: "形如 {name,type,required,description} 的 JSON 数组" }, managed_by: { - label: "Managed By", - help: "Record provenance: platform = framework built-in / package = app/package-declared (boot-seeded from declared email_template metadata) / admin = created in Studio.", + label: "管理方", + help: "记录来源:platform = 框架内置 / package = 应用或包声明(启动时根据声明的 email_template 元数据写入)/ admin = 在 Studio 中创建。", options: { - platform: "platform", - package: "package", - admin: "admin" + platform: "平台", + package: "包", + admin: "管理员" } }, customized: { - label: "Customized", - help: "Set when an admin edits a package-declared template; boot seeding will no longer overwrite the row (a reworded password-reset mail survives redeploys). Meaningless on admin rows." + label: "已自定义", + help: "管理员编辑包声明的模板时设置;启动种子将不再覆盖该记录(改写过的密码重置邮件在重新部署后得以保留)。对 admin 记录无意义。" }, created_at: { label: "创建时间" @@ -3100,7 +3100,7 @@ export const zhCNObjects: NonNullable = { }, recorded_by: { label: "记录人", - help: "User who made this change. NULL = system-initiated (boot sync, migration, scheduled job) — never a sentinel string." + help: "做出此变更的用户。NULL 表示由系统发起(启动同步、迁移、定时任务)——绝不是哨兵字符串。" }, recorded_at: { label: "记录时间" @@ -3232,8 +3232,8 @@ export const zhCNObjects: NonNullable = { label: "锁定状态", options: { none: "无", - nooverlay: "no-overlay", - nodelete: "no-delete", + nooverlay: "禁止叠加", + nodelete: "禁止删除", full: "完全锁定" } }, @@ -3367,7 +3367,7 @@ export const zhCNObjects: NonNullable = { }, _views: { all: { - label: "All Secrets" + label: "全部密钥" } } }, @@ -3447,7 +3447,7 @@ export const zhCNObjects: NonNullable = { }, _views: { recent: { - label: "Recent" + label: "最近" } } }, @@ -3485,16 +3485,16 @@ export const zhCNObjects: NonNullable = { help: "最近一次运行的计数,JSON 编码,供诊断用。" }, deviation_observed_at: { - label: "Deviation Observed At", - help: "When this deployment last ADMITTED a value its own verified contract rejects, through an OS_ALLOW_LAX_* escape hatch. Deliberately does NOT clear verified_at: it withdraws only the irreversible half of what the certificate authorises — byte deletion stops, validation and tombstoning continue. Cleared by the next apply-mode run." + label: "偏差发现时间", + help: "本部署最近一次经由 OS_ALLOW_LAX_* 逃生开关「放行」一个其自身已验证契约会拒绝的值的时间。刻意「不」清空 verified_at:它只撤回该证书所授权内容中不可逆的那一半——字节删除停止,校验与墓碑化照常进行。下一次 apply 模式运行时清空。" }, deviation_detail: { - label: "Deviation Detail (JSON)", - help: "JSON-encoded first counterexample behind deviation_observed_at (object, field, type, parse issue), so an operator can find the value that closed the irreversible gate." + label: "偏差详情(JSON)", + help: "deviation_observed_at 背后的第一个反例,JSON 编码(object、field、type、parse issue),便于运维人员找到关闭了不可逆门禁的那个值。" }, columns_moved_at: { - label: "Columns Moved At", - help: "When this deployment last completed the COLUMN MOVE for this migration — the step that retypes the migrated columns and rewrites the values they hold into the new encoding. Separate evidence from applied_at and verified_at, which attest the backfill and its self-check only: a deployment can carry both and still store the legacy encoding. Null says exactly that, and is an expected steady state rather than an error — it is what a consumer that cannot read this field must assume." + label: "列迁移时间", + help: "本部署最近一次完成该迁移「列迁移」的时间——即把已迁移的列改为新类型、并将其中的值重写为新编码的那一步。它是独立于 applied_at 和 verified_at 的证据,后两者只证明回填及其自检:一个部署可以两者都有,却仍以旧编码存储。为空恰恰表示这一点,是预期的稳态而非错误——这也是无法读取本字段的消费方必须作出的假设。" }, created_at: { label: "创建时间" From 2cff20842aeae0a5da314a03210cecaaa0c41abf Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 17:44:51 +0000 Subject: [PATCH 2/5] chore(platform-objects): regenerate the zh-CN provenance companion after the translations (pnpm i18n:extract) The extractor drops a leaf's copy record once the leaf is no longer a byte copy of its source: 320 rows go, the 42 leaves kept in English stay. Claude-Session: https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN Co-authored-by: Claude --- .../zh-CN.source-hashes.generated.ts | 320 ------------------ 1 file changed, 320 deletions(-) diff --git a/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts b/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts index c15bc9b9526..76ba4293863 100644 --- a/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts +++ b/packages/platform-objects/src/apps/translations/zh-CN.source-hashes.generated.ts @@ -25,339 +25,31 @@ export const zhCNGeneratedSourceHashes: Readonly> = { "objects.sys_account._actions.link_social.params.provider.options.gitlab": "bc3dbbf4b650e600", "objects.sys_account._actions.link_social.params.provider.options.google": "6fadcd05bb8da367", "objects.sys_account._actions.link_social.params.provider.options.microsoft": "17309efbdb1ec122", - "objects.sys_account.fields.access_token.help": "814695a136172228", - "objects.sys_account.fields.id_token.help": "b545f62224b21f69", - "objects.sys_account.fields.previous_password_hashes.help": "3a98e8164b0daf11", - "objects.sys_account.fields.previous_password_hashes.label": "2aa498ce717c7d77", - "objects.sys_account.fields.refresh_token.help": "f337bcd15c9b4cb3", - "objects.sys_api_key.fields.active_organization_id.help": "74718b93fdaa52cc", - "objects.sys_api_key.fields.active_organization_id.label": "51bce7fbc99fbf87", "objects.sys_email.fields.message_id.label": "14cd089a4062f4b1", - "objects.sys_email_template.fields.customized.help": "fc75c32a37f906ea", - "objects.sys_email_template.fields.customized.label": "6990986111e53429", "objects.sys_email_template.fields.id.label": "00b0385c9c152888", - "objects.sys_email_template.fields.managed_by.help": "0d7397e9e0e84cfe", - "objects.sys_email_template.fields.managed_by.label": "be9070801491e6af", - "objects.sys_email_template.fields.managed_by.options.admin": "f8c9f123caf6217d", - "objects.sys_email_template.fields.managed_by.options.package": "1c8c6168730324a3", - "objects.sys_email_template.fields.managed_by.options.platform": "820d30a5082ebc6c", - "objects.sys_invitation.fields.business_unit_id.help": "b4e37b1bfcc40f34", - "objects.sys_invitation.fields.business_unit_id.label": "bf0e0fdbda66ec9b", - "objects.sys_invitation.fields.positions.help": "abfa7911007e38f1", - "objects.sys_invitation.fields.positions.label": "3428d066379ee33b", - "objects.sys_invitation.fields.role.options.delegated_admin": "13f0e7f118c839e0", - "objects.sys_member._views.mine.emptyState.message": "36cf7e3a3eebed0b", - "objects.sys_member._views.mine.emptyState.title": "df533ee25aba6de9", - "objects.sys_member._views.mine.label": "46b6227bcdb2d02e", - "objects.sys_member.fields.role.options.delegated_admin": "13f0e7f118c839e0", "objects.sys_metadata.fields.id.label": "00b0385c9c152888", "objects.sys_metadata_audit.fields.id.label": "00b0385c9c152888", - "objects.sys_metadata_audit.fields.lock_state.options.nodelete": "248b810d57fe8bb9", - "objects.sys_metadata_audit.fields.lock_state.options.nooverlay": "49a44e4a03ff124c", "objects.sys_metadata_history.fields.id.label": "00b0385c9c152888", - "objects.sys_metadata_history.fields.recorded_by.help": "e293bd6cf3c47060", - "objects.sys_migration.fields.columns_moved_at.help": "eaa31d8860c680ec", - "objects.sys_migration.fields.columns_moved_at.label": "9f0cfcef656a7ec8", - "objects.sys_migration.fields.deviation_detail.help": "681fe28dc0c34386", - "objects.sys_migration.fields.deviation_detail.label": "5bf0f0f59a89e2fb", - "objects.sys_migration.fields.deviation_observed_at.help": "d6720808eb570acd", - "objects.sys_migration.fields.deviation_observed_at.label": "d68ffbef206322e0", - "objects.sys_notification._views.by_topic.label": "a0ddbe432474ed94", - "objects.sys_notification._views.recent.emptyState.message": "4a1e91a49eaf59d6", - "objects.sys_notification._views.recent.emptyState.title": "6f708a09bb4c9a5c", - "objects.sys_notification._views.recent.label": "62d27bb9d0349c99", - "objects.sys_notification.fields.dedup_key.help": "58a5e28b6a87e6d6", - "objects.sys_notification.fields.dedup_key.label": "33a740837f882c98", - "objects.sys_notification.fields.payload.help": "e1e8514cd730b06f", - "objects.sys_notification.fields.payload.label": "4488e1328e37dcb2", - "objects.sys_notification.fields.severity.help": "4925b29cf7e10346", - "objects.sys_notification.fields.severity.label": "d59e4345bdc57b59", - "objects.sys_notification.fields.severity.options.critical": "7ff0ff69c0abaf81", - "objects.sys_notification.fields.severity.options.info": "3e0c8611029f253b", - "objects.sys_notification.fields.severity.options.warning": "2673ee95caf83284", - "objects.sys_notification.fields.suppressed_channels.help": "1fbbc17b95ea75d2", - "objects.sys_notification.fields.suppressed_channels.label": "910cb46f687f6270", - "objects.sys_notification.fields.topic.help": "80e1790edfda49df", - "objects.sys_notification.fields.topic.label": "819afdb3853e9d80", - "objects.sys_oauth_access_token.fields.authorization_code_id.help": "84ad4d5d8c4c1cee", - "objects.sys_oauth_access_token.fields.authorization_code_id.label": "1c1d06cc01295862", - "objects.sys_oauth_access_token.fields.confirmation.help": "9d086fdc90baa01d", - "objects.sys_oauth_access_token.fields.confirmation.label": "64755493e6425b37", "objects.sys_oauth_access_token.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_access_token.fields.requested_user_info_claims.help": "dc0cd8121cbde60f", - "objects.sys_oauth_access_token.fields.requested_user_info_claims.label": "5a6338a357257661", - "objects.sys_oauth_access_token.fields.resources.help": "8c153517b30bd6a5", - "objects.sys_oauth_access_token.fields.resources.label": "f5753a2fa351119e", - "objects.sys_oauth_access_token.fields.revoked.help": "ff6a4b6dac031959", - "objects.sys_oauth_access_token.fields.revoked.label": "054f918e632528c7", - "objects.sys_oauth_application._actions.create_oauth_application.params.type.options.web": "2a7ead3da8c035c5", "objects.sys_oauth_application._actions.create_oauth_application.resultDialog.fields.client.client_id": "09cb452151e7b1b6", "objects.sys_oauth_application._actions.create_oauth_application.resultDialog.fields.client.client_secret": "8c703fe05bf2ed5d", - "objects.sys_oauth_application._views.mine.label": "d1cb1174cd96176c", - "objects.sys_oauth_application.fields.backchannel_logout_session_required.help": "2d12d1e1f9461576", - "objects.sys_oauth_application.fields.backchannel_logout_session_required.label": "fbc6eee84fb8a1d7", - "objects.sys_oauth_application.fields.backchannel_logout_uri.help": "e7c8abeac494b145", - "objects.sys_oauth_application.fields.backchannel_logout_uri.label": "f78777a91cebd19f", - "objects.sys_oauth_application.fields.client_credentials_scopes.help": "bf69fe7f91bb78e7", - "objects.sys_oauth_application.fields.client_credentials_scopes.label": "e257098b80b760d2", - "objects.sys_oauth_application.fields.client_discovery_id.help": "6d7fff4d4e7fb705", - "objects.sys_oauth_application.fields.client_discovery_id.label": "2070f4b2f6456352", - "objects.sys_oauth_application.fields.dpop_bound_access_tokens.help": "e7257c5c6ea7043b", - "objects.sys_oauth_application.fields.dpop_bound_access_tokens.label": "3772715f1d9588af", "objects.sys_oauth_application.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_application.fields.jwks.help": "6a6c5fe835f213b8", "objects.sys_oauth_application.fields.jwks.label": "b2cf79f9d66c0dbc", - "objects.sys_oauth_application.fields.jwks_uri.help": "217cff7cca47a35e", "objects.sys_oauth_application.fields.jwks_uri.label": "2a4339df734ab269", - "objects.sys_oauth_client_assertion.description": "82a3f5fec7571bd4", - "objects.sys_oauth_client_assertion.fields.expires_at.help": "90b732ea4d289003", - "objects.sys_oauth_client_assertion.fields.expires_at.label": "df0ef5fae02b2044", "objects.sys_oauth_client_assertion.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_client_assertion.label": "964d685e79999dce", - "objects.sys_oauth_client_assertion.pluralLabel": "286f417fcbf2ab81", - "objects.sys_oauth_client_resource.description": "c63dda9f9c51165b", - "objects.sys_oauth_client_resource.fields.client_id.help": "8df79a6c07fc32b4", - "objects.sys_oauth_client_resource.fields.client_id.label": "09cb452151e7b1b6", - "objects.sys_oauth_client_resource.fields.created_at.label": "1f02d416befb595b", "objects.sys_oauth_client_resource.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_client_resource.fields.metadata.help": "c51d0437d1b00c8b", - "objects.sys_oauth_client_resource.fields.metadata.label": "9cabc04013c80ef3", - "objects.sys_oauth_client_resource.fields.resource_id.help": "5c7d52276882432d", - "objects.sys_oauth_client_resource.fields.resource_id.label": "21668ca570b12d71", - "objects.sys_oauth_client_resource.label": "882f5ca283a58ed1", - "objects.sys_oauth_client_resource.pluralLabel": "ab6a91aa51de6ac0", "objects.sys_oauth_consent.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_consent.fields.requested_user_info_claims.help": "6f1fc3c5e6b4031d", - "objects.sys_oauth_consent.fields.requested_user_info_claims.label": "5a6338a357257661", - "objects.sys_oauth_consent.fields.resources.help": "f1e24c7b80ba287a", - "objects.sys_oauth_consent.fields.resources.label": "f5753a2fa351119e", - "objects.sys_oauth_refresh_token.fields.authorization_code_id.help": "b16f370e0a06cf43", - "objects.sys_oauth_refresh_token.fields.authorization_code_id.label": "1c1d06cc01295862", - "objects.sys_oauth_refresh_token.fields.confirmation.help": "9d086fdc90baa01d", - "objects.sys_oauth_refresh_token.fields.confirmation.label": "64755493e6425b37", "objects.sys_oauth_refresh_token.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_refresh_token.fields.requested_user_info_claims.help": "dc0cd8121cbde60f", - "objects.sys_oauth_refresh_token.fields.requested_user_info_claims.label": "5a6338a357257661", - "objects.sys_oauth_refresh_token.fields.resources.help": "8c153517b30bd6a5", - "objects.sys_oauth_refresh_token.fields.resources.label": "f5753a2fa351119e", - "objects.sys_oauth_refresh_token.fields.rotated_at.help": "704d34a1f46f4412", - "objects.sys_oauth_refresh_token.fields.rotated_at.label": "aa747daa25d440d1", - "objects.sys_oauth_refresh_token.fields.rotation_replay_expires_at.help": "7f5925e4b2d73586", - "objects.sys_oauth_refresh_token.fields.rotation_replay_expires_at.label": "f6a0bbe6ef73bded", - "objects.sys_oauth_refresh_token.fields.rotation_replay_response.help": "ea6d3f140afbbca7", - "objects.sys_oauth_refresh_token.fields.rotation_replay_response.label": "ddf6cf0ccba55c30", - "objects.sys_oauth_resource.description": "3c7f0cfae5b1a887", - "objects.sys_oauth_resource.fields.access_token_ttl.help": "293dc402a9669032", - "objects.sys_oauth_resource.fields.access_token_ttl.label": "afebf5750ed4d9ee", - "objects.sys_oauth_resource.fields.allowed_scopes.help": "af9195bf5efc4b27", - "objects.sys_oauth_resource.fields.allowed_scopes.label": "1a3202eecb314841", - "objects.sys_oauth_resource.fields.created_at.label": "1f02d416befb595b", - "objects.sys_oauth_resource.fields.custom_claims.help": "0afe2b2a099c7813", - "objects.sys_oauth_resource.fields.custom_claims.label": "c6182d11456325c4", - "objects.sys_oauth_resource.fields.disabled.label": "639459b8a7bbec04", - "objects.sys_oauth_resource.fields.dpop_bound_access_tokens_required.help": "d82b668d32d9d48f", - "objects.sys_oauth_resource.fields.dpop_bound_access_tokens_required.label": "715d383f9fc4fcfb", "objects.sys_oauth_resource.fields.id.label": "00b0385c9c152888", - "objects.sys_oauth_resource.fields.identifier.help": "b69d2662e0438576", - "objects.sys_oauth_resource.fields.identifier.label": "85b28b4a09f37cd0", - "objects.sys_oauth_resource.fields.metadata.help": "896f351a40678f21", - "objects.sys_oauth_resource.fields.metadata.label": "9cabc04013c80ef3", - "objects.sys_oauth_resource.fields.name.label": "5274417ff1ccaf01", - "objects.sys_oauth_resource.fields.policy_version.help": "18b93d988a1d6107", - "objects.sys_oauth_resource.fields.policy_version.label": "55fdeadcaba6cd2a", - "objects.sys_oauth_resource.fields.refresh_token_ttl.help": "9bbb700667d7cee7", - "objects.sys_oauth_resource.fields.refresh_token_ttl.label": "e4b35b5501ac588f", - "objects.sys_oauth_resource.fields.signing_algorithm.help": "3f8231cc5435a673", - "objects.sys_oauth_resource.fields.signing_algorithm.label": "c26616cf69746887", - "objects.sys_oauth_resource.fields.signing_key_id.help": "8504e8cddac3b67c", - "objects.sys_oauth_resource.fields.signing_key_id.label": "50da11ac4977fa58", - "objects.sys_oauth_resource.fields.updated_at.label": "aba63dc2a9c79b8d", - "objects.sys_oauth_resource.label": "5077fa14e8d7418e", - "objects.sys_oauth_resource.pluralLabel": "1c6ad6e11287866f", - "objects.sys_organization.fields.parent_organization_id.help": "2ad4ebe3782901b9", - "objects.sys_organization.fields.parent_organization_id.label": "24129608643b897f", - "objects.sys_organization.fields.sort_order.help": "7355b98a96f85dfc", - "objects.sys_organization.fields.sort_order.label": "5f6b33fdc89e9d9f", - "objects.sys_scim_connection_binding._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_connection_binding.description": "b895133352f6681c", - "objects.sys_scim_connection_binding.fields.connection_id.help": "034eb7d93a212da1", - "objects.sys_scim_connection_binding.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_connection_binding.fields.connection_key.help": "7df9975f32bdf0bc", - "objects.sys_scim_connection_binding.fields.connection_key.label": "d6f7536848750bc1", - "objects.sys_scim_connection_binding.fields.created_at.label": "1f02d416befb595b", - "objects.sys_scim_connection_binding.fields.decommission_batch_count.label": "69d0d27bdfad1158", - "objects.sys_scim_connection_binding.fields.decommission_completed_at.label": "4b4367514668f16b", - "objects.sys_scim_connection_binding.fields.decommission_cursor_user_id.help": "1d826764513040e4", - "objects.sys_scim_connection_binding.fields.decommission_cursor_user_id.label": "05a4591457a4e80f", - "objects.sys_scim_connection_binding.fields.decommission_lease_expires_at.label": "8593f0a433758002", - "objects.sys_scim_connection_binding.fields.decommission_lease_id.help": "4baba8767b4bd19d", - "objects.sys_scim_connection_binding.fields.decommission_lease_id.label": "3f5bbd3bde910338", - "objects.sys_scim_connection_binding.fields.decommission_reconciled_user_count.label": "bc1a74ac6ea6dc87", - "objects.sys_scim_connection_binding.fields.decommission_revision.help": "08fc0bb780421ed4", - "objects.sys_scim_connection_binding.fields.decommission_revision.label": "a017c828e4cc0b22", - "objects.sys_scim_connection_binding.fields.decommission_status.help": "f766f15ae7b4e26e", - "objects.sys_scim_connection_binding.fields.decommission_status.label": "7d49c647b4e1e843", - "objects.sys_scim_connection_binding.fields.decommissioned_at.label": "912fef87cf041169", "objects.sys_scim_connection_binding.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_connection_binding.fields.provisioning_domain_id.help": "16baa93cc3b3ca9e", - "objects.sys_scim_connection_binding.fields.provisioning_domain_id.label": "d3da6908c7123b00", - "objects.sys_scim_connection_binding.label": "a86dce83ff9ae560", - "objects.sys_scim_connection_binding.pluralLabel": "074d8c7e8bd7e51b", - "objects.sys_scim_connection_credential._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_connection_credential.description": "e298fae44c1fb26b", - "objects.sys_scim_connection_credential.fields.active.help": "f1bb8af835e80434", - "objects.sys_scim_connection_credential.fields.active.label": "eee107cf4e466779", - "objects.sys_scim_connection_credential.fields.connection_id.help": "e12a9e64684333ba", - "objects.sys_scim_connection_credential.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_connection_credential.fields.created_at.label": "1f02d416befb595b", - "objects.sys_scim_connection_credential.fields.expires_at.help": "219771cb7e23e7f0", - "objects.sys_scim_connection_credential.fields.expires_at.label": "df0ef5fae02b2044", "objects.sys_scim_connection_credential.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_connection_credential.fields.label.help": "4c9becbaf107e198", - "objects.sys_scim_connection_credential.fields.label.label": "c680364257b11569", - "objects.sys_scim_connection_credential.fields.organization_id.help": "6b3f4cd8ef844bc5", - "objects.sys_scim_connection_credential.fields.organization_id.label": "3e55836156e1c1de", - "objects.sys_scim_connection_credential.fields.provisioning_domain_id.help": "dbcc622262a32b57", - "objects.sys_scim_connection_credential.fields.provisioning_domain_id.label": "d3da6908c7123b00", - "objects.sys_scim_connection_credential.fields.token_digest.help": "657e4fa81f3972f5", - "objects.sys_scim_connection_credential.fields.token_digest.label": "4373e0d7f2686878", - "objects.sys_scim_connection_credential.fields.updated_at.label": "aba63dc2a9c79b8d", - "objects.sys_scim_connection_credential.fields.user_id.help": "d960168361e9bf6a", - "objects.sys_scim_connection_credential.fields.user_id.label": "31bf172b446396d0", - "objects.sys_scim_connection_credential.label": "115ec12ad3c5cd52", - "objects.sys_scim_connection_credential.pluralLabel": "dc5e36622fb23f62", - "objects.sys_scim_group._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_group.description": "2cefe59ab8f2d6a2", - "objects.sys_scim_group.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_group.fields.created_at.label": "1f02d416befb595b", - "objects.sys_scim_group.fields.display_name.help": "9dfb190daeafc7ca", - "objects.sys_scim_group.fields.display_name.label": "5512fceb5183fd1f", - "objects.sys_scim_group.fields.display_name_key.help": "44628861d6565776", - "objects.sys_scim_group.fields.display_name_key.label": "ce0b9207c2a0b3e2", - "objects.sys_scim_group.fields.external_id.help": "6f779f6f163b3028", - "objects.sys_scim_group.fields.external_id.label": "b81498d9908b2ed1", - "objects.sys_scim_group.fields.external_id_key.help": "d91a6810e74d9d74", - "objects.sys_scim_group.fields.external_id_key.label": "70076aa519914607", "objects.sys_scim_group.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_group.fields.order_key.help": "d19cba034fc15454", - "objects.sys_scim_group.fields.order_key.label": "929e5f874fa283d5", - "objects.sys_scim_group.fields.provisioning_domain_id.label": "d3da6908c7123b00", - "objects.sys_scim_group.fields.revision.help": "9a4a009aaad3d9f7", - "objects.sys_scim_group.fields.revision.label": "9736a257b7ba380b", - "objects.sys_scim_group.fields.updated_at.label": "aba63dc2a9c79b8d", - "objects.sys_scim_group.label": "b1e8cffa120eaaf3", - "objects.sys_scim_group.pluralLabel": "041e7e49c26e6e23", - "objects.sys_scim_group_member._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_group_member.description": "5da1f5a9f6c74dce", - "objects.sys_scim_group_member.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_group_member.fields.created_at.label": "1f02d416befb595b", - "objects.sys_scim_group_member.fields.group_id.label": "588222bcabb4c16e", "objects.sys_scim_group_member.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_group_member.fields.membership_key.help": "127024a3ec9d4924", - "objects.sys_scim_group_member.fields.membership_key.label": "8fcb9f17bcc8cae9", - "objects.sys_scim_group_member.fields.scim_user_id.label": "ff9e9e3696e17ae8", - "objects.sys_scim_group_member.label": "a15085ccdbba4e72", - "objects.sys_scim_group_member.pluralLabel": "3f643c5a50a46d0d", - "objects.sys_scim_identity_tombstone._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_identity_tombstone.description": "e0c9699fda63d907", - "objects.sys_scim_identity_tombstone.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_identity_tombstone.fields.deleted_at.label": "ecae63a743df29cd", - "objects.sys_scim_identity_tombstone.fields.external_id.help": "62b69d5bd951252c", - "objects.sys_scim_identity_tombstone.fields.external_id.label": "b81498d9908b2ed1", - "objects.sys_scim_identity_tombstone.fields.external_id_key.help": "d91a6810e74d9d74", - "objects.sys_scim_identity_tombstone.fields.external_id_key.label": "70076aa519914607", "objects.sys_scim_identity_tombstone.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_identity_tombstone.fields.profile.help": "d11763773ca4c440", - "objects.sys_scim_identity_tombstone.fields.profile.label": "b174cad0a9c78e11", - "objects.sys_scim_identity_tombstone.fields.provisioning_domain_id.label": "d3da6908c7123b00", - "objects.sys_scim_identity_tombstone.fields.user_id.help": "b4c468629790014b", - "objects.sys_scim_identity_tombstone.fields.user_id.label": "6c0d22a931e235bd", - "objects.sys_scim_identity_tombstone.label": "1c70519325beeb22", - "objects.sys_scim_identity_tombstone.pluralLabel": "525ddcdf78b4ed15", - "objects.sys_scim_projection_grant._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_projection_grant.description": "8603e83095133dee", - "objects.sys_scim_projection_grant.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_projection_grant.fields.created_at.label": "1f02d416befb595b", - "objects.sys_scim_projection_grant.fields.grant_key.help": "d55c81e0237a4286", - "objects.sys_scim_projection_grant.fields.grant_key.label": "c5fbfa14170b0a49", "objects.sys_scim_projection_grant.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_projection_grant.fields.provisioning_domain_id.label": "d3da6908c7123b00", - "objects.sys_scim_projection_grant.fields.role.help": "5c3718daca38e97e", - "objects.sys_scim_projection_grant.fields.role.label": "6e45203a573cd5ab", - "objects.sys_scim_projection_grant.fields.scim_user_id.help": "da657b19880f3536", - "objects.sys_scim_projection_grant.fields.scim_user_id.label": "ff9e9e3696e17ae8", - "objects.sys_scim_projection_grant.fields.source_id.help": "ba8fcdf2adba6295", - "objects.sys_scim_projection_grant.fields.source_id.label": "9764aa679981804c", - "objects.sys_scim_projection_grant.fields.source_kind.help": "fbf04bdf23967c33", - "objects.sys_scim_projection_grant.fields.source_kind.label": "44c76b7b2471dd7c", - "objects.sys_scim_projection_grant.fields.source_value.help": "eb7d8b2966e31fb1", - "objects.sys_scim_projection_grant.fields.source_value.label": "5699bf94c3a3d655", - "objects.sys_scim_projection_grant.fields.updated_at.label": "aba63dc2a9c79b8d", - "objects.sys_scim_projection_grant.fields.user_id.help": "e1e49423749a2d12", - "objects.sys_scim_projection_grant.fields.user_id.label": "6c0d22a931e235bd", - "objects.sys_scim_projection_grant.label": "fbf273320dc0e8cb", - "objects.sys_scim_projection_grant.pluralLabel": "b8bb5769deedfbe3", - "objects.sys_scim_subject._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_subject.description": "8fc839e493ef3e75", - "objects.sys_scim_subject.fields.created_at.label": "1f02d416befb595b", "objects.sys_scim_subject.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_subject.fields.profile_source_id.help": "c109ad373576afe5", - "objects.sys_scim_subject.fields.profile_source_id.label": "6a263b010b51ecd1", - "objects.sys_scim_subject.fields.revision.help": "9a4a009aaad3d9f7", - "objects.sys_scim_subject.fields.revision.label": "9736a257b7ba380b", - "objects.sys_scim_subject.fields.updated_at.label": "aba63dc2a9c79b8d", - "objects.sys_scim_subject.fields.user_id.help": "6798a366e9db4bb8", - "objects.sys_scim_subject.fields.user_id.label": "6c0d22a931e235bd", - "objects.sys_scim_subject.label": "350900f1977ecb7f", - "objects.sys_scim_subject.pluralLabel": "6ae4d4963680cee7", - "objects.sys_scim_user._views.all.label": "6d6f653f8264ab17", - "objects.sys_scim_user.description": "efe9c1a95d6eeb8e", - "objects.sys_scim_user.fields.active.help": "d82a2ec5aebe530f", - "objects.sys_scim_user.fields.active.label": "eee107cf4e466779", - "objects.sys_scim_user.fields.connection_id.help": "e18a3d5a0d3d1ac8", - "objects.sys_scim_user.fields.connection_id.label": "0208b246b41cd035", - "objects.sys_scim_user.fields.connection_user_key.help": "efb51acc3fea954a", - "objects.sys_scim_user.fields.connection_user_key.label": "58622a8cc908c01e", - "objects.sys_scim_user.fields.created_at.label": "1f02d416befb595b", - "objects.sys_scim_user.fields.display_name.label": "5512fceb5183fd1f", - "objects.sys_scim_user.fields.email_value_index.help": "4f3c5b1f20c870be", - "objects.sys_scim_user.fields.email_value_index.label": "b31d7d6d561bcde3", - "objects.sys_scim_user.fields.external_id.help": "6f779f6f163b3028", - "objects.sys_scim_user.fields.external_id.label": "b81498d9908b2ed1", - "objects.sys_scim_user.fields.external_id_key.help": "d91a6810e74d9d74", - "objects.sys_scim_user.fields.external_id_key.label": "70076aa519914607", - "objects.sys_scim_user.fields.family_name.label": "9190adafe369fb71", - "objects.sys_scim_user.fields.formatted_name.label": "90c57aa3a7dfffd6", - "objects.sys_scim_user.fields.given_name.label": "055d37cebecaf97e", "objects.sys_scim_user.fields.id.label": "00b0385c9c152888", - "objects.sys_scim_user.fields.order_key.help": "d19cba034fc15454", - "objects.sys_scim_user.fields.order_key.label": "929e5f874fa283d5", - "objects.sys_scim_user.fields.primary_email.label": "15da02d3854d82c1", - "objects.sys_scim_user.fields.provisioning_domain_id.label": "d3da6908c7123b00", - "objects.sys_scim_user.fields.serialized_attributes.help": "e865a06565b3e303", - "objects.sys_scim_user.fields.serialized_attributes.label": "93c3785f905ff51e", - "objects.sys_scim_user.fields.serialized_emails.help": "5eea0721c9a26b9c", - "objects.sys_scim_user.fields.serialized_emails.label": "100eb0a58d7c9d5a", - "objects.sys_scim_user.fields.updated_at.label": "aba63dc2a9c79b8d", - "objects.sys_scim_user.fields.user_id.help": "8d35db5208c6bdf4", - "objects.sys_scim_user.fields.user_id.label": "6c0d22a931e235bd", - "objects.sys_scim_user.fields.user_name.help": "a72cc81d09cd66b6", - "objects.sys_scim_user.fields.user_name.label": "bf59c7fd3e98bc55", - "objects.sys_scim_user.fields.user_name_key.help": "72b94b4a5964572b", - "objects.sys_scim_user.fields.user_name_key.label": "632218ca52daf77b", - "objects.sys_scim_user.fields.work_email_value_index.help": "4f3c5b1f20c870be", - "objects.sys_scim_user.fields.work_email_value_index.label": "8d37193924db29c7", - "objects.sys_scim_user.label": "ff9e9e3696e17ae8", - "objects.sys_scim_user.pluralLabel": "b8538685c24f5084", - "objects.sys_secret._views.all.label": "20d032bd60c81773", "objects.sys_secret.fields.id.label": "00b0385c9c152888", - "objects.sys_session.fields.last_activity_at.help": "f7851e9373505e73", - "objects.sys_session.fields.last_activity_at.label": "43bd2f1b231bc12b", - "objects.sys_session.fields.revoke_reason.help": "fcd18baf6b341b7f", - "objects.sys_session.fields.revoke_reason.label": "13b0146153a2ecf8", - "objects.sys_session.fields.revoked_at.help": "77a508fdceda2f6d", - "objects.sys_session.fields.revoked_at.label": "054f918e632528c7", - "objects.sys_setting_audit._views.recent.label": "62d27bb9d0349c99", "objects.sys_setting_audit.fields.id.label": "00b0385c9c152888", "objects.sys_setting_audit.fields.source.options.api": "4baeeff968e192d1", "objects.sys_setting_audit.fields.source.options.ui": "95caad102a5c97ba", @@ -367,17 +59,5 @@ export const zhCNGeneratedSourceHashes: Readonly> = { "objects.sys_sso_provider._actions.register_sso_provider.params.mapName.placeholder": "a484c34aaf624bd6", "objects.sys_sso_provider._actions.register_sso_provider.params.scopes.placeholder": "58ac90cde28c764d", "objects.sys_sso_provider.fields.id.label": "00b0385c9c152888", - "objects.sys_team.fields.member_count.help": "498d7d7119ffff12", - "objects.sys_team.fields.member_count.label": "7bb48f7c92af14e0", - "objects.sys_team_member.fields.membership_key.help": "08a5017306c3ac4e", - "objects.sys_team_member.fields.membership_key.label": "8fcb9f17bcc8cae9", - "objects.sys_two_factor.fields.failed_verification_count.help": "8cea41d6de7f4d5a", - "objects.sys_two_factor.fields.failed_verification_count.label": "e0438d2e39cb0500", - "objects.sys_two_factor.fields.locked_until.help": "059956062c752f2c", - "objects.sys_two_factor.fields.locked_until.label": "c7f013ad9b7208d2", - "objects.sys_two_factor.fields.verified.help": "0d351ba4c31608c2", - "objects.sys_two_factor.fields.verified.label": "866e3a245ef04734", - "objects.sys_user.fields.manager_id.help": "a53dec9ccd9d131f", - "objects.sys_user.fields.primary_business_unit_id.help": "e01690f4a9b83956", "objects.sys_view_definition.fields.id.label": "00b0385c9c152888", }; From 18930de2e7dce3e7aa8d8468f7656828563ee97b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 17:51:28 +0000 Subject: [PATCH 3/5] test(platform-objects): record the zh-CN objects echoes kept in English and pin the reproduced strings A decision ledger for the objects bundle, in the shape the metadata-form ledgers use: 42 leaves declared English by design with a reason each, and the two reproduced strings pinned translated. The nine panel ledgers' zh-CN provenance floors assumed the old copy debt (more than 100 or 300 rows, more than 50 echoing objects leaves); they now ask for a non-empty table and at least one sample, and the Access Token TTL near-twin records that zh-CN is now authored. Claude-Session: https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN Co-authored-by: Claude --- .../action-body-panel-echo-decisions.test.ts | 4 +- .../bare-type-display-echo-decisions.test.ts | 8 +- .../dataset-panel-echo-decisions.test.ts | 4 +- .../field-panel-echo-decisions.test.ts | 4 +- ...ook-execution-panel-echo-decisions.test.ts | 4 +- ...-collapsed-sections-echo-decisions.test.ts | 12 +- ...ect-lifecycle-panel-echo-decisions.test.ts | 27 +- .../objects-zh-cn-echo-decisions.test.ts | 320 ++++++++++++++++++ ...age-interface-panel-echo-decisions.test.ts | 4 +- .../report-form-echo-decisions.test.ts | 8 +- 10 files changed, 376 insertions(+), 19 deletions(-) create mode 100644 packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts diff --git a/packages/platform-objects/src/apps/translations/action-body-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/action-body-panel-echo-decisions.test.ts index 978dd53564f..706af281023 100644 --- a/packages/platform-objects/src/apps/translations/action-body-panel-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/action-body-panel-echo-decisions.test.ts @@ -528,7 +528,9 @@ describe('#19403 round 5 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); }); diff --git a/packages/platform-objects/src/apps/translations/bare-type-display-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/bare-type-display-echo-decisions.test.ts index 65837a697d2..19a8c76afb7 100644 --- a/packages/platform-objects/src/apps/translations/bare-type-display-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/bare-type-display-echo-decisions.test.ts @@ -703,7 +703,9 @@ describe('#19403 round 7 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); }); @@ -754,7 +756,9 @@ describe('#19403 round 7 — the provenance table agrees these leaves are now au // of my twelve is still a fill", but "no metadata type's own display pair // is still a fill, anywhere in this table". Lit by the table being large, // so a zero cannot come from an empty import. - expect(Object.keys(table).length).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length).toBeGreaterThan(0); const typeLevel = Object.keys(table).filter((k) => /^metadataForms\.[^.]+\.(label|description)$/.test(k)); expect(typeLevel, 'a metadata type display pair is still an extractor fill').toEqual([]); }); diff --git a/packages/platform-objects/src/apps/translations/dataset-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/dataset-panel-echo-decisions.test.ts index ec3cf9ea003..20d59d3b355 100644 --- a/packages/platform-objects/src/apps/translations/dataset-panel-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/dataset-panel-echo-decisions.test.ts @@ -556,7 +556,9 @@ describe('#19403 round 3 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); }); diff --git a/packages/platform-objects/src/apps/translations/field-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/field-panel-echo-decisions.test.ts index c4e6035ba5e..284dceae8cd 100644 --- a/packages/platform-objects/src/apps/translations/field-panel-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/field-panel-echo-decisions.test.ts @@ -557,7 +557,9 @@ describe('#19403 round 4 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); }); diff --git a/packages/platform-objects/src/apps/translations/hook-execution-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/hook-execution-panel-echo-decisions.test.ts index d04e25e57a6..882fc797ce9 100644 --- a/packages/platform-objects/src/apps/translations/hook-execution-panel-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/hook-execution-panel-echo-decisions.test.ts @@ -669,7 +669,9 @@ describe('#19403 round 6 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); }); diff --git a/packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.ts index ae25091ee36..b65d23d0e4a 100644 --- a/packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/object-collapsed-sections-echo-decisions.test.ts @@ -770,7 +770,9 @@ describe('#19403 round 8 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); }); @@ -807,7 +809,9 @@ describe('#19403 round 8 — the provenance table agrees these leaves are now au const authored = [...enObjectPaths] .filter(([path, en]) => localeObjects.has(path) && localeObjects.get(path) !== en) .map(([path]) => path); - expect(echoing.length, `${locale} has no echoing objects leaf to sample`).toBeGreaterThan(50); + // At least one of each is what makes a positive AND a negative; since + // #20462 zh-CN's echoing objects leaves are its 42 declared English ones. + expect(echoing.length, `${locale} has no echoing objects leaf to sample`).toBeGreaterThan(0); expect(authored.length, `${locale} has no authored objects leaf to sample`).toBeGreaterThan(50); expect( echoing.filter((path) => table[`objects.${path}`] === undefined), @@ -848,7 +852,9 @@ describe('#19403 round 8 — the provenance table agrees these leaves are now au // The strongest form the verdict above can take for this class: not "none // of my eleven", but "nothing this population reaches, outside the // declared deferral". Lit by the table being large. - expect(Object.keys(table).length).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length).toBeGreaterThan(0); const stillFilled = PANEL_LEAVES.filter( (l) => !inDeferral(l) && table[`metadataForms.object.fields.${l.path}.${l.prop}`] !== undefined, ).map((l) => `${l.path}.${l.prop}`); diff --git a/packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts index 5fc078ca9bb..9af0ba001ce 100644 --- a/packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts @@ -1283,15 +1283,24 @@ describe('#19403 round 10 — ⚠️⚠️ the phantom-translation trap, asserte }); it('⭐ the near-twin that was LOOKED UP AND REFUSED is asserted to be a fill, not a decision', () => { - // `Access Token TTL` is byte-identical in all three locales and reads like a - // standing decision to keep TTL verbatim. It is an unauthored fill in every - // locale — including zh-CN — and the provenance tables say so. Asserted so - // that no later round leans on it. + // `Access Token TTL` was byte-identical in all three locales and read like a + // standing decision to keep TTL verbatim. It was an unauthored fill in every + // locale, and the provenance tables said so. Asserted so that no later round + // leans on it. #20462 then AUTHORED the zh-CN leaf (访问令牌 TTL): the + // concept is rendered and the initialism survives, the same treatment the + // lifecycle rows give TTL. ja-JP and es-ES are still fills. const key = 'sys_oauth_resource.fields.access_token_ttl.label'; const en = FLAT_OBJECTS.get('en')!.get(key); expect(en).toBe('Access Token TTL'); for (const [locale, table] of PROVENANCE) { - expect(FLAT_OBJECTS.get(locale)!.get(key), `${locale} ${key}`).toBe(en); + const value = FLAT_OBJECTS.get(locale)!.get(key); + if (locale === 'zh-CN') { + expect(value, `${locale} ${key} reads its en source again`).not.toBe(en); + expect(carriesToken(value!, 'TTL'), `${locale} dropped the machine token`).toBe(true); + expect(table[`objects.${key}`], `${locale} still records the authored ${key} as a fill`).toBeUndefined(); + continue; + } + expect(value, `${locale} ${key}`).toBe(en); expect( table[`objects.${key}`], `${locale} no longer records ${key} as a fill — if a translator authored it, this ledger note is stale`, @@ -1308,7 +1317,9 @@ describe('#19403 round 10 — the SECOND WITNESS, over the `metadataForms.`-pref // exists exactly while the leaf IS a byte copy of the source revision, so // a leaf this round authored must have lost its row. const keys = Object.keys(table); - expect(keys.length, 'the provenance table is empty — the witness cannot testify').toBeGreaterThan(300); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(keys.length, 'the provenance table is empty — the witness cannot testify').toBeGreaterThan(0); const metadataFormRows = keys.filter((k) => k.startsWith('metadataForms.')); // The reading: NOTHING under the metadataForms. prefix is a fill any more. expect(metadataFormRows, `${locale} still records a metadata-form leaf as an unauthored fill`).toEqual([]); @@ -1333,7 +1344,9 @@ describe('#19403 round 10 — the SECOND WITNESS, over the `metadataForms.`-pref const loc = FLAT_OBJECTS.get(locale)!; const echoing = [...en].filter(([k, v]) => loc.get(k) === v).map(([k]) => k); const authored = [...en].filter(([k, v]) => loc.get(k) !== undefined && loc.get(k) !== v).map(([k]) => k); - expect(echoing.length, `${locale} has no echoing objects leaf to sample`).toBeGreaterThan(50); + // At least one of each is what makes a positive AND a negative; since + // #20462 zh-CN's echoing objects leaves are its 42 declared English ones. + expect(echoing.length, `${locale} has no echoing objects leaf to sample`).toBeGreaterThan(0); expect(authored.length, `${locale} has no authored objects leaf to sample`).toBeGreaterThan(50); expect( echoing.filter((k) => table[`objects.${k}`] === undefined), diff --git a/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts new file mode 100644 index 00000000000..c1694eaa4c2 --- /dev/null +++ b/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts @@ -0,0 +1,320 @@ +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. +// +// #20462 — the DECISION LEDGER for the zh-CN `objects` bundle's en-echoes. +// +// An en-echo is not automatically a defect: a leaf that reads its English +// source may be an unauthored extractor fill, or it may be the right rendering +// for that locale. The two are byte-identical, so the distinction cannot be +// recovered from the catalog later — it has to be RECORDED when someone looks. +// The metadata-form panels keep that record in their own ledgers +// (`report-dataset-panel-echo-decisions.test.ts` and the rounds after it); this +// file is the same record, in the same shape, for the `objects` bundle: +// `Verdict` per row, a reason for every row, and a per-locale `departure` for +// every `echo`. +// +// ## What was decided, and where it was measured +// +// Walk of `en.objects.generated.ts` against `zh-CN.objects.generated.ts` at +// base b810ddb6f, counting every string leaf byte-equal to its `en` leaf: +// +// before 362 copies — `label` 196 · `options.*` 20 · `pluralLabel` 11 · +// `help` 114 · `description` 11 · `placeholder` 4 · +// `emptyState.*` 4 · result-dialog field 2 +// after 42 copies — every one of them a row below with verdict `echo` +// +// The other 320 were extractor fills and are translated. The extractor files a +// field's `help` / `description` / `placeholder` under the same `source` kind +// as its `label` (`ExpectedEntry.source` in `packages/cli/src/utils/ +// i18n-extract.ts`), so they were decided as the same class. +// +// Per-leaf witness: the package's provenance table +// (`zh-CN.source-hashes.generated.ts`) holds an entry exactly while a leaf is +// still a byte copy of its source revision. `pnpm i18n:extract` dropped the 320 +// rows for the translated leaves and kept exactly the 42 below; asserted. +// +// ## What this file deliberately does NOT assert +// +// That no OTHER zh-CN objects leaf reads its `en` source. A new field's label +// arrives in every translated locale as a `--fill=default` copy, so that +// assertion would red every future PR that adds a platform-object field without +// a zh-CN word. It is the coverage-ratchet half of #20462, which the triage kept +// out of this card: widening a gate is a separate decision. +// +// Only zh-CN is decided here. ja-JP and es-ES carry the same copy class and are +// not touched. +// +// ⛔ Do not add a row here to make a red go away. A row is a decision someone +// took about one leaf; the `echo` verdict needs its own reason precisely so that +// recording "the English is right here" costs a sentence. + +import { describe, it, expect } from 'vitest'; + +import { enObjects } from './en.objects.generated.js'; +import { zhCNObjects } from './zh-CN.objects.generated.js'; +import { zhCNGeneratedSourceHashes } from './zh-CN.source-hashes.generated.js'; +import { hashSource } from './source-hash.js'; + +const LOCALE = 'zh-CN'; + +/** `translate` — the echo was an unauthored fill. `echo` — the English IS the rendering. */ +type Verdict = 'translate' | 'echo'; + +interface Decision { + /** Dotted leaf path under `objects`. */ + path: string; + /** + * The `en` source the verdict was taken against. Held equal to the live + * bundle, so a reworded source reds this file instead of leaving a decision + * standing over text nobody judged. + */ + en: string; + /** The verdict for zh-CN. */ + verdict: Verdict; + /** Why — recorded for `translate` as much as for `echo`. */ + reason: string; + /** Required for every `echo` verdict: why the English is right in zh-CN. */ + departure?: string; +} + +const BRAND = + 'A sign-in provider brand, shown as the name a user recognises on the link button. The bundle renders no brand name: the authored SSO empty state keeps Okta, Entra and Auth0 verbatim.'; +const BARE_ID = + 'The bare initialism ID. This bundle keeps ID verbatim inside every label that carries it (用户 ID, 团队 ID, 客户端 ID); a bare en ID has no noun to render, and adding one would invent content.'; +const JWKS = + 'A protocol name (the RFC 7517 JWK Set) that this bundle keeps verbatim: sys_jwks is authored as 签名密钥 (JWKS), and every URI stays URI (重定向 URI).'; +const RESULT_DIALOG_CREDENTIAL = + 'The OAuth credential name an admin copies out of this one-time dialog. The same dialog family authored its zh-CN text with the name kept verbatim (我已保存 Client Secret, 新的 Client Secret).'; +const IDP_SSO_URL = + 'Nothing but protocol initialisms (IdP, SSO, URL), each of which this bundle keeps verbatim; the sibling SAML params are authored as IdP 实体 ID and IdP 签名证书.'; +const TYPED_CLAIM = + 'A placeholder shows the literal value the admin types: OIDC scope and claim names the IdP matches byte for byte. The authored help on the same param keeps them verbatim (默认为 “email”).'; +const TYPED_URN = + 'A placeholder shows the literal value the admin types, here the SAML NameID format URN: an identifier matched byte for byte, not prose.'; +const MESSAGE_ID = + 'The RFC 5322 header name. The authored help on the same field keeps it verbatim (传输层分配的 RFC-5322 Message-ID).'; +const CHANNEL_INITIALISM = + 'An initialism this bundle keeps verbatim wherever it appears (API 密钥, 在 UI 中暴露); the option names the channel a setting change came through.'; + +function echo(path: string, en: string, departure: string): Decision { + return { + path, + en, + verdict: 'echo', + reason: 'Kept in English by design, in the small brand / protocol / typed-value class the triage names.', + departure, + }; +} + +const DECISIONS: readonly Decision[] = [ + // ── The two reproduced strings (three leaves), pinned translated ───────── + { + path: 'sys_member.fields.role.options.delegated_admin', + en: 'Delegated Admin', + verdict: 'translate', + reason: + 'Reproduced: the membership role list read 所有者 / 管理员 / Delegated Admin / 成员. Rendered with the word the console already uses for this role value.', + }, + { + path: 'sys_invitation.fields.role.options.delegated_admin', + en: 'Delegated Admin', + verdict: 'translate', + reason: + 'Reproduced on the Invite user dialog, which lists these options. The same word as the sys_member row, asserted below, so one role is not translated two ways.', + }, + { + path: 'sys_team.fields.member_count.label', + en: 'Member Count', + verdict: 'translate', + reason: 'Reproduced on the team record page as MEMBER COUNT: an ordinary field label an admin reads, an unauthored fill.', + }, + + // ── Kept in English by design (42) ─────────────────────────────────────── + echo('sys_account._actions.link_social.params.provider.options.google', 'Google', BRAND), + echo('sys_account._actions.link_social.params.provider.options.github', 'GitHub', BRAND), + echo('sys_account._actions.link_social.params.provider.options.microsoft', 'Microsoft', BRAND), + echo('sys_account._actions.link_social.params.provider.options.apple', 'Apple', BRAND), + echo('sys_account._actions.link_social.params.provider.options.facebook', 'Facebook', BRAND), + echo('sys_account._actions.link_social.params.provider.options.gitlab', 'GitLab', BRAND), + echo('sys_account._actions.link_social.params.provider.options.discord', 'Discord', BRAND), + + echo('sys_oauth_application.fields.jwks.label', 'JWKS', JWKS), + echo('sys_oauth_application.fields.jwks_uri.label', 'JWKS URI', JWKS), + echo( + 'sys_oauth_application._actions.create_oauth_application.resultDialog.fields.client.client_id', + 'Client ID', + RESULT_DIALOG_CREDENTIAL, + ), + echo( + 'sys_oauth_application._actions.create_oauth_application.resultDialog.fields.client.client_secret', + 'Client Secret', + RESULT_DIALOG_CREDENTIAL, + ), + + echo('sys_sso_provider._actions.register_saml_provider.params.entryPoint.label', 'IdP SSO URL', IDP_SSO_URL), + echo('sys_sso_provider._actions.register_sso_provider.params.scopes.placeholder', 'openid email profile', TYPED_CLAIM), + echo('sys_sso_provider._actions.register_sso_provider.params.mapEmail.placeholder', 'email', TYPED_CLAIM), + echo('sys_sso_provider._actions.register_sso_provider.params.mapName.placeholder', 'name', TYPED_CLAIM), + echo( + 'sys_sso_provider._actions.register_saml_provider.params.identifierFormat.placeholder', + 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', + TYPED_URN, + ), + + echo('sys_email.fields.message_id.label', 'Message-ID', MESSAGE_ID), + echo('sys_setting_audit.fields.source.options.ui', 'UI', CHANNEL_INITIALISM), + echo('sys_setting_audit.fields.source.options.api', 'API', CHANNEL_INITIALISM), + + ...[ + 'sys_oauth_application', + 'sys_oauth_access_token', + 'sys_oauth_refresh_token', + 'sys_oauth_consent', + 'sys_oauth_resource', + 'sys_oauth_client_resource', + 'sys_oauth_client_assertion', + 'sys_sso_provider', + 'sys_scim_connection_binding', + 'sys_scim_connection_credential', + 'sys_scim_group', + 'sys_scim_group_member', + 'sys_scim_identity_tombstone', + 'sys_scim_projection_grant', + 'sys_scim_subject', + 'sys_scim_user', + 'sys_email_template', + 'sys_metadata', + 'sys_metadata_history', + 'sys_view_definition', + 'sys_metadata_audit', + 'sys_secret', + 'sys_setting_audit', + ].map((object) => echo(`${object}.fields.id.label`, 'ID', BARE_ID)), +]; + +/** Every string leaf of a bundle, keyed by its dotted path. */ +function flatten(node: unknown, prefix = '', out = new Map()): Map { + if (typeof node === 'string') { + out.set(prefix, node); + } else if (node && typeof node === 'object') { + for (const [k, v] of Object.entries(node)) flatten(v, prefix ? `${prefix}.${k}` : k, out); + } + return out; +} + +const EN = flatten(enObjects); +const ZH = flatten(zhCNObjects); + +/** + * Every `echo` verdict that carries no departure reason. A predicate rather + * than an inlined loop so the suite can prove it FIRES. + */ +function undeclaredEchoes(rows: readonly Decision[]): string[] { + return rows.filter((d) => d.verdict === 'echo' && (d.departure ?? '').length <= 40).map((d) => d.path); +} + +describe('#20462 — the ledger itself (controls before verdicts)', () => { + it('is the size it claims: 3 pinned translations and 42 declared echoes, no path twice', () => { + expect(DECISIONS.length).toBe(45); + expect(DECISIONS.filter((d) => d.verdict === 'translate').length).toBe(3); + expect(DECISIONS.filter((d) => d.verdict === 'echo').length).toBe(42); + expect(new Set(DECISIONS.map((d) => d.path)).size).toBe(DECISIONS.length); + }); + + it('every row is pinned to the live `en` source it was decided against', () => { + for (const d of DECISIONS) { + expect(EN.get(d.path), `en ${d.path} moved — re-judge the decision, do not refresh this row`).toBe(d.en); + } + }); + + it('the echo predicate can say "echo" — fed the `en` catalog, it flags every row', () => { + // Dark. `value === en` is the whole verdict test below; run it against the + // source catalog itself and it must hold for every row, or a green verdict + // run means nothing. + const flagged = DECISIONS.filter((d) => EN.get(d.path) === d.en); + expect(flagged.length).toBe(DECISIONS.length); + }); + + it('every decision records a reason, and every `echo` its departure', () => { + for (const d of DECISIONS) { + expect(d.reason.length, `${d.path} records no reason`).toBeGreaterThan(40); + } + expect(undeclaredEchoes(DECISIONS), 'a declared echo here carries no departure reason').toEqual([]); + }); + + it('refuses an `echo` verdict that carries no departure — proved on a synthetic row', () => { + const synthetic: Decision = { + path: 'sys_team.fields.member_count.label', + en: 'Member Count', + verdict: 'echo', + reason: 'A synthetic row that exists only to prove this file can refuse an undeclared echo.', + }; + expect(undeclaredEchoes([synthetic])).toEqual(['sys_team.fields.member_count.label']); + expect( + undeclaredEchoes([ + { ...synthetic, departure: 'A departure reason long enough to satisfy the rule, standing in for a real one.' }, + ]), + ).toEqual([]); + }); +}); + +describe('#20462 — the zh-CN catalog holds what the ledger decided', () => { + it('every decided leaf matches its verdict', () => { + for (const d of DECISIONS) { + const id = `${LOCALE} ${d.path}`; + const value = ZH.get(d.path); + expect(typeof value, `${id} is missing from the catalog`).toBe('string'); + expect((value as string).length, `${id} is empty`).toBeGreaterThan(0); + if (d.verdict === 'translate') { + expect(value, `${id} reads its en source again — the decision was that this echo is a fill`).not.toBe(d.en); + expect(value, `${id} carries no Chinese`).toMatch(/\p{Script=Han}/u); + } else { + expect(value, `${id} is a declared echo and must stay the en source`).toBe(d.en); + } + } + }); + + it('⭐ the role options read one word per role, on both objects the console lists them from', () => { + // The members list and the Invite user dialog render the same role values + // from two objects, which declare them from one spec constant + // (`BUILTIN_MEMBERSHIP_ROLE_OPTIONS`). One word per role on both. + const roles = (object: string): Record => + (zhCNObjects as Record)[object].fields.role.options; + expect(Object.keys(roles('sys_member'))).toContain('delegated_admin'); + expect(roles('sys_invitation')).toEqual(roles('sys_member')); + // DISTINCT words: a copy of one role's word onto another would pass the + // equality above. + const words = Object.values(roles('sys_member')); + expect(new Set(words).size).toBe(words.length); + for (const word of words) expect(word).toMatch(/\p{Script=Han}/u); + }); +}); + +describe('#20462 — the provenance table agrees', () => { + const table = zhCNGeneratedSourceHashes; + + it('every declared echo is still recorded as a byte copy of its CURRENT source', () => { + // Lit — the table really loaded. + expect(Object.keys(table).length, `${LOCALE} provenance table is empty`).toBeGreaterThan(0); + for (const d of DECISIONS.filter((r) => r.verdict === 'echo')) { + expect(table[`objects.${d.path}`], `${d.path} is a declared echo with no provenance row`).toBe( + hashSource(d.en), + ); + } + }); + + it('no translated row is still recorded as an extractor fill', () => { + const stillFilled = DECISIONS.filter((d) => d.verdict === 'translate' && table[`objects.${d.path}`] !== undefined); + expect(stillFilled.map((d) => d.path)).toEqual([]); + }); + + it('the provenance lookup can say "still a fill" and "authored" — both directions, on this bundle', () => { + // Dark. The verdict above is a run of `undefined`s, which is also what a + // misspelt key shape returns. The echo rows prove the composed key finds a + // real row; a leaf a translator wrote long before this card proves it does + // not find one where there is none. + const echoRow = DECISIONS.find((d) => d.verdict === 'echo')!; + expect(table[`objects.${echoRow.path}`]).toBeTypeOf('string'); + expect(ZH.get('sys_user.fields.email.label')).not.toBe(EN.get('sys_user.fields.email.label')); + expect(table['objects.sys_user.fields.email.label']).toBeUndefined(); + }); +}); diff --git a/packages/platform-objects/src/apps/translations/page-interface-panel-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/page-interface-panel-echo-decisions.test.ts index 5c2d443253d..ca91b604de5 100644 --- a/packages/platform-objects/src/apps/translations/page-interface-panel-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/page-interface-panel-echo-decisions.test.ts @@ -569,7 +569,9 @@ describe('#19403 round 2 — the provenance table agrees these leaves are now au it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { // Lit — the table really loaded, so "no entry" cannot pass by the import // having come back empty. - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map( (d) => `page.${d.scope}.${d.key}.${d.prop}`, ); diff --git a/packages/platform-objects/src/apps/translations/report-form-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/report-form-echo-decisions.test.ts index 3b0f3e1935e..5e4be812491 100644 --- a/packages/platform-objects/src/apps/translations/report-form-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/report-form-echo-decisions.test.ts @@ -1009,7 +1009,9 @@ describe('#19403 round 9 — the provenance table agrees these leaves are now au // catalog assertion above. for (const [locale, table] of PROVENANCE) { it(`${locale}: no decided leaf is still recorded as an extractor fill`, () => { - expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(100); + // Non-empty, not a debt size: since #20462 zh-CN's objects slice holds only + // its declared English-by-design leaves, so the table is small by design. + expect(Object.keys(table).length, `${locale} provenance table is empty`).toBeGreaterThan(0); const stillFilled = DECISIONS.filter((d) => table[provenanceKey(d)] !== undefined).map(idOf); expect(stillFilled, 'these leaves are still byte copies of their source revision').toEqual([]); // Stronger, and shrink-only: NOTHING under `report.` is a fill any more. @@ -1080,7 +1082,9 @@ describe('#19403 round 9 — the provenance table agrees these leaves are now au const objectAuthored = [...enObjectPaths] .filter(([p, en]) => localeObjectPaths.has(p) && localeObjectPaths.get(p) !== en) .map(([p]) => p); - expect(objectEchoes.length, `${locale} has no echoing objects leaf to sample`).toBeGreaterThan(50); + // At least one of each is what makes a positive AND a negative; since + // #20462 zh-CN's echoing objects leaves are its 42 declared English ones. + expect(objectEchoes.length, `${locale} has no echoing objects leaf to sample`).toBeGreaterThan(0); expect(objectAuthored.length, `${locale} has no authored objects leaf to sample`).toBeGreaterThan(50); expect( objectEchoes.filter((p) => table[`objects.${p}`] === undefined), From e1bf4e8b882e68660b07a75ebec2357e29c5d2a9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 17:52:35 +0000 Subject: [PATCH 4/5] chore(changeset): platform-objects patch for the zh-CN object label translations Claude-Session: https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN Co-authored-by: Claude --- .changeset/20462-zh-cn-object-labels.md | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .changeset/20462-zh-cn-object-labels.md diff --git a/.changeset/20462-zh-cn-object-labels.md b/.changeset/20462-zh-cn-object-labels.md new file mode 100644 index 00000000000..5d628d98c3a --- /dev/null +++ b/.changeset/20462-zh-cn-object-labels.md @@ -0,0 +1,28 @@ +--- +'@objectstack/platform-objects': patch +--- + +fix(platform-objects): the zh-CN platform-object bundle no longer ships English labels, options and help as copies of the source (#20462) + +Clause-②: no + +A zh-CN console showed English on Setup surfaces: the Invite user dialog listed +the membership roles as 所有者 / 管理员 / Delegated Admin / 成员, and a team record +read MEMBER COUNT. The keys were present in `zh-CN.objects.generated.ts`, but +their values were byte copies of the English source that `os i18n extract +--fill=default` seeds. + +- 320 of the 362 zh-CN string leaves that equalled their `en` source are now + translated: labels, plural labels, select options, help, descriptions, + placeholders and empty states. `delegated_admin` reads 受托管理员 on both + `sys_member` and `sys_invitation`, the word the console already uses for that + role. +- The other 42 stay English by design, and each is recorded with its reason in + `objects-zh-cn-echo-decisions.test.ts`: sign-in provider brands (Google, GitHub, + …), the bare `ID` initialism, protocol names (JWKS, IdP SSO URL, Message-ID, + UI / API), the OAuth credential names in the create-application result dialog, + and placeholders that show a value the admin types. + +`zh-CN.source-hashes.generated.ts` was regenerated by `pnpm i18n:extract`: it +records a leaf only while the leaf is a copy of its source, so it now lists +exactly those 42. `ja-JP` and `es-ES` are unchanged. From 4265c40cad6550088f9c325730acb321fc8ef770 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 28 Sep 2026 18:41:16 +0000 Subject: [PATCH 5/5] docs(platform-objects): the changeset lists no translated placeholders, and the ledger header says what it asserts All four placeholders were decided as echoes, so the changeset's translated class list drops them. The ledger header now names the two assertion directions instead of claiming the provenance rows equal the echoes. Claude-Session: https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN Co-authored-by: Claude --- .changeset/20462-zh-cn-object-labels.md | 4 ++-- .../apps/translations/objects-zh-cn-echo-decisions.test.ts | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.changeset/20462-zh-cn-object-labels.md b/.changeset/20462-zh-cn-object-labels.md index 5d628d98c3a..e78c4881a17 100644 --- a/.changeset/20462-zh-cn-object-labels.md +++ b/.changeset/20462-zh-cn-object-labels.md @@ -13,8 +13,8 @@ their values were byte copies of the English source that `os i18n extract --fill=default` seeds. - 320 of the 362 zh-CN string leaves that equalled their `en` source are now - translated: labels, plural labels, select options, help, descriptions, - placeholders and empty states. `delegated_admin` reads 受托管理员 on both + translated: labels, plural labels, select options, help, descriptions and + empty states. `delegated_admin` reads 受托管理员 on both `sys_member` and `sys_invitation`, the word the console already uses for that role. - The other 42 stay English by design, and each is recorded with its reason in diff --git a/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts b/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts index c1694eaa4c2..5f9d83ea888 100644 --- a/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts +++ b/packages/platform-objects/src/apps/translations/objects-zh-cn-echo-decisions.test.ts @@ -30,7 +30,11 @@ // Per-leaf witness: the package's provenance table // (`zh-CN.source-hashes.generated.ts`) holds an entry exactly while a leaf is // still a byte copy of its source revision. `pnpm i18n:extract` dropped the 320 -// rows for the translated leaves and kept exactly the 42 below; asserted. +// rows for the translated leaves and kept 42 rows, one per echo below (measured +// equal at the time). What is asserted is one direction per verdict: every +// declared echo still has its row, and no pinned translation has one. That the +// table holds nothing BEYOND the echoes is not asserted, for the reason the +// next section gives. // // ## What this file deliberately does NOT assert //