diff --git a/docs/conf.py b/docs/conf.py index 1da83df0a..22626a36d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -217,6 +217,7 @@ intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "dpy": (f"https://discordpy.readthedocs.io/en/v{dpy_version}/", None), "motor": ("https://motor.readthedocs.io/en/stable/", None), + "babel": ("http://babel.pocoo.org/en/stable/", None), } # Extlinks diff --git a/redbot/core/bot.py b/redbot/core/bot.py index 34b783be6..8126eacda 100644 --- a/redbot/core/bot.py +++ b/redbot/core/bot.py @@ -89,6 +89,7 @@ class RedBase( whitelist=[], blacklist=[], locale="en-US", + regional_format=None, embeds=True, color=15158332, fuzzy=False, @@ -537,6 +538,8 @@ class RedBase( i18n_locale = await self._config.locale() i18n.set_locale(i18n_locale) + i18n_regional_format = await self._config.regional_format() + i18n.set_regional_format(i18n_regional_format) self.add_cog(Core(self)) self.add_cog(CogManagerUI()) diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index c9f173335..29f64e49c 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -897,18 +897,21 @@ class Core(commands.Cog, CoreLogic): prefixes = await ctx.bot._prefix_cache.get_prefixes(ctx.guild) locale = await ctx.bot._config.locale() + regional_format = await ctx.bot._config.regional_format() or _("Same as bot's locale") prefix_string = " ".join(prefixes) settings = _( "{bot_name} Settings:\n\n" "Prefixes: {prefixes}\n" "{guild_settings}" - "Locale: {locale}" + "Locale: {locale}\n" + "Regional format: {regional_format}" ).format( bot_name=ctx.bot.user.name, prefixes=prefix_string, guild_settings=guild_settings, locale=locale, + regional_format=regional_format, ) for page in pagify(settings): await ctx.send(box(page)) @@ -1303,6 +1306,42 @@ class Core(commands.Cog, CoreLogic): await ctx.bot._config.locale.set(standardized_locale_name) await ctx.send(_("Locale has been set.")) + @_set.command(aliases=["region"]) + @checks.is_owner() + async def regionalformat(self, ctx: commands.Context, language_code: str = None): + """ + Changes bot's regional format. This is used for formatting date, time and numbers. + + `` can be any language code with country code included, + e.g. `en-US`, `de-DE`, `fr-FR`, `pl-PL`, etc. + + Leave `` empty to base regional formatting on bot's locale. + """ + if language_code is None: + i18n.set_regional_format(None) + await ctx.bot._config.regional_format.set(None) + await ctx.send(_("Regional formatting will now be based on bot's locale.")) + return + + try: + locale = BabelLocale.parse(language_code, sep="-") + except (ValueError, UnknownLocaleError): + await ctx.send(_("Invalid language code. Use format: `en-US`")) + return + if locale.territory is None: + await ctx.send( + _("Invalid format - language code has to include country code, e.g. `en-US`") + ) + return + standardized_locale_name = f"{locale.language}-{locale.territory}" + i18n.set_regional_format(standardized_locale_name) + await ctx.bot._config.regional_format.set(standardized_locale_name) + await ctx.send( + _("Regional formatting will now be based on `{language_code}` locale.").format( + language_code=standardized_locale_name + ) + ) + @_set.command() @checks.is_owner() async def custominfo(self, ctx: commands.Context, *, text: str = None): diff --git a/redbot/core/i18n.py b/redbot/core/i18n.py index 7790e0ee5..6ac08eb89 100644 --- a/redbot/core/i18n.py +++ b/redbot/core/i18n.py @@ -18,6 +18,7 @@ __all__ = [ ] _current_locale = "en-US" +_current_regional_format = None WAITING_FOR_MSGID = 1 IN_MSGID = 2 @@ -30,17 +31,28 @@ MSGSTR = 'msgstr "' _translators = [] -def get_locale(): +def get_locale() -> str: return _current_locale -def set_locale(locale): +def set_locale(locale: str) -> None: global _current_locale _current_locale = locale reload_locales() -def reload_locales(): +def get_regional_format() -> str: + if _current_regional_format is None: + return _current_locale + return _current_regional_format + + +def set_regional_format(regional_format: Optional[str]) -> None: + global _current_regional_format + _current_regional_format = regional_format + + +def reload_locales() -> None: for translator in _translators: translator.load_translations() @@ -192,7 +204,7 @@ def _get_babel_locale(red_locale: str) -> babel.core.Locale: def get_babel_locale(locale: Optional[str] = None) -> babel.core.Locale: - """Function to convert a locale to a ``babel.core.Locale``. + """Function to convert a locale to a `babel.core.Locale`. Parameters ---------- @@ -209,6 +221,26 @@ def get_babel_locale(locale: Optional[str] = None) -> babel.core.Locale: return _get_babel_locale(locale) +def get_babel_regional_format(regional_format: Optional[str] = None) -> babel.core.Locale: + """Function to convert a regional format to a `babel.core.Locale`. + + If ``regional_format`` parameter is passed, this behaves the same as `get_babel_locale`. + + Parameters + ---------- + regional_format : Optional[str] + The regional format to convert, if not specified it defaults to the bot's regional format. + + Returns + ------- + babel.core.Locale + The babel locale object. + """ + if regional_format is None: + regional_format = get_regional_format() + return _get_babel_locale(regional_format) + + # This import to be down here to avoid circular import issues. # This will be cleaned up at a later date # noinspection PyPep8 diff --git a/redbot/core/utils/chat_formatting.py b/redbot/core/utils/chat_formatting.py index fe85cd1f3..370360e4a 100644 --- a/redbot/core/utils/chat_formatting.py +++ b/redbot/core/utils/chat_formatting.py @@ -7,7 +7,7 @@ from io import BytesIO import discord from babel.numbers import format_decimal -from redbot.core.i18n import Translator, get_babel_locale +from redbot.core.i18n import Translator, get_babel_regional_format _ = Translator("UtilsChatFormatting", __file__) @@ -473,14 +473,14 @@ def humanize_number(val: Union[int, float], override_locale=None) -> str: val : Union[int, float] The int/float to be formatted. override_locale: Optional[str] - A value to override the bots locale. + A value to override bot's regional format. Returns ------- str locale aware formatted number. """ - return format_decimal(val, locale=get_babel_locale(override_locale)) + return format_decimal(val, locale=get_babel_regional_format(override_locale)) def text_to_file(