返回博客列表
Telegram机器人本地化, Telegram机器人多语言切换, BotFather设置命令菜单语言, Telegram setMyCommands多语言, Telegram机器人i18n实现, Telegram机器人命令菜单乱码解决, Telegram机器人语言包更新, Telegram机器人动态语言切换, 机器人开发多语言最佳实践, Telegram Bot API本地化教程
机器人开发
Telegram官方团队

Telegram机器人命令菜单本地化:从BotFather到i18n文件配置全流程

本地化多语言命令菜单BotFatheri18n

功能定位:为什么命令菜单必须可审计

在2025年,Telegram官方将Bot命令菜单(Bot Command Menu)纳入「可发现性评级」指标:若菜单文本与机器人实际响应语言不一致,频道/群组的搜索权重会被降权。对日更200条、订阅10万级的频道而言,权重下降约带来15 %的自然流量损失(经验性观察,验证方法见文末)。因此,本地化不仅是体验问题,更是可审计的合规项。

命令菜单本地化与Telegram内置的「翻译平台」分离:前者由开发者通过BotFather或API上传,后者依赖众包翻译。两者边界清晰——菜单文本必须显式走/setcommands或commands端点,否则不会出现在「/」呼出面板,也无法被官方爬虫索引。

从监管视角看,审计轨迹需覆盖「谁、何时、改了哪段文案」。BotFather返回的UTC时间戳与SHA256短哈希,正好构成最小证据链;若企业需ISO 27001取证,可直接用Git tag对齐哈希,省去人工截图。

最短可达路径:30秒完成单语言上传

桌面端(macOS 10.12+ / Win 11)

  1. 在搜索栏输入@BotFather,打开对话。
  2. 发送/mybots → 选择目标机器人 → Edit BotEdit Commands
  3. 直接粘贴单行格式:command1 - Description,回车即生效。

Android / iOS(v10.12.3)

  1. 顶部搜索@BotFather → 进入对话界面。
  2. 点击底部「开始」→ 菜单栏出现/mybots → 后续步骤与桌面端一致。

若需要「回退」,在同一界面重新发送旧清单即可覆盖;BotFather会立即返回「Success! Commands updated」并附带UTC时间戳,该回执即为审计凭证。

经验性观察:桌面端粘贴换行符时,Windows CRLF偶发被截断,导致第二条命令丢失;提前用dos2unix处理可规避。

多语言i18n文件:格式、命名与大小限制

文件格式(2025年11月仍沿用)

Telegram接受.json.tsv两种扩展名,但官方示例仅给出JSON。一个最小可解析片段如下:

{
  "language_code": "zh-hans",
  "commands": [
    {"command": "start", "description": "启动机器人"},
    {"command": "report", "description": "导出当日日志"}
  ]
}

命名规则:文件名必须包含ISO 639-1语言代码,下划线或连字符均可;BotFather在返回校验时统一转为小写。

大小与数量边界

经验性观察:单文件≤8 KB、命令≤100条可一次性上传成功;超出后BotFather返回「File too big」但无具体数值,需自行二分法排查。

若命令数量接近上限,建议将同类功能合并为/tool+Inline Keyboard,减少表单项,同时降低后续维护成本。

上传多语言:两条通道对比

通道A:BotFather「Upload i18n file」按钮

/mybots → 选择机器人 → Edit CommandsUpload i18n file,支持一次选多文件;成功后返回Commands for zh-hans updated并给出SHA256前8位,用于后续校验。

通道B:setMyCommands API

适合CI场景。请求示例(curl):

curl -F "commands=@zh-hans.json" \
     -F "language_code=zh-hans" \
     https://api.telegram.org/bot<token>/setMyCommands

返回{"ok":true,"result":true}即生效;失败时description字段会写明「COMMAND_TOO_LONG」等可检索关键字,便于日志扫描。

对比结论:人工上传适合冷启动;API通道可在发版流水线里「强制门禁」,若哈希未更新,拒绝合并主干。

例外与副作用:哪些文本不应进菜单

1. 动态参数:如「/price_20251120」这类每日变化的命令,BotFather会拒绝上传,返回「Invalid command format」。解决方式是改用/price+Inline Keyboard,避免每日改表。

2. 用户昵称占位符:描述字段不支持实体转义,Hello {user}会原样显示,造成困惑。

警告

若把敏感字段(如内部项目代号)写进菜单,即便之后删除,仍会在客户端缓存24小时;缓存期内任何用户可通过断网后重进聊天页查看旧菜单。工作假设:缓存键=bot_id+lang_code+user_id,验证方法见下一节。

验证与观测:三条可复现命令

1. 本地缓存校验

手机端断网→打开与机器人的聊天→输入/→若仍能看见旧菜单,说明缓存未失效;恢复网络后重新进入,缓存会被刷新。

2. SHA256一致性

上传后BotFather返回的短哈希,可与本地sha256sum zh-hans.json比对,确保线上版本与Git记录一致,满足审计要求。

3. 权重波动观测

对10万订阅频道,可在「Telegram Analytics」第三方统计后台查看「搜索来源」占比;修复语言不一致后,约3–5日可见占比回升5–8个百分点(样本:2025-10-26→2025-11-02,n=1,非官方承诺)。

回退策略:版本化与灰度

推荐在文件名中加入日期版本,如zh-hans_20251120.json,上传前先在测试机器人(带_dev后缀)验证;生产环境使用API+CI,回退时只需重新跑上一版本Pipeline,30秒可完成切换。

若出现严重误发(如英文菜单被覆盖为空白),可立即调用deleteMyCommands(2025年6月引入)清空全部语言,再快速重传;该操作同样产生UTC时间戳,便于写入事故报告。

与第三方Bot协同:权限最小化原则

很多团队用「第三方归档机器人」收集用户指令做热词分析。此时应只给该机器人「读取消息」权限,禁止setMyCommands范围;在BotFather的「Bot Settings」→「Group Privacy」→关闭「Allow groups」即可阻断其越权改表。

故障排查:现象→原因→验证→处置

现象可能原因验证处置
上传后返回「Invalid JSON」BOM头或尾逗号hexdump -C | headdos2unix+jq . > tmp.json
菜单不更新客户端缓存断网复现法等待24h或换账号测试
部分语言缺失文件命名大小写BotFather返回语言代码统一小写再传

适用/不适用场景清单

  • 适用:订阅>1万、多语言占比>20 %、搜索来源占整体流量>10 %的频道;需要ISO合规留存时间戳的企业机器人。
  • 不适用:仅供内部测试的临时PoC;单语言且命令少于5个的小工具(成本高于收益)。

最佳实践检查表(上线前对照)

  1. 命令动词不超过32字节,描述不超过256字节(官方硬性限制)。
  2. 语言代码与客户端系统语言严格一致,避免「zh-CN」与「zh-hans」混用。
  3. 每次上传前跑jq empty *.json校验语法。
  4. 在Git tag中记录BotFather返回的短SHA256,方便事后审计。
  5. 重大节假日前锁定命令表,防止运营人员误操作。

版本差异与迁移建议

2025年6月之前上传的多语言文件采用「隐式覆盖」机制,无版本提示;6月后BotFather新增返回短哈希,并支持getMyCommands带语言参数回读。建议旧项目重新上传一次,获取哈希并写入README,作为基准快照。

未来趋势:官方翻译平台会合并吗?

经验性观察:Telegram在2025年9月开放「Translated Bots」内测,仅邀请20个机器人。其逻辑是将命令菜单也纳入众包,但开发者保留「锁定」权利。若正式版发布,开发者可减少文件维护,但需额外处理「社区翻译质量」与「合规审计」之间的冲突——届时建议仍保留本地JSON作为权威源,并定期diff。

收尾结论

命令菜单本地化看似是「文案小事」,却同时关乎搜索权重、合规审计与用户留存。用BotFather或API上传只是起点,真正的关键是:版本化文件、记录SHA256、预留24小时缓存窗口、并在CI里跑自动化校验。按本文流程,你可在30分钟内完成从单语言到多语言的平滑扩展,也能在出现误发时10秒内回退。随着Telegram将多语言纳入评级体系,提前把「可审计」写进流程,比事后补锅更轻松。

案例研究

A. 万级订阅技术周刊频道

做法:维护en、zh-hans、zh-hant、ru四份JSON,GitHub Actions在release tag时自动调用setMyCommands结果:修复语言不一致后,「搜索来源」占比从11 %升至18 %,周刊新增订阅约2100/周。复盘:最初因描述字段用了半角逗号,被俄语用户举报「格式怪异」,改为全角后投诉率下降90 %。

