From 3a20c113315fbae5dcc5aa43a5d498625c94777c Mon Sep 17 00:00:00 2001 From: Toby Harradine Date: Thu, 16 Aug 2018 10:10:03 +1000 Subject: [PATCH] [i18n] User-facing string pass over admin, alias and audio --- redbot/cogs/admin/admin.py | 97 +++-- redbot/cogs/admin/announcer.py | 7 +- redbot/cogs/admin/converters.py | 7 +- redbot/cogs/alias/alias.py | 56 +-- redbot/cogs/audio/audio.py | 638 ++++++++++++++++++-------------- 5 files changed, 439 insertions(+), 366 deletions(-) diff --git a/redbot/cogs/admin/admin.py b/redbot/cogs/admin/admin.py index 30136b980..35eb7a964 100644 --- a/redbot/cogs/admin/admin.py +++ b/redbot/cogs/admin/admin.py @@ -14,26 +14,30 @@ log = logging.getLogger("red.admin") _ = Translator("Admin", __file__) -GENERIC_FORBIDDEN = _( +# The following are all lambdas to allow us to fetch the translation +# during runtime, without having to copy the large strings everywhere +# in the code. + +generic_forbidden = lambda: _( "I attempted to do something that Discord denied me permissions for." " Your command failed to successfully complete." ) -HIERARCHY_ISSUE = _( +hierarchy_issue = lambda: _( "I tried to add {role.name} to {member.display_name} but that role" " is higher than my highest role in the Discord hierarchy so I was" " unable to successfully add it. Please give me a higher role and " "try again." ) -USER_HIERARCHY_ISSUE = _( +user_hierarchy_issue = lambda: _( "I tried to add {role.name} to {member.display_name} but that role" " is higher than your highest role in the Discord hierarchy so I was" " unable to successfully add it. Please get a higher role and " "try again." ) -RUNNING_ANNOUNCEMENT = _( +running_announcement = lambda: _( "I am already announcing something. If you would like to make a" " different announcement please use `{prefix}announce cancel`" " first." @@ -42,6 +46,7 @@ RUNNING_ANNOUNCEMENT = _( @cog_i18n(_) class Admin(commands.Cog): + """A collection of server administration utilities.""" def __init__(self, config=Config): super().__init__() self.conf = config.get_conf(self, 8237492837454039, force_registration=True) @@ -101,9 +106,9 @@ class Admin(commands.Cog): await member.add_roles(role) except discord.Forbidden: if not self.pass_hierarchy_check(ctx, role): - await self.complain(ctx, HIERARCHY_ISSUE, role=role, member=member) + await self.complain(ctx, hierarchy_issue(), role=role, member=member) else: - await self.complain(ctx, GENERIC_FORBIDDEN) + await self.complain(ctx, generic_forbidden()) else: await ctx.send( _("I successfully added {role.name} to {member.display_name}").format( @@ -116,9 +121,9 @@ class Admin(commands.Cog): await member.remove_roles(role) except discord.Forbidden: if not self.pass_hierarchy_check(ctx, role): - await self.complain(ctx, HIERARCHY_ISSUE, role=role, member=member) + await self.complain(ctx, hierarchy_issue(), role=role, member=member) else: - await self.complain(ctx, GENERIC_FORBIDDEN) + await self.complain(ctx, generic_forbidden()) else: await ctx.send( _("I successfully removed {role.name} from {member.display_name}").format( @@ -132,8 +137,8 @@ class Admin(commands.Cog): async def addrole( self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None ): - """ - Adds a role to a user. + """Add a role to a user. + If user is left blank it defaults to the author of the command. """ if user is None: @@ -142,7 +147,7 @@ class Admin(commands.Cog): # noinspection PyTypeChecker await self._addrole(ctx, user, rolename) else: - await self.complain(ctx, USER_HIERARCHY_ISSUE, member=ctx.author, role=rolename) + await self.complain(ctx, user_hierarchy_issue(), member=ctx.author, role=rolename) @commands.command() @commands.guild_only() @@ -150,8 +155,8 @@ class Admin(commands.Cog): async def removerole( self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None ): - """ - Removes a role from a user. + """Remove a role from a user. + If user is left blank it defaults to the author of the command. """ if user is None: @@ -160,38 +165,40 @@ class Admin(commands.Cog): # noinspection PyTypeChecker await self._removerole(ctx, user, rolename) else: - await self.complain(ctx, USER_HIERARCHY_ISSUE) + await self.complain(ctx, user_hierarchy_issue()) @commands.group() @commands.guild_only() @checks.admin_or_permissions(manage_roles=True) async def editrole(self, ctx: commands.Context): - """Edits roles settings""" + """Edit role settings.""" pass @editrole.command(name="colour", aliases=["color"]) async def editrole_colour( self, ctx: commands.Context, role: discord.Role, value: discord.Colour ): - """Edits a role's colour + """Edit a role's colour. Use double quotes if the role contains spaces. Colour must be in hexadecimal format. - \"http://www.w3schools.com/colors/colors_picker.asp\" + [Online colour picker](http://www.w3schools.com/colors/colors_picker.asp) + Examples: - !editrole colour \"The Transistor\" #ff0000 - !editrole colour Test #ff9900""" + `[p]editrole colour "The Transistor" #ff0000` + `[p]editrole colour Test #ff9900` + """ author = ctx.author reason = "{}({}) changed the colour of role '{}'".format(author.name, author.id, role.name) if not self.pass_user_hierarchy_check(ctx, role): - await self.complain(ctx, USER_HIERARCHY_ISSUE) + await self.complain(ctx, user_hierarchy_issue()) return try: await role.edit(reason=reason, color=value) except discord.Forbidden: - await self.complain(ctx, GENERIC_FORBIDDEN) + await self.complain(ctx, generic_forbidden()) else: log.info(reason) await ctx.send(_("Done.")) @@ -199,11 +206,13 @@ class Admin(commands.Cog): @editrole.command(name="name") @checks.admin_or_permissions(administrator=True) async def edit_role_name(self, ctx: commands.Context, role: discord.Role, *, name: str): - """Edits a role's name + """Edit a role's name. Use double quotes if the role or the name contain spaces. + Examples: - !editrole name \"The Transistor\" Test""" + `[p]editrole name \"The Transistor\" Test` + """ author = ctx.message.author old_name = role.name reason = "{}({}) changed the name of role '{}' to '{}'".format( @@ -211,13 +220,13 @@ class Admin(commands.Cog): ) if not self.pass_user_hierarchy_check(ctx, role): - await self.complain(ctx, USER_HIERARCHY_ISSUE) + await self.complain(ctx, user_hierarchy_issue()) return try: await role.edit(reason=reason, name=name) except discord.Forbidden: - await self.complain(ctx, GENERIC_FORBIDDEN) + await self.complain(ctx, generic_forbidden()) else: log.info(reason) await ctx.send(_("Done.")) @@ -225,9 +234,7 @@ class Admin(commands.Cog): @commands.group(invoke_without_command=True) @checks.is_owner() async def announce(self, ctx: commands.Context, *, message: str): - """ - Announces a message to all servers the bot is in. - """ + """Announce a message to all servers the bot is in.""" if not self.is_announcing(): announcer = Announcer(ctx, message, config=self.conf) announcer.start() @@ -237,14 +244,12 @@ class Admin(commands.Cog): await ctx.send(_("The announcement has begun.")) else: prefix = ctx.prefix - await self.complain(ctx, RUNNING_ANNOUNCEMENT, prefix=prefix) + await self.complain(ctx, running_announcement(), prefix=prefix) @announce.command(name="cancel") @checks.is_owner() async def announce_cancel(self, ctx): - """ - Cancels a running announce. - """ + """Cancel a running announce.""" try: self.__current_announcer.cancel() except AttributeError: @@ -256,9 +261,7 @@ class Admin(commands.Cog): @commands.guild_only() @checks.guildowner_or_permissions(administrator=True) async def announce_channel(self, ctx, *, channel: discord.TextChannel = None): - """ - Changes the channel on which the bot makes announcements. - """ + """Change the channel to which the bot makes announcements.""" if channel is None: channel = ctx.channel await self.conf.guild(ctx.guild).announce_channel.set(channel.id) @@ -271,9 +274,7 @@ class Admin(commands.Cog): @commands.guild_only() @checks.guildowner_or_permissions(administrator=True) async def announce_ignore(self, ctx): - """ - Toggles whether the announcements will ignore the current server. - """ + """Toggle announcements being enabled this server.""" ignored = await self.conf.guild(ctx.guild).announce_ignore() await self.conf.guild(ctx.guild).announce_ignore.set(not ignored) @@ -309,8 +310,9 @@ class Admin(commands.Cog): @commands.guild_only() @commands.group(invoke_without_command=True) async def selfrole(self, ctx: commands.Context, *, selfrole: SelfRole): - """ - Add a role to yourself that server admins have configured as user settable. + """Add a role to yourself. + + Server admins must have configured the role as user settable. NOTE: The role is case sensitive! """ @@ -319,8 +321,7 @@ class Admin(commands.Cog): @selfrole.command(name="remove") async def selfrole_remove(self, ctx: commands.Context, *, selfrole: SelfRole): - """ - Removes a selfrole from yourself. + """Remove a selfrole from yourself. NOTE: The role is case sensitive! """ @@ -330,8 +331,7 @@ class Admin(commands.Cog): @selfrole.command(name="add") @checks.admin_or_permissions(manage_roles=True) async def selfrole_add(self, ctx: commands.Context, *, role: discord.Role): - """ - Add a role to the list of available selfroles. + """Add a role to the list of available selfroles. NOTE: The role is case sensitive! """ @@ -344,8 +344,7 @@ class Admin(commands.Cog): @selfrole.command(name="delete") @checks.admin_or_permissions(manage_roles=True) async def selfrole_delete(self, ctx: commands.Context, *, role: SelfRole): - """ - Removes a role from the list of available selfroles. + """Remove a role from the list of available selfroles. NOTE: The role is case sensitive! """ @@ -362,7 +361,7 @@ class Admin(commands.Cog): selfroles = await self._valid_selfroles(ctx.guild) fmt_selfroles = "\n".join(["+ " + r.name for r in selfroles]) - msg = _("Available Selfroles:\n{selfroles}").format(selfroles=fmt_selfroles) + msg = _("Available Selfroles: {selfroles}").format(selfroles=fmt_selfroles) await ctx.send(box(msg, "diff")) async def _serverlock_check(self, guild: discord.Guild) -> bool: @@ -379,9 +378,7 @@ class Admin(commands.Cog): @commands.command() @checks.is_owner() async def serverlock(self, ctx: commands.Context): - """ - Locks a bot to its current servers only. - """ + """Lock a bot to its current servers only.""" serverlocked = await self.conf.serverlocked() await self.conf.serverlocked.set(not serverlocked) diff --git a/redbot/cogs/admin/announcer.py b/redbot/cogs/admin/announcer.py index 8c02b6e10..154eacb48 100644 --- a/redbot/cogs/admin/announcer.py +++ b/redbot/cogs/admin/announcer.py @@ -2,6 +2,9 @@ import asyncio import discord from redbot.core import commands +from redbot.core.i18n import Translator + +_ = Translator("Announcer", __file__) class Announcer: @@ -63,7 +66,9 @@ class Announcer: try: await channel.send(self.message) except discord.Forbidden: - await bot_owner.send("I could not announce to server: {}".format(g.id)) + await bot_owner.send( + _("I could not announce to server: {server.id}").format(server=g) + ) await asyncio.sleep(0.5) self.active = False diff --git a/redbot/cogs/admin/converters.py b/redbot/cogs/admin/converters.py index f507d975f..073511d90 100644 --- a/redbot/cogs/admin/converters.py +++ b/redbot/cogs/admin/converters.py @@ -1,5 +1,8 @@ import discord from redbot.core import commands +from redbot.core.i18n import Translator + +_ = Translator("AdminConverters", __file__) class MemberDefaultAuthor(commands.Converter): @@ -19,7 +22,7 @@ class SelfRole(commands.Converter): async def convert(self, ctx: commands.Context, arg: str) -> discord.Role: admin = ctx.command.instance if admin is None: - raise commands.BadArgument("Admin is not loaded.") + raise commands.BadArgument(_("The Admin cog is not loaded.")) conf = admin.conf selfroles = await conf.guild(ctx.guild).selfroles() @@ -28,5 +31,5 @@ class SelfRole(commands.Converter): role = await role_converter.convert(ctx, arg) if role.id not in selfroles: - raise commands.BadArgument("The provided role is not a valid selfrole.") + raise commands.BadArgument(_("The provided role is not a valid selfrole.")) return role diff --git a/redbot/cogs/alias/alias.py b/redbot/cogs/alias/alias.py index 6b3596e72..e0ccdef1e 100644 --- a/redbot/cogs/alias/alias.py +++ b/redbot/cogs/alias/alias.py @@ -15,15 +15,14 @@ _ = Translator("Alias", __file__) @cog_i18n(_) class Alias(commands.Cog): - """ - Alias - - Aliases are per server shortcuts for commands. They - can act as both a lambda (storing arguments for repeated use) - or as simply a shortcut to saying "x y z". - + """Create aliases for commands. + + Aliases are alternative names shortcuts for commands. They + can act as both a lambda (storing arguments for repeated use) + or as simply a shortcut to saying "x y z". + When run, aliases will accept any additional arguments - and append them to the stored alias + and append them to the stored alias. """ default_global_settings = {"entries": []} @@ -114,9 +113,8 @@ class Alias(commands.Cog): return False async def get_prefix(self, message: discord.Message) -> str: - """ - Tries to determine what prefix is used in a message object. - Looks to identify from longest prefix to smallest. + """Tries to determine what prefix is used in a message object. + Looks to identify from longest prefix to smallest. Will raise ValueError if no prefix is found. :param message: Message object @@ -177,23 +175,19 @@ class Alias(commands.Cog): @commands.group() @commands.guild_only() async def alias(self, ctx: commands.Context): - """Manage per-server aliases for commands""" + """Manage per-server aliases for commands.""" pass @alias.group(name="global") async def global_(self, ctx: commands.Context): - """ - Manage global aliases. - """ + """Manage global aliases.""" pass @checks.mod_or_permissions(manage_guild=True) @alias.command(name="add") @commands.guild_only() async def _add_alias(self, ctx: commands.Context, alias_name: str, *, command): - """ - Add an alias for a command. - """ + """Add an alias for a command.""" # region Alias Add Validity Checking is_command = self.is_command(alias_name) if is_command: @@ -242,9 +236,7 @@ class Alias(commands.Cog): @checks.is_owner() @global_.command(name="add") async def _add_global_alias(self, ctx: commands.Context, alias_name: str, *, command): - """ - Add a global alias for a command. - """ + """Add a global alias for a command.""" # region Alias Add Validity Checking is_command = self.is_command(alias_name) if is_command: @@ -292,7 +284,7 @@ class Alias(commands.Cog): @alias.command(name="help") @commands.guild_only() async def _help_alias(self, ctx: commands.Context, alias_name: str): - """Tries to execute help for the base command of the alias""" + """Try to execute help for the base command of the alias.""" is_alias, alias = await self.is_alias(ctx.guild, alias_name=alias_name) if is_alias: base_cmd = alias.command[0] @@ -308,7 +300,7 @@ class Alias(commands.Cog): @alias.command(name="show") @commands.guild_only() async def _show_alias(self, ctx: commands.Context, alias_name: str): - """Shows what command the alias executes.""" + """Show what command the alias executes.""" is_alias, alias = await self.is_alias(ctx.guild, alias_name) if is_alias: @@ -324,14 +316,12 @@ class Alias(commands.Cog): @alias.command(name="del") @commands.guild_only() async def _del_alias(self, ctx: commands.Context, alias_name: str): - """ - Deletes an existing alias on this server. - """ + """Delete an existing alias on this server.""" aliases = await self.unloaded_aliases(ctx.guild) try: next(aliases) except StopIteration: - await ctx.send(_("There are no aliases on this guild.")) + await ctx.send(_("There are no aliases on this server.")) return if await self.delete_alias(ctx, alias_name): @@ -344,9 +334,7 @@ class Alias(commands.Cog): @checks.is_owner() @global_.command(name="del") async def _del_global_alias(self, ctx: commands.Context, alias_name: str): - """ - Deletes an existing global alias. - """ + """Delete an existing global alias.""" aliases = await self.unloaded_global_aliases() try: next(aliases) @@ -364,9 +352,7 @@ class Alias(commands.Cog): @alias.command(name="list") @commands.guild_only() async def _list_alias(self, ctx: commands.Context): - """ - Lists the available aliases on this server. - """ + """List the available aliases on this server.""" names = [_("Aliases:")] + sorted( ["+ " + a.name for a in (await self.unloaded_aliases(ctx.guild))] ) @@ -377,9 +363,7 @@ class Alias(commands.Cog): @global_.command(name="list") async def _list_global_alias(self, ctx: commands.Context): - """ - Lists the available global aliases on this bot. - """ + """List the available global aliases on this bot.""" names = [_("Aliases:")] + sorted( ["+ " + a.name for a in await self.unloaded_global_aliases()] ) diff --git a/redbot/cogs/audio/audio.py b/redbot/cogs/audio/audio.py index dd17228d8..d91eeaf0c 100644 --- a/redbot/cogs/audio/audio.py +++ b/redbot/cogs/audio/audio.py @@ -34,6 +34,7 @@ __author__ = ["aikaterna", "billy/bollo/ati"] @cog_i18n(_) class Audio(commands.Cog): + """Play audio through voice channels.""" def __init__(self, bot): super().__init__() self.bot = bot @@ -146,7 +147,7 @@ class Audio(commands.Cog): dur = lavalink.utils.format_time(player.current.length) embed = discord.Embed( colour=(await self._get_embed_colour(notify_channel)), - title="Now Playing", + title=_("Now Playing"), description=description, ) embed.set_footer( @@ -174,7 +175,7 @@ class Audio(commands.Cog): if playing_servers > 1: await self.bot.change_presence( activity=discord.Activity( - name="music in {} servers".format(playing_servers), + name=_("music in {num} servers").format(num=playing_servers), type=discord.ActivityType.playing, ) ) @@ -184,7 +185,7 @@ class Audio(commands.Cog): if notify_channel: notify_channel = self.bot.get_channel(notify_channel) embed = discord.Embed( - colour=(await self._get_embed_colour(notify_channel)), title="Queue ended." + colour=(await self._get_embed_colour(notify_channel)), title=_("Queue ended.") ) await notify_channel.send(embed=embed) @@ -213,12 +214,12 @@ class Audio(commands.Cog): message_channel = self.bot.get_channel(message_channel) embed = discord.Embed( colour=(await self._get_embed_colour(message_channel)), - title="Track Error", + title=_("Track Error"), description="{}\n**[{}]({})**".format( extra, player.current.title, player.current.uri ), ) - embed.set_footer(text="Skipping...") + embed.set_footer(text=_("Skipping...")) await message_channel.send(embed=embed) await player.skip() @@ -231,11 +232,14 @@ class Audio(commands.Cog): @audioset.command() @checks.admin_or_permissions(manage_roles=True) async def dj(self, ctx): - """Toggle DJ mode (users need a role to use audio commands).""" + """Toggle DJ mode. + + DJ mode allows users with the DJ role to use audio commands. + """ dj_role_id = await self.config.guild(ctx.guild).dj_role() if dj_role_id is None and ctx.guild.get_role(dj_role_id): await self._embed_msg( - ctx, "Please set a role to use with DJ mode. Enter the role name or ID now." + ctx, _("Please set a role to use with DJ mode. Enter the role name or ID now.") ) try: @@ -254,16 +258,19 @@ class Audio(commands.Cog): async def emptydisconnect(self, ctx, seconds: int): """Auto-disconnection after x seconds while stopped. 0 to disable.""" if seconds < 0: - return await self._embed_msg(ctx, "Can't be less than zero.") + return await self._embed_msg(ctx, _("Can't be less than zero.")) if seconds < 10 and seconds > 0: seconds = 10 if seconds == 0: enabled = False - await self._embed_msg(ctx, "Empty disconnect disabled.") + await self._embed_msg(ctx, _("Empty disconnect disabled.")) else: enabled = True await self._embed_msg( - ctx, "Empty disconnect timer set to {}.".format(self._dynamic_time(seconds)) + ctx, + _("Empty disconnect timer set to {num_seconds}.").format( + num_seconds=self._dynamic_time(seconds) + ), ) await self.config.guild(ctx.guild).emptydc_timer.set(seconds) @@ -272,7 +279,7 @@ class Audio(commands.Cog): @audioset.command() @checks.admin_or_permissions(manage_roles=True) async def role(self, ctx, role_name: discord.Role): - """Sets the role to use for DJ mode.""" + """Set the role to use for DJ mode.""" await self.config.guild(ctx.guild).dj_role.set(role_name.id) dj_role_obj = ctx.guild.get_role(await self.config.guild(ctx.guild).dj_role()) await self._embed_msg(ctx, "DJ role set to: {}.".format(dj_role_obj.name)) @@ -280,18 +287,18 @@ class Audio(commands.Cog): @audioset.command() @checks.mod_or_permissions(administrator=True) async def jukebox(self, ctx, price: int): - """Set a price for queueing songs for non-mods. 0 to disable.""" + """Set a price for queueing tracks for non-mods. 0 to disable.""" if price < 0: - return await self._embed_msg(ctx, "Can't be less than zero.") + return await self._embed_msg(ctx, _("Can't be less than zero.")) if price == 0: jukebox = False - await self._embed_msg(ctx, "Jukebox mode disabled.") + await self._embed_msg(ctx, _("Jukebox mode disabled.")) else: jukebox = True await self._embed_msg( ctx, - "Track queueing command price set to {} {}.".format( - price, await bank.get_currency_name(ctx.guild) + _("Track queueing command price set to {price} {currency}.").format( + price=price, currency=await bank.get_currency_name(ctx.guild) ), ) @@ -301,10 +308,12 @@ class Audio(commands.Cog): @audioset.command() @checks.mod_or_permissions(manage_messages=True) async def notify(self, ctx): - """Toggle song announcement and other bot messages.""" + """Toggle track announcement and other bot messages.""" notify = await self.config.guild(ctx.guild).notify() await self.config.guild(ctx.guild).notify.set(not notify) - await self._embed_msg(ctx, "Verbose mode on: {}.".format(not notify)) + await self._embed_msg( + ctx, _("Verbose mode on: {true_or_false}.").format(true_or_false=not notify) + ) @audioset.command() async def settings(self, ctx): @@ -321,32 +330,34 @@ class Audio(commands.Cog): jarbuild = redbot.core.__version__ vote_percent = data["vote_percent"] - msg = "```ini\n" "----Server Settings----\n" + msg = _("```ini\n----Server Settings----\n") if emptydc_enabled: - msg += "Disconnect timer: [{0}]\n".format(self._dynamic_time(emptydc_timer)) + msg += _("Disconnect timer: [{num_seconds}]\n").format( + num_seconds=self._dynamic_time(emptydc_timer) + ) if dj_enabled: - msg += "DJ Role: [{}]\n".format(dj_role_obj.name) + msg += _("DJ Role: [{role.name}]\n").format(role=dj_role_obj) if jukebox: - msg += "Jukebox: [{0}]\n".format(jukebox) - msg += "Command price: [{0}]\n".format(jukebox_price) - msg += ( + msg += _("Jukebox: [{jukebox_name}]\n").format(jukebox_name=jukebox) + msg += _("Command price: [{jukebox_price}]\n").format(jukebox_price=jukebox_price) + msg += _( "Repeat: [{repeat}]\n" "Shuffle: [{shuffle}]\n" "Song notify msgs: [{notify}]\n" - "Songs as status: [{status}]\n".format(**global_data, **data) - ) + "Songs as status: [{status}]\n" + ).format(**global_data, **data) if thumbnail: msg += "Thumbnails: [{0}]\n".format(thumbnail) if vote_percent > 0: - msg += ( - "Vote skip: [{vote_enabled}]\n" "Skip percentage: [{vote_percent}%]\n" + msg += _( + "Vote skip: [{vote_enabled}]\nSkip percentage: [{vote_percent}%]\n" ).format(**data) - msg += ( + msg += _( "---Lavalink Settings---\n" - "Cog version: [{}]\n" - "Jar build: [{}]\n" + "Cog version: [{version}]\n" + "Jar build: [{jarbuild}]\n" "External server: [{use_external_lavalink}]```" - ).format(__version__, jarbuild, **global_data) + ).format(version=__version__, jarbuild=jarbuild, **global_data) embed = discord.Embed(colour=await ctx.embed_colour(), description=msg) return await ctx.send(embed=embed) @@ -362,19 +373,21 @@ class Audio(commands.Cog): @audioset.command() @checks.mod_or_permissions(administrator=True) async def vote(self, ctx, percent: int): - """Percentage needed for non-mods to skip songs. 0 to disable.""" + """Percentage needed for non-mods to skip tracks. 0 to disable.""" if percent < 0: - return await self._embed_msg(ctx, "Can't be less than zero.") + return await self._embed_msg(ctx, _("Can't be less than zero.")) elif percent > 100: percent = 100 if percent == 0: enabled = False await self._embed_msg( - ctx, "Voting disabled. All users can use queue management commands." + ctx, _("Voting disabled. All users can use queue management commands.") ) else: enabled = True - await self._embed_msg(ctx, "Vote percentage set to {}%.".format(percent)) + await self._embed_msg( + ctx, _("Vote percentage set to {percent}%.").format(percent=percent) + ) await self.config.guild(ctx.guild).vote_percent.set(percent) await self.config.guild(ctx.guild).vote_enabled.set(enabled) @@ -382,10 +395,12 @@ class Audio(commands.Cog): @checks.is_owner() @audioset.command() async def status(self, ctx): - """Enables/disables songs' titles as status.""" + """Enable/disable tracks' titles as status.""" status = await self.config.status() await self.config.status.set(not status) - await self._embed_msg(ctx, "Song titles as status: {}.".format(not status)) + await self._embed_msg( + ctx, _("Song titles as status: {true_or_false}.").format(true_or_false=not status) + ) @commands.command() @commands.guild_only() @@ -424,16 +439,16 @@ class Audio(commands.Cog): except AttributeError: server_list.append( "{} [`{}`]: **{}**".format( - p.channel.guild.name, connect_dur, "Nothing playing." + p.channel.guild.name, connect_dur, _("Nothing playing.") ) ) if server_num == 0: - servers = "Not connected anywhere." + servers = _("Not connected anywhere.") else: servers = "\n".join(server_list) embed = discord.Embed( colour=await ctx.embed_colour(), - title="Connected in {} servers:".format(server_num), + title=_("Connected in {num} servers:").format(num=server_num), description=servers, ) await ctx.send(embed=embed) @@ -441,21 +456,23 @@ class Audio(commands.Cog): @commands.command() @commands.guild_only() async def bump(self, ctx, index: int): - """Bump a song number to the top of the queue.""" + """Bump a track number to the top of the queue.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You must be in the voice channel to bump a song.") + return await self._embed_msg( + ctx, _("You must be in the voice channel to bump a track.") + ) if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to bump songs.") + return await self._embed_msg(ctx, _("You need the DJ role to bump tracks.")) if index > len(player.queue) or index < 1: return await self._embed_msg( - ctx, "Song number must be greater than 1 and within the queue limit." + ctx, _("Song number must be greater than 1 and within the queue limit.") ) bump_index = index - 1 @@ -469,7 +486,9 @@ class Audio(commands.Cog): removed_title = "{} - {}".format(removed.author, removed.title) else: removed_title = removed.title - await self._embed_msg(ctx, "Moved {} to the top of the queue.".format(removed_title)) + await self._embed_msg( + ctx, _("Moved {track} to the top of the queue.").format(track=removed_title) + ) @commands.command(aliases=["dc"]) @commands.guild_only() @@ -642,12 +661,12 @@ class Audio(commands.Cog): else: return True - @commands.command(aliases=["np", "n", "song"]) + @commands.command(aliases=["np", "n", "song", "track"]) @commands.guild_only() async def now(self, ctx): """Now playing.""" if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) expected = ("⏮", "⏹", "⏸", "⏭") emoji = {"prev": "⏮", "stop": "⏹", "pause": "⏸", "next": "⏭"} player = lavalink.get_player(ctx.guild.id) @@ -660,34 +679,22 @@ class Audio(commands.Cog): dur = lavalink.utils.format_time(player.current.length) if "localtracks" in player.current.uri: if not player.current.title == "Unknown title": - song = "**{} - {}**\n{}\nRequested by: **{}**\n\n{}`{}`/`{}`".format( - player.current.author, - player.current.title, - player.current.uri.replace("localtracks/", ""), - player.current.requester, - arrow, - pos, - dur, - ) + song = "**{track.author} - {track.title}**\n{uri}\n" else: - song = "{}\nRequested by: **{}**\n\n{}`{}`/`{}`".format( - player.current.uri.replace("localtracks/", ""), - player.current.requester, - arrow, - pos, - dur, - ) + song = "{uri}\n" else: - song = "**[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`".format( - player.current.title, - player.current.uri, - player.current.requester, - arrow, - pos, - dur, - ) + song = "**[{track.title}]({track.uri})**\n" + song += _("Requested by: **{track.requester}**") + song += "\n\n{arrow}`{pos}`/`{dur}`" + song = song.format( + track=player.current, + uri=player.current.uri.replace("localtracks/", ""), + arrow=arrow, + pos=pos, + dur=dur, + ) else: - song = "Nothing." + song = _("Nothing.") if player.fetch("np_message") is not None: try: @@ -696,7 +703,7 @@ class Audio(commands.Cog): pass embed = discord.Embed( - colour=await ctx.embed_colour(), title="Now Playing", description=song + colour=await ctx.embed_colour(), title=_("Now Playing"), description=song ) if await self.config.guild(ctx.guild).thumbnail() and player.current: if player.current.thumbnail: @@ -749,19 +756,19 @@ class Audio(commands.Cog): """Pause and resume.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to pause the music." + ctx, _("You must be in the voice channel to pause the music.") ) if dj_enabled: if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone( ctx, ctx.author ): - return await self._embed_msg(ctx, "You need the DJ role to pause songs.") + return await self._embed_msg(ctx, _("You need the DJ role to pause tracks.")) command = ctx.invoked_with if not player.current: @@ -775,29 +782,29 @@ class Audio(commands.Cog): if player.current and not player.paused and command != "resume": await player.pause() embed = discord.Embed( - colour=await ctx.embed_colour(), title="Track Paused", description=description + colour=await ctx.embed_colour(), title=_("Track Paused"), description=description ) return await ctx.send(embed=embed) if player.paused and command != "pause": await player.pause(False) embed = discord.Embed( - colour=await ctx.embed_colour(), title="Track Resumed", description=description + colour=await ctx.embed_colour(), title=_("Track Resumed"), description=description ) return await ctx.send(embed=embed) if player.paused and command == "pause": - return await self._embed_msg(ctx, "Track is paused.") + return await self._embed_msg(ctx, _("Track is paused.")) if player.current and command == "resume": - return await self._embed_msg(ctx, "Track is playing.") - await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Track is playing.")) + await self._embed_msg(ctx, _("Nothing playing.")) @commands.command() @commands.guild_only() async def percent(self, ctx): """Queue percentage.""" if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) queue_tracks = player.queue requesters = {"total": 0, "users": {}} @@ -821,7 +828,7 @@ class Audio(commands.Cog): ) await _usercount(req_username) except AttributeError: - return await self._embed_msg(ctx, "Nothing in the queue.") + return await self._embed_msg(ctx, _("Nothing in the queue.")) for req_username in requesters["users"]: percentage = float(requesters["users"][req_username]["songcount"]) / float( @@ -843,7 +850,7 @@ class Audio(commands.Cog): queue_user_list = "\n".join(queue_user) embed = discord.Embed( colour=await ctx.embed_colour(), - title="Queued and playing songs:", + title=_("Queued and playing tracks:"), description=queue_user_list, ) await ctx.send(embed=embed) @@ -851,7 +858,7 @@ class Audio(commands.Cog): @commands.command() @commands.guild_only() async def play(self, ctx, *, query): - """Play a URL or search for a song.""" + """Play a URL or search for a track.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() jukebox_price = await self.config.guild(ctx.guild).jukebox_price() shuffle = await self.config.guild(ctx.guild).shuffle() @@ -861,16 +868,16 @@ class Audio(commands.Cog): ctx.author.voice.channel ): return await self._embed_msg( - ctx, "I don't have permission to connect to your channel." + ctx, _("I don't have permission to connect to your channel.") ) await lavalink.connect(ctx.author.voice.channel) player = lavalink.get_player(ctx.guild.id) player.store("connect", datetime.datetime.utcnow()) except AttributeError: - return await self._embed_msg(ctx, "Connect to a voice channel first.") + return await self._embed_msg(ctx, _("Connect to a voice channel first.")) if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to queue songs.") + return await self._embed_msg(ctx, _("You need the DJ role to queue tracks.")) player = lavalink.get_player(ctx.guild.id) player.store("channel", ctx.channel.id) player.store("guild", ctx.guild.id) @@ -879,13 +886,13 @@ class Audio(commands.Cog): not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to use the play command." + ctx, _("You must be in the voice channel to use the play command.") ) if not await self._currency_check(ctx, jukebox_price): return if not query: - return await self._embed_msg(ctx, "No songs to play.") + return await self._embed_msg(ctx, _("No tracks to play.")) query = query.strip("<>") if query.startswith("localtrack:"): @@ -899,7 +906,7 @@ class Audio(commands.Cog): tracks = await player.get_tracks(query) if not tracks: - return await self._embed_msg(ctx, "Nothing found.") + return await self._embed_msg(ctx, _("Nothing found.")) queue_duration = await self._queue_duration(ctx) queue_total_duration = lavalink.utils.format_time(queue_duration) @@ -910,14 +917,14 @@ class Audio(commands.Cog): player.add(ctx.author, track) embed = discord.Embed( colour=await ctx.embed_colour(), - title="Playlist Enqueued", - description="Added {} tracks to the queue.".format(len(tracks)), + title=_("Playlist Enqueued"), + description=_("Added {num} tracks to the queue.").format(num=len(tracks)), ) if not shuffle and queue_duration > 0: embed.set_footer( - text="{} until start of playlist playback: starts at #{} in queue".format( - queue_total_duration, before_queue_length + 1 - ) + text=_( + "{time} until start of playlist playback: starts at #{position} in queue" + ).format(time=queue_total_duration, position=before_queue_length + 1) ) if not player.current: await player.play() @@ -937,16 +944,16 @@ class Audio(commands.Cog): else: description = "**[{}]({})**".format(single_track.title, single_track.uri) embed = discord.Embed( - colour=await ctx.embed_colour(), title="Track Enqueued", description=description + colour=await ctx.embed_colour(), title=_("Track Enqueued"), description=description ) if not shuffle and queue_duration > 0: embed.set_footer( - text="{} until track playback: #{} in queue".format( - queue_total_duration, before_queue_length + 1 + text=_("{time} until track playback: #{position} in queue").format( + time=queue_total_duration, position=before_queue_length + 1 ) ) elif queue_duration > 0: - embed.set_footer(text="#{} in queue".format(len(player.queue))) + embed.set_footer(text=_("#{position} in queue").format(position=len(player.queue))) if not player.current: await player.play() await ctx.send(embed=embed) @@ -959,7 +966,10 @@ class Audio(commands.Cog): @playlist.command(name="append") async def _playlist_append(self, ctx, playlist_name, *url): - """Add a song URL, playlist link, or quick search to the end of a saved playlist.""" + """Add a track URL, playlist link, or quick search to a playlist. + + The track(s) will be appended to the end of the playlist. + """ if not await self._playlist_check(ctx): return async with self.config.guild(ctx.guild).playlists() as playlists: @@ -967,7 +977,9 @@ class Audio(commands.Cog): if playlists[playlist_name][ "author" ] != ctx.author.id and not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You are not the author of that playlist.") + return await self._embed_msg( + ctx, _("You are not the author of that playlist.") + ) player = lavalink.get_player(ctx.guild.id) to_append = await self._playlist_tracks(ctx, player, url) if not to_append: @@ -983,16 +995,22 @@ class Audio(commands.Cog): else: playlists[playlist_name]["tracks"] = to_append except KeyError: - return await self._embed_msg(ctx, "No playlist with that name.") + return await self._embed_msg(ctx, _("No playlist with that name.")) if playlists[playlist_name]["playlist_url"] is not None: playlists[playlist_name]["playlist_url"] = None if len(to_append) == 1: track_title = to_append[0]["info"]["title"] return await self._embed_msg( - ctx, "{} appended to {}.".format(track_title, playlist_name) + ctx, + _("{track} appended to {playlist}.").format( + track=track_title, playlist=playlist_name + ), ) await self._embed_msg( - ctx, "{} tracks appended to {}.".format(len(to_append), playlist_name) + ctx, + _("{num} tracks appended to {playlist}.").format( + num=len(to_append), playlist=playlist_name + ), ) @playlist.command(name="create") @@ -1001,17 +1019,17 @@ class Audio(commands.Cog): dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to save playlists.") + return await self._embed_msg(ctx, _("You need the DJ role to save playlists.")) async with self.config.guild(ctx.guild).playlists() as playlists: if playlist_name in playlists: return await self._embed_msg( - ctx, "Playlist name already exists, try again with a different name." + ctx, _("Playlist name already exists, try again with a different name.") ) playlist_name = playlist_name.split(" ")[0].strip('"') playlist_list = self._to_json(ctx, None, None) async with self.config.guild(ctx.guild).playlists() as playlists: playlists[playlist_name] = playlist_list - await self._embed_msg(ctx, "Empty playlist {} created.".format(playlist_name)) + await self._embed_msg(ctx, _("Empty playlist {name} created.").format(name=playlist_name)) @playlist.command(name="delete") async def _playlist_delete(self, ctx, playlist_name): @@ -1021,11 +1039,13 @@ class Audio(commands.Cog): if playlists[playlist_name][ "author" ] != ctx.author.id and not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You are not the author of that playlist.") + return await self._embed_msg( + ctx, _("You are not the author of that playlist.") + ) del playlists[playlist_name] except KeyError: - return await self._embed_msg(ctx, "No playlist with that name.") - await self._embed_msg(ctx, "{} playlist deleted.".format(playlist_name)) + return await self._embed_msg(ctx, _("No playlist with that name.")) + await self._embed_msg(ctx, _("{name} playlist deleted.").format(name=playlist_name)) @playlist.command(name="info") async def _playlist_info(self, ctx, playlist_name): @@ -1034,7 +1054,7 @@ class Audio(commands.Cog): try: author_id = playlists[playlist_name]["author"] except KeyError: - return await self._embed_msg(ctx, "No playlist with that name.") + return await self._embed_msg(ctx, _("No playlist with that name.")) author_obj = self.bot.get_user(author_id) playlist_url = playlists[playlist_name]["playlist_url"] try: @@ -1042,15 +1062,17 @@ class Audio(commands.Cog): except TypeError: track_len = 0 if playlist_url is None: - playlist_url = "**Custom playlist.**" + playlist_url = _("**Custom playlist.**") else: - playlist_url = "URL: <{}>".format(playlist_url) + playlist_url = _("URL: <{url}>").format(url=playlist_url) embed = discord.Embed( colour=await ctx.embed_colour(), - title="Playlist info for {}:".format(playlist_name), - description="Author: **{}**\n{}".format(author_obj, playlist_url), + title=_("Playlist info for {playlist_name}:").format(playlist_name=playlist_name), + description=_("Author: **{author_name}**\n{url}").format( + author_name=author_obj, url=playlist_url + ), ) - embed.set_footer(text="{} track(s)".format(track_len)) + embed.set_footer(text=_("{num} track(s)").format(num=track_len)) await ctx.send(embed=embed) @playlist.command(name="list") @@ -1095,7 +1117,7 @@ class Audio(commands.Cog): plist += "`{}.` {}".format(item_idx, playlist_info) embed = discord.Embed( colour=await ctx.embed_colour(), - title="Playlists for {}:".format(ctx.guild.name), + title=_("Playlists for {server_name}:").format(server_name=ctx.guild.name), description=plist, ) embed.set_footer( @@ -1110,14 +1132,14 @@ class Audio(commands.Cog): dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to save playlists.") + return await self._embed_msg(ctx, _("You need the DJ role to save playlists.")) async with self.config.guild(ctx.guild).playlists() as playlists: if playlist_name in playlists: return await self._embed_msg( - ctx, "Playlist name already exists, try again with a different name." + ctx, _("Playlist name already exists, try again with a different name.") ) if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) tracklist = [] np_song = self._track_creator(player, "np") @@ -1127,7 +1149,7 @@ class Audio(commands.Cog): track_obj = self._track_creator(player, queue_idx) tracklist.append(track_obj) if not playlist_name: - await self._embed_msg(ctx, "Please enter a name for this playlist.") + await self._embed_msg(ctx, _("Please enter a name for this playlist.")) try: playlist_name_msg = await ctx.bot.wait_for( @@ -1137,56 +1159,63 @@ class Audio(commands.Cog): ) playlist_name = playlist_name_msg.content.split(" ")[0].strip('"') if len(playlist_name) > 20: - return await self._embed_msg(ctx, "Try the command again with a shorter name.") + return await self._embed_msg( + ctx, _("Try the command again with a shorter name.") + ) if playlist_name in playlists: return await self._embed_msg( - ctx, "Playlist name already exists, try again with a different name." + ctx, _("Playlist name already exists, try again with a different name.") ) except asyncio.TimeoutError: - return await self._embed_msg(ctx, "No playlist name entered, try again later.") + return await self._embed_msg(ctx, _("No playlist name entered, try again later.")) playlist_list = self._to_json(ctx, None, tracklist) async with self.config.guild(ctx.guild).playlists() as playlists: playlist_name = playlist_name.split(" ")[0].strip('"') playlists[playlist_name] = playlist_list await self._embed_msg( ctx, - "Playlist {} saved from current queue: {} tracks added.".format( - playlist_name.split(" ")[0].strip('"'), len(tracklist) + _("Playlist {name} saved from current queue: {num} tracks added.").format( + name=playlist_name.split(" ")[0].strip('"'), num=len(tracklist) ), ) @playlist.command(name="remove") async def _playlist_remove(self, ctx, playlist_name, url): - """Remove a song from a playlist by url.""" + """Remove a track from a playlist by url.""" async with self.config.guild(ctx.guild).playlists() as playlists: try: if playlists[playlist_name][ "author" ] != ctx.author.id and not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You are not the author of that playlist.") + return await self._embed_msg( + ctx, _("You are not the author of that playlist.") + ) except KeyError: - return await self._embed_msg(ctx, "No playlist with that name.") + return await self._embed_msg(ctx, _("No playlist with that name.")) track_list = playlists[playlist_name]["tracks"] clean_list = [track for track in track_list if not url == track["info"]["uri"]] if len(playlists[playlist_name]["tracks"]) == len(clean_list): - return await self._embed_msg(ctx, "URL not in playlist.") + return await self._embed_msg(ctx, _("URL not in playlist.")) del_count = len(playlists[playlist_name]["tracks"]) - len(clean_list) if not clean_list: del playlists[playlist_name] - return await self._embed_msg(ctx, "No songs left, removing playlist.") + return await self._embed_msg(ctx, _("No tracks left, removing playlist.")) playlists[playlist_name]["tracks"] = clean_list if playlists[playlist_name]["playlist_url"] is not None: playlists[playlist_name]["playlist_url"] = None if del_count > 1: await self._embed_msg( ctx, - "{} entries have been removed from the {} playlist.".format( - del_count, playlist_name + _("{num} entries have been removed from the {playlist_name} playlist.").format( + num=del_count, playlist_name=playlist_name ), ) else: await self._embed_msg( - ctx, "The track has been removed from the {} playlist.".format(playlist_name) + ctx, + _("The track has been removed from the {playlist_name} playlist.").format( + playlist_name=playlist_name + ), ) @playlist.command(name="save") @@ -1203,7 +1232,9 @@ class Audio(commands.Cog): playlists[playlist_name] = playlist_list return await self._embed_msg( ctx, - "Playlist {} saved: {} tracks added.".format(playlist_name, len(tracklist)), + _("Playlist {name} saved: {num} tracks added.").format( + name=playlist_name, num=len(tracklist) + ), ) @playlist.command(name="start") @@ -1221,8 +1252,8 @@ class Audio(commands.Cog): track_count = track_count + 1 embed = discord.Embed( colour=await ctx.embed_colour(), - title="Playlist Enqueued", - description="Added {} tracks to the queue.".format(track_count), + title=_("Playlist Enqueued"), + description=_("Added {num} tracks to the queue.").format(num=track_count), ) await ctx.send(embed=embed) if not player.current: @@ -1230,7 +1261,7 @@ class Audio(commands.Cog): except TypeError: await ctx.invoke(self.play, query=playlists[playlist_name]["playlist_url"]) except KeyError: - await self._embed_msg(ctx, "That playlist doesn't exist.") + await self._embed_msg(ctx, _("That playlist doesn't exist.")) @checks.is_owner() @playlist.command(name="upload") @@ -1240,7 +1271,8 @@ class Audio(commands.Cog): return player = lavalink.get_player(ctx.guild.id) await self._embed_msg( - ctx, "Please upload the playlist file. Any other message will cancel this operation." + ctx, + _("Please upload the playlist file. Any other message will cancel this operation."), ) try: @@ -1248,20 +1280,20 @@ class Audio(commands.Cog): "message", timeout=30.0, check=MessagePredicate.same_context(ctx) ) except asyncio.TimeoutError: - return await self._embed_msg(ctx, "No file detected, try again later.") + return await self._embed_msg(ctx, _("No file detected, try again later.")) try: file_url = file_message.attachments[0].url except IndexError: - return await self._embed_msg(ctx, "Upload canceled.") + return await self._embed_msg(ctx, _("Upload cancelled.")) v2_playlist_name = (file_url.split("/")[6]).split(".")[0] file_suffix = file_url.rsplit(".", 1)[1] if file_suffix != "txt": - return await self._embed_msg(ctx, "Only playlist files can be uploaded.") + return await self._embed_msg(ctx, _("Only playlist files can be uploaded.")) try: async with self.session.request("GET", file_url) as r: v2_playlist = await r.json(content_type="text/plain") except UnicodeDecodeError: - return await self._embed_msg(ctx, "Not a valid playlist file.") + return await self._embed_msg(ctx, _("Not a valid playlist file.")) try: v2_playlist_url = v2_playlist["link"] except KeyError: @@ -1277,12 +1309,12 @@ class Audio(commands.Cog): try: if v3_playlists[v2_playlist_name]: return await self._embed_msg( - ctx, "A playlist already exists with this name." + ctx, _("A playlist already exists with this name.") ) except KeyError: pass embed1 = discord.Embed( - colour=await ctx.embed_colour(), title="Please wait, adding tracks..." + colour=await ctx.embed_colour(), title=_("Please wait, adding tracks...") ) playlist_msg = await ctx.send(embed=embed1) for song_url in v2_playlist["playlist"]: @@ -1296,26 +1328,28 @@ class Audio(commands.Cog): if track_count % 5 == 0: embed2 = discord.Embed( colour=await ctx.embed_colour(), - title="Loading track {}/{}...".format( - track_count, len(v2_playlist["playlist"]) + title=_("Loading track {num}/{total}...").format( + num=track_count, total=len(v2_playlist["playlist"]) ), ) await playlist_msg.edit(embed=embed2) if not track_list: - return await self._embed_msg(ctx, "No tracks found.") + return await self._embed_msg(ctx, _("No tracks found.")) playlist_list = self._to_json(ctx, v2_playlist_url, track_list) async with self.config.guild(ctx.guild).playlists() as v3_playlists: v3_playlists[v2_playlist_name] = playlist_list if len(v2_playlist["playlist"]) != track_count: bad_tracks = len(v2_playlist["playlist"]) - track_count - msg = ( - "Added {} tracks from the {} playlist. {} track(s) could not " - "be loaded.".format(track_count, v2_playlist_name, bad_tracks) - ) + msg = _( + "Added {num} tracks from the {playlist_name} playlist. {num_bad} track(s) " + "could not be loaded." + ).format(num=track_count, playlist_name=v2_playlist_name, num_bad=bad_tracks) else: - msg = "Added {} tracks from the {} playlist.".format(track_count, v2_playlist_name) + msg = _("Added {num} tracks from the {playlist_name} playlist.").format( + num=track_count, playlist_name=v2_playlist_name + ) embed3 = discord.Embed( - colour=await ctx.embed_colour(), title="Playlist Saved", description=msg + colour=await ctx.embed_colour(), title=_("Playlist Saved"), description=msg ) await playlist_msg.edit(embed=embed3) else: @@ -1326,7 +1360,7 @@ class Audio(commands.Cog): jukebox_price = await self.config.guild(ctx.guild).jukebox_price() if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - await self._embed_msg(ctx, "You need the DJ role to use playlists.") + await self._embed_msg(ctx, _("You need the DJ role to use playlists.")) return False if not self._player_check(ctx): try: @@ -1334,13 +1368,13 @@ class Audio(commands.Cog): ctx.author.voice.channel ): return await self._embed_msg( - ctx, "I don't have permission to connect to your channel." + ctx, _("I don't have permission to connect to your channel.") ) await lavalink.connect(ctx.author.voice.channel) player = lavalink.get_player(ctx.guild.id) player.store("connect", datetime.datetime.utcnow()) except AttributeError: - await self._embed_msg(ctx, "Connect to a voice channel first.") + await self._embed_msg(ctx, _("Connect to a voice channel first.")) return False player = lavalink.get_player(ctx.guild.id) player.store("channel", ctx.channel.id) @@ -1349,7 +1383,7 @@ class Audio(commands.Cog): not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): await self._embed_msg( - ctx, "You must be in the voice channel to use the playlist command." + ctx, _("You must be in the voice channel to use the playlist command.") ) return False if not await self._currency_check(ctx, jukebox_price): @@ -1367,7 +1401,7 @@ class Audio(commands.Cog): search = True tracks = await player.get_tracks(query) if not tracks: - return await self._embed_msg(ctx, "Nothing found.") + return await self._embed_msg(ctx, _("Nothing found.")) tracklist = [] if not search: for track in tracks: @@ -1381,9 +1415,9 @@ class Audio(commands.Cog): @commands.command() @commands.guild_only() async def prev(self, ctx): - """Skips to the start of the previously played track.""" + """Skip to the start of the previously played track.""" if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) dj_enabled = await self.config.guild(ctx.guild).dj_enabled() player = lavalink.get_player(ctx.guild.id) shuffle = await self.config.guild(ctx.guild).shuffle() @@ -1391,17 +1425,17 @@ class Audio(commands.Cog): if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone( ctx, ctx.author ): - return await self._embed_msg(ctx, "You need the DJ role to skip songs.") + return await self._embed_msg(ctx, _("You need the DJ role to skip tracks.")) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to skip the music." + ctx, _("You must be in the voice channel to skip the music.") ) if shuffle: - return await self._embed_msg(ctx, "Turn shuffle off to use this command.") + return await self._embed_msg(ctx, _("Turn shuffle off to use this command.")) if player.fetch("prev_song") is None: - return await self._embed_msg(ctx, "No previous track.") + return await self._embed_msg(ctx, _("No previous track.")) else: last_track = await player.get_tracks(player.fetch("prev_song")) player.add(player.fetch("prev_requester"), last_track[0]) @@ -1417,21 +1451,21 @@ class Audio(commands.Cog): else: description = "**[{}]({})**".format(player.current.title, player.current.uri) embed = discord.Embed( - colour=await ctx.embed_colour(), title="Replaying Track", description=description + colour=await ctx.embed_colour(), title=_("Replaying Track"), description=description ) await ctx.send(embed=embed) @commands.command(aliases=["q"]) @commands.guild_only() async def queue(self, ctx, *, page="1"): - """Lists the queue. + """List the queue. Use [p]queue search to search the queue.""" if not self._player_check(ctx): - return await self._embed_msg(ctx, "There's nothing in the queue.") + return await self._embed_msg(ctx, _("There's nothing in the queue.")) player = lavalink.get_player(ctx.guild.id) if not player.queue: - return await self._embed_msg(ctx, "There's nothing in the queue.") + return await self._embed_msg(ctx, _("There's nothing in the queue.")) if not page.isdigit(): if page.startswith("search "): return await self._queue_search(ctx=ctx, search_words=page.replace("search ", "")) @@ -1458,7 +1492,7 @@ class Audio(commands.Cog): try: arrow = await self._draw_time(ctx) except AttributeError: - return await self._embed_msg(ctx, "There's nothing in the queue.") + return await self._embed_msg(ctx, _("There's nothing in the queue.")) pos = lavalink.utils.format_time(player.position) if player.current.is_stream: @@ -1467,9 +1501,7 @@ class Audio(commands.Cog): dur = lavalink.utils.format_time(player.current.length) if player.current.is_stream: - queue_list += "**Currently livestreaming:** **[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n".format( - player.current.title, player.current.uri, player.current.requester, arrow, pos, dur - ) + queue_list += _("**Currently livestreaming:**") elif "localtracks" in player.current.uri: if not player.current.title == "Unknown title": @@ -1491,9 +1523,10 @@ class Audio(commands.Cog): dur, ) else: - queue_list += "Playing: **[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n".format( - player.current.title, player.current.uri, player.current.requester, arrow, pos, dur - ) + queue_list += _("Playing:") + queue_list += " **[{current.title}]({current.uri})**\n".format(current=player.current) + queue_list += _("Requested by: **{user}**").format(user=player.current.requester) + queue_list += "\n\n{arrow}`{pos}`/`{dur}`\n\n".format(arrow=arrow, pos=pos, dur=dur) for i, track in enumerate( player.queue[queue_idx_start:queue_idx_end], start=queue_idx_start @@ -1515,9 +1548,10 @@ class Audio(commands.Cog): track_idx, track.author, track_title, req_user ) else: - queue_list += "`{}.` **[{}]({})**, requested by **{}**\n".format( - track_idx, track_title, track.uri, req_user - ) + queue_list += "`{idx}.` **[{title}]({uri})**, ".format( + idx=track_idx, title=track_title, uri=track.uri + ) + queue_list += _("requested by **{user}**\n").format(user=req_user) embed = discord.Embed( colour=await ctx.embed_colour(), @@ -1528,13 +1562,18 @@ class Audio(commands.Cog): embed.set_thumbnail(url=player.current.thumbnail) queue_duration = await self._queue_duration(ctx) queue_total_duration = lavalink.utils.format_time(queue_duration) - text = "Page {}/{} | {} tracks, {} remaining".format( - page_num, queue_num_pages, len(player.queue) + 1, queue_total_duration + text = _( + "Page {page_num}/{total_pages} | {num_tracks} tracks, {num_remaining} remaining" + ).format( + page_num=page_num, + total_pages=queue_num_pages, + num_tracks=len(player.queue) + 1, + num_remaining=queue_total_duration, ) if repeat: - text += " | Repeat: \N{WHITE HEAVY CHECK MARK}" + text += " | " + _("Repeat") + ": \N{WHITE HEAVY CHECK MARK}" if shuffle: - text += " | Shuffle: \N{WHITE HEAVY CHECK MARK}" + text += " | " + _("Shuffle") + ": \N{WHITE HEAVY CHECK MARK}" embed.set_footer(text=text) return embed @@ -1601,13 +1640,13 @@ class Audio(commands.Cog): @commands.command() @commands.guild_only() async def repeat(self, ctx): - """Toggles repeat.""" + """Toggle repeat.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if dj_enabled: if not await self._can_instaskip(ctx, ctx.author) and not await self._has_dj_role( ctx, ctx.author ): - return await self._embed_msg(ctx, "You need the DJ role to toggle repeat.") + return await self._embed_msg(ctx, _("You need the DJ role to toggle repeat.")) repeat = await self.config.guild(ctx.guild).repeat() await self.config.guild(ctx.guild).repeat.set(not repeat) repeat = await self.config.guild(ctx.guild).repeat() @@ -1618,32 +1657,34 @@ class Audio(commands.Cog): not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to toggle repeat." + ctx, _("You must be in the voice channel to toggle repeat.") ) - await self._embed_msg(ctx, "Repeat songs: {}.".format(repeat)) + await self._embed_msg( + ctx, _("Repeat tracks: {true_or_false}.").format(true_or_false=repeat) + ) @commands.command() @commands.guild_only() async def remove(self, ctx, index: int): - """Remove a specific song number from the queue.""" + """Remove a specific track number from the queue.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) if not player.queue: - return await self._embed_msg(ctx, "Nothing queued.") + return await self._embed_msg(ctx, _("Nothing queued.")) if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to remove songs.") + return await self._embed_msg(ctx, _("You need the DJ role to remove tracks.")) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to manage the queue." + ctx, _("You must be in the voice channel to manage the queue.") ) if index > len(player.queue) or index < 1: return await self._embed_msg( - ctx, "Song number must be greater than 1 and within the queue limit." + ctx, _("Song number must be greater than 1 and within the queue limit.") ) index -= 1 removed = player.queue.pop(index) @@ -1654,14 +1695,17 @@ class Audio(commands.Cog): removed_title = "{} - {}".format(removed.author, removed.title) else: removed_title = removed.title - await self._embed_msg(ctx, "Removed {} from the queue.".format(removed_title)) + await self._embed_msg( + ctx, _("Removed {track} from the queue.").format(track=removed_title) + ) @commands.command() @commands.guild_only() async def search(self, ctx, *, query): - """Pick a song with a search. - Use [p]search list to queue all songs found on YouTube. - [p]search sc will search SoundCloud instead of YouTube. + """Pick a track with a search. + + Use `[p]search list ` to queue all tracks found on YouTube. + `[p]search sc ` will search SoundCloud instead of YouTube. """ async def _search_menu( @@ -1695,13 +1739,13 @@ class Audio(commands.Cog): ctx.author.voice.channel ): return await self._embed_msg( - ctx, "I don't have permission to connect to your channel." + ctx, _("I don't have permission to connect to your channel.") ) await lavalink.connect(ctx.author.voice.channel) player = lavalink.get_player(ctx.guild.id) player.store("connect", datetime.datetime.utcnow()) except AttributeError: - return await self._embed_msg(ctx, "Connect to a voice channel first.") + return await self._embed_msg(ctx, _("Connect to a voice channel first.")) player = lavalink.get_player(ctx.guild.id) shuffle = await self.config.guild(ctx.guild).shuffle() player.store("channel", ctx.channel.id) @@ -1709,7 +1753,9 @@ class Audio(commands.Cog): if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You must be in the voice channel to enqueue songs.") + return await self._embed_msg( + ctx, _("You must be in the voice channel to enqueue tracks.") + ) await self._data_check(ctx) if not isinstance(query, list): @@ -1722,17 +1768,17 @@ class Audio(commands.Cog): query = query.replace("folder:", "") tracks = await self._folder_tracks(ctx, player, query) if not tracks: - return await self._embed_msg(ctx, "Nothing found.") + return await self._embed_msg(ctx, _("Nothing found.")) songembed = discord.Embed( colour=await ctx.embed_colour(), - title="Queued {} track(s).".format(len(tracks)), + title=_("Queued {num} track(s).").format(num=len(tracks)), ) queue_duration = await self._queue_duration(ctx) queue_total_duration = lavalink.utils.format_time(queue_duration) if not shuffle and queue_duration > 0: songembed.set_footer( - text="{} until start of search playback: starts at #{} in queue".format( - queue_total_duration, (len(player.queue) + 1) + text=_("{time} until start of search playback: starts at #{position} in queue").format( + time=queue_total_duration, position=len(player.queue) + 1 ) ) for track in tracks: @@ -1759,7 +1805,7 @@ class Audio(commands.Cog): else: tracks = await player.get_tracks(query) if not tracks: - return await self._embed_msg(ctx, "Nothing found.") + return await self._embed_msg(ctx, _("Nothing found.")) else: tracks = query @@ -1829,18 +1875,20 @@ class Audio(commands.Cog): return await ctx.invoke(self.play, query=("localtrack:{}".format(search_choice))) embed = discord.Embed( - colour=await ctx.embed_colour(), title="Track Enqueued", description=description + colour=await ctx.embed_colour(), title=_("Track Enqueued"), description=description ) queue_duration = await self._queue_duration(ctx) queue_total_duration = lavalink.utils.format_time(queue_duration) if not shuffle and queue_duration > 0: embed.set_footer( - text="{} until track playback: #{} in queue".format( - queue_total_duration, (len(player.queue) + 1) + text=_("{time} until track playback: #{position} in queue").format( + time=queue_total_duration, position=len(player.queue) + 1 + ) + ) + elif queue_duration > 0: + embed.set_footer( + text=_("#{position} in queue").format(position=len(player.queue) + 1) ) - ) - elif queue_duration > 0: - embed.set_footer(text="#{} in queue".format(len(player.queue) + 1)) player.add(ctx.author, search_choice) if not player.current: @@ -1888,64 +1936,76 @@ class Audio(commands.Cog): folder = False try: title_check = tracks[0].uri - title = "Tracks Found:" - footer = "search results" + title = _("Tracks Found:") + footer = _("search results") except AttributeError: if folder: - title = "Folders Found:" - footer = "local folders" + title = _("Folders Found:") + footer = _("local folders") else: - title = "Files Found:" - footer = "local tracks" + title = _("Files Found:") + footer = _("local tracks") embed = discord.Embed( colour=await ctx.embed_colour(), title=title, description=search_list ) embed.set_footer( - text="Page {}/{} | {} {}".format(page_num, search_num_pages, len(tracks), footer) + text=( + _("Page {page_num}/{total_pages}") + " | {num_results} {footer}" + ).format( + page_num=page_num, + total_pages=search_num_pages, + num_results=len(tracks), + footer=footer + ) ) return embed @commands.command() @commands.guild_only() async def seek(self, ctx, seconds: int = 30): - """Seeks ahead or behind on a track by seconds.""" + """Seek ahead or behind on a track by seconds.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You must be in the voice channel to use seek.") + return await self._embed_msg(ctx, _("You must be in the voice channel to use seek.")) if dj_enabled: if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone( ctx, ctx.author ): - return await self._embed_msg(ctx, "You need the DJ role to use seek.") + return await self._embed_msg(ctx, _("You need the DJ role to use seek.")) if player.current: if player.current.is_stream: - return await self._embed_msg(ctx, "Can't seek on a stream.") + return await self._embed_msg(ctx, _("Can't seek on a stream.")) else: time_sec = seconds * 1000 seek = player.position + time_sec if seek <= 0: - await self._embed_msg(ctx, "Moved {}s to 00:00:00".format(seconds)) + await self._embed_msg( + ctx, _("Moved {num_seconds}s to 00:00:00").format(num_seconds=seconds) + ) else: await self._embed_msg( - ctx, "Moved {}s to {}".format(seconds, lavalink.utils.format_time(seek)) + ctx, + _("Moved {num_seconds}s to {time}").format( + num_seconds=seconds, time=lavalink.utils.format_time(seek) + ), ) return await player.seek(seek) else: - await self._embed_msg(ctx, "Nothing playing.") + await self._embed_msg(ctx, _("Nothing playing.")) @commands.command() @commands.guild_only() async def shuffle(self, ctx): - """Toggles shuffle.""" + """Toggle shuffle.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if dj_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to toggle shuffle.") + return await self._embed_msg(ctx, _("You need the DJ role to toggle shuffle.")) shuffle = await self.config.guild(ctx.guild).shuffle() await self.config.guild(ctx.guild).shuffle.set(not shuffle) shuffle = await self.config.guild(ctx.guild).shuffle() @@ -1956,9 +2016,11 @@ class Audio(commands.Cog): not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to toggle shuffle." + ctx, _("You must be in the voice channel to toggle shuffle.") ) - await self._embed_msg(ctx, "Shuffle songs: {}.".format(shuffle)) + await self._embed_msg( + ctx, _("Shuffle tracks: {true_or_false}.").format(true_or_false=shuffle) + ) @commands.command() @commands.guild_only() @@ -1980,27 +2042,27 @@ class Audio(commands.Cog): async def skip(self, ctx): """Skips to the next track.""" if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to skip the music." + ctx, _("You must be in the voice channel to skip the music.") ) dj_enabled = await self.config.guild(ctx.guild).dj_enabled() vote_enabled = await self.config.guild(ctx.guild).vote_enabled() if dj_enabled and not vote_enabled and not await self._can_instaskip(ctx, ctx.author): if not await self._is_alone(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to skip songs.") + return await self._embed_msg(ctx, _("You need the DJ role to skip tracks.")) if vote_enabled: if not await self._can_instaskip(ctx, ctx.author): if ctx.author.id in self.skip_votes[ctx.message.guild]: self.skip_votes[ctx.message.guild].remove(ctx.author.id) - reply = "I removed your vote to skip." + reply = _("I removed your vote to skip.") else: self.skip_votes[ctx.message.guild].append(ctx.author.id) - reply = "You voted to skip." + reply = _("You voted to skip.") num_votes = len(self.skip_votes[ctx.message.guild]) vote_mods = [] @@ -2013,11 +2075,15 @@ class Audio(commands.Cog): percent = await self.config.guild(ctx.guild).vote_percent() if vote >= percent: self.skip_votes[ctx.message.guild] = [] - await self._embed_msg(ctx, "Vote threshold met.") + await self._embed_msg(ctx, _("Vote threshold met.")) return await self._skip_action(ctx) else: - reply += " Votes: %d/%d" % (num_votes, num_members) - reply += " (%d%% out of %d%% needed)" % (vote, percent) + reply += _(" Votes: {num_votes}/{num_members}").format( + num_votes=num_votes, num_members=num_members + ) + reply += _(" ({cur_percent}% out of {required_percent}% needed)").format( + cur_percent=vote, required_percent=percent + ) return await self._embed_msg(ctx, reply) else: return await self._skip_action(ctx) @@ -2085,18 +2151,24 @@ class Audio(commands.Cog): try: pos, dur = player.position, player.current.length except AttributeError: - return await self._embed_msg(ctx, "There's nothing in the queue.") + return await self._embed_msg(ctx, _("There's nothing in the queue.")) time_remain = lavalink.utils.format_time(dur - pos) if player.current.is_stream: embed = discord.Embed( - colour=await ctx.embed_colour(), title="There's nothing in the queue." + colour=await ctx.embed_colour(), title=_("There's nothing in the queue.") + ) + embed.set_footer( + text=_("Currently livestreaming {track}").format(track=player.current.title) ) - embed.set_footer(text="Currently livestreaming {}".format(player.current.title)) else: embed = discord.Embed( - colour=await ctx.embed_colour(), title="There's nothing in the queue." + colour=await ctx.embed_colour(), title=_("There's nothing in the queue.") + ) + embed.set_footer( + text=_("{time} left on {track}").format( + time=time_remain, track=player.current.title + ) ) - embed.set_footer(text="{} left on {}".format(time_remain, player.current.title)) return await ctx.send(embed=embed) if "localtracks" in player.current.uri: @@ -2111,7 +2183,7 @@ class Audio(commands.Cog): else: description = "**[{}]({})**".format(player.current.title, player.current.uri) embed = discord.Embed( - colour=await ctx.embed_colour(), title="Track Skipped", description=description + colour=await ctx.embed_colour(), title=_("Track Skipped"), description=description ) await ctx.send(embed=embed) await player.skip() @@ -2119,30 +2191,30 @@ class Audio(commands.Cog): @commands.command(aliases=["s"]) @commands.guild_only() async def stop(self, ctx): - """Stops playback and clears the queue.""" + """Stop playback and clear the queue.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() vote_enabled = await self.config.guild(ctx.guild).vote_enabled() if not self._player_check(ctx): - return await self._embed_msg(ctx, "Nothing playing.") + return await self._embed_msg(ctx, _("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) if ( not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to stop the music." + ctx, _("You must be in the voice channel to stop the music.") ) if vote_enabled or vote_enabled and dj_enabled: if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone( ctx, ctx.author ): return await self._embed_msg( - ctx, "There are other people listening - vote to skip instead." + ctx, _("There are other people listening - vote to skip instead.") ) if dj_enabled and not vote_enabled: if not await self._can_instaskip(ctx, ctx.author): - return await self._embed_msg(ctx, "You need the DJ role to stop the music.") + return await self._embed_msg(ctx, _("You need the DJ role to stop the music.")) if player.is_playing: - await self._embed_msg(ctx, "Stopping...") + await self._embed_msg(ctx, _("Stopping...")) await player.stop() player.store("prev_requester", None) player.store("prev_song", None) @@ -2152,17 +2224,17 @@ class Audio(commands.Cog): @commands.command() @commands.guild_only() async def volume(self, ctx, vol: int = None): - """Sets the volume, 1% - 150%.""" + """Set the volume, 1% - 150%.""" dj_enabled = await self.config.guild(ctx.guild).dj_enabled() if not vol: vol = await self.config.guild(ctx.guild).volume() embed = discord.Embed( colour=await ctx.embed_colour(), - title="Current Volume:", + title=_("Current Volume:"), description=str(vol) + "%", ) if not self._player_check(ctx): - embed.set_footer(text="Nothing playing.") + embed.set_footer(text=_("Nothing playing.")) return await ctx.send(embed=embed) if self._player_check(ctx): player = lavalink.get_player(ctx.guild.id) @@ -2170,13 +2242,13 @@ class Audio(commands.Cog): not ctx.author.voice or ctx.author.voice.channel != player.channel ) and not await self._can_instaskip(ctx, ctx.author): return await self._embed_msg( - ctx, "You must be in the voice channel to change the volume." + ctx, _("You must be in the voice channel to change the volume.") ) if dj_enabled: if not await self._can_instaskip(ctx, ctx.author) and not await self._has_dj_role( ctx, ctx.author ): - return await self._embed_msg(ctx, "You need the DJ role to change the volume.") + return await self._embed_msg(ctx, _("You need the DJ role to change the volume.")) if vol < 0: vol = 0 if vol > 150: @@ -2189,10 +2261,10 @@ class Audio(commands.Cog): if self._player_check(ctx): await lavalink.get_player(ctx.guild.id).set_volume(vol) embed = discord.Embed( - colour=await ctx.embed_colour(), title="Volume:", description=str(vol) + "%" + colour=await ctx.embed_colour(), title=_("Volume:"), description=str(vol) + "%" ) if not self._player_check(ctx): - embed.set_footer(text="Nothing playing.") + embed.set_footer(text=_("Nothing playing.")) await ctx.send(embed=embed) @commands.group(aliases=["llset"]) @@ -2204,7 +2276,7 @@ class Audio(commands.Cog): @llsetup.command() async def external(self, ctx): - """Toggles using external lavalink servers.""" + """Toggle using external lavalink servers.""" external = await self.config.use_external_lavalink() await self.config.use_external_lavalink.set(not external) if external: @@ -2214,12 +2286,17 @@ class Audio(commands.Cog): await self.config.ws_port.set(2332) embed = discord.Embed( colour=await ctx.embed_colour(), - title="External lavalink server: {}.".format(not external), + title=_("External lavalink server: {true_or_false}.").format( + true_or_false=not external + ), ) - embed.set_footer(text="Defaults reset.") + embed.set_footer(text=_("Defaults reset.")) return await ctx.send(embed=embed) else: - await self._embed_msg(ctx, "External lavalink server: {}.".format(not external)) + await self._embed_msg( + ctx, + _("External lavalink server: {true_or_false}.").format(true_or_false=not external), + ) @llsetup.command() async def host(self, ctx, host): @@ -2227,12 +2304,13 @@ class Audio(commands.Cog): await self.config.host.set(host) if await self._check_external(): embed = discord.Embed( - colour=await ctx.embed_colour(), title="Host set to {}.".format(host) + colour=await ctx.embed_colour(), + title=_("Host set to {host}.").format(host=host), ) - embed.set_footer(text="External lavalink server set to True.") + embed.set_footer(text=_("External lavalink server set to True.")) await ctx.send(embed=embed) else: - await self._embed_msg(ctx, "Host set to {}.".format(host)) + await self._embed_msg(ctx, _("Host set to {host}.").format(host=host)) @llsetup.command() async def password(self, ctx, password): @@ -2241,12 +2319,14 @@ class Audio(commands.Cog): if await self._check_external(): embed = discord.Embed( colour=await ctx.embed_colour(), - title="Server password set to {}.".format(password), + title=_("Server password set to {password}.").format(password=password), ) - embed.set_footer(text="External lavalink server set to True.") + embed.set_footer(text=_("External lavalink server set to True.")) await ctx.send(embed=embed) else: - await self._embed_msg(ctx, "Server password set to {}.".format(password)) + await self._embed_msg( + ctx, _("Server password set to {password}.").format(password=password) + ) @llsetup.command() async def restport(self, ctx, rest_port: int): @@ -2254,12 +2334,13 @@ class Audio(commands.Cog): await self.config.rest_port.set(rest_port) if await self._check_external(): embed = discord.Embed( - colour=await ctx.embed_colour(), title="REST port set to {}.".format(rest_port) + colour=await ctx.embed_colour(), + title=_("REST port set to {port}.").format(port=rest_port), ) - embed.set_footer(text="External lavalink server set to True.") + embed.set_footer(text=_("External lavalink server set to True.")) await ctx.send(embed=embed) else: - await self._embed_msg(ctx, "REST port set to {}.".format(rest_port)) + await self._embed_msg(ctx, _("REST port set to {port}.").format(port=rest_port)) @llsetup.command() async def wsport(self, ctx, ws_port: int): @@ -2267,12 +2348,12 @@ class Audio(commands.Cog): await self.config.ws_port.set(ws_port) if await self._check_external(): embed = discord.Embed( - colour=await ctx.embed_colour(), title="Websocket port set to {}.".format(ws_port) + colour=await ctx.embed_colour(), title=_("Websocket port set to {}.").format(ws_port) ) - embed.set_footer(text="External lavalink server set to True.") + embed.set_footer(text=_("External lavalink server set to True.")) await ctx.send(embed=embed) else: - await self._embed_msg(ctx, "Websocket port set to {}.".format(ws_port)) + await self._embed_msg(ctx, _("Websocket port set to {port}.").format(port=ws_port)) async def _check_external(self): external = await self.config.use_external_lavalink() @@ -2298,7 +2379,10 @@ class Audio(commands.Cog): except ValueError: credits_name = await bank.get_currency_name(ctx.guild) await self._embed_msg( - ctx, "Not enough {} ({} required).".format(credits_name, jukebox_price) + ctx, + _("Not enough {currency} ({required_credits} required).").format( + currency=credits_name, required_credits=jukebox_price + ), ) return False else: