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">
|
||||
<words>
|
||||
<w>commandstats</w>
|
||||
<w>francais</w>
|
||||
<w>ipinfo</w>
|
||||
<w>iplocalise</w>
|
||||
<w>localiseip</w>
|
||||
|
|
22
Makefile
22
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"`
|
||||
$(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
|
||||
asyncpg==0.20.1
|
||||
attrs==19.3.0
|
||||
babel==2.8.0
|
||||
black==19.10b0
|
||||
braceexpand==0.1.5
|
||||
cachetools==4.1.0
|
||||
|
|
|
@ -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)
|
||||
|
|
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.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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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 "<Translator, name=%s, file_location=%s>" % (
|
||||
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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue