分类: Discord 机器人开发
Discord 机器人开发#10支持多语言(i18n)!(Python 示例)
本文译自韩语原文。
目录10 项
大家好!我是 Mojangcam 😎
上一篇 #9 我们给机器人接入了 AI(Claude·ChatGPT API),做出了能聊天的机器人。这一篇要把我们的机器人升级成全球化机器人,也就是支持多语言(i18n)!
运营有海外玩家的游戏服务器时,只会用一种语言回复的机器人难免让人觉得有点可惜。Discord 的每个用户都有自己的客户端语言设置,只要读取这个设置,就能做出给韩国用户回复韩语、给海外用户回复英语的自动回复机器人。甚至连斜杠命令的名称和描述都可以按语言显示成不同的内容!

🧠 i18n 是什么?为什么需要它?
i18n 是 internationalization(国际化)的缩写。因为 i 和 n 之间有 18 个字母,所以叫 i18n 💡
在 Discord 机器人里需要 i18n 的场景比想象中多。
- 有海外玩家的游戏服务器(Minecraft、ARK 等)里的公告机器人
- 部署到多个国家服务器的公开机器人
- 想用用户的语言显示命令说明,降低上手门槛的时候
discord.py 已经内置了实现这些的功能。只要掌握 interaction.locale(用户语言)和 Translator(命令翻译器)这两样就够了!
📌 准备工作
- Python 3.8 及以上
- discord.py 2.x(本文以最新版 2.7.1 为准)
- 机器人 Token + 已邀请机器人的测试服务器(参考 #1)
pip install -U discord.py📌 第 1 步 - 获取用户语言(interaction.locale)
执行斜杠命令时,Discord 会把该用户的语言信息一起发过来。我们先看看会收到什么值。
@bot.tree.command(name="lang", description="查看我的语言设置")
async def lang(interaction: discord.Interaction):
await interaction.response.send_message(
f"客户端语言:{interaction.locale}"
)我们逐个拆开来看 💡
- interaction.locale:执行命令的用户的 Discord 应用语言设置。韩语客户端会收到
ko,英语(美国)是en-US,日语是ja。 - interaction.guild_locale:这个不是用户的语言,而是服务器(公会)的默认语言。适合用在公告这类以服务器为单位的消息上。
- 返回类型是一个叫
discord.Locale的枚举(enum),用str()包一下就会变成'ko'这样的字符串。
📌 第 2 步 - 用翻译字典切换回复消息
接下来创建一个保存各语言回复的翻译字典(dict),再根据 interaction.locale 选出对应的消息发送。
RESPONSES = {
"ko": "안녕하세요, {user}님! 만나서 반가워요 🙌",
"ja": "こんにちは、{user}さん!",
"en-US": "Hello, {user}! Nice to meet you 🙌",
}
DEFAULT_LOCALE = "en-US"
@bot.tree.command(name="hello", description="Send a friendly greeting")
async def hello(interaction: discord.Interaction):
lang = str(interaction.locale)
template = RESPONSES.get(lang, RESPONSES[DEFAULT_LOCALE])
await interaction.response.send_message(
template.format(user=interaction.user.display_name)
)我们逐个拆开来看 💡
- RESPONSES:以语言代码为键的翻译字典。想新增语言的话,在这里加一行就行。
- RESPONSES.get(lang, 默认值):如果传进来的是字典里没有的语言(例如法语
fr),就改用默认语言(英语)回复。这是多语言处理的核心安全措施! - {user} + format():在消息里嵌入昵称这类变量的占位符。
📌 第 3 步 - 连命令名称和描述也翻译(Translator)
只换回复的话只做了一半。如果韩国用户的界面上命令本身就显示为 /인사(意为"问候"),是不是更好?这时候要用的就是 app_commands.Translator。
from discord import app_commands
from discord.app_commands import locale_str as _T
COMMAND_I18N = {
"ko": {
"hello": "인사",
"Send a friendly greeting": "봇이 반갑게 인사를 건네요",
},
"ja": {
"hello": "あいさつ",
"Send a friendly greeting": "ボットがあいさつします",
},
}
class MyTranslator(app_commands.Translator):
async def translate(self, string, locale, context):
# 有翻译就返回译文,没有就返回 None(保留原文)
return COMMAND_I18N.get(str(locale), {}).get(string.message)我们逐个拆开来看 💡
- locale_str(_T):用来标记"这个字符串需要翻译"的标记。创建命令时像
name=_T("hello")这样包起来。 - Translator:把命令注册(sync)到服务器时,Discord 会针对它支持的所有语言调用
translate()。没有翻译时返回None,就会直接使用原文。 - string.message:用
_T()包起来的原文字符串。以它为键去翻译字典里查找。 - ⚠️ 命令名称的规则同样适用于译文。不能有空格,英文只能用小写!(韩文、日文可以直接用)
最后,在机器人启动时先于 sync 注册翻译器。
@bot.event
async def on_ready():
await bot.tree.set_translator(MyTranslator()) # 一定要在 sync 之前!
await bot.tree.sync()
print(f"{bot.user} 登录成功!")📌 完整代码(可直接复制)
# discord.py 2.7.x / Python 3.8+
from typing import Optional
import discord
from discord import app_commands
from discord.app_commands import locale_str as _T
from discord.ext import commands
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
# 命令名称·描述的翻译表(供 Translator 使用)
COMMAND_I18N = {
"ko": {
"hello": "인사",
"Send a friendly greeting": "봇이 반갑게 인사를 건네요",
},
"ja": {
"hello": "あいさつ",
"Send a friendly greeting": "ボットがあいさつします",
},
}
# 回复消息的翻译表(根据 interaction.locale 选择)
RESPONSES = {
"ko": "안녕하세요, {user}님! 만나서 반가워요 🙌",
"ja": "こんにちは、{user}さん!",
"en-US": "Hello, {user}! Nice to meet you 🙌",
}
DEFAULT_LOCALE = "en-US"
class MyTranslator(app_commands.Translator):
async def translate(
self,
string: app_commands.locale_str,
locale: discord.Locale,
context: app_commands.TranslationContext,
) -> Optional[str]:
return COMMAND_I18N.get(str(locale), {}).get(string.message)
@bot.tree.command(name=_T("hello"), description=_T("Send a friendly greeting"))
async def hello(interaction: discord.Interaction):
lang = str(interaction.locale) # 例如:'ko', 'ja', 'en-US'
template = RESPONSES.get(lang, RESPONSES[DEFAULT_LOCALE])
await interaction.response.send_message(
template.format(user=interaction.user.display_name)
)
@bot.event
async def on_ready():
await bot.tree.set_translator(MyTranslator()) # 一定要在 sync 之前!
await bot.tree.sync()
print(f"{bot.user} 登录成功!")
bot.run("在这里输入机器人 Token")📌 运行结果
启动机器人后输入命令试试……
- 韩语客户端:命令列表里显示为 /인사 - 봇이 반갑게 인사를 건네요(意为"/问候 - 机器人热情地向你打招呼"),执行后回复"안녕하세요, ○○님! 만나서 반가워요 🙌"("你好,○○!很高兴见到你 🙌")
- 英语客户端:显示为 /hello - Send a friendly greeting,回复"Hello, ○○! Nice to meet you 🙌"
- 日语客户端:显示为 /あいさつ!明明是同一个命令,在不同语言下看起来却完全不一样。


也别忘了确认一下:用翻译字典里没有的语言(比如法语)执行时,会用默认的英语回复!
📌 常见报错
- 命令名称没有被翻译,只显示英文
原因:在
sync()之后才调用set_translator(),或者注册翻译器后没有重新同步。因为翻译是在 sync 的时候生效的。 解决:遵守await bot.tree.set_translator(...)→await bot.tree.sync()的顺序,然后在 Discord 客户端按 Ctrl+R 刷新。生效可能需要几分钟。 - sync 时出现 400 Bad Request(CommandSyncFailure)错误 原因:翻译后的命令名称违反了 Discord 的规则。命令名称里不能有空格,也不能用英文大写字母。 解决:检查翻译字典里命令名称的部分。"인사 하기"(有空格 ❌)→ "인사하기"(⭕),"Hello"(大写 ❌)→ "hello"(⭕)
- interaction.locale 总是 en-US
原因:
locale依据的不是服务器语言,而是每个用户自己的 Discord 应用语言设置。如果你的应用设置成英语,显示 en-US 是正常的。 解决:在 Discord 设置 → 语言里改成韩语(或其他语言)后再测试一次。如果需要以服务器为准的语言,用interaction.guild_locale就行。
📌 结语
今天我们用 interaction.locale 读取用户语言,用翻译字典切换回复,再用 Translator 把命令名称和描述也翻译过来,做出了一个三步搞定的多语言机器人。只要在翻译字典里加一行,就能支持任何语言,大家可以根据自己的服务器去扩展!
下一篇准备讲防止刷命令的冷却时间(Cooldown)与权限管理。敬请期待 🙌
📚 Discord 机器人开发系列
- Discord 机器人开发 - 彻底掌握 Slash Command!
- Discord 机器人开发 #2 - 给 Slash Command 添加选项(Arguments)!
- Discord 机器人开发 #3 - 给 Slash Command 加入子命令(Subcommand)!
- Discord 机器人开发 #4 - 用 Slash Command 发送嵌入消息!
- Discord 机器人开发 #5 - 实现按钮(Button)交互
- Discord 机器人开发 #6 - 实现下拉菜单(Select Menu)
- Discord 机器人开发 #7 - 用模态框(Modal)接收输入
- Discord 机器人开发 #8 - 用嵌入消息(Embed)的图片和字段美化消息
- Discord 机器人开发 #9 - 接入 AI(Claude·ChatGPT API)
- Discord 机器人开发 #10 - 支持多语言(i18n)← 就是这一篇!
连载 · 共 32 篇中的第 10 篇
Discord 机器人开发
- #1Discord 机器人开发 - Slash Command 完全攻略!
- #2为 Slash Command 添加选项(Arguments)!
- #3在 Slash Command 中添加子命令(Subcommand)!
- #4用 Slash Command 发送 Embed 嵌入消息!
- #5实现按钮(Button)交互!
- #6实现下拉菜单(Select Menu)!
- #7用模态框(Modal)接收用户输入(Python 示例)
- #8用嵌入消息(Embed)的图片和字段美化消息(Python 示例)
- #9接入 AI(Claude·ChatGPT API)!(Python 示例)
- #10支持多语言(i18n)!(Python 示例)当前文章
- #11用 Flask 制作网页仪表盘!(Python 示例)
- #12管理命令冷却时间(Cooldown)与权限(Permission)!(Python 示例)
- #13用身份组·频道自动化管理服务器!(Python 示例)
- #14保存数据!JSON vs SQLite(Python 示例)
- #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (韩语)
- #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (韩语)
- #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (韩语)
- #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (韩语)
- #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (韩语)
- #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (韩语)
- #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (韩语)
- #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (韩语)
- #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (韩语)
- #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (韩语)
- #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (韩语)
- #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (韩语)
- #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (韩语)
- #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (韩语)
- #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (韩语)
- #30打造投票·问卷(Poll)机器人!原生投票 + 按钮实时统计(Python 示例)🗳️
- #32打造服务器日志·审核日志(Audit Log)频道!自动记录消息删除、编辑、成员进出和踢出(Python 示例)🕵️
- #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (韩语)
