mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
[Utils] Add humanize_number() function to chat formatting (#2836)
This adds babel as a dependency, and also includes `redbot.core.i18n.get_babel_locale()`
This commit is contained in:
parent
6c3a3fea66
commit
3c1b6ae4cf
1
changelog.d/2836.feature.rst
Normal file
1
changelog.d/2836.feature.rst
Normal file
@ -0,0 +1 @@
|
||||
New :func:`humanize_number` in :module:`redbot.core.utils.chat_formatting` function to convert numbers into text which respect locale.
|
||||
1
changelog.d/2836.misc.rst
Normal file
1
changelog.d/2836.misc.rst
Normal file
@ -0,0 +1 @@
|
||||
New :func:`humanize_number` is used throughout the bot.
|
||||
@ -19,7 +19,7 @@ import redbot.core
|
||||
from redbot.core import Config, commands, checks, bank
|
||||
from redbot.core.data_manager import cog_data_path
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import bold, box, pagify
|
||||
from redbot.core.utils.chat_formatting import bold, box, pagify, humanize_number
|
||||
from redbot.core.utils.menus import (
|
||||
menu,
|
||||
DEFAULT_CONTROLS,
|
||||
@ -442,7 +442,7 @@ class Audio(commands.Cog):
|
||||
await self._embed_msg(
|
||||
ctx,
|
||||
_("Track queueing command price set to {price} {currency}.").format(
|
||||
price=price, currency=await bank.get_currency_name(ctx.guild)
|
||||
price=humanize_number(price), currency=await bank.get_currency_name(ctx.guild)
|
||||
),
|
||||
)
|
||||
|
||||
@ -613,7 +613,9 @@ class Audio(commands.Cog):
|
||||
msg += _("DJ Role: [{role.name}]\n").format(role=dj_role_obj)
|
||||
if jukebox:
|
||||
msg += _("Jukebox: [{jukebox_name}]\n").format(jukebox_name=jukebox)
|
||||
msg += _("Command price: [{jukebox_price}]\n").format(jukebox_price=jukebox_price)
|
||||
msg += _("Command price: [{jukebox_price}]\n").format(
|
||||
jukebox_price=humanize_number(jukebox_price)
|
||||
)
|
||||
if maxlength > 0:
|
||||
msg += _("Max track length: [{tracklength}]\n").format(
|
||||
tracklength=self._dynamic_time(maxlength)
|
||||
@ -762,11 +764,15 @@ class Audio(commands.Cog):
|
||||
em = discord.Embed(
|
||||
colour=await ctx.embed_colour(),
|
||||
title=_("Playing in {num}/{total} servers:").format(
|
||||
num=server_num, total=total_num
|
||||
num=humanize_number(server_num), total=humanize_number(total_num)
|
||||
),
|
||||
description=page,
|
||||
)
|
||||
em.set_footer(text="Page {}/{}".format(pages, (math.ceil(len(msg) / 1500))))
|
||||
em.set_footer(
|
||||
text="Page {}/{}".format(
|
||||
humanize_number(pages), humanize_number((math.ceil(len(msg) / 1500)))
|
||||
)
|
||||
)
|
||||
pages += 1
|
||||
servers_embed.append(em)
|
||||
|
||||
@ -933,7 +939,9 @@ class Audio(commands.Cog):
|
||||
embed = discord.Embed(
|
||||
colour=await ctx.embed_colour(), description=(f"{header}\n{formatted_page}")
|
||||
)
|
||||
embed.set_footer(text=_("{num} preset(s)").format(num=len(list(eq_presets.keys()))))
|
||||
embed.set_footer(
|
||||
text=_("{num} preset(s)").format(num=humanize_number(len(list(eq_presets.keys()))))
|
||||
)
|
||||
page_list.append(embed)
|
||||
if len(page_list) == 1:
|
||||
return await ctx.send(embed=page_list[0])
|
||||
@ -1869,6 +1877,7 @@ class Audio(commands.Cog):
|
||||
song_info = "{} {}".format(i["name"], i["artists"][0]["name"])
|
||||
else:
|
||||
song_info = "{} {}".format(i["track"]["name"], i["track"]["artists"][0]["name"])
|
||||
|
||||
try:
|
||||
track_url = await self._youtube_api_search(yt_key, song_info)
|
||||
except (RuntimeError, aiohttp.client_exceptions.ServerDisconnectedError):
|
||||
@ -1878,7 +1887,6 @@ class Audio(commands.Cog):
|
||||
)
|
||||
await playlist_msg.edit(embed=error_embed)
|
||||
return None
|
||||
pass
|
||||
try:
|
||||
yt_track = await player.get_tracks(track_url)
|
||||
except (RuntimeError, aiohttp.client_exceptions.ServerDisconnectedError):
|
||||
@ -3416,8 +3424,8 @@ class Audio(commands.Cog):
|
||||
" Votes: {num_votes}/{num_members}"
|
||||
" ({cur_percent}% out of {required_percent}% needed)"
|
||||
).format(
|
||||
num_votes=num_votes,
|
||||
num_members=num_members,
|
||||
num_votes=humanize_number(num_votes),
|
||||
num_members=humanize_number(num_members),
|
||||
cur_percent=vote,
|
||||
required_percent=percent,
|
||||
)
|
||||
@ -3869,7 +3877,7 @@ class Audio(commands.Cog):
|
||||
await self._embed_msg(
|
||||
ctx,
|
||||
_("Not enough {currency} ({required_credits} required).").format(
|
||||
currency=credits_name, required_credits=jukebox_price
|
||||
currency=credits_name, required_credits=humanize_number(jukebox_price)
|
||||
),
|
||||
)
|
||||
return False
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import discord
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
from redbot.core.utils.chat_formatting import box, humanize_number
|
||||
|
||||
from redbot.core import checks, bank, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
@ -88,7 +88,9 @@ class Bank(commands.Cog):
|
||||
"Bank settings:\n\nBank name: {bank_name}\nCurrency: {currency_name}\n"
|
||||
"Default balance: {default_balance}"
|
||||
).format(
|
||||
bank_name=bank_name, currency_name=currency_name, default_balance=default_balance
|
||||
bank_name=bank_name,
|
||||
currency_name=currency_name,
|
||||
default_balance=humanize_number(default_balance),
|
||||
)
|
||||
await ctx.send(box(settings))
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import discord
|
||||
from redbot.core import checks, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
from redbot.core.utils.mod import slow_deletion, mass_purge
|
||||
from redbot.core.utils.predicates import MessagePredicate
|
||||
from .converters import RawMessageIds
|
||||
@ -39,7 +40,9 @@ class Cleanup(commands.Cog):
|
||||
return True
|
||||
|
||||
prompt = await ctx.send(
|
||||
_("Are you sure you want to delete {number} messages? (y/n)").format(number=number)
|
||||
_("Are you sure you want to delete {number} messages? (y/n)").format(
|
||||
number=humanize_number(number)
|
||||
)
|
||||
)
|
||||
response = await ctx.bot.wait_for("message", check=MessagePredicate.same_context(ctx))
|
||||
|
||||
@ -152,7 +155,11 @@ class Cleanup(commands.Cog):
|
||||
to_delete.append(ctx.message)
|
||||
|
||||
reason = "{}({}) deleted {} messages containing '{}' in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), text, channel.id
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_us"),
|
||||
text,
|
||||
channel.id,
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
@ -208,7 +215,14 @@ class Cleanup(commands.Cog):
|
||||
reason = (
|
||||
"{}({}) deleted {} messages "
|
||||
" made by {}({}) in channel {}."
|
||||
"".format(author.name, author.id, len(to_delete), member or "???", _id, channel.name)
|
||||
"".format(
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_US"),
|
||||
member or "???",
|
||||
_id,
|
||||
channel.name,
|
||||
)
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
@ -240,7 +254,10 @@ class Cleanup(commands.Cog):
|
||||
)
|
||||
|
||||
reason = "{}({}) deleted {} messages in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), channel.name
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_US"),
|
||||
channel.name,
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
@ -277,7 +294,10 @@ class Cleanup(commands.Cog):
|
||||
to_delete.append(ctx.message)
|
||||
|
||||
reason = "{}({}) deleted {} messages in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), channel.name
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_US"),
|
||||
channel.name,
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
@ -319,7 +339,10 @@ class Cleanup(commands.Cog):
|
||||
)
|
||||
to_delete.append(ctx.message)
|
||||
reason = "{}({}) deleted {} messages in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), channel.name
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_US"),
|
||||
channel.name,
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
@ -420,7 +443,12 @@ class Cleanup(commands.Cog):
|
||||
reason = (
|
||||
"{}({}) deleted {} "
|
||||
" command messages in channel {}."
|
||||
"".format(author.name, author.id, len(to_delete), channel.name)
|
||||
"".format(
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_US"),
|
||||
channel.name,
|
||||
)
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
@ -500,7 +528,12 @@ class Cleanup(commands.Cog):
|
||||
reason = (
|
||||
"{}({}) deleted {} messages "
|
||||
"sent by the bot in {}."
|
||||
"".format(author.name, author.id, len(to_delete), channel_name)
|
||||
"".format(
|
||||
author.name,
|
||||
author.id,
|
||||
humanize_number(len(to_delete), override_locale="en_US"),
|
||||
channel_name,
|
||||
)
|
||||
)
|
||||
log.info(reason)
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import discord
|
||||
from redbot.cogs.bank import check_global_setting_guildowner, check_global_setting_admin
|
||||
from redbot.core import Config, bank, commands, errors
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
from redbot.core.utils.chat_formatting import box, humanize_number
|
||||
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
||||
|
||||
from redbot.core.bot import Red
|
||||
@ -162,7 +162,7 @@ class Economy(commands.Cog):
|
||||
|
||||
await ctx.send(
|
||||
_("{user}'s balance is {num} {currency}").format(
|
||||
user=user.display_name, num=bal, currency=currency
|
||||
user=user.display_name, num=humanize_number(bal), currency=currency
|
||||
)
|
||||
)
|
||||
|
||||
@ -179,7 +179,10 @@ class Economy(commands.Cog):
|
||||
|
||||
await ctx.send(
|
||||
_("{user} transferred {num} {currency} to {other_user}").format(
|
||||
user=from_.display_name, num=amount, currency=currency, other_user=to.display_name
|
||||
user=from_.display_name,
|
||||
num=humanize_number(amount),
|
||||
currency=currency,
|
||||
other_user=to.display_name,
|
||||
)
|
||||
)
|
||||
|
||||
@ -203,7 +206,7 @@ class Economy(commands.Cog):
|
||||
await bank.deposit_credits(to, creds.sum)
|
||||
msg = _("{author} added {num} {currency} to {user}'s account.").format(
|
||||
author=author.display_name,
|
||||
num=creds.sum,
|
||||
num=humanize_number(creds.sum),
|
||||
currency=currency,
|
||||
user=to.display_name,
|
||||
)
|
||||
@ -211,7 +214,7 @@ class Economy(commands.Cog):
|
||||
await bank.withdraw_credits(to, creds.sum)
|
||||
msg = _("{author} removed {num} {currency} from {user}'s account.").format(
|
||||
author=author.display_name,
|
||||
num=creds.sum,
|
||||
num=humanize_number(creds.sum),
|
||||
currency=currency,
|
||||
user=to.display_name,
|
||||
)
|
||||
@ -219,7 +222,7 @@ class Economy(commands.Cog):
|
||||
await bank.set_balance(to, creds.sum)
|
||||
msg = _("{author} set {user}'s account balance to {num} {currency}.").format(
|
||||
author=author.display_name,
|
||||
num=creds.sum,
|
||||
num=humanize_number(creds.sum),
|
||||
currency=currency,
|
||||
user=to.display_name,
|
||||
)
|
||||
@ -271,7 +274,9 @@ class Economy(commands.Cog):
|
||||
"You've reached the maximum amount of {currency}!"
|
||||
"Please spend some more \N{GRIMACING FACE}\n\n"
|
||||
"You currently have {new_balance} {currency}."
|
||||
).format(currency=credits_name, new_balance=exc.max_balance)
|
||||
).format(
|
||||
currency=credits_name, new_balance=humanize_number(exc.max_balance)
|
||||
)
|
||||
)
|
||||
return
|
||||
next_payday = cur_time + await self.config.PAYDAY_TIME()
|
||||
@ -287,9 +292,9 @@ class Economy(commands.Cog):
|
||||
).format(
|
||||
author=author,
|
||||
currency=credits_name,
|
||||
amount=await self.config.PAYDAY_CREDITS(),
|
||||
new_balance=await bank.get_balance(author),
|
||||
pos=pos,
|
||||
amount=humanize_number(await self.config.PAYDAY_CREDITS()),
|
||||
new_balance=humanize_number(await bank.get_balance(author)),
|
||||
pos=humanize_number(pos) if pos else pos,
|
||||
)
|
||||
)
|
||||
|
||||
@ -319,7 +324,9 @@ class Economy(commands.Cog):
|
||||
"You've reached the maximum amount of {currency}! "
|
||||
"Please spend some more \N{GRIMACING FACE}\n\n"
|
||||
"You currently have {new_balance} {currency}."
|
||||
).format(currency=credits_name, new_balance=exc.max_balance)
|
||||
).format(
|
||||
currency=credits_name, new_balance=humanize_number(exc.max_balance)
|
||||
)
|
||||
)
|
||||
return
|
||||
next_payday = cur_time + await self.config.guild(guild).PAYDAY_TIME()
|
||||
@ -334,9 +341,9 @@ class Economy(commands.Cog):
|
||||
).format(
|
||||
author=author,
|
||||
currency=credits_name,
|
||||
amount=credit_amount,
|
||||
new_balance=await bank.get_balance(author),
|
||||
pos=pos,
|
||||
amount=humanize_number(credit_amount),
|
||||
new_balance=humanize_number(await bank.get_balance(author)),
|
||||
pos=humanize_number(pos) if pos else pos,
|
||||
)
|
||||
)
|
||||
else:
|
||||
@ -364,7 +371,7 @@ class Economy(commands.Cog):
|
||||
else:
|
||||
bank_sorted = await bank.get_leaderboard(positions=top, guild=guild)
|
||||
try:
|
||||
bal_len = len(str(bank_sorted[0][1]["balance"]))
|
||||
bal_len = len(humanize_number(bank_sorted[0][1]["balance"]))
|
||||
# first user is the largest we'll see
|
||||
except IndexError:
|
||||
return await ctx.send(_("There are no accounts in the bank."))
|
||||
@ -387,14 +394,17 @@ class Economy(commands.Cog):
|
||||
if await ctx.bot.is_owner(ctx.author):
|
||||
user_id = f"({str(acc[0])})"
|
||||
name = f"{acc[1]['name']} {user_id}"
|
||||
balance = acc[1]["balance"]
|
||||
balance = humanize_number(acc[1]["balance"])
|
||||
|
||||
if acc[0] != author.id:
|
||||
temp_msg += f"{f'{pos}.': <{pound_len+2}} {balance: <{bal_len + 5}} {name}\n"
|
||||
temp_msg += (
|
||||
f"{f'{humanize_number(pos)}.': <{pound_len+2}} "
|
||||
f"{balance: <{bal_len + 5}} {name}\n"
|
||||
)
|
||||
|
||||
else:
|
||||
temp_msg += (
|
||||
f"{f'{pos}.': <{pound_len+2}} "
|
||||
f"{f'{humanize_number(pos)}.': <{pound_len+2}} "
|
||||
f"{balance: <{bal_len + 5}} "
|
||||
f"<<{author.display_name}>>\n"
|
||||
)
|
||||
@ -503,8 +513,8 @@ class Economy(commands.Cog):
|
||||
"Please spend some more \N{GRIMACING FACE}\n{old_balance} -> {new_balance}!"
|
||||
).format(
|
||||
currency=await bank.get_currency_name(getattr(channel, "guild", None)),
|
||||
old_balance=then,
|
||||
new_balance=exc.max_balance,
|
||||
old_balance=humanize_number(then),
|
||||
new_balance=humanize_number(exc.max_balance),
|
||||
)
|
||||
)
|
||||
return
|
||||
@ -523,10 +533,10 @@ class Economy(commands.Cog):
|
||||
slot=slot,
|
||||
author=author,
|
||||
phrase=phrase,
|
||||
bid=bid,
|
||||
old_balance=then,
|
||||
new_balance=now,
|
||||
pay=pay,
|
||||
bid=humanize_number(bid),
|
||||
old_balance=humanize_number(then),
|
||||
new_balance=humanize_number(now),
|
||||
pay=humanize_number(pay),
|
||||
)
|
||||
)
|
||||
|
||||
@ -552,12 +562,12 @@ class Economy(commands.Cog):
|
||||
"Payday cooldown: {payday_time}\n"
|
||||
"Amount given at account registration: {register_amount}"
|
||||
).format(
|
||||
slot_min=await conf.SLOT_MIN(),
|
||||
slot_max=await conf.SLOT_MAX(),
|
||||
slot_time=await conf.SLOT_TIME(),
|
||||
payday_time=await conf.PAYDAY_TIME(),
|
||||
payday_amount=await conf.PAYDAY_CREDITS(),
|
||||
register_amount=await bank.get_default_balance(guild),
|
||||
slot_min=humanize_number(await conf.SLOT_MIN()),
|
||||
slot_max=humanize_number(await conf.SLOT_MAX()),
|
||||
slot_time=humanize_number(await conf.SLOT_TIME()),
|
||||
payday_time=humanize_number(await conf.PAYDAY_TIME()),
|
||||
payday_amount=humanize_number(await conf.PAYDAY_CREDITS()),
|
||||
register_amount=humanize_number(await bank.get_default_balance(guild)),
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -575,7 +585,9 @@ class Economy(commands.Cog):
|
||||
await self.config.guild(guild).SLOT_MIN.set(bid)
|
||||
credits_name = await bank.get_currency_name(guild)
|
||||
await ctx.send(
|
||||
_("Minimum bid is now {bid} {currency}.").format(bid=bid, currency=credits_name)
|
||||
_("Minimum bid is now {bid} {currency}.").format(
|
||||
bid=humanize_number(bid), currency=credits_name
|
||||
)
|
||||
)
|
||||
|
||||
@economyset.command()
|
||||
@ -594,7 +606,9 @@ class Economy(commands.Cog):
|
||||
else:
|
||||
await self.config.guild(guild).SLOT_MAX.set(bid)
|
||||
await ctx.send(
|
||||
_("Maximum bid is now {bid} {currency}.").format(bid=bid, currency=credits_name)
|
||||
_("Maximum bid is now {bid} {currency}.").format(
|
||||
bid=humanize_number(bid), currency=credits_name
|
||||
)
|
||||
)
|
||||
|
||||
@economyset.command()
|
||||
@ -635,7 +649,7 @@ class Economy(commands.Cog):
|
||||
await self.config.guild(guild).PAYDAY_CREDITS.set(creds)
|
||||
await ctx.send(
|
||||
_("Every payday will now give {num} {currency}.").format(
|
||||
num=creds, currency=credits_name
|
||||
num=humanize_number(creds), currency=credits_name
|
||||
)
|
||||
)
|
||||
|
||||
@ -655,7 +669,7 @@ class Economy(commands.Cog):
|
||||
_(
|
||||
"Every payday will now give {num} {currency} "
|
||||
"to people with the role {role_name}."
|
||||
).format(num=creds, currency=credits_name, role_name=role.name)
|
||||
).format(num=humanize_number(creds), currency=credits_name, role_name=role.name)
|
||||
)
|
||||
|
||||
@economyset.command()
|
||||
@ -668,7 +682,7 @@ class Economy(commands.Cog):
|
||||
await bank.set_default_balance(creds, guild)
|
||||
await ctx.send(
|
||||
_("Registering an account will now give {num} {currency}.").format(
|
||||
num=creds, currency=credits_name
|
||||
num=humanize_number(creds), currency=credits_name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import discord
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
||||
from redbot.core.utils.chat_formatting import escape, italics
|
||||
from redbot.core.utils.chat_formatting import escape, italics, humanize_number
|
||||
|
||||
_ = T_ = Translator("General", __file__)
|
||||
|
||||
@ -89,7 +89,11 @@ class General(commands.Cog):
|
||||
author = ctx.author
|
||||
if number > 1:
|
||||
n = randint(1, number)
|
||||
await ctx.send("{author.mention} :game_die: {n} :game_die:".format(author=author, n=n))
|
||||
await ctx.send(
|
||||
"{author.mention} :game_die: {n} :game_die:".format(
|
||||
author=author, n=humanize_number(n)
|
||||
)
|
||||
)
|
||||
else:
|
||||
await ctx.send(_("{author.mention} Maybe higher than 1? ;P").format(author=author))
|
||||
|
||||
@ -223,10 +227,12 @@ class General(commands.Cog):
|
||||
async def serverinfo(self, ctx):
|
||||
"""Show server information."""
|
||||
guild = ctx.guild
|
||||
online = len([m.status for m in guild.members if m.status != discord.Status.offline])
|
||||
total_users = len(guild.members)
|
||||
text_channels = len(guild.text_channels)
|
||||
voice_channels = len(guild.voice_channels)
|
||||
online = humanize_number(
|
||||
len([m.status for m in guild.members if m.status != discord.Status.offline])
|
||||
)
|
||||
total_users = humanize_number(len(guild.members))
|
||||
text_channels = humanize_number(len(guild.text_channels))
|
||||
voice_channels = humanize_number(len(guild.voice_channels))
|
||||
passed = (ctx.message.created_at - guild.created_at).days
|
||||
created_at = _("Since {date}. That's over {num} days ago!").format(
|
||||
date=guild.created_at.strftime("%d %b %Y %H:%M"), num=passed
|
||||
@ -234,9 +240,9 @@ class General(commands.Cog):
|
||||
data = discord.Embed(description=created_at, colour=(await ctx.embed_colour()))
|
||||
data.add_field(name=_("Region"), value=str(guild.region))
|
||||
data.add_field(name=_("Users"), value=f"{online}/{total_users}")
|
||||
data.add_field(name=_("Text Channels"), value=str(text_channels))
|
||||
data.add_field(name=_("Voice Channels"), value=str(voice_channels))
|
||||
data.add_field(name=_("Roles"), value=str(len(guild.roles)))
|
||||
data.add_field(name=_("Text Channels"), value=text_channels)
|
||||
data.add_field(name=_("Voice Channels"), value=voice_channels)
|
||||
data.add_field(name=_("Roles"), value=humanize_number(len(guild.roles)))
|
||||
data.add_field(name=_("Owner"), value=str(guild.owner))
|
||||
data.set_footer(text=_("Server ID: ") + str(guild.id))
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ from typing import cast, Optional, Union
|
||||
|
||||
import discord
|
||||
from redbot.core import commands, i18n, checks, modlog
|
||||
from redbot.core.utils.chat_formatting import pagify
|
||||
from redbot.core.utils.chat_formatting import pagify, humanize_number
|
||||
from redbot.core.utils.mod import is_allowed_by_hierarchy, get_audit_reason
|
||||
from .abc import MixinMeta
|
||||
from .converters import RawUserIds
|
||||
@ -244,7 +244,9 @@ class KickBanMixin(MixinMeta):
|
||||
errors = {}
|
||||
|
||||
async def show_results():
|
||||
text = _("Banned {num} users from the server.").format(num=len(banned))
|
||||
text = _("Banned {num} users from the server.").format(
|
||||
num=humanize_number(len(banned))
|
||||
)
|
||||
if errors:
|
||||
text += _("\nErrors:\n")
|
||||
text += "\n".join(errors.values())
|
||||
|
||||
@ -6,7 +6,7 @@ from collections import Counter
|
||||
import discord
|
||||
from redbot.core import bank
|
||||
from redbot.core.i18n import Translator
|
||||
from redbot.core.utils.chat_formatting import box, bold, humanize_list
|
||||
from redbot.core.utils.chat_formatting import box, bold, humanize_list, humanize_number
|
||||
from redbot.core.utils.common_filters import normalize_smartquotes
|
||||
from .log import LOG
|
||||
|
||||
@ -292,7 +292,7 @@ class TriviaSession:
|
||||
" for coming first."
|
||||
).format(
|
||||
user=winner.display_name,
|
||||
num=amount,
|
||||
num=humanize_number(amount),
|
||||
currency=await bank.get_currency_name(self.ctx.guild),
|
||||
)
|
||||
)
|
||||
|
||||
@ -5,6 +5,7 @@ from functools import wraps
|
||||
|
||||
import discord
|
||||
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
from . import Config, errors, commands
|
||||
from .i18n import Translator
|
||||
|
||||
@ -237,11 +238,20 @@ async def withdraw_credits(member: discord.Member, amount: int) -> int:
|
||||
if not isinstance(amount, int):
|
||||
raise TypeError("Withdrawal amount must be of type int, not {}.".format(type(amount)))
|
||||
if _invalid_amount(amount):
|
||||
raise ValueError("Invalid withdrawal amount {} < 0".format(amount))
|
||||
raise ValueError(
|
||||
"Invalid withdrawal amount {} < 0".format(
|
||||
humanize_number(amount, override_locale="en_US")
|
||||
)
|
||||
)
|
||||
|
||||
bal = await get_balance(member)
|
||||
if amount > bal:
|
||||
raise ValueError("Insufficient funds {} > {}".format(amount, bal))
|
||||
raise ValueError(
|
||||
"Insufficient funds {} > {}".format(
|
||||
humanize_number(amount, override_locale="en_US"),
|
||||
humanize_number(bal, override_locale="en_US"),
|
||||
)
|
||||
)
|
||||
|
||||
return await set_balance(member, bal - amount)
|
||||
|
||||
@ -272,7 +282,11 @@ async def deposit_credits(member: discord.Member, amount: int) -> int:
|
||||
if not isinstance(amount, int):
|
||||
raise TypeError("Deposit amount must be of type int, not {}.".format(type(amount)))
|
||||
if _invalid_amount(amount):
|
||||
raise ValueError("Invalid deposit amount {} <= 0".format(amount))
|
||||
raise ValueError(
|
||||
"Invalid deposit amount {} <= 0".format(
|
||||
humanize_number(amount, override_locale="en_US")
|
||||
)
|
||||
)
|
||||
|
||||
bal = await get_balance(member)
|
||||
return await set_balance(member, amount + bal)
|
||||
@ -309,7 +323,11 @@ async def transfer_credits(from_: discord.Member, to: discord.Member, amount: in
|
||||
if not isinstance(amount, int):
|
||||
raise TypeError("Transfer amount must be of type int, not {}.".format(type(amount)))
|
||||
if _invalid_amount(amount):
|
||||
raise ValueError("Invalid transfer amount {} <= 0".format(amount))
|
||||
raise ValueError(
|
||||
"Invalid transfer amount {} <= 0".format(
|
||||
humanize_number(amount, override_locale="en_US")
|
||||
)
|
||||
)
|
||||
|
||||
if await get_balance(to) + amount > MAX_BALANCE:
|
||||
currency = await get_currency_name(to.guild)
|
||||
@ -727,7 +745,7 @@ def cost(amount: int):
|
||||
credits_name = await get_currency_name(context.guild)
|
||||
raise commands.UserFeedbackCheckFailure(
|
||||
_("You need at least {cost} {currency} to use this command.").format(
|
||||
cost=amount, currency=credits_name
|
||||
cost=humanize_number(amount), currency=credits_name
|
||||
)
|
||||
)
|
||||
else:
|
||||
|
||||
@ -2,6 +2,7 @@ import importlib.machinery
|
||||
|
||||
import discord
|
||||
|
||||
from redbot.core.utils.chat_formatting import humanize_number
|
||||
from .i18n import Translator
|
||||
|
||||
_ = Translator(__name__, __file__)
|
||||
@ -45,8 +46,8 @@ class BalanceTooHigh(BankError, OverflowError):
|
||||
self.currency_name = currency_name
|
||||
|
||||
def __str__(self) -> str:
|
||||
return _("{user}'s balance cannot rise above {max:,} {currency}.").format(
|
||||
user=self.user, max=self.max_balance, currency=self.currency_name
|
||||
return _("{user}'s balance cannot rise above max {currency}.").format(
|
||||
user=self.user, max=humanize_number(self.max_balance), currency=self.currency_name
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -1,10 +1,21 @@
|
||||
import contextlib
|
||||
import functools
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Callable, Union, Dict
|
||||
from typing import Callable, Union, Dict, Optional
|
||||
|
||||
__all__ = ["get_locale", "set_locale", "reload_locales", "cog_i18n", "Translator"]
|
||||
import babel.localedata
|
||||
from babel.core import Locale
|
||||
|
||||
__all__ = [
|
||||
"get_locale",
|
||||
"set_locale",
|
||||
"reload_locales",
|
||||
"cog_i18n",
|
||||
"Translator",
|
||||
"get_babel_locale",
|
||||
]
|
||||
|
||||
_current_locale = "en-US"
|
||||
|
||||
@ -160,6 +171,44 @@ class Translator(Callable[[str], str]):
|
||||
self.translations[untranslated] = translated
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
def _get_babel_locale(red_locale: str) -> babel.core.Locale:
|
||||
supported_locales = babel.localedata.locale_identifiers()
|
||||
try: # Handles cases where red_locale is already Babel supported
|
||||
babel_locale = Locale(*babel.parse_locale(red_locale))
|
||||
except (ValueError, babel.core.UnknownLocaleError):
|
||||
try:
|
||||
babel_locale = Locale(*babel.parse_locale(red_locale, sep="-"))
|
||||
except (ValueError, babel.core.UnknownLocaleError):
|
||||
# ValueError is Raised by `parse_locale` when an invalid Locale is given to it
|
||||
# Lets handle it silently and default to "en_US"
|
||||
try:
|
||||
# Try to find a babel locale that's close to the one used by red
|
||||
babel_locale = Locale(Locale.negotiate([red_locale], supported_locales, sep="-"))
|
||||
except (ValueError, TypeError, babel.core.UnknownLocaleError):
|
||||
# If we fail to get a close match we will then default to "en_US"
|
||||
babel_locale = Locale("en", "US")
|
||||
return babel_locale
|
||||
|
||||
|
||||
def get_babel_locale(locale: Optional[str] = None) -> babel.core.Locale:
|
||||
"""Function to convert a locale to a ``babel.core.Locale``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
locale : Optional[str]
|
||||
The locale to convert, if not specified it defaults to the bot's locale.
|
||||
|
||||
Returns
|
||||
-------
|
||||
babel.core.Locale
|
||||
The babel locale object.
|
||||
"""
|
||||
if locale is None:
|
||||
locale = get_locale()
|
||||
return _get_babel_locale(locale)
|
||||
|
||||
|
||||
# This import to be down here to avoid circular import issues.
|
||||
# This will be cleaned up at a later date
|
||||
# noinspection PyPep8
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import itertools
|
||||
import datetime
|
||||
from typing import Sequence, Iterator, List, Optional
|
||||
from typing import Sequence, Iterator, List, Optional, Union
|
||||
from io import BytesIO
|
||||
|
||||
import discord
|
||||
|
||||
from redbot.core.i18n import Translator
|
||||
import discord
|
||||
from babel.numbers import format_decimal
|
||||
|
||||
from redbot.core.i18n import Translator, get_babel_locale
|
||||
|
||||
_ = Translator("UtilsChatFormatting", __file__)
|
||||
|
||||
@ -432,6 +434,25 @@ def humanize_timedelta(
|
||||
return ", ".join(strings)
|
||||
|
||||
|
||||
def humanize_number(val: Union[int, float], override_locale=None) -> str:
|
||||
"""
|
||||
Convert an int or float to a str with digit separators based on bot locale
|
||||
|
||||
Parameters
|
||||
----------
|
||||
val : Union[int, float]
|
||||
The int/float to be formatted.
|
||||
override_locale: Optional[str]
|
||||
A value to override the bots locale.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
locale aware formatted number.
|
||||
"""
|
||||
return format_decimal(val, locale=get_babel_locale(override_locale))
|
||||
|
||||
|
||||
def text_to_file(
|
||||
text: str, filename: str = "file.txt", *, spoiler: bool = False, encoding: str = "utf-8"
|
||||
):
|
||||
|
||||
@ -31,6 +31,7 @@ install_requires =
|
||||
appdirs==1.4.3
|
||||
async-timeout==3.0.1
|
||||
attrs==19.1.0
|
||||
babel==2.7.0
|
||||
chardet==3.0.4
|
||||
Click==7.0
|
||||
colorama==0.4.1
|
||||
|
||||
@ -9,6 +9,7 @@ install_requires =
|
||||
aiohttp
|
||||
aiohttp-json-rpc
|
||||
appdirs
|
||||
babel
|
||||
click
|
||||
colorama
|
||||
discord.py
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user