feat(i18n): finish i18n class, todo: persist data in DB

This commit is contained in:
Romain J 2020-06-11 01:06:30 +02:00
parent 85506c8db4
commit 5482429cba
15 changed files with 264 additions and 24 deletions

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View file

@ -2,6 +2,7 @@
<dictionary name="romain">
<words>
<w>commandstats</w>
<w>francais</w>
<w>ipinfo</w>
<w>iplocalise</w>
<w>localiseip</w>

View file

@ -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

View file

@ -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

View file

@ -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)

View 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))

View 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)

View 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 ""

View 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 ""

View 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 : "

View 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 ""

View file

@ -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

View file

@ -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):

View file

@ -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:

View file

@ -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: