From 5482429cbad167357e692e4dcfa78e66d1c52a81 Mon Sep 17 00:00:00 2001 From: Romain J Date: Thu, 11 Jun 2020 01:06:30 +0200 Subject: [PATCH] feat(i18n): finish i18n class, todo: persist data in DB --- .idea/codeStyles/codeStyleConfig.xml | 5 +++ .idea/dictionaries/romain.xml | 1 + Makefile | 22 ++++++++++-- setup.cfg | 1 + tuxbot/__main__.py | 8 ++--- tuxbot/cogs/admin/__init__.py | 18 ++++++++++ tuxbot/cogs/admin/admin.py | 48 ++++++++++++++++++++++++++ tuxbot/cogs/admin/locales/en-US.po | 32 +++++++++++++++++ tuxbot/cogs/admin/locales/en-US.po~ | 28 +++++++++++++++ tuxbot/cogs/admin/locales/fr-FR.po | 35 +++++++++++++++++++ tuxbot/cogs/admin/locales/messages.pot | 31 +++++++++++++++++ tuxbot/cogs/anti_raid/anti_raid.py | 8 ++--- tuxbot/core/bot.py | 2 +- tuxbot/core/i18n.py | 47 ++++++++++++++++++------- tuxbot/core/utils/functions/extra.py | 2 +- 15 files changed, 264 insertions(+), 24 deletions(-) create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 tuxbot/cogs/admin/__init__.py create mode 100644 tuxbot/cogs/admin/admin.py create mode 100644 tuxbot/cogs/admin/locales/en-US.po create mode 100644 tuxbot/cogs/admin/locales/en-US.po~ create mode 100644 tuxbot/cogs/admin/locales/fr-FR.po create mode 100644 tuxbot/cogs/admin/locales/messages.pot diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries/romain.xml b/.idea/dictionaries/romain.xml index 0299aeb..3f737c1 100644 --- a/.idea/dictionaries/romain.xml +++ b/.idea/dictionaries/romain.xml @@ -2,6 +2,7 @@ commandstats + francais ipinfo iplocalise localiseip diff --git a/Makefile b/Makefile index 572fa01..59bc550 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ PYTHON = python -VENV = ~/tuxvenv +VENV = venv + +XGETTEXT_FLAGS = --no-wrap --language='python' --keyword=_ --from-code='UTF-8' --msgid-bugs-address='rick@gnous.eu' --width=79 --package-name='Tuxbot-bot' # Init main: @@ -12,4 +14,20 @@ update: # Blackify code reformat: - $(PYTHON) -m black `git ls-files "*.py"` \ No newline at end of file + $(PYTHON) -m black `git ls-files "*.py"` + +# Translations +xgettext: + for cog in tuxbot/cogs/*/; do \ + xgettext `find $$cog -type f -name '*.py'` --output=$$cog/locales/messages.pot $(XGETTEXT_FLAGS); \ + done +msginit: + for cog in tuxbot/cogs/*/; do \ + msginit --input=$$cog/locales/messages.pot --output=$$cog/locales/fr-FR.po --locale=fr_FR.UTF-8 --no-translator; \ + msginit --input=$$cog/locales/messages.pot --output=$$cog/locales/en-US.po --locale=en_US.UTF-8 --no-translator; \ + done +msgmerge: + for cog in tuxbot/cogs/*/; do \ + msgmerge --update $$cog/locales/fr-FR.po $$cog/locales/messages.pot; \ + msgmerge --update $$cog/locales/en-US.po $$cog/locales/messages.pot; \ + done \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 15755a6..94e1e30 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,6 +17,7 @@ install_requires = async-timeout==3.0.1 asyncpg==0.20.1 attrs==19.3.0 + babel==2.8.0 black==19.10b0 braceexpand==0.1.5 cachetools==4.1.0 diff --git a/tuxbot/__main__.py b/tuxbot/__main__.py index ae7e6d4..b102edb 100644 --- a/tuxbot/__main__.py +++ b/tuxbot/__main__.py @@ -31,12 +31,12 @@ def list_instances() -> NoReturn: with data_manager.config_file.open() as fs: datas = json.load(fs) - instances = list(datas.keys()) - info = {"title": "Instances", "rows": []} - for instance in instances: - info["rows"].append(f"-> {instance}") + for instance, details in datas.items(): + info["rows"].append( + f"-> {instance} " f"{'up' if details.get('IS_RUNNING') else 'down'}" + ) print(bordered(info)) sys.exit(0) diff --git a/tuxbot/cogs/admin/__init__.py b/tuxbot/cogs/admin/__init__.py new file mode 100644 index 0000000..463e1d1 --- /dev/null +++ b/tuxbot/cogs/admin/__init__.py @@ -0,0 +1,18 @@ +from collections import namedtuple + +from .admin import Admin +from ...core.bot import Tux + +VersionInfo = namedtuple("VersionInfo", "major minor micro releaselevel") +version_info = VersionInfo(major=2, minor=0, micro=0, releaselevel="alpha") + +__version__ = "v{}.{}.{}-{}".format( + version_info.major, + version_info.minor, + version_info.micro, + version_info.releaselevel, +).replace("\n", "") + + +def setup(bot: Tux): + bot.add_cog(Admin(bot)) diff --git a/tuxbot/cogs/admin/admin.py b/tuxbot/cogs/admin/admin.py new file mode 100644 index 0000000..6c1b13f --- /dev/null +++ b/tuxbot/cogs/admin/admin.py @@ -0,0 +1,48 @@ +import logging + +import discord +from discord.ext import commands + +from tuxbot.core import checks +from tuxbot.core.bot import Tux +from tuxbot.core.i18n import Translator, set_locale, _locale_key_value +from tuxbot.core.utils.functions.extra import group_extra, ContextPlus + +log = logging.getLogger("tuxbot.cogs.admin") +_ = Translator("Admin", __file__) + + +class Admin(commands.Cog, name="Admin"): + def __init__(self, bot: Tux): + self.bot = bot + + @group_extra( + name="lang", + aliases=["locale", "langue"], + deletable=True + ) + @commands.guild_only() + @checks.is_admin() + async def _lang(self, ctx: ContextPlus): + """Manage lang settings.""" + + @_lang.command(name="set", aliases=["define", "choice"]) + async def _lang_set(self, ctx: ContextPlus, lang: str): + try: + set_locale(lang.lower()) + await ctx.send( + _("Locale changed to {lang} successfully") + .format(lang=f"`{lang}`") + ) + except NotImplementedError: + await ctx.send(_("This locale isn't available, execute `lang list` to view available locales")) + + @_lang.command(name="list", aliases=["liste", "all", "view"]) + async def _lang_list(self, ctx: ContextPlus): + e = discord.Embed( + title=_("List of available locales: "), + description='\n'.join([i[0] for i in _locale_key_value.values()]), + color=0x36393E + ) + + await ctx.send(embed=e) diff --git a/tuxbot/cogs/admin/locales/en-US.po b/tuxbot/cogs/admin/locales/en-US.po new file mode 100644 index 0000000..fbf8e4f --- /dev/null +++ b/tuxbot/cogs/admin/locales/en-US.po @@ -0,0 +1,32 @@ +# English translations for Tuxbot-bot package. +# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# Automatically generated, 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-06-11 00:59+0200\n" +"PO-Revision-Date: 2020-06-10 00:38+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: tuxbot/cogs/admin/admin.py:33 +#, fuzzy, python-brace-format +msgid "Locale changed to {lang} successfully" +msgstr "Lang changed to {lang} successfully" + +#: tuxbot/cogs/admin/admin.py:37 +msgid "" +"This locale isn't available, execute `lang list` to view available locales" +msgstr "" + +#: tuxbot/cogs/admin/admin.py:42 +msgid "List of available locales: " +msgstr "" diff --git a/tuxbot/cogs/admin/locales/en-US.po~ b/tuxbot/cogs/admin/locales/en-US.po~ new file mode 100644 index 0000000..ca18c7c --- /dev/null +++ b/tuxbot/cogs/admin/locales/en-US.po~ @@ -0,0 +1,28 @@ +# English translations for Tuxbot-bot package. +# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# Automatically generated, 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-06-11 00:49+0200\n" +"PO-Revision-Date: 2020-06-10 00:38+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: tuxbot/cogs/admin/admin.py:33 +#, fuzzy, python-brace-format +msgid "Locale changed to {lang} successfully" +msgstr "Lang changed to {lang} successfully" + +#: tuxbot/cogs/admin/admin.py:37 +msgid "" +"This locale isn't available, execute `lang list` to view available locales" +msgstr "" diff --git a/tuxbot/cogs/admin/locales/fr-FR.po b/tuxbot/cogs/admin/locales/fr-FR.po new file mode 100644 index 0000000..78cb879 --- /dev/null +++ b/tuxbot/cogs/admin/locales/fr-FR.po @@ -0,0 +1,35 @@ +# French translations for Tuxbot-bot package +# Traductions françaises du paquet Tuxbot-bot. +# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# Automatically generated, 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-06-11 00:59+0200\n" +"PO-Revision-Date: 2020-06-10 00:38+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: tuxbot/cogs/admin/admin.py:33 +#, fuzzy, python-brace-format +msgid "Locale changed to {lang} successfully" +msgstr "Langue changée pour {lang} avec succès" + +#: tuxbot/cogs/admin/admin.py:37 +msgid "" +"This locale isn't available, execute `lang list` to view available locales" +msgstr "" +"Cette langue n'est pas disponible, exécutez `lang list` pour voir les " +"langues disponibles" + +#: tuxbot/cogs/admin/admin.py:42 +msgid "List of available locales: " +msgstr "Liste des langues disponibles : " diff --git a/tuxbot/cogs/admin/locales/messages.pot b/tuxbot/cogs/admin/locales/messages.pot new file mode 100644 index 0000000..7b5dc0f --- /dev/null +++ b/tuxbot/cogs/admin/locales/messages.pot @@ -0,0 +1,31 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Tuxbot-bot package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Tuxbot-bot\n" +"Report-Msgid-Bugs-To: rick@gnous.eu\n" +"POT-Creation-Date: 2020-06-11 00:59+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: tuxbot/cogs/admin/admin.py:33 +#, python-brace-format +msgid "Locale changed to {lang} successfully" +msgstr "" + +#: tuxbot/cogs/admin/admin.py:37 +msgid "This locale isn't available, execute `lang list` to view available locales" +msgstr "" + +#: tuxbot/cogs/admin/admin.py:42 +msgid "List of available locales: " +msgstr "" diff --git a/tuxbot/cogs/anti_raid/anti_raid.py b/tuxbot/cogs/anti_raid/anti_raid.py index 61f096c..41e6a7c 100644 --- a/tuxbot/cogs/anti_raid/anti_raid.py +++ b/tuxbot/cogs/anti_raid/anti_raid.py @@ -6,11 +6,11 @@ from tuxbot.core import checks from tuxbot.core.bot import Tux from tuxbot.core.i18n import Translator -log = logging.getLogger("tuxbot.cogs.admin") -T_ = Translator("Admin", __file__) +log = logging.getLogger("tuxbot.cogs.anti_raid") +T_ = Translator("AntiRaid", __file__) -class Admin(commands.Cog, name="Admin"): +class AntiRaid(commands.Cog, name="AntiRaid"): def __init__(self, bot: Tux): self.bot = bot @@ -20,5 +20,5 @@ class Admin(commands.Cog, name="Admin"): ) @commands.guild_only() @checks.is_admin() - async def _warn(self, ctx: commands.Context): + async def _anti_raid(self, ctx: commands.Context): pass diff --git a/tuxbot/core/bot.py b/tuxbot/core/bot.py index 15d669d..61c0719 100644 --- a/tuxbot/core/bot.py +++ b/tuxbot/core/bot.py @@ -26,7 +26,7 @@ NAME = r""" |_| \__,_/_/\_\_.__/ \___/ \__| |_.__/ \___/ \__| """ -packages: List[str] = ["jishaku", "tuxbot.cogs.warnings"] +packages: List[str] = ["jishaku", "tuxbot.cogs.warnings", "tuxbot.cogs.admin"] class Tux(commands.AutoShardedBot): diff --git a/tuxbot/core/i18n.py b/tuxbot/core/i18n.py index 7993910..dfb594b 100644 --- a/tuxbot/core/i18n.py +++ b/tuxbot/core/i18n.py @@ -1,29 +1,41 @@ import logging import os from pathlib import Path -from typing import Callable, Union +from typing import Callable, Union, Dict, List -__all__ = [ - "get_locale", - "set_locale", - "reload_locales", - "Translator", -] +from babel.messages.pofile import read_po log = logging.getLogger("tuxbot.core.i18n") _translators = [] + _current_locale = "en-US" +_locale_key_value: Dict[str, List[str]] = { + "en": ["english", "anglais", "en", "us"], + "fr": ["français", "francais", "french", "fr", "be"], +} +_available_locales: Dict[str, str] = {"en": "en-US", "fr": "fr-FR"} def get_locale() -> str: return _current_locale +def find_locale(locale: str) -> str: + """We suppose `locale` is in `_locale_key_value.values()`""" + + for key, val in _locale_key_value.items(): + if locale in val: + return key + + def set_locale(locale: str) -> None: - global _current_locale - _current_locale = locale - reload_locales() + if not any(locale in values for values in _locale_key_value.values()): + raise NotImplementedError("This locale isn't implemented") + else: + global _current_locale + _current_locale = _available_locales.get(find_locale(locale)) + reload_locales() def reload_locales() -> None: @@ -32,7 +44,7 @@ def reload_locales() -> None: class Translator(Callable[[str], str]): - """Class to load locales at init.""" + """Class to load texts at init.""" def __init__(self, name: str, file_location: Union[str, Path, os.PathLike]): """Initializes the Translator object. @@ -59,6 +71,12 @@ class Translator(Callable[[str], str]): except KeyError: return untranslated + def __repr__(self): + return "" % ( + self.cog_name, + self.cog_folder, + ) + def load_translations(self): """Loads the current translations. @@ -66,7 +84,12 @@ class Translator(Callable[[str], str]): self.translations = {} locale_path = self.cog_folder / "locales" / f"{get_locale()}.po" - ... + with locale_path.open("r") as f: + catalog = read_po(f) + + for message in catalog: + if message.id: + self._add_translation(message.id, message.string) def _add_translation(self, untranslated, translated): if translated: diff --git a/tuxbot/core/utils/functions/extra.py b/tuxbot/core/utils/functions/extra.py index f675eba..4571200 100644 --- a/tuxbot/core/utils/functions/extra.py +++ b/tuxbot/core/utils/functions/extra.py @@ -20,7 +20,7 @@ class ContextPlus(commands.Context): ) try: - await self.bot.wait_for("reaction_add", timeout=60.0, check=check) + await self.bot.wait_for("reaction_add", timeout=45.0, check=check) except asyncio.TimeoutError: await message.remove_reaction("🗑", self.bot.user) else: