Conventions
Source unique de vérité pour le nommage du code, le glossaire de traduction i18n et le guide de ton pour le chinois.
Cette page est la source unique de vérité pour le nommage du code, le glossaire de traduction i18n et le guide de ton pour le chinois. Tout ce qui se trouvait auparavant dans packages/views/locales/glossary.md ou dans des commentaires épars se trouve désormais ici.
Si vous écrivez du code Multica, modifiez une traduction ou rédigez des textes produit en chinois, c'est la page de référence.
1. Nommage du code
Routes
Les routes pré-espace de travail (celles qui existent avant que l'utilisateur n'entre dans un espace de travail) DOIVENT utiliser soit un seul mot, soit le motif /{noun}/{verb}.
- ✅
/login,/inbox,/workspaces/new - ❌
/new-workspace,/create-team,/accept-invite
Les groupes de mots reliés par des traits d'union à la racine entrent en collision avec les slugs d'espace de travail choisis par les utilisateurs et imposent des audits sans fin des slugs réservés. Réserver le nom (workspaces) protège automatiquement tout le sous-arbre /workspaces/*.
Routes liées à un espace de travail
Elles se trouvent toujours sous /{slug}/{section} — /{slug}/issues, /{slug}/agents, /{slug}/settings. Ne dupliquez jamais la logique de routage des espaces de travail ; utilisez useNavigation().push() depuis le code partagé, jamais les API de lien propres à un framework.
Packages et modules
Le monorepo impose des frontières strictes entre les packages :
| Package | Peut dépendre de | Ne doit PAS dépendre de |
|---|---|---|
packages/core | rien de spécifique à une application | react-dom, localStorage, process.env, next/*, bibliothèques d'UI |
packages/ui | rien | @multica/core, logique métier |
packages/views | core/, ui/ | next/*, react-router-dom, stores |
apps/web/platform/ | next/* | autres applications |
apps/desktop/.../platform/ | react-router-dom, electron | autres applications |
apps/mobile/ | types et fonctions pures de @multica/core | pages React, stores et implémentations de plateforme de Web/Desktop |
Si une logique apparaît dans les deux applications, elle DOIT être extraite dans un package partagé. Aucune exception pour une « petite » duplication. Mobile possède sa propre UI, sa propre couche de données et son propre processus de publication ; il ne partage que les types et les fonctions pures.
Fichiers et composants
- Fichiers :
kebab-case.tsx/kebab-case.ts(par ex.agent-row-actions.tsx) - Composants :
PascalCase(par ex.AgentRowActions) - Hooks :
useCamelCase(par ex.useWorkspaceId) - Tests : placés à côté du fichier, sous la forme
<file>.test.ts(x) - Stores (Zustand) :
<feature>-store.ts, exportés sous le nomuse<Feature>Store
Base de données (Go + sqlc)
- Tables :
snake_caseau singulier (user,workspace,agent_runtime) - Colonnes :
snake_case(workspace_id,created_at,last_seen_at) - Clés étrangères :
<table>_id - Booléens :
is_<state>ou<state>_at(la forme horodatée est préférée pour les changements d'état) - Fichiers de migration :
NNN_descriptive_name.up.sql+.down.sql— fournissez toujours les deux sens - Ne créez pas de clés étrangères en base de données et n'utilisez pas de suppressions ni de mises à jour en cascade ; garantissez les relations et le nettoyage dans la couche applicative.
- Chaque index doit utiliser
CREATE INDEX CONCURRENTLYouCREATE UNIQUE INDEX CONCURRENTLY, chaque index concurrent étant placé dans son propre fichier de migration qui ne contient qu'une seule instruction.
Go
gofmt+go vetstandard. Sans exception.- Les fichiers de handler reflètent le domaine :
agent.go,auth.go,runtime.go - Tests :
<file>_test.goplacé à côté du fichier - Pour le parsing des UUID dans les handlers, suivez la règle du
AGENTS.mdracine —parseUUIDOrBadRequestpour les entrées aux frontières,parseUUID(qui panique) pour les allers-retours de confiance, et jamaisutil.ParseUUIDdirectement sans vérifier l'erreur.
TypeScript
- Les réponses d'API qui transitent sur le réseau sont en
snake_case; le client API les convertit encamelCaseà la frontière. Dans le code TS, toujours en camelCase. - Types :
PascalCase(Issue,AgentRuntime) ; jamais deIPrefix, jamais de suffixe_t. - Enums : préférez les unions de littéraux de chaîne ; réservez
enumaux cas qui doivent pouvoir être parcourus dynamiquement. - Clés TanStack Query : fonctions factory dans
<feature>/queries.ts, par ex.issueKeys.detail(id).
Frontières d'API
- Analysez les réponses réseau avec
parseWithFallbacket les schémas zod depackages/core/api/schema.ts; ne les castez pas directement avecas T. - Lorsque vous ajoutez ou modifiez un endpoint, mettez à jour son schéma et couvrez les champs manquants ou malformés dans les tests.
- L'UI en aval doit fournir des valeurs par défaut pour les champs optionnels, et chaque
switchsur un enum serveur doit inclure une branchedefault. - Un client Desktop installé peut se connecter à un backend plus récent ; ne supposez jamais que les versions du frontend et du backend correspondent toujours.
Noms d'affichage des runtimes
AgentRuntime.name est le nom technique brut du daemon (par ex. Codex (host)) ; l'alias de l'utilisateur se trouve dans custom_name. Un texte visible par l'utilisateur ne doit jamais afficher runtime.name directement — utilisez les helpers partagés pour que les alias et le fournisseur restent cohérents (MUL-5248, #5260) :
- Libellé de runtime autonome (listes, chips, boîtes de dialogue de confirmation, titres de document) :
runtimeDisplayLabel(runtime)→ alias + fournisseur, avec repli sur le nom du daemon. - Lorsqu'une icône ou un texte de fournisseur figure déjà à côté :
runtimeDisplayName(runtime)→ alias seul, sans répéter le fournisseur. - Dans un groupe de machine : l'en-tête de la machine utilise
machine.title, les lignes enfants utilisentruntimeRowLabel(runtime, machine.title). - Les sélecteurs de runtime regroupent par machine via
buildRuntimeMachines; ne construisez pas une liste plate de noms bruts.
Le runtime.name brut n'est autorisé que pour l'identité interne — parsing du nom d'hôte, regroupement, texte indexé pour la recherche et payloads de protocole — jamais pour du texte JSX, des paramètres i18n, des libellés de <Select> ou des titres de fenêtre.
Clés de tâche
Chaque tâche possède une clé lisible comme MUL-123 : le issue_prefix de l'espace de travail (lettres majuscules et chiffres, généralement 3 caractères, 10 au maximum) + un numéro de séquence. Les administrateurs de l'espace de travail peuvent modifier le préfixe dans Paramètres → Général ; ce changement renumérote toutes les tâches existantes, si bien que les références externes qui contiennent l'ancien préfixe (titres de PR, noms de branche, liens dans la documentation et les messageries) ne se résolvent plus.
Commentaires dans le code
Anglais uniquement. Le dépôt l'impose pour Go comme pour TypeScript. Si vous trouvez un commentaire en chinois dans le code, c'est un bug — remplacez-le.
Messages de commit
Format conventionnel : feat(scope), fix(scope), refactor(scope), docs, test(scope), chore(scope). Des commits atomiques, regroupés par intention.
2. Glossaire de traduction i18n
Voici le glossaire obligatoire pour toute PR de traduction. Il se trouvait auparavant dans packages/views/locales/glossary.md ; ce fichier a été supprimé et cette page le remplace.
La distinction essentielle : nom courant vs terme propre à Multica
Les noms de produit de Multica se répartissent en deux catégories :
- Nom courant — le mot qu'un utilisateur emploierait à voix haute pour le désigner. Traduisez-le entièrement, qu'il s'agisse ou non d'une entité de base de données :
issue→ 任务,workspace→ 工作区,project→ 项目. - Terme propre à Multica — un concept qu'aucun mot local ne porte (
skill), ou un identifiant de niveau schéma qu'un utilisateur peut avoir à saisir ou à faire correspondre (todo,in_progress,task_id). Écrivez-le en anglais minuscule pour qu'il se lise comme un nom de type.
Les pages chinoises apps/docs/content/docs/*.zh.mdx sont la norme de fait pour le ton de tout le reste de cette page. Le texte des pages *.zh.mdx, *.ja.mdx et *.ko.mdx suit désormais aussi le tableau ci-dessous.
issue est la tâche du produit — traduisez-le
issue est le nom produit anglais de ce qu'un utilisateur crée et de ce sur quoi un agent travaille. Dans toutes les autres langues, c'est le mot courant pour « tâche » :
| Entité | en | zh-Hans | ja | ko | fr |
|---|---|---|---|---|---|
l'unité de travail suivie (issue) | Issue | 任务 | タスク | 태스크 | Tâche |
un enregistrement d'exécution d'agent (task dans l'API / la base de données) | Run | 运行 | 実行 | 실행 | Exécution |
Ces deux concepts sont visibles par l'utilisateur et ne sont pas la même chose : une tâche peut avoir plusieurs exécutions. Ne laissez jamais une langue écrire les deux avec le même mot. Task n'est plus un nom de produit visible par l'utilisateur pour une exécution d'agent ; il ne subsiste que comme identifiant interne établi.
Ce qui ne change pas :
- Les champs d'API / de base de données restent
issue/task/skillpartout :issue_status,task_id,skill_uuid. La prose destinée aux développeurs appelle l'objet produit un Run et peut préciser « Run (task_iddans l'API) » lorsque l'identifiant compte. - Les références de code et les commandes littérales restent en anglais :
multica issue ..., la commande slash/issuede Slack et de Lark. skillreste en anglais minuscule dans le texte chinois — c'est un concept propre à Multica sans terme chinois établi ; les titres peuvent l'écrire avec une majuscule,Skills.issueau sens de « problème » (santé du runtime) est un nom ordinaire, pas l'entité :{{count}} issuessur une carte de machine devient{{count}} 个异常/問題 {{count}} 件/문제 {{count}}개, jamais le mot de l'entité.
Pourquoi issue est traduit alors que skill ne l'est pas : les utilisateurs créent et lisent des tâches toute la journée, et « issue » n'a aucun sens en chinois, en japonais ou en coréen en dehors du jargon des développeurs. Le mot courant pour « tâche » est celui que les gens emploient déjà pour cet objet. skill est un concept propre à Multica, pour lequel aucun mot local ne porte ce sens.
Les autres noms de produit suivent le même critère, « traduire ce qui a un mot local établi » :
project→ "项目" : mot chinois courant et bien établi. Feishu / Tower / Teambition / PingCode / GitHub Projects — tous les produits chinois le traduisent. Aucun produit ne conserveprojectdans un contexte chinois.autopilot→ "自动化" : en chinois, « autopilot » évoque le « 自动驾驶 » de Tesla et ne correspond pas à ce que fait la fonctionnalité (lancer des exécutions d'agent selon une planification). Notion et Feishu utilisent tous deux « 自动化 » ; c'est le consensus du secteur.
Ne pas traduire — marques et acronymes
| Catégorie | Termes |
|---|---|
| Marques | Multica, GitHub, Slack, Google, Anthropic, OpenAI, Claude, Codex, Cursor, Linear, Jira |
| Acronymes | API, CLI, URL, SDK, OAuth, JWT, SSO, WebSocket, HTTP, JSON, YAML, SQL |
Traduire entièrement — concepts
| Anglais | Chinois |
|---|---|
| Workspace | 工作区 |
| Agent | 智能体 |
| Project | 项目 |
| Autopilot | 自动化 |
| Daemon | 守护进程 |
| Runtime | 运行时 |
| Inbox | 收件箱 |
| Comment | 评论 |
| Reply | 回复 |
| Notifications | 通知 |
| Member | 成员 |
| Label | 标签 |
| Settings | 设置 |
| Onboarding | 上手引导 |
Traduire entièrement — mots génériques de l'UI
| Anglais | Chinois |
|---|---|
| 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 | 个人资料 / 账号 / 外观 |
| Theme / Language | 主题 / 语言 |
| Light / Dark / System | 浅色 / 深色 / 跟随系统 |
| Active / Archived | 活跃 (or 启用) / 已归档 |
| Status / Priority | 状态 / 优先级 |
| Assignee / Reporter | 负责人 / 报告人 |
| Description / Title | 描述 / 标题 |
| Date / Time | 日期 / 时间 |
| Today / Yesterday / Tomorrow | 今天 / 昨天 / 明天 |
| Empty / Failed / Success | 空 / 失败 / 成功 |
| Error / Warning | 错误 / 警告 |
Rôles et enums de statut (anglais minuscule, non traduits)
Ce sont des identifiants de niveau schéma ; écrivez-les en anglais minuscule, même dans un contexte chinois.
- Rôles :
owner/admin/member - Statut de tâche :
backlog/todo/in_progress/in_review/done/blocked/cancelled - Catégorie de statut de tâche :
unstarted/started/done/closed
Dans l'UI, affichez-les en anglais (éventuellement entourés en code-style) :
- "你需要 owner 权限"
- "已切换到 in_progress"
Règles de combinaison des mots
Mettez toujours un seul espace entre un mot anglais (entité / marque / acronyme) et le chinois qui l'entoure :
- "Create new issue" → "新建任务"(
任务est du chinois, donc pas d'espace) - "Assign to agent" → "分配给智能体"
- "Configure runtime" → "配置运行时"
- "Stop daemon" → "停止守护进程"
Pluriels et nombres
i18next utilise _one / _other ; le chinois n'a pas de nombre grammatical, ne renseignez donc que _other.
// en/issues.json
{
"issue_count_one": "{{count}} issue",
"issue_count_other": "{{count}} issues"
}
// zh-Hans/issues.json
{
"issue_count_other": "{{count}} 个任务"
}Formats de nombre courants :
{{count}} issues→{{count}} 个任务{{count}} agents→{{count}} 个智能体{{count}} workspaces→{{count}} 个工作区{{count}} comments→{{count}} 条评论{{count}} members→{{count}} 位成员{{count}} skills→{{count}} 个 skill
Interpolation
Utilisez {{var}}. Les traductions chinoises peuvent changer l'ordre des éléments pour que la phrase se lise naturellement.
// en
{ "welcome_message": "Welcome back, {{name}}!" }
// zh-Hans
{ "welcome_message": "欢迎回来,{{name}}!" }Nommage des clés de traduction
Trois niveaux d'imbrication : feature.component.action.
{
"feature_or_component": {
"subcomponent_or_section": {
"action_or_label": "..."
}
}
}Exemples :
issues.toolbar.batch_update_successissues.detail.comment_form.placeholderinbox.empty.titlesettings.preferences.language.title
Textes réservés au Web ou au Desktop
- Textes partagés : au premier niveau du JSON du namespace
- Web uniquement : section
web - Desktop uniquement : section
desktop
Consultez auth.json pour l'exemple de référence (la section web contient prefer_desktop / desktop_handoff.*).
3. Ton et style en chinois
Ponctuation
- Ponctuation pleine chasse en chinois :
,。:;!? - Guillemets : guillemets doubles droits
"...", comme dans la source anglaise. N'utilisez ni「」ni les guillemets typographiques. - Points de suspension : trois points
...et non le caractère unique…. Suivez la source anglaise. - Mélange chinois-anglais : un seul espace de chaque côté du mot anglais (voir les règles de combinaison des mots).
Principes de style
- Concis et direct. Évitez les tournures de traduction : "对于 X 来说"、"作为 X"、"我们的"。
- Messages d'erreur : doux mais clairs. "无法保存修改" est préférable à "保存修改失败了!".
- Boutons : verbe en premier, 2 à 4 caractères. "取消"、"保存修改"、"立即同步".
- Infobulles : une phrase courte et complète. "复制链接到剪贴板".
- Placeholders : sous forme d'exemple. "输入任务标题...".
Descriptions dans l'UI
Les descriptions sont facultatives et omises par défaut. Avant d'en ajouter une, demandez-vous : qu'est-ce que l'utilisateur comprendrait mal ou ferait de travers sans cette phrase ? Si le titre, le libellé, le contrôle, la valeur ou le bouton y répond déjà, omettez la phrase.
- Énoncez un fait une seule fois, à côté du contrôle concerné. Ne le répétez pas dans les descriptions de la page, de la section, de la ligne, de l'état vide et de la boîte de dialogue.
- Préférez un libellé précis ou un exemple à un paragraphe qui explique une action évidente. Évitez les instructions génériques comme « Create one to get started », « Click below » ou « You can change this later », sauf si elles lèvent une réelle ambiguïté.
- Gardez visibles, lorsqu'ils sont pertinents, les permissions, le coût, les conséquences destructrices, les prérequis d'exécution, les contraintes de saisie et la reprise après erreur. Ne les cachez pas dans une aide qui n'apparaît qu'au survol.
- N'affichez des indications d'introduction que là où elles sont nécessaires. Placez l'utilisation avancée et les diagnostics dans une aide explicite et accessible plutôt que dans le corps de page par défaut.
- Conservez les libellés de champ, les noms accessibles et les associations de description nécessaires. Ne déplacez pas en bloc une prose visible redondante vers du texte réservé aux lecteurs d'écran.
- Relisez ensemble les textes anglais et traduits, y compris les chaînes indépendantes de l'application mobile. En revue de PR, vérifiez l'information ajoutée, la répétition sur un même écran, les conditions d'affichage et les contraintes préservées. La longueur est un signal de revue, pas une règle de suppression automatique.
Les composants de paramètres partagés acceptent déjà des descriptions facultatives. Les exemples et les nouveaux points d'appel doivent les omettre sauf justification ; n'ajoutez pas de props de description obligatoires ni de politique de rédaction distincte.
En cas de doute
Lorsque le glossaire ne couvre pas un terme, consultez :
apps/docs/content/docs/*.zh.mdx— la norme de fait pour le ton en chinois, plus de 20 pages de traduction cohérentepackages/views/locales/zh-Hans/auth.jsoneteditor.json— structure JSON + modèles d'API de sélecteurpackages/views/auth/login-page.tsx— point d'appel de l'API de sélecteur au niveau d'un composantpackages/views/settings/components/preferences-tab.tsx— référence pour le sélecteur de langue
Mettre à jour cette page
Si vous modifiez une règle ici, pensez aussi à :
- L'appliquer dans les JSON de langue, AGENTS.md ou la page de documentation concernés
- Signaler le changement dans la description de la PR, pour que les relecteurs sachent qu'ils doivent vérifier la propagation en aval
Cette page est le contrat ; rien d'autre ne prévaut sur elle.