feat(i18n): finish persisting data for i18n

This commit is contained in:
Romain J 2020-06-11 19:43:00 +02:00
parent 5482429cba
commit 1f88499d44
9 changed files with 120 additions and 79 deletions

View file

@ -5,7 +5,7 @@ from discord.ext import commands
from tuxbot.core import checks from tuxbot.core import checks
from tuxbot.core.bot import Tux from tuxbot.core.bot import Tux
from tuxbot.core.i18n import Translator, set_locale, _locale_key_value from tuxbot.core.i18n import Translator, find_locale, get_locale_name, available_locales
from tuxbot.core.utils.functions.extra import group_extra, ContextPlus from tuxbot.core.utils.functions.extra import group_extra, ContextPlus
log = logging.getLogger("tuxbot.cogs.admin") log = logging.getLogger("tuxbot.cogs.admin")
@ -16,11 +16,10 @@ class Admin(commands.Cog, name="Admin"):
def __init__(self, bot: Tux): def __init__(self, bot: Tux):
self.bot = bot self.bot = bot
@group_extra( async def _save_lang(self, ctx: ContextPlus, lang: str):
name="lang", await self.bot.config.update("core", f"guild.{ctx.guild.id}.locale", lang)
aliases=["locale", "langue"],
deletable=True @group_extra(name="lang", aliases=["locale", "langue"], deletable=True)
)
@commands.guild_only() @commands.guild_only()
@checks.is_admin() @checks.is_admin()
async def _lang(self, ctx: ContextPlus): async def _lang(self, ctx: ContextPlus):
@ -29,20 +28,21 @@ class Admin(commands.Cog, name="Admin"):
@_lang.command(name="set", aliases=["define", "choice"]) @_lang.command(name="set", aliases=["define", "choice"])
async def _lang_set(self, ctx: ContextPlus, lang: str): async def _lang_set(self, ctx: ContextPlus, lang: str):
try: try:
set_locale(lang.lower()) await self._save_lang(ctx, find_locale(lang.lower()))
await ctx.send( await ctx.send(
_("Locale changed to {lang} successfully") _("Locale changed to {lang} successfully", ctx, self.bot.config).format(
.format(lang=f"`{lang}`") lang=f"`{get_locale_name(lang).lower()}`"
)
) )
except NotImplementedError: except NotImplementedError:
await ctx.send(_("This locale isn't available, execute `lang list` to view available locales")) await self._lang_list(ctx)
@_lang.command(name="list", aliases=["liste", "all", "view"]) @_lang.command(name="list", aliases=["liste", "all", "view"])
async def _lang_list(self, ctx: ContextPlus): async def _lang_list(self, ctx: ContextPlus):
e = discord.Embed( e = discord.Embed(
title=_("List of available locales: "), title=_("List of available locales: ", ctx, self.bot.config),
description='\n'.join([i[0] for i in _locale_key_value.values()]), description="\n".join([i[0] for i in available_locales.values()]),
color=0x36393E color=0x36393E,
) )
await ctx.send(embed=e) await ctx.send(embed=e)

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2020-06-11 00:59+0200\n" "POT-Creation-Date: 2020-06-11 19:07+0200\n"
"PO-Revision-Date: 2020-06-10 00:38+0200\n" "PO-Revision-Date: 2020-06-10 00:38+0200\n"
"Last-Translator: Automatically generated\n" "Last-Translator: Automatically generated\n"
"Language-Team: none\n" "Language-Team: none\n"
@ -18,15 +18,10 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tuxbot/cogs/admin/admin.py:33 #: tuxbot/cogs/admin/admin.py:33
#, fuzzy, python-brace-format #, python-brace-format
msgid "Locale changed to {lang} successfully" 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 "" msgstr ""
#: tuxbot/cogs/admin/admin.py:42 #: tuxbot/cogs/admin/admin.py:43
msgid "List of available locales: " msgid "List of available locales: "
msgstr "" msgstr ""

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2020-06-11 00:49+0200\n" "POT-Creation-Date: 2020-06-11 18:24+0200\n"
"PO-Revision-Date: 2020-06-10 00:38+0200\n" "PO-Revision-Date: 2020-06-10 00:38+0200\n"
"Last-Translator: Automatically generated\n" "Last-Translator: Automatically generated\n"
"Language-Team: none\n" "Language-Team: none\n"
@ -17,12 +17,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tuxbot/cogs/admin/admin.py:33 #: tuxbot/cogs/admin/admin.py:38
#, fuzzy, python-brace-format #, python-brace-format
msgid "Locale changed to {lang} successfully" msgid "Locale changed to {lang} successfully"
msgstr "Lang changed to {lang} successfully" msgstr ""
#: tuxbot/cogs/admin/admin.py:37 #: tuxbot/cogs/admin/admin.py:47
msgid "" msgid "List of available locales: "
"This locale isn't available, execute `lang list` to view available locales"
msgstr "" msgstr ""

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2020-06-11 00:59+0200\n" "POT-Creation-Date: 2020-06-11 19:07+0200\n"
"PO-Revision-Date: 2020-06-10 00:38+0200\n" "PO-Revision-Date: 2020-06-10 00:38+0200\n"
"Last-Translator: Automatically generated\n" "Last-Translator: Automatically generated\n"
"Language-Team: none\n" "Language-Team: none\n"
@ -23,13 +23,6 @@ msgstr ""
msgid "Locale changed to {lang} successfully" msgid "Locale changed to {lang} successfully"
msgstr "Langue changée pour {lang} avec succès" msgstr "Langue changée pour {lang} avec succès"
#: tuxbot/cogs/admin/admin.py:37 #: tuxbot/cogs/admin/admin.py:43
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: " msgid "List of available locales: "
msgstr "Liste des langues disponibles : " msgstr "Liste des langues disponibles : "

