| from bot.i18n import get_cmd_desc
|
| """
|
| Language cog: Multi-language support for the bot.
|
| Provides a beautiful panel for changing server language.
|
| """
|
|
|
| import discord
|
| from discord.ext import commands
|
|
|
| from bot.i18n import SUPPORTED_LANGUAGES, translate
|
| from bot.theme import NEON_CYAN, NEON_LIME, panel_divider, success_embed, shimmer
|
|
|
| LANGUAGE_META: dict[str, tuple[str, str]] = {
|
| "ar": ("العربية", "🇸🇦"),
|
| "en": ("English", "🇬🇧"),
|
| "es": ("Español", "🇪🇸"),
|
| "fr": ("Français", "🇫🇷"),
|
| "de": ("Deutsch", "🇩🇪"),
|
| "tr": ("Türkçe", "🇹🇷"),
|
| "it": ("Italiano", "🇮🇹"),
|
| "pt": ("Português", "🇵🇹"),
|
| "ru": ("Русский", "🇷🇺"),
|
| "hi": ("हिन्दी", "🇮🇳"),
|
| "id": ("Indonesia", "🇮🇩"),
|
| "ja": ("日本語", "🇯🇵"),
|
| "zh": ("中文", "🇨🇳"),
|
| "he": ("עברית", "🇮🇱"),
|
| }
|
|
|
|
|
| class LanguageSelect(discord.ui.Select):
|
| def __init__(self, cog: "Language", guild_id: int, current_code: str) -> None:
|
| self.cog = cog
|
| self.guild_id = guild_id
|
|
|
| options: list[discord.SelectOption] = []
|
| dynamic_supported = sorted(
|
| getattr(getattr(cog.bot, "translator", None), "supported_languages", set(SUPPORTED_LANGUAGES))
|
| )
|
| for code in dynamic_supported:
|
| label, emoji = LANGUAGE_META.get(code, (code.upper(), "🌐"))
|
| options.append(
|
| discord.SelectOption(
|
| label=label,
|
| value=code,
|
| emoji=emoji,
|
| description=f"{code.upper()} language",
|
| default=code == current_code,
|
| )
|
| )
|
|
|
| super().__init__(
|
| placeholder="Choose server language",
|
| min_values=1,
|
| max_values=1,
|
| options=options[:25],
|
| custom_id="lang:select",
|
| )
|
|
|
| async def callback(self, interaction: discord.Interaction) -> None:
|
| if not interaction.guild:
|
| await interaction.response.send_message(translate("en", "common.server_only"), ephemeral=True)
|
| return
|
|
|
| selected = self.values[0]
|
|
|
|
|
| if selected == "he":
|
| current_code = await self.cog._current_code(interaction.guild.id)
|
| for option in self.options:
|
| option.default = option.value == current_code
|
| embed = await self.cog._language_embed(interaction.guild.id, current_code)
|
| await interaction.response.edit_message(embed=embed, view=self.view)
|
| await interaction.followup.send("only you know this language", ephemeral=True)
|
| return
|
|
|
| await self.cog.bot.db.execute(
|
| "INSERT INTO guild_config(guild_id, guild_language) VALUES (?, ?) "
|
| "ON CONFLICT(guild_id) DO UPDATE SET guild_language = excluded.guild_language",
|
| interaction.guild.id,
|
| selected,
|
| )
|
|
|
| for option in self.options:
|
| option.default = option.value == selected
|
|
|
| embed = await self.cog._language_embed(interaction.guild.id, selected)
|
| await interaction.response.edit_message(embed=embed, view=self.view)
|
|
|
|
|
| lang_name = LANGUAGE_META.get(selected, (selected.upper(), "🌐"))[0]
|
| hint_msg = translate(selected, "lang.updated")
|
|
|
| followup_embed = discord.Embed(
|
| title=f"✅ Language Changed!",
|
| description=f"{panel_divider('lime')}\n{hint_msg}\n\n💡 Use `/menu` to see all commands in your selected language!\n{panel_divider('lime')}",
|
| color=NEON_LIME,
|
| )
|
| await interaction.followup.send(embed=followup_embed, ephemeral=True)
|
|
|
|
|
| class LanguagePanelView(discord.ui.View):
|
| def __init__(self, cog: "Language", guild_id: int, current_code: str) -> None:
|
| super().__init__(timeout=None)
|
| self.add_item(LanguageSelect(cog, guild_id, current_code))
|
|
|
|
|
| class Language(commands.Cog):
|
| def __init__(self, bot: commands.Bot) -> None:
|
| self.bot = bot
|
|
|
| async def cog_load(self) -> None:
|
| self.bot.add_view(LanguagePanelView(self, 0, "ar"))
|
|
|
| async def _current_code(self, guild_id: int) -> str:
|
| row = await self.bot.db.fetchone("SELECT guild_language FROM guild_config WHERE guild_id = ?", guild_id)
|
| supported = set(getattr(getattr(self.bot, "translator", None), "supported_languages", set(SUPPORTED_LANGUAGES)))
|
| return row[0] if row and row[0] in supported else "ar"
|
|
|
| async def _language_embed(self, guild_id: int, current_code: str) -> discord.Embed:
|
| current_name = LANGUAGE_META.get(current_code, (current_code.upper(), "🌐"))[0]
|
| current_emoji = LANGUAGE_META.get(current_code, (current_code.upper(), "🌐"))[1]
|
|
|
| lines = []
|
| supported = sorted(
|
| getattr(getattr(self.bot, "translator", None), "supported_languages", set(SUPPORTED_LANGUAGES))
|
| )
|
| for code in supported:
|
| name, emoji = LANGUAGE_META.get(code, (code.upper(), "🌐"))
|
| marker = "✅" if code == current_code else "▫️"
|
| lines.append(f"{marker} {emoji} **{name}** `({code})`")
|
|
|
|
|
| title = translate(current_code, "lang.current").replace("{globe}", "🌍")
|
|
|
| embed = discord.Embed(
|
| title="🌍 Language Control Panel",
|
| description=(
|
| f"{shimmer('Current Language')}: **{current_emoji} {current_name}** (`{current_code}`)\n"
|
| f"{panel_divider('cyan')}\n"
|
| f"Pick your server language from the dropdown below.\n"
|
| f"All bot messages and panels will use the selected language!"
|
| ),
|
| color=NEON_CYAN,
|
| )
|
| embed.add_field(name="🌐 Supported Languages", value="\n".join(lines[:20]), inline=False)
|
| embed.add_field(
|
| name="💡 Tips",
|
| value=(
|
| "• Language changes apply instantly\n"
|
| "• Use `/menu` to see commands in your language\n"
|
| "• Available full locales: Arabic, English, Spanish, French, German"
|
| ),
|
| inline=False
|
| )
|
| embed.set_footer(text="Changes apply instantly across bot messages and panels")
|
| return embed
|
|
|
| @commands.hybrid_command(name="language", description=get_cmd_desc("commands.tools.language_desc"))
|
| @commands.has_permissions(manage_guild=True)
|
| async def language(self, ctx: commands.Context) -> None:
|
| if not ctx.guild:
|
| await ctx.reply(translate("en", "common.server_only"))
|
| return
|
|
|
| current_code = await self._current_code(ctx.guild.id)
|
| embed = await self._language_embed(ctx.guild.id, current_code)
|
| view = LanguagePanelView(self, ctx.guild.id, current_code)
|
| await ctx.reply(embed=embed, view=view)
|
|
|
| @commands.hybrid_command(name="languages", description=get_cmd_desc("commands.tools.languages_desc"), hidden=True, with_app_command=False)
|
| async def languages(self, ctx: commands.Context) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| pretty = [f"{LANGUAGE_META.get(code, (code.upper(), '🌐'))[1]} **{LANGUAGE_META.get(code, (code.upper(), '🌐'))[0]}** (`{code}`)" for code in LANGUAGE_META]
|
|
|
| embed = discord.Embed(
|
| title="🌍 Supported Languages",
|
| description=f"{panel_divider('cyan')}\n" + "\n".join(pretty) + f"\n{panel_divider('cyan')}",
|
| color=NEON_CYAN,
|
| )
|
| embed.set_footer(text=f"Current: {LANGUAGE_META.get(lang, (lang.upper(), '🌐'))[0]}")
|
| await ctx.reply(embed=embed)
|
|
|
|
|
| async def setup(bot: commands.Bot) -> None:
|
| await bot.add_cog(Language(bot))
|
|
|