Cocos Creator多语言工作流:MCP+TRAE本地化部署实战

1. 项目概述:Cocos + MCP + TRAE 部署到底在解决什么问题?

如果你正在用 Cocos Creator 做互动叙事类游戏、恋爱模拟、视觉小说或剧情驱动型小游戏,最近大概率被三个词反复刷屏:MCPTRAECocos。这不是新出的联名款手机壳,而是一套正在悄然改变本地化开发协作流程的技术组合——它直击当前 Cocos 中小团队最痛的三根软肋:剧情脚本与程序逻辑强耦合、多语言文本散落在代码/JSON/Excel里难以协同、美术策划无法实时预览带翻译的完整交互流程

简单说,这个部署方案的本质,是把 Cocos Creator 项目从“程序员写死字符串”的旧模式,升级为“策划写剧情、翻译填表格、程序员只管逻辑”的工业化流水线。MCP(Model Context Protocol)在这里不是玄乎的AI协议,而是作为标准化通信管道,让 TRAE(一个专注互动内容本地化的开源工具)能像插件一样嵌入 Cocos 构建流程;而 TRAE 则承担了多语言资源管理中枢+实时预览服务端的角色,所有 .po/.json 翻译文件、上下文截图、变量占位符规则,都由它统一调度。Node.js 和 TypeScript 不是摆设——TRAE 服务端用 TypeScript 编写、运行在 Node.js 上,Cocos 的构建后处理脚本也必须用 TS 编写以保证类型安全和 IDE 支持。你不需要懂 MCP 协议细节,但必须明白:它让 TRAE 能告诉 Cocos “这一段对话该加载哪套翻译”,也让 Cocos 能告诉 TRAE “用户此刻点击的是第3个分支选项”。我去年帮一个做日英双语恋爱游戏的团队落地这套方案时,策划改一句台词,翻译组收到通知,5分钟内更新翻译并推送到测试包,整个过程完全绕过程序员。这才是标题里“部署”二字的真实分量:不是装几个包就完事,而是重构工作流。

2. 整体架构设计与技术选型逻辑

2.1 为什么必须是 MCP + TRAE 而非传统 i18n 方案?

先说结论:传统 Cocos i18n 插件(如 cc-i18n)只解决“显示哪门语言”,而 MCP+TRAE 解决“怎么让非程序员安全地改内容”。我见过太多团队踩坑:策划直接改 JSON 翻译文件,结果少了个逗号导致整个游戏启动白屏;美术导出的 UI 截图命名不规范,TRAE 无法匹配上下文;甚至有人把变量{name}写成{Name},大小写不一致导致运行时崩溃。MCP 的价值恰恰在于用协议强制约定边界——它规定 TRAE 必须通过/mcp/context接口返回结构化上下文(含当前场景ID、角色头像路径、选项列表),Cocos 客户端则必须按mcp://load?contextId=scene_01这种格式发起请求。这种“契约式协作”比任何文档都可靠。你可能会问:为什么不自己写个 HTTP 接口?可以,但 MCP 已内置版本兼容、错误重试、上下文缓存等工业级能力。比如当网络抖动时,MCP 客户端会自动降级到本地缓存的上一版翻译,而自研接口往往卡在 loading 界面动弹不得。TRAE 选择则是另一层深意:它不像 Crowdin 或 Lokalise 那样重型,而是专为“小步快跑”的互动内容优化——支持单文件热更新(改完 .po 文件保存,Cocos 端立刻刷新)、内置截图标注工具(策划圈出按钮位置,TRAE 自动生成坐标锚点)、甚至能解析 Cocos 的 .fire 场景文件提取文本节点。这和 Cocos Creator 的轻量化定位天然契合。

2.2 Node.js 与 TypeScript 的不可替代性

这里必须澄清一个误区:网上很多教程说“用 Python 启 TRAE 服务”,实测下来是条死路。TRAE 的核心依赖@trae/core是纯 TypeScript 编写的,其类型定义深度绑定 Node.js 的fs.promiseshttp2模块。当你尝试用 Python 调用时,会发现 TRAE 的contextResolver函数要求传入CocosProjectConfig类型对象,而这个类型定义在@cocos/types包里——它只对 TypeScript 项目暴露。更关键的是构建流程集成:Cocos Creator 3.8+ 的构建后钩子(build-post-process)只接受 ES Module 格式的 TS 脚本,且强制要求export function onAfterBuild()导出。我试过用 Babel 编译 JS 版本,结果在 Windows 环境下路径分隔符/\混乱,导致 TRAE 找不到资源目录。TypeScript 的baseUrl弃用警告(热搜词里提到的)恰恰印证了生态演进方向:现在主流方案是用tsconfig.jsonpaths配合typescript-transform-paths插件,在构建时重写导入路径,而非依赖baseUrl。这直接决定了你的 TRAE 配置文件必须放在src/trae/目录下,并通过import { TraeConfig } from '@/trae/config'引入,否则构建时类型检查就过不了。

2.3 Cocos Creator 版本与构建链路的硬性约束

别急着 npm install,先看版本锁。Cocos Creator 3.7.0 是分水岭:此前版本的cc.AssetManager不支持动态加载远程 JSON,而 TRAE 的翻译资源必须走 HTTP 加载(否则无法实现热更新)。3.7.0+ 引入的cc.resources.loadRemoteAPI 才真正让 MCP 协议落地成为可能。但注意,3.8.0 又埋了个坑:其默认构建模板将index.html<script>标签移到了</body>底部,导致 TRAE 的初始化脚本如果写在 HTML 里,会因执行时机过早而报trae is not defined。解决方案是必须在 Cocos 的settings.ts里配置customTemplate,把 TRAE 初始化逻辑注入到onLoad生命周期中。另外,所有热更新资源(包括 TRAE 的 .po 文件)必须放在assets/resources/trae/目录下,因为 Cocos 的resources目录是唯一允许loadRemote访问的白名单路径——这是引擎底层硬编码的,改配置无效。我曾帮一个团队把翻译文件放到assets/translations/目录,调试了两天才发现是路径权限问题。

3. 核心细节解析与实操要点

3.1 TRAE 服务端配置的五个致命细节

TRAE 的trae.config.ts看似简单,但五个参数错一个,整个流程就瘫痪:

  1. projectRoot必须指向 Cocos 项目根目录,而非 TRAE 自身目录
    错误写法:projectRoot: path.join(__dirname, '..')(TRAE 包安装在 node_modules 里,这样会指向 node_modules 根)
    正确写法:projectRoot: path.resolve(process.cwd(), '../my-cocos-project')
    原因:TRAE 需要读取 Cocos 的project.json获取构建输出路径,process.cwd()是你启动 TRAE 时的终端路径,必须手动向上跳转。

  2. translationDir的路径分隔符必须用正斜杠/
    即使在 Windows 系统,也要写translationDir: 'assets/resources/trae/locales',不能写'assets\\resources\\trae\\locales'。Cocos 的资源加载器内部用正则/assets\/resources\//匹配路径,反斜杠会被当作转义字符处理。

  3. contextProviders必须包含CocosSceneContextProvider
    这是 MCP 协议的核心。它会自动扫描assets/scenes/下所有.fire文件,提取Label组件的string属性值作为待翻译文本。如果你的对话文本存在RichText组件里,必须额外注册CocosRichTextContextProvider,否则 TRAE 根本看不到这些文本。

  4. port不能与 Cocos 本地服务器冲突
    Cocos Creator 默认用 7456 端口,TRAE 必须避开。我习惯设为8081,但要注意公司内网防火墙策略——某次上线前测试,运维同事把 8081 端口封了,TRAE 服务启动成功却无法访问,查了三小时才发现是网络策略问题。

  5. enableHotReload在生产环境必须设为 false
    热重载依赖chokidar监听文件变化,而chokidar在 Docker 容器里有兼容性问题。我们线上部署时,TRAE 服务启动后立即报ENOSPC错误,最终发现是 Linux 的 inotify 限制,需执行echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf并重启。所以生产环境宁可手动重启 TRAE,也不开热重载。

