feat(i18n): finish i18n class, todo: persist data in DB
This commit is contained in:
parent
85506c8db4
commit
5482429cba
15 changed files with 264 additions and 24 deletions
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
|
@ -2,6 +2,7 @@
|
||||||
<dictionary name="romain">
|
<dictionary name="romain">
|
||||||
<words>
|
<words>
|
||||||
<w>commandstats</w>
|
<w>commandstats</w>
|
||||||
|
<w>francais</w>
|
||||||
<w>ipinfo</w>
|
<w>ipinfo</w>
|
||||||
<w>iplocalise</w>
|
<w>iplocalise</w>
|
||||||
<w>localiseip</w>
|
<w>localiseip</w>
|
||||||
|
|
20
Makefile
20
Makefile
|
@ -1,5 +1,7 @@
|
||||||
PYTHON = python
|
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
|
# Init
|
||||||
main:
|
main:
|
||||||
|
@ -13,3 +15,19 @@ update:
|
||||||
# Blackify code
|
# Blackify code
|
||||||
reformat:
|
reformat:
|
||||||
$(PYTHON) -m black `git ls-files "*.py"`
|
$(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
|
|
@ -17,6 +17,7 @@ install_requires =
|
||||||
async-timeout==3.0.1
|
async-timeout==3.0.1
|
||||||
asyncpg==0.20.1
|
asyncpg==0.20.1
|
||||||
attrs==19.3.0
|
attrs==19.3.0
|
||||||
|
babel==2.8.0
|
||||||
black==19.10b0
|
black==19.10b0
|
||||||
braceexpand==0.1.5
|
braceexpand==0.1.5
|
||||||
cachetools==4.1.0
|
cachetools==4.1.0
|
||||||
|
|
|
@ -31,12 +31,12 @@ def list_instances() -> NoReturn:
|
||||||
with data_manager.config_file.open() as fs:
|
with data_manager.config_file.open() as fs:
|
||||||
datas = json.load(fs)
|
datas = json.load(fs)
|
||||||
|
|
||||||
instances = list(datas.keys())
|
|
||||||
|
|
||||||
info = {"title": "Instances", "rows": []}
|
info = {"title": "Instances", "rows": []}
|
||||||
|
|
||||||
for instance in instances:
|
for instance, details in datas.items():
|
||||||
info["rows"].append(f"-> {instance}")
|
info["rows"].append(
|
||||||
|
f"-> {instance} " f"{'up' if details.get('IS_RUNNING') else 'down'}"
|
||||||
|
)
|
||||||
|
|
||||||
print(bordered(info))
|
print(bordered(info))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
18
tuxbot/cogs/admin/__init__.py
Normal file
18
tuxbot/cogs/admin/__init__.py
Normal file
|
@ -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))
|
48
tuxbot/cogs/admin/admin.py
Normal file
48
tuxbot/cogs/admin/admin.py
Normal file
|
@ -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)
|
32
tuxbot/cogs/admin/locales/en-US.po
Normal file
32
tuxbot/cogs/admin/locales/en-US.po
Normal file
|
@ -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 ""
|
28
tuxbot/cogs/admin/locales/en-US.po~
Normal file
28
tuxbot/cogs/admin/locales/en-US.po~
Normal file
|
@ -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 ""
|
35
tuxbot/cogs/admin/locales/fr-FR.po
Normal file
35
tuxbot/cogs/admin/locales/fr-FR.po
Normal file
|
@ -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 : "
|
31
tuxbot/cogs/admin/locales/messages.pot
Normal file
31
tuxbot/cogs/admin/locales/messages.pot
Normal file
|
@ -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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\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 ""
|
|
@ -6,11 +6,11 @@ from tuxbot.core import checks
|
||||||
from tuxbot.core.bot import Tux
|
from tuxbot.core.bot import Tux
|
||||||
from tuxbot.core.i18n import Translator
|
from tuxbot.core.i18n import Translator
|
||||||
|
|
||||||
log = logging.getLogger("tuxbot.cogs.admin")
|
log = logging.getLogger("tuxbot.cogs.anti_raid")
|
||||||
T_ = Translator("Admin", __file__)
|
T_ = Translator("AntiRaid", __file__)
|
||||||
|
|
||||||
|
|
||||||
class Admin(commands.Cog, name="Admin"):
|
class AntiRaid(commands.Cog, name="AntiRaid"):
|
||||||
def __init__(self, bot: Tux):
|
def __init__(self, bot: Tux):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
|
@ -20,5 +20,5 @@ class Admin(commands.Cog, name="Admin"):
|
||||||
)
|
)
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@checks.is_admin()
|
@checks.is_admin()
|
||||||
async def _warn(self, ctx: commands.Context):
|
async def _anti_raid(self, ctx: commands.Context):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -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):
|
class Tux(commands.AutoShardedBot):
|
||||||
|
|
|
@ -1,29 +1,41 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Callable, Union
|
from typing import Callable, Union, Dict, List
|
||||||
|
|
||||||
__all__ = [
|
from babel.messages.pofile import read_po
|
||||||
"get_locale",
|
|
||||||
"set_locale",
|
|
||||||
"reload_locales",
|
|
||||||
"Translator",
|
|
||||||
]
|
|
||||||
|
|
||||||
log = logging.getLogger("tuxbot.core.i18n")
|
log = logging.getLogger("tuxbot.core.i18n")
|
||||||
|
|
||||||
_translators = []
|
_translators = []
|
||||||
|
|
||||||
_current_locale = "en-US"
|
_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:
|
def get_locale() -> str:
|
||||||
return _current_locale
|
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:
|
def set_locale(locale: str) -> None:
|
||||||
global _current_locale
|
if not any(locale in values for values in _locale_key_value.values()):
|
||||||
_current_locale = locale
|
raise NotImplementedError("This locale isn't implemented")
|
||||||
reload_locales()
|
else:
|
||||||
|
global _current_locale
|
||||||
|
_current_locale = _available_locales.get(find_locale(locale))
|
||||||
|
reload_locales()
|
||||||
|
|
||||||
|
|
||||||
def reload_locales() -> None:
|
def reload_locales() -> None:
|
||||||
|
@ -32,7 +44,7 @@ def reload_locales() -> None:
|
||||||
|
|
||||||
|
|
||||||
class Translator(Callable[[str], str]):
|
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]):
|
def __init__(self, name: str, file_location: Union[str, Path, os.PathLike]):
|
||||||
"""Initializes the Translator object.
|
"""Initializes the Translator object.
|
||||||
|
@ -59,6 +71,12 @@ class Translator(Callable[[str], str]):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return untranslated
|
return untranslated
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Translator, name=%s, file_location=%s>" % (
|
||||||
|
self.cog_name,
|
||||||
|
self.cog_folder,
|
||||||
|
)
|
||||||
|
|
||||||
def load_translations(self):
|
def load_translations(self):
|
||||||
"""Loads the current translations.
|
"""Loads the current translations.
|
||||||
|
|
||||||
|
@ -66,7 +84,12 @@ class Translator(Callable[[str], str]):
|
||||||
self.translations = {}
|
self.translations = {}
|
||||||
locale_path = self.cog_folder / "locales" / f"{get_locale()}.po"
|
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):
|
def _add_translation(self, untranslated, translated):
|
||||||
if translated:
|
if translated:
|
||||||
|
|
|
@ -20,7 +20,7 @@ class ContextPlus(commands.Context):
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
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:
|
except asyncio.TimeoutError:
|
||||||
await message.remove_reaction("🗑", self.bot.user)
|
await message.remove_reaction("🗑", self.bot.user)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in a new issue