From 1f88499d440db7c1c9ff62a381b197191dcfcef3 Mon Sep 17 00:00:00 2001 From: Romain J Date: Thu, 11 Jun 2020 19:43:00 +0200 Subject: [PATCH] feat(i18n): finish persisting data for i18n --- tuxbot/cogs/admin/admin.py | 26 +++++----- tuxbot/cogs/admin/locales/en-US.po | 11 ++--- tuxbot/cogs/admin/locales/en-US.po~ | 15 +++--- tuxbot/cogs/admin/locales/fr-FR.po | 11 +---- tuxbot/cogs/admin/locales/fr-FR.po~ | 28 +++++++++++ tuxbot/cogs/admin/locales/messages.pot | 8 +--- tuxbot/core/config.py | 32 ++++++++++++- tuxbot/core/data_manager.py | 2 +- tuxbot/core/i18n.py | 66 +++++++++++++------------- 9 files changed, 120 insertions(+), 79 deletions(-) create mode 100644 tuxbot/cogs/admin/locales/fr-FR.po~ diff --git a/tuxbot/cogs/admin/admin.py b/tuxbot/cogs/admin/admin.py index 6c1b13f..e86316e 100644 --- a/tuxbot/cogs/admin/admin.py +++ b/tuxbot/cogs/admin/admin.py @@ -5,7 +5,7 @@ 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.i18n import Translator, find_locale, get_locale_name, available_locales from tuxbot.core.utils.functions.extra import group_extra, ContextPlus log = logging.getLogger("tuxbot.cogs.admin") @@ -16,11 +16,10 @@ class Admin(commands.Cog, name="Admin"): def __init__(self, bot: Tux): self.bot = bot - @group_extra( - name="lang", - aliases=["locale", "langue"], - deletable=True - ) + async def _save_lang(self, ctx: ContextPlus, lang: str): + await self.bot.config.update("core", f"guild.{ctx.guild.id}.locale", lang) + + @group_extra(name="lang", aliases=["locale", "langue"], deletable=True) @commands.guild_only() @checks.is_admin() async def _lang(self, ctx: ContextPlus): @@ -29,20 +28,21 @@ class Admin(commands.Cog, name="Admin"): @_lang.command(name="set", aliases=["define", "choice"]) async def _lang_set(self, ctx: ContextPlus, lang: str): try: - set_locale(lang.lower()) + await self._save_lang(ctx, find_locale(lang.lower())) await ctx.send( - _("Locale changed to {lang} successfully") - .format(lang=f"`{lang}`") + _("Locale changed to {lang} successfully", ctx, self.bot.config).format( + lang=f"`{get_locale_name(lang).lower()}`" + ) ) 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"]) 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 + title=_("List of available locales: ", ctx, self.bot.config), + description="\n".join([i[0] for i in available_locales.values()]), + color=0x36393E, ) await ctx.send(embed=e) diff --git a/tuxbot/cogs/admin/locales/en-US.po b/tuxbot/cogs/admin/locales/en-US.po index fbf8e4f..e3e2632 100644 --- a/tuxbot/cogs/admin/locales/en-US.po +++ b/tuxbot/cogs/admin/locales/en-US.po @@ -7,7 +7,7 @@ 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" +"POT-Creation-Date: 2020-06-11 19:07+0200\n" "PO-Revision-Date: 2020-06-10 00:38+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -18,15 +18,10 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: tuxbot/cogs/admin/admin.py:33 -#, fuzzy, python-brace-format +#, 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 +#: tuxbot/cogs/admin/admin.py:43 msgid "List of available locales: " msgstr "" diff --git a/tuxbot/cogs/admin/locales/en-US.po~ b/tuxbot/cogs/admin/locales/en-US.po~ index ca18c7c..fad1457 100644 --- a/tuxbot/cogs/admin/locales/en-US.po~ +++ b/tuxbot/cogs/admin/locales/en-US.po~ @@ -7,7 +7,7 @@ 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" +"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" @@ -17,12 +17,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tuxbot/cogs/admin/admin.py:33 -#, fuzzy, python-brace-format +#: tuxbot/cogs/admin/admin.py:38 +#, 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:47 +msgid "List of available locales: " msgstr "" diff --git a/tuxbot/cogs/admin/locales/fr-FR.po b/tuxbot/cogs/admin/locales/fr-FR.po index 78cb879..05626fd 100644 --- a/tuxbot/cogs/admin/locales/fr-FR.po +++ b/tuxbot/cogs/admin/locales/fr-FR.po @@ -8,7 +8,7 @@ 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" +"POT-Creation-Date: 2020-06-11 19:07+0200\n" "PO-Revision-Date: 2020-06-10 00:38+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -23,13 +23,6 @@ msgstr "" 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 +#: tuxbot/cogs/admin/admin.py:43 msgid "List of available locales: " msgstr "Liste des langues disponibles : " diff --git a/tuxbot/cogs/admin/locales/fr-FR.po~ b/tuxbot/cogs/admin/locales/fr-FR.po~ new file mode 100644 index 0000000..ee3ea87 --- /dev/null +++ b/tuxbot/cogs/admin/locales/fr-FR.po~ @@ -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 : " diff --git a/tuxbot/cogs/admin/locales/messages.pot b/tuxbot/cogs/admin/locales/messages.pot index 7b5dc0f..c522501 100644 --- a/tuxbot/cogs/admin/locales/messages.pot +++ b/tuxbot/cogs/admin/locales/messages.pot @@ -8,7 +8,7 @@ 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" +"POT-Creation-Date: 2020-06-11 19:07+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,10 +22,6 @@ msgstr "" 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 +#: tuxbot/cogs/admin/admin.py:43 msgid "List of available locales: " msgstr "" diff --git a/tuxbot/core/config.py b/tuxbot/core/config.py index 02b4484..5a4702c 100644 --- a/tuxbot/core/config.py +++ b/tuxbot/core/config.py @@ -2,6 +2,7 @@ import asyncio import json import logging from typing import List, Dict, Union, Any +from flatten_dict import flatten, unflatten import discord @@ -124,7 +125,9 @@ class Config: datas = self.__getitem__(cog_name) 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 @@ -139,3 +142,30 @@ class Config: await self.loop.run_in_executor(None, self._dump) 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 diff --git a/tuxbot/core/data_manager.py b/tuxbot/core/data_manager.py index 789641c..d96661c 100644 --- a/tuxbot/core/data_manager.py +++ b/tuxbot/core/data_manager.py @@ -83,4 +83,4 @@ def logs_data_path(instance_name: str) -> Path: Path Generated path for logs files. """ - return data_path(instance_name) / "data" / instance_name / "logs" + return data_path(instance_name) / "logs" diff --git a/tuxbot/core/i18n.py b/tuxbot/core/i18n.py index dfb594b..4190dc0 100644 --- a/tuxbot/core/i18n.py +++ b/tuxbot/core/i18n.py @@ -5,42 +5,34 @@ from typing import Callable, Union, Dict, List 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") _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, List[str]] = { + "en-US": ["english", "anglais", "en", "us", "en-us"], + "fr-FR": ["français", "francais", "french", "fr", "be", "fr-fr"], } -_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()`""" + """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: 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") - else: - global _current_locale - _current_locale = _available_locales.get(find_locale(locale)) - reload_locales() + raise NotImplementedError("This locale isn't implemented") -def reload_locales() -> None: - for translator in _translators: - translator.load_translations() +def get_locale_name(locale: str) -> str: + """Return the name of this `locale` + + """ + return available_locales.get(find_locale(locale))[0] class Translator(Callable[[str], str]): @@ -65,9 +57,14 @@ class Translator(Callable[[str], str]): self.load_translations() - def __call__(self, untranslated: str) -> str: + def __call__(self, untranslated: str, ctx: ContextPlus, config: Config) -> str: 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: return untranslated @@ -81,16 +78,19 @@ class Translator(Callable[[str], str]): """Loads the current translations. """ - self.translations = {} - locale_path = self.cog_folder / "locales" / f"{get_locale()}.po" + for locale in available_locales.keys(): + locale_path = self.cog_folder / "locales" / f"{locale}.po" - with locale_path.open("r") as f: - catalog = read_po(f) + 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) + for message in catalog: + if message.id: + 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: - self.translations[untranslated] = translated + if not self.translations.get(locale, False): + self.translations[locale] = {} + + self.translations[locale][untranslated] = translated