开发规范
代码命名规范、i18n 翻译术语表、中文风格指南的唯一权威来源。
本页是代码命名规范、i18n 翻译术语表、中文风格指南的唯一权威来源。原本散落在 packages/views/locales/glossary.md 和各处注释里的规则现在都收拢到这里。
写 Clowld Space 代码、改翻译、写中文产品文案,都从这一页查。
术语与概念真源
- 产品对象的固定名称、含义和关系以
docs/知识库/开始使用/核心概念.md为领域真源;官网apps/docs/content/docs/concepts.zh.mdx保持同一语义。 - 本页定义代码命名、i18n 术语与中文产品文风;仓库镜像
docs/知识库/开发者/开发规范.md除 Markdown 标题包装外与本页逐字同步。 - 不创建
CONTEXT.md、独立 glossary 或其他平行术语表。术语或概念变化必须在同一改动中同步所有受影响的真源,冲突解决后才能合并。
1. 代码命名
路由
工作区前置路由(用户进入工作区之前能访问的路由)必须用单个单词,或者 /{noun}/{verb} 格式。
- ✅
/login、/inbox、/workspaces/new - ❌
/new-workspace、/create-team、/accept-invite
根目录的连字符词组会跟用户自选 workspace slug 冲突,逼着团队不停审保留字列表。把名词(workspaces)保留下来,整个 /workspaces/* 子树自动受保护。
工作区路由
永远用 /{slug}/{section} —— /{slug}/issues、/{slug}/agents、/{slug}/settings。共享代码不要复制路由逻辑,统一走 useNavigation().push(),不要直接用框架的 link API。
包与模块
monorepo 的包边界是硬约束:
| 包 | 可依赖 | 不能依赖 |
|---|---|---|
packages/core | 仅平台无关基础库 | react-dom、localStorage、process.env、next/*、UI 库 |
packages/ui | 无业务依赖 | @clowld/core、业务逻辑 |
packages/views | core/、ui/ | next/*、react-router-dom、stores |
apps/web/platform/ | next/* | 其他 app |
apps/desktop/.../platform/ | react-router-dom、electron | 其他 app |
apps/mobile/ | @clowld/core 的类型和纯函数 | Web/Desktop 的 React 页面、store 和平台实现 |
Web 和 Desktop 都有的逻辑,必须抽到共享包。"小段重复"也不算例外。Mobile 拥有独立的 UI、数据层和发布流程,只共享类型与纯函数。
文件与组件
- 文件名:
kebab-case.tsx/kebab-case.ts(如agent-row-actions.tsx) - 组件:
PascalCase(如AgentRowActions) - Hook:
useCamelCase(如useWorkspaceId) - 测试:与源文件同目录,命名
<file>.test.ts(x) - Zustand store:
<feature>-store.ts,导出名use<Feature>Store
数据库(Go + sqlc)
- 表名:
snake_case单数(user、workspace、agent_runtime) - 字段:
snake_case(workspace_id、created_at、last_seen_at) - 关联字段:
<table>_id - 布尔:
is_<state>或者<state>_at(状态变化优先用时间戳形式) - 迁移文件:
NNN_descriptive_name.up.sql+.down.sql,永远写双向 - 不创建数据库 foreign key,也不使用级联删除或级联更新;关系校验和清理由应用层完成
- 所有索引都使用
CREATE INDEX CONCURRENTLY或CREATE UNIQUE INDEX CONCURRENTLY,每条 concurrent index 单独占一个 migration 文件
Go
- 标准
gofmt+go vet,无例外 - Handler 文件按域命名:
agent.go、auth.go、runtime.go - 测试:
<file>_test.go同目录 - handler 里 UUID 解析遵守根
AGENTS.md的规则:边界输入用parseUUIDOrBadRequest,可信回环用parseUUID(panic 版),永远不要直接用util.ParseUUID不查 error
TypeScript
- 网络上 API 响应是
snake_case,api client 在边界处转成camelCase。TS 代码内部一律 camelCase - 类型:
PascalCase(Issue、AgentRuntime),不加IPrefix,不加_t后缀 - 枚举:优先用 string literal union,需要 runtime 迭代时才用
enum - TanStack Query key:用
<feature>/queries.ts里的工厂函数,例如issueKeys.detail(id)
API 边界
- 网络响应必须用
packages/core/api/schema.ts中的parseWithFallback和 zod schema 解析,不能直接as T - 新增或修改 endpoint 时,同步更新 schema,并覆盖字段缺失或格式错误的测试
- 下游 UI 对可选字段提供默认值;服务端枚举的
switch必须有default分支 - 已安装的 Desktop 可能连接更新的 backend,不能假设前后端永远同版本
Runtime 显示名
AgentRuntime.name 是 daemon 的原始技术名(例如 Codex (host)),用户别名在 custom_name。用户可见文案不得直接渲染 runtime.name,要用共享 helper,保证别名和 provider 一致(MUL-5248、#5260):
- 独立展示 runtime(列表、标签、确认弹窗、窗口标题):
runtimeDisplayLabel(runtime)→ 别名 + provider,无别名时回退 daemon 名。 - 旁边已经单独显示 provider 图标/文字时:
runtimeDisplayName(runtime)→ 只显示别名,避免重复 provider。 - 在机器分组内:机器标题用
machine.title,子行用runtimeRowLabel(runtime, machine.title)。 - runtime 选择器用
buildRuntimeMachines按机器分组,不要自己拼扁平的原始名列表。
原始 runtime.name 只允许用于内部识别——hostname 解析、分组、搜索 haystack、协议 payload——绝不能进入 JSX 文本、i18n 参数、<Select> label 或窗口标题。
任务编号
每个任务有人类可读的编号,比如 CS-123:工作区 issue_prefix(大写字母和数字,通常 3 个字符,最长 10 个)+ 流水号。工作区管理员可以在设置 → 常规中修改前缀;修改会让所有现有任务重新编号,外部引用——PR 标题、分支名、文档与聊天里的链接——里的旧前缀会失效。
代码注释
只允许英文。Go 和 TypeScript 都强制。如果在代码里看到中文注释,那就是 bug,替换掉。
Commit message
Conventional 格式:feat(scope)、fix(scope)、refactor(scope)、docs、test(scope)、chore(scope)。按意图原子化分组。
2. i18n 翻译术语表
这是每个翻译 PR 都必须遵守的术语表。原本在 packages/views/locales/glossary.md,那个文件已删除,由这一页取代。
核心区分:日常词 vs Clowld Space 专有词
Clowld Space 的产品名词分两类:
- 日常词 —— 用户会直接说出口的词。完整翻译成中文,是不是数据库实体都一样:
issue→ 任务、workspace→ 工作区、topic→ 主题。 - Clowld Space 专有词 —— 中文里没有对应词的概念(
skill),或用户可能要照着敲、照着比对的 schema 标识符(todo、in_progress、task_id)。只有在展示或输入标识符本身时才保留小写英文;界面显示名应本地化。
其余规则以 apps/docs/content/docs/*.zh.mdx 为准 —— docs 是已经实战 20+ 篇的 CN voice 标准,*.zh.mdx、*.ja.mdx、*.ko.mdx 的正文现在也一律按下面的表格来,正文中的产品实体统一称为“任务”。
issue 就是产品里的「任务」,必须翻译
issue 是这个「用户提出、智能体去做的事」的英文产品名。在英文之外的每种语言里,它就是当地最日常的那个“任务”词:
| 实体 | en | zh-Hans | ja | ko |
|---|---|---|---|---|
提交出来的一件事(issue) | Issue | 任务 | タスク | 태스크 |
智能体的一次执行记录(task) | Run | 执行 | 実行 | 실행 |
这两个词用户都看得到,而且不是一回事 —— 一个任务下面可以跑很多次执行。中文 UI 和自然语言文案中,issue 显示为“任务”,task 显示为“执行”,两者不能混用。
不跟着改的部分:
- API / DB 字段永远是
issue/task/skill:issue_status、task_id、skill_uuid。 - 代码引用和字面命令保持英文:
clowld issue ...、Slack 与飞书的/issue斜杠命令。 - 原始执行标识符保持英文:API 字段、CLI 参数、日志和代码示例中的
task/task_id不翻译;只有面向用户的显示名翻成“执行”。 skill在中文里仍用小写英文 —— Clowld Space 特有概念,没有公认中文译法;标题可大写为Skills。plugin是软件领域已有稳定中文含义的普通概念,中文界面和正文统一译为“插件”。只有代码、字段、URL、manifest 名称等技术标识保留plugin。- **表示“问题”的
issue**不是这个实体:机器卡片上的{{count}} issues是{{count}} 个异常/問題 {{count}} 件/문제 {{count}}개,不是任务。
为什么 issue 要译,而 skill 不译:用户每天都在提任务、看任务,而 "issue" 这个词在中文、日文、韩文里除了开发圈黑话之外没有含义,当地人本来就用“任务”在说这件事。skill 则是 Clowld Space 特有概念,没有哪个中文词能承载它的意思。
其它产品名词同样按「有没有稳定的本地日常词」来判断:
topic翻成"主题":表示承载相关工作和上下文的共同方向。外部聊天或论坛中的 topic 译为"话题"或"讨论串";视觉 theme 统一称为"外观"。autopilot翻成"自动化":autopilot 在中文里联想到特斯拉的"自动驾驶",跟产品功能(按周期发起执行)对应不上。Notion / 飞书都用"自动化",是行业共识。Promotion翻成"晋级":表示把验证完成的dev快照冻结后合入main,不等同于Release(版本发布/发行)或Deployment(部署)。clowld-promotion、promote:dev、promote/*、promotion-staging/*、chore(promotion)等技术标识保持英文。
完整翻译 —— 概念词
| 英 | 中 |
|---|---|
| Workspace | 工作区 |
| Agent | 智能体 |
| Topic | 主题 |
| Autopilot | 自动化 |
| Daemon | 守护进程 |
| Runtime | 运行时 |
| Inbox | 收件箱 |
| Comment | 评论 |
| Reply | 回复 |
| Notifications | 通知 |
| Member | 成员 |
| Label | 标签 |
| Settings | 设置 |
| Onboarding | 上手引导 |
不翻 —— 品牌名 + 通用缩写
| 类别 | 词 |
|---|---|
| 品牌 | Clowld Space、GitHub、Slack、Google、Anthropic、OpenAI、Claude、Codex、Cursor、Linear、Jira |
| 缩写 | API、CLI、URL、SDK、OAuth、JWT、SSO、WebSocket、HTTP、JSON、YAML、SQL、PR、MR |
代码托管平台的评审对象保留官方名称:GitHub、Forgejo、Gitea 使用 Pull Request(PR),GitLab 使用 Merge Request(MR)。中文 UI 和文档直接写 PR、MR;跨平台聚合界面写 PR / MR,不翻成“拉取请求”或“合并请求”。
完整翻译 —— 通用 UI 词
| 英 | 中 |
|---|---|
| Invite / Invitation | 邀请 |
| Search | 搜索 |
| 邮箱(label)/ 邮件(action) | |
| Password | 密码 |
| Sign in / Log in | 登录 |
| Sign up | 注册 |
| Sign out / Log out | 退出登录 |
| Save / Cancel / Delete | 保存 / 取消 / 删除 |
| Confirm / Continue / Back | 确认 / 继续 / 返回 |
| Edit / New / Create / Add | 编辑 / 新建 / 创建 / 添加 |
| Remove / Send / Open / Close | 移除 / 发送 / 打开 / 关闭 |
| Preview / Download / Upload | 预览 / 下载 / 上传 |
| Done / Loading... | 完成 / 加载中... |
| Profile / Account / Appearance | 个人资料 / 账号 / 外观 |
| Appearance / Language | 外观 / 语言 |
| Light / Dark / System | 浅色 / 深色 / 跟随系统 |
| Active / Archived | 活跃(或 启用)/ 已归档 |
| Status / Priority | 状态 / 优先级 |
| Assignee / Reporter | 负责人 / 报告人 |
| Description / Title | 描述 / 标题 |
| Date / Time | 日期 / 时间 |
| Today / Yesterday / Tomorrow | 今天 / 昨天 / 明天 |
| Empty / Failed / Success | 空 / 失败 / 成功 |
| Error / Warning | 错误 / 警告 |
角色和状态:显示名翻译,标识符保留
以下 schema-level 标识符在 API、数据库字段、CLI 命令、日志和代码示例中保持小写英文:
- 角色:
owner/admin/member - 任务状态:
backlog/todo/in_progress/in_review/done/blocked/cancelled - 任务状态分类:
unstarted/started/done/closed
中文 UI 和自然语言文案必须显示本地化后的内置角色名、状态名。只有用户需要输入、复制或核对标识符时才展示原始英文;自定义状态名属于用户内容,始终保持创建者填写的原文。
- "你需要所有者权限"
- "已切换到进行中"
clowld issue status CS-42 in_progress
词组组合规则
英文词(实体名 + 品牌名 + 缩写)与中文之间加单空格:
- "Create new issue" → "新建任务"(“任务”是中文,不加空格)
- "Assign to agent" → "分配给智能体"
- "Configure runtime" → "配置运行时"
- "Stop daemon" → "停止守护进程"
复数与计数
i18next 用 _one / _other;中文不区分语法单复数,只填 _other。
// en/issues.json
{
"issue_count_one": "{{count}} issue",
"issue_count_other": "{{count}} issues"
}
// zh-Hans/issues.json
{
"issue_count_other": "{{count}} 个任务"
}常见计数格式:
{{count}} issues→{{count}} 个任务{{count}} agents→{{count}} 个智能体{{count}} workspaces→{{count}} 个工作区{{count}} comments→{{count}} 条评论{{count}} members→{{count}} 位成员{{count}} skills→{{count}} 个 skill
插值
用 {{var}} 形式。中文翻译可以调整位置以符合中文语序。
// en
{ "welcome_message": "Welcome back, {{name}}!" }
// zh-Hans
{ "welcome_message": "欢迎回来,{{name}}!" }Key 命名约定
3 层嵌套:feature.component.action。
{
"feature_or_component": {
"subcomponent_or_section": {
"action_or_label": "..."
}
}
}实例:
issues.toolbar.batch_update_successissues.detail.comment_form.placeholderinbox.empty.titlesettings.preferences.language.title
Web-only / Desktop-only 文案位置
- 共享文案:放 namespace JSON 顶层
- Web-only:放
web段 - Desktop-only:放
desktop段
参考 auth.json(web 段含 prefer_desktop / desktop_handoff.*)。
3. 中文风格
标点
- 中文用全角标点:
,。:;!? - 引号:用
"..."(直引号),与英文 source 保持一致。不要用「」或弯引号 - 省略号:用
...(三点)而非…(单字符),与英文 source 保持一致 - 中英混排:英文词左右各加 1 个空格(详见词组组合规则)
风格原则
- 简洁直白:避免翻译腔,"对于 X 来说"、"作为 X"、"我们的"
- 错误信息:温和但明确,"无法保存修改" 优于 "保存修改失败了!"
- 按钮:动词开头,2-4 字最佳。"取消"、"保存修改"、"立即同步"
- Tooltip:完整短句。"复制链接到剪贴板"
- placeholder:示例性提示。"输入任务标题..."
UI 描述性文案
description 默认省略。添加前先问:没有这句话,用户会误解什么或做错什么? 如果标题、标签、控件、当前值或按钮已经表达清楚,就不添加。
- 同一事实只说一次,放在最相关的控件旁,不在页头、分组、字段、空状态和弹窗中反复解释。
- 优先用准确的标签或具体示例,避免用一段话讲解显然的操作。除非能消除实际歧义,不写“创建一个开始使用”“点击下方”“之后可以修改”等通用提示。
- 权限、费用、不可撤销后果、运行前提、输入限制和错误恢复信息应在相关状态下直接可见,不藏进只能悬停查看的帮助中。
- 首次使用说明只在需要的位置展示;高级用法与诊断细节放入可明确打开、支持键盘操作的帮助中。
- 保留输入标签、无障碍名称和必要的描述关联。不要把删掉的视觉废话全部转成屏幕阅读器专用文本。
- 同时检查英文、各语言翻译和移动端独立文案。PR 评审检查新增信息、同屏重复、显示条件和保留的约束;字数只是复查信号,不是自动删除标准。
共享设置组件已经支持可选 description。示例与新增调用默认省略,不增加强制填写描述的组件属性,也不另建一份文案规范。
拿不准的时候去哪查
术语表没覆盖的词,按这个顺序查:
apps/docs/content/docs/*.zh.mdx—— CN voice 事实标准,20+ 篇高度一致packages/views/locales/zh-Hans/auth.json和editor.json—— JSON 结构 + selector API 用法参考packages/views/auth/login-page.tsx—— 组件层 selector API 调用参考packages/views/settings/components/preferences-tab.tsx—— 语言切换器参考
修改这一页时
改本页规则的同时还要:
- 把规则在相关 locale JSON / AGENTS.md / docs 页面里同步落地
- PR 描述里写明改了什么,方便 reviewer 检查下游是否跟着改了
本页是契约,其他文档不能 override。