feat(i18n): localize Connectors and Tools in zh-CN - #1717
lilyshen0722 wants to merge 10 commits into
Conversation
Wren — UX Lead copy review of
|
| where | what a zh-CN user sees |
|---|---|
V2ConnectorTools.tsx:93 relativeTime |
just now / 2h ago / 3d from now / in a moment inside 已授权 {{rel}}, the trail's when column, and budgetWindow (whose .replace(' ago','') hack only works in English) |
V2ConnectorsPage.tsx:169 second relativeTime |
same, English only |
V2ConnectorsPage.tsx:565,578,594,612,655,713,714,778,960 |
template literals started ${…}, since ${…}, added ${…}, Slack answered ${…}, paused ${…} |
Ask: one shared relativeTime(t, date) (or reuse the existing time.* keys at en.json:385, which already have _one/_other plurals) returning 刚刚 / {{count}} 分钟前 / {{count}} 小时前 / {{count}} 天前 / {{count}} 天后; the five literal prefixes become keys (connectors.sinceRel 自 {{rel}}… or restructure); budgetWindow gets its own window formatter (每 {{window}} 可调用 {{calls}} 次 with window = 1 小时 / 1 天), no string surgery. Extend the invariant so a template literal containing ${relativeTime( in these two files fails.
Once rel is 2 小时前, the zh word order must lead with it (the trailing-adverbial calque is a banned pattern in the skill):
| key | before | after |
|---|---|---|
| tools.grantedWhen | 已授权 {{rel}} | {{rel}}授权 |
| tools.revokedByLine | 已由 {{member}} 撤销 {{rel}} | {{rel}}由 {{member}} 撤销 |
| tools.revokedLine | 已撤销 {{rel}} | {{rel}}撤销 |
| tools.expiredLine | 已过期 {{rel}} | {{rel}}过期 |
| tools.grantedByOn | 由 {{member}} 授权于 {{rel}}。 | {{rel}}由 {{member}} 授权。 |
| tools.grantedOn | 已授权 {{rel}}。 | {{rel}}授权。 |
| tools.endedRevokedBy | 已由 {{member}} 撤销({{rel}})。 | {{rel}}由 {{member}} 撤销。 |
| tools.endedRevoked | 已撤销({{rel}})。 | {{rel}}撤销。 |
| tools.endedExpired | 已过期({{rel}})。 | {{rel}}过期。 |
| tools.endsRel | 将于 {{rel}} 结束。 | {{rel}}结束。 (rel = 3 天后) |
Terminology corrections (rulings)
| key | before | after | reason |
|---|---|---|---|
| connectors.codeError | 无法创建新代码。 | 无法生成新的启用码。 | 代码 = source code; the enable code is 启用码 |
| connectors.newCode | 新代码 | 新启用码 | same |
| connectors.showCode | 显示代码 | 显示启用码 | same |
| connectors.codeExpired | 启用代码已过期。 | 启用码已过期。 | same |
| connectors.askOperator | 联系你的管理员 | 联系实例管理员 | operator ≠ administrator; the EN keeps them distinct and so must zh |
| connectors.providerNotConfigured | 此实例尚未启用 {{connector}}。请联系你的管理员。 | 此实例尚未启用 {{connector}},请联系实例管理员。 | same |
| connectors.pausedRefusal | 管理员已暂停此连接器,请联系你的管理员。 | 管理员已暂停此连接器,请联系实例管理员。 | removes the 管理员…管理员 loop |
| tools.notEnabled | 此实例尚未启用 · 联系你的管理员 | 此实例尚未启用 · 联系实例管理员 | same |
| connectors.ask, tools.ask | 请求 | 申请 | a bare 请求 is not a button; 申请 is the verb-first request-access button |
| connectors.activeTag | 活跃 | 当前 | active here = the pod this channel currently serves, not "lively" |
| connectors.makeActive | 设为活跃 | 设为当前 | same |
| connectors.rowRelayOff / mode / gateSwitch / relayOffHint | 中继 | 转发 | 转发 is what Chinese chat products call relaying messages to a channel; 中继 is a network-hardware term. Apply to every 中继: 转发已关闭, 转发模式, 转发 {{pod}}, 你的转发、模式和 Pod 都会保留 |
| connectors.rowAttention | 仅提醒 · 升级消息会发送到频道 | 仅提醒 · 需要关注的消息才会发送到频道 | 升级 reads as "upgrade"; escalation = 需要关注的消息 |
| connectors.attentionHint | 只有升级消息和主导智能体的消息会发送到频道。 | 只有需要关注的消息和主导智能体的消息会发送到频道。 | same |
Voice (rhythm; take them)
| key | before | after |
|---|---|---|
| connectors.description | …它会在那里用自己的名字回复… | …它会在那里以自己的名义回复… |
| connectors.gatesTitle | 会将消息发送到此频道的 Pod | 接入此频道的 Pod |
| connectors.pickWhere | 选择消息发送位置 | 选择消息发往哪里 |
| connectors.notLinkedDetail | 你的消息没有发送目标 | 你的消息还没有去处 |
| connectors.slackConfirmRow | {{workspace}} 显示 {{user}} 已连接 — 是你吗? | {{workspace}} 显示 {{user}} 已连接,是你吗? |
| connectors.leadAny | 任意智能体均可主导 | 任一智能体都可主导 |
| tools.asksNothing | 无需先请求确认 | 无需确认 |
| tools.asksEveryWrite | 每次写入都需先请求确认 | 每次写入前都需确认 |
| tools.asksList | {{tools}} 需先请求确认 | {{tools}} 调用前需确认 |
| tools.asksFirst | 需先请求人工确认 | 调用前需人工确认 |
| tools.modeWriteConfirm | 读取和写入,先请求确认 | 读取和写入,写入前需确认 |
| tools.staleAfterChange | …撤销没有完成。 | …撤销未成功。 |
Out of scope for this PR (filed on the board)
One Telegram chat, one pod. / One Slack workspace, one pod. / GitHub issues and pull requests. in the capture are server data: backend/integrations/manifests.ts catalogue descriptions and the Installable description. A frontend PR cannot localise them; that is a manifest-level description map or a client override keyed by connector id — separate task.
Evidence: connectors-tools-zh-CN-1200.png is a real PNG (1200×1000), zh-CN rail active, page in Chinese except the server strings above. I look again at the next head.
|
Addendum to the change table (Sam 68723):
Row descriptions ("One Telegram chat, one pod." etc.) are |
|
Second pass at exact head
Note for the gate (Vera's call, not blocking my look): the negative check in The 管理员 wrap in the GitHub row's "联系实例管理员" (管理 / 员 across two lines) is CJK line breaking in a narrow column, not copy; out of scope here. I look again at the next head; then Vera's gate and the hold for Sam's native pass. |
|
Follow-up at head |
|
Structural follow-up at head |
Wren — two-pass copy review at exact head
|
| key | before | after | reason |
|---|---|---|---|
tools.budgetWindow |
每 {{window}} 可调用 {{calls}} 次 |
每 {{window}}可调用 {{calls}} 次 |
{{window}} renders through time.*Duration and always ends in CJK (分钟/小时/天); the half-width space rule is CJK↔Latin only, so today's output is 每 1 小时 可调用 5 次 with a stray space before 可. |
connectors.description |
每个频道从一个 Pod 接入 1 个智能体。… |
每个频道从一个 Pod 接入一个智能体。… |
One sentence mixes 一个 and 1 个; use the character form for both (the numeral form is the marketing-count register). |
Notes for Sam's ear (no change proposed):
{{rel}}起withrel = 刚刚renders刚刚起— only reachable whengate.sinceis absent; acceptable to me, flagging for the native read.tools.days({{count}} 天后) is the expiry<select>label, distinct fromtime.daysFromNow; keeping both is right.time.*carries base +_one+_othertriplets in zh-CN although zh-CN has only theothercategory — harmless, and the parity test wants identical key sets, so leave it.
Code follow-up, not blocking (Wren's call): localizeRelativeTime now branches on missing === 'just now' || missing === 'in a moment' to pick the key — an English-literal compare in miniature. Cleaner shape when this file is next touched: missingAsNow?: boolean (or missingKey) on RelativeTimeOptions, relativeParts returns { kind: 'now', future: false } for a missing date when set, and the page passes that instead of English text. Output unchanged.
Cleared for my part at 2008e7aa with the two rows above riding Sam's native pass. Vera re-gates the head; HOLD for Sam.
2008e7a to
57fe417
Compare
Change table addendum: zh-CN strings for the nine
|
| key | en (from #1722) | zh-CN | reason |
|---|---|---|---|
tools.installGitHubApp |
Install GitHub App | 安装 GitHub App | button, verb-first; matches 请先安装 GitHub App in noConnection |
tools.adminSetup |
administrator setup | 管理员设置 | eyebrow label, noun phrase |
tools.githubAppSetupHint |
Connect the GitHub App once so people can grant GitHub tools to their rooms. | 只需连接一次 GitHub App,成员就能把 GitHub 工具授权给自己的 Pod。 | once → 只需…一次; rooms → Pod; no 通过…进行… calque |
tools.installationId |
installation ID | 安装 ID | field label; ID stays Latin, half-width space |
tools.owner |
owner | 所有者 | GitHub's own zh UI term for the owner field |
tools.repository |
repository | 仓库 | matches #1719's 仓库中的 issue 和 pull request |
tools.installingGitHubApp |
Installing… | 安装中… | parallels granting = 授权中… |
tools.githubAppRequired |
Enter the installation ID, owner, and repository. | 请填写安装 ID、所有者和仓库。 | enumeration with 、; 填写 for form fields |
tools.githubAppError |
Could not install the GitHub App. | 无法安装 GitHub App。 | parallels grantError = 无法授权。 |
Sam's native pass sees these with the rest of the table.
Addendum (Wren, after #1722 head e758bda): #1722 also carries a bare English literal for the second-admin case; once keyed as tools.githubAppOwnedByOther (en entry in #1722), its zh-CN entry for #1717 is:
| key | en | zh-CN |
|---|---|---|
tools.githubAppOwnedByOther |
This GitHub App is already installed by another administrator. | 这个 GitHub App 已由另一位管理员安装。 |
Ten keys total, not nine.
en column = the exact defaultValue strings in #1722 at 084f431; copy them verbatim into en.json.
57fe417 to
ef96cca
Compare
ef96cca to
2c54935
Compare
Summary
connectors.*andtools.*key used by the v2 pagesVerification
npx jest --watchAll=false --runInBand src/v2/__tests__/v2-i18n-invariants.test.tsnpx jest --watchAll=false --runInBand src/v2/__tests__/V2ConnectorsPage.test.tsx src/v2/__tests__/V2ConnectorTools.test.tsxnpm run buildUX Lead review and Vera gate required before merge; Sam native-speaker pass is the merge gate.