View file

@ -0,0 +1,28 @@
# 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 18:24+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:38
#, fuzzy, python-brace-format
msgid "Locale changed to {lang} successfully"
msgstr "Langue changée pour {lang} avec succès"
#: tuxbot/cogs/admin/admin.py:47
msgid "List of available locales: "
msgstr "Liste des langues disponibles : "

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2020-06-11 00:59+0200\n" "POT-Creation-Date: 2020-06-11 19:07+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -22,10 +22,6 @@ msgstr ""
msgid "Locale changed to {lang} successfully" msgid "Locale changed to {lang} successfully"
msgstr "" msgstr ""
#: tuxbot/cogs/admin/admin.py:37 #: tuxbot/cogs/admin/admin.py:43
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: " msgid "List of available locales: "
msgstr "" msgstr ""

View file

@ -2,6 +2,7 @@ import asyncio
import json import json
import logging import logging
from typing import List, Dict, Union, Any from typing import List, Dict, Union, Any
from flatten_dict import flatten, unflatten
import discord import discord
@ -124,7 +125,9 @@ class Config:
datas = self.__getitem__(cog_name) datas = self.__getitem__(cog_name)
path = data_path(self._cog_instance) path = data_path(self._cog_instance)
datas[item] = value flat_datas = flatten(datas)
flat_datas[tuple(item.split("."))] = value
datas = unflatten(flat_datas)
self._datas = datas self._datas = datas
@ -139,3 +142,30 @@ class Config:
await self.loop.run_in_executor(None, self._dump) await self.loop.run_in_executor(None, self._dump)
return datas return datas
def get_value(self, cog_name: str, key: str, default: Any = None) -> Any:
"""Get value by key.
Parameters
----------
cog_name:str
Name of cog who's corresponding to the config file.
key:str
Key to fetch.
default:Any|Optional
Default value.
Returns
-------
Any:
Recovered value.
"""
datas = self.__getitem__(cog_name)
flat_datas = flatten(datas)
try:
return flat_datas[tuple(key.split("."))]
except KeyError:
return default

View file

@ -83,4 +83,4 @@ def logs_data_path(instance_name: str) -> Path:
Path Path
Generated path for logs files. Generated path for logs files.
""" """
return data_path(instance_name) / "data" / instance_name / "logs" return data_path(instance_name) / "logs"

View file

@ -5,42 +5,34 @@ from typing import Callable, Union, Dict, List
from babel.messages.pofile import read_po from babel.messages.pofile import read_po
from tuxbot.core import Config
from tuxbot.core.utils.functions.extra import ContextPlus
log = logging.getLogger("tuxbot.core.i18n") log = logging.getLogger("tuxbot.core.i18n")
_translators = [] _translators = []
_current_locale = "en-US" available_locales: Dict[str, List[str]] = {
_locale_key_value: Dict[str, List[str]] = { "en-US": ["english", "anglais", "en", "us", "en-us"],
"en": ["english", "anglais", "en", "us"], "fr-FR": ["français", "francais", "french", "fr", "be", "fr-fr"],
"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: def find_locale(locale: str) -> str:
"""We suppose `locale` is in `_locale_key_value.values()`""" """We suppose `locale` is in `_available_locales.values()`"""
for key, val in _locale_key_value.items(): for key, val in available_locales.items():
if locale in val: if locale in val:
return key return key
def set_locale(locale: str) -> None:
if not any(locale in values for values in _locale_key_value.values()):
raise NotImplementedError("This locale isn't implemented") 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: def get_locale_name(locale: str) -> str:
for translator in _translators: """Return the name of this `locale`
translator.load_translations()
"""
return available_locales.get(find_locale(locale))[0]
class Translator(Callable[[str], str]): class Translator(Callable[[str], str]):
@ -65,9 +57,14 @@ class Translator(Callable[[str], str]):
self.load_translations() self.load_translations()
def __call__(self, untranslated: str) -> str: def __call__(self, untranslated: str, ctx: ContextPlus, config: Config) -> str:
try: try:
return self.translations[untranslated] locale = config.get_value(
"core",
f"guild.{ctx.guild.id}.locale",
config.get_value("core", "locale"),
)
return self.translations[locale][untranslated]
except KeyError: except KeyError:
return untranslated return untranslated
@ -81,16 +78,19 @@ class Translator(Callable[[str], str]):
"""Loads the current translations. """Loads the current translations.
""" """
self.translations = {} for locale in available_locales.keys():
locale_path = self.cog_folder / "locales" / f"{get_locale()}.po" locale_path = self.cog_folder / "locales" / f"{locale}.po"
with locale_path.open("r") as f: with locale_path.open("r") as f:
catalog = read_po(f) catalog = read_po(f)
for message in catalog: for message in catalog:
if message.id: if message.id:
self._add_translation(message.id, message.string) self._add_translation(locale, message.id, message.string)
def _add_translation(self, untranslated, translated): def _add_translation(self, locale: str, untranslated: str, translated: str):
if translated: if translated:
self.translations[untranslated] = translated if not self.translations.get(locale, False):
self.translations[locale] = {}
self.translations[locale][untranslated] = translated