本地化不是把中文换成英文
Godot 提供 TranslationServer,可以加载翻译资源并按 key 取文本。很多项目第一次做多语言时,只是把 UI 文本替换成 tr(“KEY”)。这一步重要,但远远不够。游戏客户端里的本地化还包括字体、换行、变量、复数、对话节奏、图片字、语音、输入法和运行时切换。
如果项目早期没有本地化规范,后期补会非常痛苦:文本散在脚本里,按钮宽度写死,中文图片字无法替换,字体缺字,德语文本挤爆弹窗。Godot 能提供基础能力,团队还需要内容管线和 UI 约束。
flowchart TD
A[文本 Key 规范] --> B[CSV/PO 翻译表]
B --> C[Godot Translation 资源]
C --> D[TranslationServer]
D --> E[UI Label/Button]
D --> F[对话系统]
G[字体与回退链] --> E
G --> F
H[语言切换事件] --> D
H --> I[UI 重新绑定]
Key 要稳定且有语义
翻译 key 不要用原文。START_GAME、SHOP_BUY_CONFIRM、DIALOGUE_NPC_OLDMAN_001 比直接用中文文本更稳定。原文会改,key 应尽量不改。key 也不要过度复用,两个地方中文一样,不代表其他语言一样。
Key 命名可以按模块分组:UI_MENU_START、ITEM_DESC_POTION_SMALL、QUEST_MAIN_010_TITLE。这样翻译表更容易维护,也方便检查缺失。脚本里不要拼接 key,除非有严格规则。动态拼接会让扫描工具找不到引用。
翻译表需要上下文。译者只看到“确定”不知道是确认购买还是确认删除,可能翻错。可以在 CSV 或 PO 注释里放场景、截图链接和字符限制。工具支持越好,翻译质量越稳定。
字体回退是 CJK 项目的核心
中文、日文、韩文、泰文、俄文、阿拉伯文对字体覆盖要求不同。Godot 的字体资源可以设置 fallback。项目要设计字体回退链:主 UI 字体、CJK 字体、符号字体、emoji 或图标字体。缺字时不应该直接显示方块。
字体文件很大,移动端尤其要注意。可以按语言包加载字体,或使用子集字体。默认包至少包含启动和设置页需要的字体,玩家才能切换语言。语言切换时,字体要先准备好,再刷新 UI。
字体风格也影响排版。中文看起来合适的字号,英文可能显得小,泰文可能上下被裁。Theme 里要给不同语言留出行高和最小尺寸,不能所有语言共用一套死数值。
变量替换要安全
游戏文本常有变量:玩家名、道具名、数量、时间、按键图标。不要用简单字符串拼接,例如 "获得" + item_name + "x" + count。不同语言语序不同,应该让翻译文本包含占位符:获得 {item} x{count},英文可能是 Received {count} x {item}。
变量替换要处理富文本。Godot RichTextLabel 支持 BBCode,但翻译文本里允许哪些标签要受控。不要让运营或翻译随意插入复杂标签。可以只允许颜色、图标、换行等白名单。
玩家名和输入内容要转义,避免破坏 BBCode。聊天、昵称、公告进入本地化文本时尤其要注意。
对话文本有节奏问题
剧情对话不是普通 Label。它可能逐字显示、自动播放语音、等待玩家点击、根据语言调整速度。中文一句短,英文一句长,如果逐字速度一样,英文会拖很久。可以按语言设置字符速度,或按预计阅读时间计算。
对话框要支持多行和滚动。翻译变长后,不应该把选项按钮挤出屏幕。重要对话可以分页,但分页点最好由文本系统自动或翻译标记控制。不要按中文长度硬切。
语音本地化也要同步。某些语言没有语音时,文本仍然正常播放。语音长度不同,自动推进要以语音和最短阅读时间共同决定。
运行时切换语言
玩家在设置里切换语言后,当前 UI 要刷新。Godot 的 tr 调用不是自动让所有已显示 Label 更新,项目需要语言变化事件。控件保存 text key,收到事件后重新取文本。不要只保存翻译后的文本,否则切换语言不知道原 key。
场景中的图片字、语音、字体、日期格式也要刷新。某些页面可以重开,核心设置页和主菜单最好即时更新。切换失败时保留旧语言,不要出现半中半英。
小结
Godot 本地化要从文本 key、翻译表、字体回退、变量替换、对话节奏和运行时刷新一起设计。TranslationServer 解决取文本的问题,项目管线解决可维护性和排版问题。越早按多语言要求写 UI,后期进入海外市场越少返工。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
我会给每个页面加一个“长文本伪语言”测试,把所有文本变长 30% 并加入特殊字符。Godot UI 在这种语言下仍不爆,真实翻译通常就不会太危险。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。