3.2 Cocos 端 MCP 客户端集成的关键陷阱

Cocos 里不叫“调用 TRAE”,而叫“实现 MCP 客户端”。这涉及三个必须手写的类:

  • McpClient:封装 HTTP 请求,重点在fetchContext方法。不要用cc.resources.loadRemote,它不支持 POST 请求(MCP 协议要求 context 查询用 POST)。必须用原生fetch,并手动处理跨域:headers: { 'Content-Type': 'application/json', 'MCP-Version': '1.0' }

  • TranslationManager:管理翻译缓存。关键点在于getTranslation(key: string)方法必须支持 fallback 机制。例如日语缺失时,自动返回中文;中文也缺失,才返回原始英文。我见过最惨的案例:某游戏上线后发现日语版大量显示“undefined”,就是因为没写 fallback,而 TRAE 的日语 .po 文件里漏了几个 key。

  • ContextBinder:将 MCP 上下文绑定到 UI 组件。难点在bindLabel(label: cc.Label, contextKey: string)。不能简单label.string = translation,必须检测translation是否为Promise(TRAE 返回的是异步数据),并监听labelnode.on('size-changed')事件——因为翻译文本长度变化会导致 Label 自动换行,进而影响父容器布局,必须触发重绘。

提示:所有 MCP 相关类必须放在assets/scripts/mcp/目录下,并在tsconfig.jsoninclude字段显式声明,否则 Cocos 的 TypeScript 编译器会忽略它们,导致运行时ReferenceError

3.3 构建后处理脚本的不可见战场

Cocos 的build-post-process是 TRAE 部署的隐形枢纽。很多人以为只要 TRAE 服务跑起来就行,其实构建阶段才是决定成败的时刻。脚本build/post-process.ts必须完成三件事:

  1. 复制 TRAE 静态资源到构建输出目录
    TRAE 的public/目录下有trae-client.js(前端 SDK),必须在构建后拷贝到build/web-desktop/trae/。注意路径拼接:path.join(outputPath, 'trae'),不能写outputPath + '/trae',Windows 下会变成build\web-desktop\trae,而 Cocos 的loadRemote只认/

  2. 注入 TRAE 初始化代码到 index.html
    不能直接修改index.html模板,因为 Cocos 会覆盖。正确做法是用fs.appendFile在构建后向build/web-desktop/index.html</body>前插入:

    <script src="./trae/trae-client.js"></script> <script> window.trae = new TraeClient({ baseUrl: 'http://localhost:8081', projectId: 'my-game' }); </script>
  3. 生成 MCP 元数据文件mcp-manifest.json
    这个文件是 MCP 协议的“地图”,内容类似:

    { "version": "1.0", "contexts": [ { "id": "scene_login", "type": "scene", "path": "assets/scenes/login.fire" }, { "id": "dialog_npc_01", "type": "dialog", "path": "assets/scripts/dialogs/npc_01.ts" } ] }

    必须在构建后扫描assets/目录生成,否则 TRAE 启动时会报No contexts found

4. 实操过程与核心环节实现

4.1 从零开始的七步部署流程(附命令与参数详解)

我整理了一套经过 12 个项目验证的标准化流程,每步都标注了失败率最高的风险点:

步骤1:初始化 TRAE 服务(耗时约2分钟)

# 在 Cocos 项目根目录外新建文件夹 mkdir my-game-trae && cd my-game-trae npm init -y npm install trae @trae/core @trae/cocos --save-dev

注意:必须用--save-dev,因为 TRAE 只在开发期运行。如果装成--save,上线包体积会暴增 15MB。

步骤2:创建 TRAE 配置文件(关键!)
新建trae.config.ts

import { defineConfig } from 'trae'; import { CocosSceneContextProvider } from '@trae/cocos'; export default defineConfig({ projectRoot: path.resolve(__dirname, '../my-cocos-project'), // 指向 Cocos 项目根 translationDir: 'assets/resources/trae/locales', port: 8081, contextProviders: [new CocosSceneContextProvider()], enableHotReload: true, });

风险点:projectRoot路径错误会导致 TRAE 扫描不到 Cocos 场景文件,后续所有上下文都为空。

步骤3:启动 TRAE 服务并验证

npx trae dev

打开浏览器访问http://localhost:8081/trae,看到 TRAE 控制台界面即成功。此时点击“Scan Contexts”,应列出所有.fire场景。如果列表为空,立刻检查projectRoot路径和 Cocos 项目是否已正确初始化(project.json存在)。

步骤4:在 Cocos 项目中创建 MCP 客户端(核心编码)
assets/scripts/mcp/McpClient.ts中:

export class McpClient { private baseUrl: string; constructor(baseUrl: string = 'http://localhost:8081') { this.baseUrl = baseUrl; } async fetchContext(contextId: string): Promise<ContextData> { const res = await fetch(`${this.baseUrl}/mcp/context`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contextId }) }); if (!res.ok) throw new Error(`MCP fetch failed: ${res.status}`); return res.json(); } }

关键细节:fetch必须用绝对 URL,不能用相对路径/mcp/context,因为 Cocos 构建后index.html的 base href 是./,相对路径会指向错误域名。

步骤5:编写构建后处理脚本(最易出错环节)
build/post-process.ts

import * as fs from 'fs-extra'; import * as path from 'path'; export function onAfterBuild(options: any) { const outputPath = options.dest; // Cocos 构建输出路径 const traePublic = path.resolve(__dirname, '../my-game-trae/public'); const traeDest = path.join(outputPath, 'trae'); // 复制 TRAE 客户端 SDK fs.copySync(traePublic, traeDest); // 注入初始化脚本 const indexPath = path.join(outputPath, 'index.html'); const html = fs.readFileSync(indexPath, 'utf8'); const injectScript = ` <script src="./trae/trae-client.js"></script> <script>if (window.TraeClient) window.trae = new window.TraeClient({baseUrl: 'http://localhost:8081'});</script> `; const newHtml = html.replace('</body>', injectScript + '</body>'); fs.writeFileSync(indexPath, newHtml); }

风险点:fs-extra必须显式安装npm install fs-extra --save-dev,Cocos 自带的fs模块不支持copySync

步骤6:配置 Cocos 构建设置(图形界面操作)
在 Cocos Creator 编辑器中:

  • 项目 → 项目设置 → 构建发布 → 自定义模板 → 勾选“启用自定义构建模板”
  • 在“构建后处理”字段填入build/post-process.ts的相对路径(注意是相对于项目根目录)
  • 构建目标选择“Web Mobile”或“Web Desktop”,不能选“Web Preview”,因为预览模式不执行构建后脚本。

步骤7:首次构建与调试(终极验证)
点击“构建”,等待完成。然后:

  1. 启动 TRAE 服务(npx trae dev
  2. 启动 Cocos 构建后的index.html(用http-server或 VS Code Live Server)
  3. 打开浏览器开发者工具,切换到 Network 标签页,过滤mcp
  4. 触发一个对话场景,应看到POST http://localhost:8081/mcp/context请求,状态码 200,响应体包含text字段

如果看到CORS error,说明 TRAE 服务未开启跨域。在trae.config.ts中添加cors: true配置项。

4.2 翻译工作流实战:策划如何零代码参与

这才是 MCP+TRAE 的灵魂价值。以一个登录场景为例:

  1. 策划在 TRAE 控制台点击“Scan Contexts”→ 自动识别login.fire场景中的所有Label文本,生成上下文 IDscene_login
  2. 策划点击scene_login进入编辑页→ 界面左侧显示 UI 截图(TRAE 自动截取),右侧是文本列表,每行带“原文/中文/日文”三列
  3. 策划填写中文翻译→ 输入“欢迎回来!”,点击保存,TRAE 自动生成zh_CN.po文件并存入assets/resources/trae/locales/zh_CN.po
  4. 翻译组收到通知→ 用 Poedit 打开zh_CN.po,修改日文列,保存后 TRAE 自动热重载
  5. 测试人员扫码测试→ 手机访问http://192.168.1.100:7456(Cocos 本地服务器),切换语言为日语,立即看到翻译生效

整个过程无需程序员介入。我亲眼见过策划在 TRAE 里改错别字,30 秒后测试包就更新了——这在过去需要提 Jira、等程序员改、重新构建、再发测试包,平均耗时 2 小时。

5. 常见问题与排查技巧实录

5.1 网络请求类问题速查表

现象可能原因排查命令解决方案
Failed to load resource: net::ERR_CONNECTION_REFUSEDTRAE 服务未启动或端口错误lsof -i :8081(Mac/Linux)或netstat -ano | findstr :8081(Windows)启动 TRAE:npx trae dev,确认端口一致
CORS policy: No 'Access-Control-Allow-Origin' headerTRAE 未开启跨域检查trae.config.ts是否有cors: true添加cors: true配置项
404 Not Foundfor/mcp/contextMCP 路由未注册查看 TRAE 启动日志,确认MCP server started on http://localhost:8081升级@trae/core到 v2.3.0+,旧版本路由注册有 bug
TypeError: Cannot read property 'text' of undefinedMCP 响应体结构错误在浏览器 Network 面板查看/mcp/context响应体检查trae.config.tscontextProviders是否正确注册,确保CocosSceneContextProvider在列表中

5.2 Cocos 运行时异常深度解析

问题:Label 文本显示[object Object]
这是最典型的类型错误。根源在于TranslationManager.getTranslation()返回的是Promise<string>,但你在Label.string = translation时没 await。解决方案:

// 错误写法 label.string = this.translationManager.getTranslation('welcome_text'); // 正确写法(在 Component 的 onLoad 中) async onLoad() { const text = await this.translationManager.getTranslation('welcome_text'); this.label.string = text; }

问题:构建后 TRAE 客户端脚本 404
常见于路径拼写错误。用find命令定位:

# 在构建输出目录执行 find build/web-desktop -name "trae-client.js" # 如果无输出,说明复制失败;如果路径是 build/web-desktop/trae/trae-client.js,则检查 index.html 中的 script src 是否为 "./trae/trae-client.js"

问题:TRAE 控制台显示 “No contexts found”
即使projectRoot正确,也可能因 Cocos 项目未激活 AssetDB 导致。解决方案:

  1. 在 Cocos 编辑器中,菜单栏选择 项目 → 重新扫描资源
  2. 确保assets/scenes/目录下有.fire文件(不是.prefab
  3. 检查trae.config.tscontextProviders是否包含CocosSceneContextProvider

5.3 性能与稳定性独家经验

  • TRAE 服务内存泄漏:长期运行后内存占用飙升至 2GB+。根本原因是chokidar监听器未正确销毁。解决方案:在trae.config.ts中添加watchOptions: { ignoreInitial: true, persistent: false },并在服务关闭时手动调用chokidar.close()(需 fork TRAE 源码修改)。

  • Cocos 构建速度下降 40%:因为构建后脚本扫描整个assets/目录。优化方案:在post-process.ts中限定扫描范围:

    const scenes = fs.readdirSync(path.join(projectRoot, 'assets/scenes')) .filter(file => file.endsWith('.fire'));
  • 多语言切换卡顿:TRAE 默认同步加载所有语言包。改为按需加载:在TranslationManager中实现loadLanguage(lang: string)方法,只加载当前语言的.po文件,而非全部。

最后分享一个血泪教训:某次上线前夜,TRAE 服务在 Linux 服务器上启动失败,日志只显示Error: EACCES。排查 4 小时才发现是trae.config.tsprojectRoot写成了绝对路径/home/user/my-cocos-project,而服务器上该路径不存在。从此我坚持用相对路径../my-cocos-project,并加了启动校验:

if (!fs.existsSync(config.projectRoot)) { console.error(`Project root not found: ${config.projectRoot}`); process.exit(1); }

这种看似琐碎的细节,恰恰是线上稳定性的基石。