Discord多语言Bot加载含表情的.po/.mo文件触发UnicodeDecodeError
解决Discord Bot多语言表情导致的UnicodeDecodeError问题
问题根源
错误UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0...是因为gettext默认用ASCII编码加载翻译文件,而你的.po/.mo文件包含UTF-8编码的emoji(🏓是4字节UTF-8字符),超出了ASCII的编码范围。
解决方案
1. 确保.po文件保存为UTF-8编码
用文本编辑器打开.po文件,确认编码设置为UTF-8(无BOM)。比如VS Code右下角可查看和切换编码,保存时选择「UTF-8」即可。
2. 编译.mo文件时指定UTF-8编码
使用msgfmt编译.po文件时,显式指定编码参数,避免生成的.mo文件默认用ASCII编码:
msgfmt --encoding=utf-8 de.po -o locales/de/LC_MESSAGES/ping.mo
3. Python代码中显式设置gettext编码
加载翻译时,给gettext.translation()加上encoding='utf-8'参数,强制用UTF-8解码翻译内容:
trans = gettext.translation( domain="ping", localedir="locales", languages=[lang], fallback=True, encoding='utf-8' )
4. 修正代码逻辑错误
原代码存在结构问题:__init__方法中直接访问interaction无效,interaction仅在命令执行时传入。正确逻辑应放在命令函数内:
import gettext import json from datetime import datetime import discord from discord import app_commands from discord.ext import commands class Ping(commands.Cog): def __init__(self, client: commands.Bot): self.client = client @app_commands.command(name="ping", description="查看机器人延迟") async def ping(self, interaction: discord.Interaction): # 加载服务器语言配置 with open("data/languages.json", encoding="utf-8") as f: guild_languages = json.load(f) lang = guild_languages.get(str(interaction.guild.id), "en") # 加载翻译并指定UTF-8编码 trans = gettext.translation( domain="ping", localedir="locales", languages=[lang], fallback=True, encoding='utf-8' ) ping = round(self.client.latency * 1000) embed = discord.Embed( title=trans.gettext("PING_TITLE"), description=trans.gettext("PING_DESCRIPTION").format(ping=ping), color=0x1365EA, timestamp=datetime.now(), ) embed.set_author( name=str(interaction.user), icon_url=interaction.user.avatar.url ) await interaction.response.send_message(embed=embed) async def setup(client): await client.add_cog(Ping(client))
验证
完成以上步骤后,重新编译.mo文件,启动Bot执行ping命令,emoji即可正常显示,不会再出现解码错误。
内容的提问来源于stack exchange,提问作者Navis
相关产品推荐
相关产品推荐