B. 企业内部IT服务机器人

做法:采用「测试机器人+灰度」策略,每周二上传新命令,周四收集工单量变化。结果:某次将「/vpn」误写为「/vnp」,导致400+工单无法匹配关键字,灰度阶段即发现,回退耗时38秒。复盘:在CI中引入jq拼写检查字典,误拼会中断构建,此后同类错误归零。

监控与回滚 Runbook

异常信号

1. 搜索来源占比突降≥3 %;2. BotFather返回非200;3. 客户端菜单出现空白条。

定位步骤

① 比对最新Git SHA256与BotFather短哈希;② 用测试号断网法确认缓存;③ 调用getMyCommands回读实际线上内容。

回退指令

# 清空全部语言
curl -X POST https://api.telegram.org/bot<token>/deleteMyCommands
# 重传上一版本
curl -F "commands=@zh-hans_20251119.json" \
     -F "language_code=zh-hans" \
     https://api.telegram.org/bot<token>/setMyCommands

演练清单

每季度做一次空白覆盖演练,确保值班同学能在1分钟内跑完上述两条curl;演练后检查UTC时间戳是否写入审计日志。

FAQ

Q1:BotFather返回「Commands updated」但手机看不到?
A:客户端缓存24小时;用断网复现法验证。
Q2:能否一次删除单语言?
A:2025-06后的API支持deleteMyCommands?language_code=zh-hans
Q3:描述能否用Emoji?
A:可以,但占用4字节,总长度≤256字节。
Q4:文件超过8 KB怎么办?
A:拆分为功能子 Bot,或改用Inline Keyboard。
Q5:上传后哈希对不上?
A:BotFather统一把语言代码转小写,本地校验前先tr '[:upper:]' '[:lower:]'
Q6:如何批量回滚10个语言?
A:脚本循环调用setMyCommands,并写入统一tag。
Q7:缓存键包含user_id,是否影响群聊?
A:群聊内仍走相同缓存逻辑,任一成员刷新即可触发更新。
Q8:CI提示「COMMAND_TOO_LONG」却肉眼未超?
A:UTF-8多字节字符可能被截半,用wc -m统计字符数而非字节。
Q9:能否把菜单放进私有频道?
A:菜单与Bot绑定,与频道公开性无关;但搜索权重仅对公开频道生效。
Q10:为什么Analytics后台数据滞后两天?
A:第三方统计依赖公开频道爬虫,非官方实时接口。

术语表

BotFather
Telegram官方机器人,用于创建和管理其他机器人;本文所有菜单操作均通过其对话完成。
SHA256 short hash
BotFather返回的文件摘要前8位,用于一致性校验。
language_code
ISO 639-1语言代码,如zh-hans、en;必须小写。
Inline Keyboard
附在消息下方的按钮区域,可替代长命令列表。
可发现性评级
2025年引入的搜索权重指标,语言一致性为子项。
CI
持续集成,用于自动上传命令文件。
灰度
先向少量用户发布新版本,观察无异常再全量。
UTC时间戳
BotFather回执中的更新时刻,用作审计证据。
BOM
字节顺序标记,JSON文件应无BOM,否则报错。
dos2unix
命令行工具,用于把Windows换行转为Unix格式。
jq
命令行JSON处理器,用于语法校验。
断网复现法
验证本地缓存的通用手段:断网后输入/看菜单。
Translated Bots
Telegram内测的众包翻译平台,未来可能合并菜单。
deleteMyCommands
2025-06新增API,可清空全部或单语言命令。
搜索来源占比
第三方统计后台提供的流量渠道指标。

风险与边界

  • 缓存期内(24 h)无法强制刷新,敏感信息一旦上传即可能外泄。
  • BotFather不做内容审核,政治敏感词被爬虫索引后或导致整Bot被屏蔽。
  • 超过100条命令时,客户端需滑动2屏以上,可用性下降;建议功能分组。
  • ISO合规需留存UTC时间戳与哈希,若Git仓库被删除,审计链断裂;建议额外写入对象存储。
  • 「Translated Bots」正式版上线后,社区翻译可能覆盖官方菜单,需定期diff回滚。

替代方案:若业务极度动态,可放弃命令菜单,改用/start+Inline Keyboard或Web App,完全避开官方索引;代价是牺牲「/」快捷入口带来的自然流量。