add(i18n): create a language switcher command for all guilds

This commit is contained in:
Romain J 2019-09-29 23:01:49 +02:00
parent 29808d41d6
commit d5f1f71a0a
8 changed files with 125 additions and 71 deletions

View file

@ -9,6 +9,7 @@ import humanize
from discord.ext import commands
from bot import TuxBot
from .utils.models.lang import Lang
from .utils.lang import Texts
from .utils.models.warn import Warn
@ -35,7 +36,7 @@ class Admin(commands.Cog):
member: discord.Member = kwargs.get('member')
reason = kwargs.get(
'reason',
Texts('admin').get("Please enter a reason")
Texts('admin', ctx).get("Please enter a reason")
)
if kwargs.get('type') == 'ban':
@ -86,7 +87,7 @@ class Admin(commands.Cog):
message_id)
await message.edit(content=content)
except (discord.errors.NotFound, discord.errors.Forbidden):
await ctx.send(Texts('utils').get("Unable to find the message"),
await ctx.send(Texts('utils', ctx).get("Unable to find the message"),
delete_after=5)
@_say.command(name='to')
@ -119,10 +120,10 @@ class Admin(commands.Cog):
await ctx.send(embed=e)
except discord.Forbidden:
await ctx.send(Texts('admin').get("Unable to ban this user"),
await ctx.send(Texts('admin', ctx).get("Unable to ban this user"),
delete_after=5)
except discord.errors.NotFound:
await ctx.send(Texts('utils').get("Unable to find the user..."),
await ctx.send(Texts('utils', ctx).get("Unable to find the user..."),
delete_after=5)
"""---------------------------------------------------------------------"""
@ -144,10 +145,10 @@ class Admin(commands.Cog):
await ctx.send(embed=e)
except discord.Forbidden:
await ctx.send(Texts('admin').get("Unable to kick this user"),
await ctx.send(Texts('admin', ctx).get("Unable to kick this user"),
delete_after=5)
except discord.errors.NotFound:
await ctx.send(Texts('utils').get("Unable to find the user..."),
await ctx.send(Texts('utils', ctx).get("Unable to find the user..."),
delete_after=5)
"""---------------------------------------------------------------------"""
@ -179,7 +180,7 @@ class Admin(commands.Cog):
for emoji in emojis:
await message.add_reaction(emoji)
except discord.errors.NotFound:
await ctx.send(Texts('utils').get("Unable to find the message"),
await ctx.send(Texts('utils', ctx).get("Unable to find the message"),
delete_after=5)
@_react.command(name='clear')
@ -189,7 +190,7 @@ class Admin(commands.Cog):
message_id)
await message.clear_reactions()
except discord.errors.NotFound:
await ctx.send(Texts('utils').get("Unable to find the message"),
await ctx.send(Texts('utils', ctx).get("Unable to find the message"),
delete_after=5)
"""---------------------------------------------------------------------"""
@ -206,7 +207,7 @@ class Admin(commands.Cog):
message_id)
await message.delete()
except (discord.errors.NotFound, discord.errors.Forbidden):
await ctx.send(Texts('utils').get("Unable to find the message"),
await ctx.send(Texts('utils', ctx).get("Unable to find the message"),
delete_after=5)
@_delete.command(name='from', aliases=['to', 'in'])
@ -222,7 +223,7 @@ class Admin(commands.Cog):
message_id)
await message.delete()
except (discord.errors.NotFound, discord.errors.Forbidden):
await ctx.send(Texts('utils').get("Unable to find the message"),
await ctx.send(Texts('utils', ctx).get("Unable to find the message"),
delete_after=5)
"""---------------------------------------------------------------------"""
@ -276,7 +277,7 @@ class Admin(commands.Cog):
if ctx.invoked_subcommand is None:
warns_list, warns = await self.get_warn(ctx)
e = discord.Embed(
title=f"{warns.count()} {Texts('admin').get('last warns')}: ",
title=f"{warns.count()} {Texts('admin', ctx).get('last warns')}: ",
description=warns_list
)
@ -288,7 +289,7 @@ class Admin(commands.Cog):
member = await ctx.guild.fetch_member(member.id)
if not member:
return await ctx.send(
Texts('utils').get("Unable to find the user...")
Texts('utils', ctx).get("Unable to find the user...")
)
def check(pld: discord.RawReactionActionEvent):
@ -301,15 +302,15 @@ class Admin(commands.Cog):
if warns.count() >= 3:
e = discord.Embed(
title=Texts('admin').get('More than 2 warns'),
title=Texts('admin', ctx).get('More than 2 warns'),
description=f"{member.mention} "
+ Texts('admin').get('has more than 2 warns')
+ Texts('admin', ctx).get('has more than 2 warns')
)
e.add_field(
name='__Actions__',
value=':one: kick\n'
':two: ban\n'
':three: ' + Texts('admin').get('ignore')
':three: ' + Texts('admin', ctx).get('ignore')
)
choice = await ctx.send(embed=e)
@ -325,7 +326,7 @@ class Admin(commands.Cog):
)
except asyncio.TimeoutError:
return await ctx.send(
Texts('admin').get('Took too long. Aborting.')
Texts('admin', ctx).get('Took too long. Aborting.')
)
finally:
await choice.delete()
@ -338,7 +339,7 @@ class Admin(commands.Cog):
content=f"{ctx.prefix}"
f"kick "
f"{member} "
f"{Texts('admin').get('More than 2 warns')}"
f"{Texts('admin', ctx).get('More than 2 warns')}"
)
return await alt_ctx.command.invoke(alt_ctx)
@ -350,15 +351,15 @@ class Admin(commands.Cog):
content=f"{ctx.prefix}"
f"ban "
f"{member} "
f"{Texts('admin').get('More than 2 warns')}"
f"{Texts('admin', ctx).get('More than 2 warns')}"
)
return await alt_ctx.command.invoke(alt_ctx)
await self.add_warn(ctx, member, reason)
await ctx.send(
content=f"{member.mention} "
f"**{Texts('admin').get('got a warn')}**"
f"\n**{Texts('admin').get('Reason')}:** `{reason}`"
f"**{Texts('admin', ctx).get('got a warn')}**"
f"\n**{Texts('admin', ctx).get('Reason')}:** `{reason}`"
)
@_warn.command(name='remove', aliases=['revoke'])
@ -366,15 +367,15 @@ class Admin(commands.Cog):
warn = self.bot.engine.query(Warn).filter(Warn.id == warn_id).one()
self.bot.engine.delete(warn)
await ctx.send(f"{Texts('admin').get('Warn with id')} `{warn_id}`"
f" {Texts('admin').get('successfully removed')}")
await ctx.send(f"{Texts('admin', ctx).get('Warn with id')} `{warn_id}`"
f" {Texts('admin', ctx).get('successfully removed')}")
@_warn.command(name='show', aliases=['list'])
async def _warn_show(self, ctx: commands.Context, member: discord.Member):
warns_list, warns = await self.get_warn(ctx, member)
e = discord.Embed(
title=f"{warns.count()} {Texts('admin').get('last warns')}: ",
title=f"{warns.count()} {Texts('admin', ctx).get('last warns')}: ",
description=warns_list
)
@ -386,35 +387,36 @@ class Admin(commands.Cog):
warn.reason = reason
self.bot.engine.commit()
await ctx.send(f"{Texts('admin').get('Warn with id')} `{warn_id}`"
f" {Texts('admin').get('successfully edited')}")
await ctx.send(f"{Texts('admin', ctx).get('Warn with id')} `{warn_id}`"
f" {Texts('admin', ctx).get('successfully edited')}")
"""---------------------------------------------------------------------"""
@commands.command(name='language', aliases=['lang', 'langue', 'langage'])
async def _language(self, ctx: commands.Context, locale):
query = """
SELECT locale
FROM lang
WHERE key = 'available'
"""
async def _language(self, ctx: commands.Context, locale: str):
available = self.bot.engine\
.query(Lang.value)\
.filter(Lang.key == 'available')\
.one()[0]\
.split(', ')
async with self.bot.engine.begin() as con:
await ctx.trigger_typing()
available = list(await con.fetchrow(query))
if locale.lower() not in available:
await ctx.send(Texts('admin', ctx).get('Unable to find this language'))
else:
current = self.bot.engine\
.query(Lang)\
.filter(Lang.key == str(ctx.guild.id))
if str(locale) in available:
query = """
IF EXISTS(SELECT * FROM lang WHERE key = $1 )
then
UPDATE lang
SET locale = $2
WHERE key = $1
ELSE
INSERT INTO lang (key, locale)
VALUES ($1, $2)
"""
await con.fetch(query, str(ctx.guild.id), str(locale))
if current.count() > 0:
current = current.one()
current.value = locale.lower()
self.bot.engine.commit()
else:
new_row = Lang(key=str(ctx.guild.id), value=locale.lower())
self.bot.engine.add(new_row)
self.bot.engine.commit()
await ctx.send(Texts('admin', ctx).get('Language changed successfully'))
def setup(bot: TuxBot):

View file

@ -68,17 +68,17 @@ class Basics(commands.Cog):
with proc.oneshot():
mem = proc.memory_full_info()
e = discord.Embed(
title=f"{Texts('basics').get('Information about TuxBot')}",
title=f"{Texts('basics', ctx).get('Information about TuxBot')}",
color=0x89C4F9)
e.add_field(
name=f"__{Texts('basics').get('Latest changes')}__",
name=f"__{Texts('basics', ctx).get('Latest changes')}__",
value=self._latest_commits(),
inline=False)
e.add_field(
name=f"__:busts_in_silhouette: "
f"{Texts('basics').get('Development')}__",
f"{Texts('basics', ctx).get('Development')}__",
value=f"**Romain#5117:** [git](https://git.gnous.eu/Romain)\n"
f"**Outout#4039:** [git](https://git.gnous.eu/mael)\n",
inline=True
@ -92,41 +92,41 @@ class Basics(commands.Cog):
e.add_field(
name="__:gear: Usage__",
value=f"**{humanize.naturalsize(mem.rss)}** "
f"{Texts('basics').get('physical memory')}\n"
f"{Texts('basics', ctx).get('physical memory')}\n"
f"**{humanize.naturalsize(mem.vms)}** "
f"{Texts('basics').get('virtual memory')}\n",
f"{Texts('basics', ctx).get('virtual memory')}\n",
inline=True
)
e.add_field(
name=f"__{Texts('basics').get('Servers count')}__",
name=f"__{Texts('basics', ctx).get('Servers count')}__",
value=str(len(self.bot.guilds)),
inline=True
)
e.add_field(
name=f"__{Texts('basics').get('Channels count')}__",
name=f"__{Texts('basics', ctx).get('Channels count')}__",
value=str(len([_ for _ in self.bot.get_all_channels()])),
inline=True
)
e.add_field(
name=f"__{Texts('basics').get('Members count')}__",
name=f"__{Texts('basics', ctx).get('Members count')}__",
value=str(len([_ for _ in self.bot.get_all_members()])),
inline=True
)
e.add_field(
name=f"__:file_folder: {Texts('basics').get('Files')}__",
name=f"__:file_folder: {Texts('basics', ctx).get('Files')}__",
value=str(files),
inline=True
)
e.add_field(
name=f"__¶ {Texts('basics').get('Lines')}__",
name=f"__¶ {Texts('basics', ctx).get('Lines')}__",
value=str(lines),
inline=True
)
e.add_field(
name=f"__:link: {Texts('basics').get('Links')}__",
name=f"__:link: {Texts('basics', ctx).get('Links')}__",
value="[tuxbot.gnous.eu](https://tuxbot.gnous.eu/) "
"| [gnous.eu](https://gnous.eu/) "
f"| [{Texts('basics').get('Invite')}](https://discordapp.com/oauth2/authorize?client_id=301062143942590465&scope=bot&permissions=268749888)",
@ -142,7 +142,7 @@ class Basics(commands.Cog):
@commands.command(name='credits', aliases=['contributors', 'authors'])
async def _credits(self, ctx: commands.Context):
e = discord.Embed(
title=Texts('basics').get('Contributors'),
title=Texts('basics', ctx).get('Contributors'),
color=0x36393f
)

View file

@ -28,7 +28,7 @@ class Utility(commands.Cog):
ip = socket.getaddrinfo(addr, None, socket.AF_INET6)[1][4][0]
except socket.gaierror:
return await ctx.send(
Texts('utility').get('ipv6 not available'))
Texts('utility', ctx).get('ipv6 not available'))
else:
ip = socket.gethostbyname(addr)
@ -37,19 +37,19 @@ class Utility(commands.Cog):
if response.get('status') == 'success':
e = discord.Embed(
title=f"{Texts('utility').get('Information for')} "
title=f"{Texts('utility', ctx).get('Information for')} "
f"``{addr}`` *`({response.get('query')})`*",
color=0x5858d7
)
e.add_field(
name=Texts('utility').get('Belongs to :'),
name=Texts('utility', ctx).get('Belongs to :'),
value=response.get('org', 'N/A'),
inline=False
)
e.add_field(
name=Texts('utility').get('Is located at :'),
name=Texts('utility', ctx).get('Is located at :'),
value=response.get('city', 'N/A'),
inline=True
)
@ -68,7 +68,7 @@ class Utility(commands.Cog):
await ctx.send(embed=e)
else:
await ctx.send(
content=f"{Texts('utility').get('info not available')}"
content=f"{Texts('utility', ctx).get('info not available')}"
f"``{response.get('query')}``")
"""---------------------------------------------------------------------"""
@ -82,7 +82,7 @@ class Utility(commands.Cog):
async with self.bot.session.get(addr) as s:
await ctx.trigger_typing()
e = discord.Embed(
title=f"{Texts('utility').get('Headers of')} {addr}",
title=f"{Texts('utility', ctx).get('Headers of')} {addr}",
color=0xd75858
)
e.add_field(name="Status", value=s.status, inline=True)
@ -96,7 +96,7 @@ class Utility(commands.Cog):
await ctx.send(embed=e)
except aiohttp.client_exceptions.ClientConnectorError:
await ctx.send(f"{Texts('utility').get('Cannot connect to host')} "
await ctx.send(f"{Texts('utility', ctx).get('Cannot connect to host')} "
f"{addr}")
"""---------------------------------------------------------------------"""
@ -104,8 +104,8 @@ class Utility(commands.Cog):
@commands.command(name='git', aliases=['sources', 'source', 'github'])
async def _git(self, ctx):
e = discord.Embed(
title=Texts('utility').get('git repo'),
description=Texts('utility').get('git text'),
title=Texts('utility', ctx).get('git repo'),
description=Texts('utility', ctx).get('git text'),
colour=0xE9D460
)
e.set_author(

View file

@ -1,10 +1,15 @@
import gettext
import config
from .models.lang import Lang
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from discord.ext import commands
class Texts:
def __init__(self, base: str = 'base'):
self.locale = config.locale
def __init__(self, base: str = 'base', ctx: commands.Context = None):
self.locale = self.get_locale(ctx)
self.base = base
def get(self, text: str) -> str:
@ -15,3 +20,25 @@ class Texts:
def set(self, lang: str):
self.locale = lang
@staticmethod
def get_locale(ctx):
engine = create_engine(config.postgresql)
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
if ctx is not None:
current = session\
.query(Lang.value)\
.filter(Lang.key == str(ctx.guild.id))
if current.count() > 0:
return current.one()[0]
default = session\
.query(Lang.value)\
.filter(Lang.key == 'default')\
.one()[0]
return default

13
cogs/utils/models/lang.py Normal file
View file

@ -0,0 +1,13 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String
Base = declarative_base()
class Lang(Base):
__tablename__ = 'lang'
key = Column(String, primary_key=True)
value = Column(String)
def __repr__(self):
return "<Lang(key='%s', locale='%s')>" % (self.key, self.value)

View file

@ -52,4 +52,10 @@ msgid "successfully removed"
msgstr ""
msgid "successfully edited"
msgstr ""
msgstr ""
msgid "Unable to find this language"
msgstr ""
msgid "Language changed successfully"
msgstr ""

View file

@ -52,4 +52,10 @@ msgid "successfully removed"
msgstr "a été enlevé avec succes"
msgid "successfully edited"
msgstr "a été édité avec succes"
msgstr "a été édité avec succes"
msgid "Unable to find this language"
msgstr "Impossible de trouver cette langue"
msgid "Language changed successfully"
msgstr "Langue changée avec succès"